diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 65812eea..7d2e8556 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,6 +7,13 @@ assignees: '' --- +**Note** +We're fortunate to have a community of highly skilled system engineers and reverse engineers contributing to HyperDbg. However, as an open-source, community-driven debugger, our resources and developer time are limited. + +Since most HyperDbg users are professional programmers, we encourage you to contribute by submitting pull requests (PRs) whenever possible. While we will address issues created by users, we greatly appreciate your efforts to resolve issues independently and submit PRs. If you're unable to create a PR, please feel free to create an issue, and we'll do our best to address it. + +Thank you for reporting issues and for your contributions! ❤️ + **Describe the bug** A clear and concise description of what the bug is. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index bbcbbe7d..e7f6d791 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,6 +7,13 @@ assignees: '' --- +**Note** +We're fortunate to have a community of highly skilled system engineers and reverse engineers contributing to HyperDbg. However, as an open-source, community-driven debugger, our resources and developer time are limited. + +Since most HyperDbg users are professional programmers, we encourage you to contribute by submitting pull requests (PRs) whenever possible. While we will address requests for new features created by users, we greatly appreciate your efforts to add them independently and submit PRs. If you're unable to create a PR, please feel free to create your request, and we'll do our best to address it. You can also create issues or discussions to discuss the possible features that you want to add to HyperDbg. + +Thank you for requesting new features and for your contributions! ❤️ + **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] diff --git a/.github/git/git-help.md b/.github/git/git-help.md index 9505f465..61ad99df 100644 --- a/.github/git/git-help.md +++ b/.github/git/git-help.md @@ -44,6 +44,32 @@ To remove the effects of `git add .` and `git commit -m "test"` or just `git add git reset --soft HEAD~1 ``` +To remove **all uncommitted and untracked changes** in Git and reset your working tree to the last commit: + +```bash +git reset --hard +git clean -fd +``` + +To modify the last pushed commit: + +```bash +# Undo the last commit but keep the changes in your working tree +git reset --soft HEAD~1 + +# Make your additional modifications +# edit files... + +# Stage everything +git add . + +# Create a new commit +git commit -m "Updated commit message" + +# Force-push to replace the remote commit +git push --force-with-lease +``` + --------------- ## Releasing instructions diff --git a/.github/workflows/vs2022.yml b/.github/workflows/vs2022.yml index dc844290..aa834a05 100644 --- a/.github/workflows/vs2022.yml +++ b/.github/workflows/vs2022.yml @@ -1,26 +1,31 @@ name: vs2022-ci on: - push: - branches: - - master - - dev - tags: - - 'v*' - paths-ignore: - - '.gitignore' - - '.gitattributes' - - '**.cmd' - - '**.bat' - - '**.md' - - pull_request: - paths-ignore: - - '.gitignore' - - '.gitattributes' - - '**.cmd' - - '**.bat' - - '**.md' + workflow_dispatch: + +# Disabled, uncomment the below line and remove the above lines to activate +# on: +# push: +# branches: +# - master +# - dev +# tags: +# - 'v*' +# paths-ignore: +# - '.gitignore' +# - '.gitattributes' +# - '**.cmd' +# - '**.bat' +# - '**.md' +# +# pull_request: +# paths-ignore: +# - '.gitignore' +# - '.gitattributes' +# - '**.cmd' +# - '**.bat' +# - '**.md' + env: # WDK for Windows 11, version 22H2 WDK_URL: https://go.microsoft.com/fwlink/?linkid=2196230 @@ -73,12 +78,12 @@ jobs: # working-directory: ${{env.GITHUB_WORKSPACE}} # run: msbuild /m /p:Configuration="Release MT" /p:Platform=${{matrix.PLATFORM}} /target:zydis /target:zycore /p:OutDir=${{ github.workspace }}/hyperdbg/libraries/zydis/ ${{ github.workspace }}/hyperdbg/dependencies/zydis/msvc/Zydis.sln - - name: Build Hyperdbg solution + - name: Build HyperDbg solution working-directory: ${{env.GITHUB_WORKSPACE}} run: msbuild /m /p:Configuration=${{matrix.BUILD_CONFIGURATION}} /p:Platform=${{matrix.PLATFORM}} ${{env.SOLUTION_FILE_PATH}} - name: Upload build directory - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4.4.0 with: name: build_files_${{matrix.BUILD_CONFIGURATION}} path: ${{ env.BUILD_BIN_DIR }} @@ -86,12 +91,12 @@ jobs: deploy-release: name: Deploy release needs: win-amd64-build - runs-on: windows-2019 + runs-on: windows-2022 if: startsWith(github.ref, 'refs/tags/') steps: - name: Download build files from "build" job - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4.1.7 with: name: build_files_release path: ${{ env.BUILD_BIN_DIR }} diff --git a/.github/workflows/vs2026.yml b/.github/workflows/vs2026.yml new file mode 100644 index 00000000..0e587b16 --- /dev/null +++ b/.github/workflows/vs2026.yml @@ -0,0 +1,99 @@ +name: vs2026-ci + +on: + push: + branches: + - '**' # matches all branch names, including ones with slashes + tags: + - 'v*' + paths-ignore: + - '.gitignore' + - '.gitattributes' + - '**.cmd' + - '**.bat' + - '**.md' + + pull_request: + paths-ignore: + - '.gitignore' + - '.gitattributes' + - '**.cmd' + - '**.bat' + - '**.md' + +env: + SOLUTION_FILE_PATH: ./hyperdbg/hyperdbg.sln + RELEASE_ZIP_FILE_NAME: hyperdbg + BUILD_BIN_DIR: ./hyperdbg/build/bin/ + +jobs: + win-amd64-build: + runs-on: windows-2025-vs2026 + strategy: + matrix: + BUILD_CONFIGURATION: [release, debug] + PLATFORM: [x64] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + + - name: Checkout submodules recursively + run: git submodule update --init --recursive --remote + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v3 + + - name: Setup NuGet + uses: NuGet/setup-nuget@v2 + + - name: Restore NuGet packages + run: nuget restore ${{ env.SOLUTION_FILE_PATH }} + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Update vcxproj files + run: python utils/replace-sdk-wdk.py + + - name: Build HyperDbg solution + working-directory: ${{env.GITHUB_WORKSPACE}} + run: msbuild /m /p:Configuration=${{matrix.BUILD_CONFIGURATION}} /p:Platform=${{matrix.PLATFORM}} ${{env.SOLUTION_FILE_PATH}} + + - name: Upload build directory + uses: actions/upload-artifact@v4.4.0 + with: + name: build_files_${{matrix.BUILD_CONFIGURATION}} + path: ${{ env.BUILD_BIN_DIR }} + + deploy-release: + name: Deploy release + needs: win-amd64-build + runs-on: windows-2025-vs2026 + if: startsWith(github.ref, 'refs/tags/') + steps: + - name: Download build files from "build" job + uses: actions/download-artifact@v4.1.7 + with: + name: build_files_release + path: ${{ env.BUILD_BIN_DIR }} + + - name: Archive release + uses: thedoctor0/zip-release@master + with: + path: ${{ env.BUILD_BIN_DIR }}release/ + type: 'zip' + filename: ${{env.RELEASE_ZIP_FILE_NAME}}-${{ github.ref_name }}.zip + + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: | + ${{env.RELEASE_ZIP_FILE_NAME}}-${{ github.ref_name }}.zip + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index c38435e2..0c2f68c0 100644 --- a/.gitignore +++ b/.gitignore @@ -377,16 +377,26 @@ MigrationBackup/ !/hyperdbg/libraries/DIA/x84/* !/hyperdbg/libraries/DIA/x64/* -# KdSerial Libraries +# kdserial libraries !/hyperdbg/libraries/kdserial/* !/hyperdbg/libraries/kdserial/x86/* !/hyperdbg/libraries/kdserial/x64/* !/hyperdbg/libraries/kdserial/arm/* !/hyperdbg/libraries/kdserial/arm64/* +# Ignore keystone libraries +!/hyperdbg/libraries/keystone/release/ +!/hyperdbg/libraries/keystone/debug/ +!/hyperdbg/libraries/keystone/release/* +!/hyperdbg/libraries/keystone/debug/* # Code review tools compile_commands.json StructLayoutSettings.json -*.metaproj \ No newline at end of file +*.metaproj + +#ignore clion config files +.idea +cmake-build-debug +/hyperdbg/hyperhv/zydis/ diff --git a/.gitmodules b/.gitmodules index c15beeab..bc4340e1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,12 @@ +[submodule "hyperdbg/tests/script-engine-test"] + path = hyperdbg/tests/script-engine-test + url = https://github.com/HyperDbg/script-engine-test.git +[submodule "hyperdbg/miscellaneous/constants/pciid"] + path = hyperdbg/miscellaneous/constants/pciid + url = https://github.com/HyperDbg/pciids [submodule "hyperdbg/dependencies/ia32-doc"] path = hyperdbg/dependencies/ia32-doc url = https://github.com/HyperDbg/ia32-doc.git -[submodule "hyperdbg/dependencies/phnt"] - path = hyperdbg/dependencies/phnt - url = https://github.com/HyperDbg/phnt.git -[submodule "hyperdbg/script-engine/modules/script-engine-test"] - path = hyperdbg/script-engine/modules/script-engine-test - url = https://github.com/HyperDbg/script-engine-test [submodule "hyperdbg/dependencies/pdbex"] path = hyperdbg/dependencies/pdbex url = https://github.com/HyperDbg/pdbex.git diff --git a/CHANGELOG.md b/CHANGELOG.md index 21c6c2ec..f4f7ddac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,412 @@ 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.21.0.0] - 2026-07-05 +New release of the HyperDbg Debugger. + +### Added +- Added structure for the hyperperf (Hardware Performance Counter) project ([link](https://github.com/HyperDbg/HyperDbg/commit/c17ebc09c4d199a642352e66feebb3159582196c)) +- The 'unload' command checks whether any module is loaded or not ([link](https://docs.hyperdbg.org/commands/debugging-commands/unload)) +- Exported SDK API for checking whether any module is loaded or not ([link](https://github.com/HyperDbg/HyperDbg/commit/19e47c804f50f5dbb698f314e66b7d685a87ac1f)) +- Added user mode and kernel mode PT parameter parser ([link](https://github.com/HyperDbg/HyperDbg/pull/631)) +- Added thread (TID) and process (PID) helper functions for Intel PT ([link](https://github.com/HyperDbg/HyperDbg/pull/633)) + +### Changed +- Separated SDK libraries for user mode and kernel mode modules ([link](https://github.com/HyperDbg/HyperDbg/commit/c17ebc09c4d199a642352e66feebb3159582196c)) +- Added hypertrace, hyperevade, and hyperperf DLL files to SDK ([link](https://github.com/HyperDbg/HyperDbg/commit/c17ebc09c4d199a642352e66feebb3159582196c)) +- Fix pool manager uninitialize list corruption ([link](https://github.com/HyperDbg/HyperDbg/pull/629)) +- Fix 'access denied' error on loading all modules using 'load all' ([link](https://docs.hyperdbg.org/commands/debugging-commands/load))([link](https://github.com/HyperDbg/HyperDbg/commit/2b818a5116d80d466aab7b343d4aa9d1d640f082)) +- Fix the concatenation error for the "hyperkd" string on the hypertrace project (https://github.com/HyperDbg/HyperDbg/commit/2b0cc18899ff532d9d590a71bf880fee5456c15f)) +- Organized header files for the libhyperdbg project ([link](https://github.com/HyperDbg/HyperDbg/pull/632)) + +## [0.20.0.0-beta] - 2026-06-21 +New release of the HyperDbg Debugger. + +### Added +- Added the libipt library to the project and the SDK +- Added Intel Processor Trace (PT) example app +- Added Linux distinction and pragmas together with new platform functions ([link](https://github.com/HyperDbg/HyperDbg/commit/9c3e0ed23b5f4bb64bd305e546dd0e86ee1910d9)) +- Added interfaces to Linux port for the serial devices ([link](https://github.com/HyperDbg/HyperDbg/commit/31b514f8df40d81d44ae07a2328c02360ce488c3)) +- Added platform IOCTL interface ([link](https://github.com/HyperDbg/HyperDbg/pull/619)) +- Added typecast for wchar, mismatch on Linux and Windows ([link](https://github.com/HyperDbg/HyperDbg/commit/10576b064a9824ab655e7bea0e35e9556ee68ca4)) +- Added missing IOCTLs for Intel PT ([link](https://github.com/HyperDbg/HyperDbg/commit/df12e9fd79851c8f378ec82a45066da510da507a)) +- Added NuGet packages for Windows SDK and WDK +- Added Signal handler platform API for Linux ([link](https://github.com/HyperDbg/HyperDbg/pull/627)) +- Added contribution guidelines for Linux ([link](https://github.com/HyperDbg/HyperDbg/tree/master/hyperdbg/linux#readme)) + +### Changed +- Moved to Visual Studio 2026 ([link](https://github.com/HyperDbg/HyperDbg/pull/626)) +- Zydis and pdbex submodules are updated to VS2026 +- Fix the new form of loading and unloading in the example app and PT app ([link](https://github.com/HyperDbg/HyperDbg/commit/9ad48d30dcf6b409ae86b2d08262584cd06f606e)) +- Check whether the top-level hypervisor is Hyper-V and disable/enable VPIDs based on that, thanks to [@Idov31](https://github.com/Idov31) ([link](https://github.com/HyperDbg/HyperDbg/pull/625)) +- Fix PT operation IOCTL buffer size ([link](https://github.com/HyperDbg/HyperDbg/commit/dabf132d31503843f90949f35f8dce4601d43126)) +- CI/CD updated with NuGet packages for Visual Studio 2026 ([link](https://github.com/HyperDbg/HyperDbg/commit/5a0fad490124268550f955f594d1211d5c74f03d)) + +## [0.19.0.0-beta] - 2026-06-10 +New release of the HyperDbg Debugger. + +### Added +- First release of the HyperTrace module ([link](https://url.hyperdbg.org/hypertrace)) +- HyperTrace now enables/disables VM-entry/VM-exit controls for Load and Save IA32_DEBUGCTL MSR +- 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/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 +- 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)) +- Refactoring the IOCTL parameter checks and status routines +- All basic types are now defined for Linux +- 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 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)) +- 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)) + +### Changed +- 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 +- Add starting structure for supporting Intel Processor Trace (PT) + +## [0.18.0.0] - 2026-02-16 +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 efforts to port HyperDbg to Linux have started thanks to [@Alish14](https://github.com/Alish14) ([link](https://github.com/HyperDbg/HyperDbg/pull/563)) + +### Changed +- Fix compilation error in Zydis with the new Windows WDK ([link](https://github.com/HyperDbg/zydis/commit/e61f59332ce49f8853006573ca853e404fafdd08)) + +## [0.17.0.0] - 2025-11-10 +New release of the HyperDbg Debugger. All credit for this release goes to [@xmaple555](https://github.com/xmaple555). + +### Added +- Added 1D and 2D arrays (multidimensional arrays) in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/variables-and-assignments#multidimensional-array))([link](https://github.com/HyperDbg/HyperDbg/pull/554)) +- Added compound assignments in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/variables-and-assignments#compound-assignment))([link](https://github.com/HyperDbg/HyperDbg/pull/554)) +- Added multiple assignments in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/variables-and-assignments#multiple-assignment))([link](https://github.com/HyperDbg/HyperDbg/pull/554)) + +### Changed +- Fix bugs for interpreting 'db_pa, 'dd_pa', 'eb_pa', and 'ed_pa' keywords in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/assumptions-and-evaluations#keywords))([link](https://github.com/HyperDbg/HyperDbg/pull/507)) +- Fix variable types in the script engine ([link](https://github.com/HyperDbg/HyperDbg/commit/43b0245fa11b5c73ce4cd21d8b8787b86a05f89d)) +- Fix and update array index for boolean expressions in the script engine ([link](https://github.com/HyperDbg/HyperDbg/commit/ba2cec3c12c3ff45ddc0004051884983ff62a0b3)) + +## [0.16.0.0] - 2025-09-08 +New release of the HyperDbg Debugger. + +### Added +- The **!xsetbv** event command was added for handling the execution of the XSETBV instruction, thanks to HyperDbg group members ([link](https://docs.hyperdbg.org/commands/extension-commands/xsetbv)) +- Display of the number of blocked context switches in the '.switch' command ([link](https://docs.hyperdbg.org/commands/meta-commands/.switch)) +- Added support for step-in (the 't' command) in the user debugger ([link](https://docs.hyperdbg.org/commands/debugging-commands/t)) +- Added support for step-over (the 'p' command) in the user debugger ([link](https://docs.hyperdbg.org/commands/debugging-commands/p)) +- Added support to show all registers or a specific register in the user debugger ([link](https://docs.hyperdbg.org/commands/debugging-commands/r)) +- Exported SDK API for running scripts in either the kernel debugger or the user debugger +- Added support to modify registers or a specific register in the user debugger ([link](https://docs.hyperdbg.org/commands/debugging-commands/r)) +- Added support to evaluate (run) scripts on the target thread in the user debugger ([link](https://docs.hyperdbg.org/commands/debugging-commands/eval)) +- Added an indication of a thread's running or paused state to the HyperDbg signature in the user debugger ([link](https://docs.hyperdbg.org/using-hyperdbg/prerequisites/signatures)) +- Added support for the '.formats' command in the user debugger ([link](https://docs.hyperdbg.org/commands/meta-commands/.formats)) +- Added support for interpreting parameters based on script engine expressions in the user debugger +- Exported SDK API for evaluating expressions based on the context of the kernel debugger or the user debugger +- Added a new mechanism for showing the 'printf' and the 'print' function messages in the user debugger ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/exports/printf))([link](https://docs.hyperdbg.org/commands/scripting-language/functions/exports/print)) + +### Changed +- Non-volatile XMM registers are no longer saved/restored on VM-exit handler ([link](https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions?view=msvc-170)) +- Fix grammar and spelling errors throughout HyperDbg codebase ([link](https://github.com/HyperDbg/HyperDbg/pull/546)) +- Relocate extension command files into their corresponding VS directory +- Fix infinite VM-exit bug for the '!monitor x' command thanks to [@unlockable](https://github.com/unlockable) ([link](https://github.com/HyperDbg/HyperDbg/pull/545)) + +## [0.15.0.0] - 2025-08-18 +New release of the HyperDbg Debugger. + +### Added +- Added the '!smi' command for performing operations related to System Management Interrupt (SMI) ([link](https://docs.hyperdbg.org/commands/extension-commands/smi)) +- Export the SDK functions for SMI operations ([link](https://docs.hyperdbg.org/commands/extension-commands/smi#sdk)) +- Check for Intel CET IBT (indirect branch tracking) support +- Check for Intel CET shadow stack support +- Added support to Intel CET for SYSCALL/SYSRET emulation ([link](https://docs.hyperdbg.org/commands/extension-commands/syscall))([link](https://docs.hyperdbg.org/commands/extension-commands/sysret)) + +### Changed +- The 'hyperhv' project now has build optimizations enabled +- Reformat VMXOFF restoring routines to restore general-purpose and XMM registers correctly before moving to the previous stack +- Fix unloading (VMXOFF) crash when restoring XMM registers +- Fix the problem with restoring XMM registers (#468) ([link](https://github.com/HyperDbg/HyperDbg/issues/468)) +- Enhanced the '.pe' command to support PE Rich Headers thanks to [@Alish14](https://github.com/Alish14) ([link](https://github.com/HyperDbg/HyperDbg/pull/539)) +- Updated ia32-doc to fix VMCS PL3 SSP fields ([link](https://github.com/HyperDbg/ia32-doc)) +- Fix the terminating process issue of the '!syscall/!sysret' commands on 11 generation (Rocket Lake/Tiger Lake) and newer Intel processors ([link](https://github.com/HyperDbg/HyperDbg/issues/392)) +- Re-enable the support for the '.start' command in the Debugger mode ([link](https://docs.hyperdbg.org/commands/meta-commands/.start)) +- The '!mode' event command is now compatible with different EPT hook commands (e.g., !epthook, !epthook2, !monitor, .start, and .restart) ([link](https://docs.hyperdbg.org/commands/extension-commands/mode)) +- The '!mode' command doesn't need allocating extra EPTPs ([link](https://docs.hyperdbg.org/commands/extension-commands/mode)) + +## [0.14.1.0] - 2025-07-27 +New release of the HyperDbg Debugger. + +### Changed +- Restored the previous optimization on the release builds +- Fixed the issue of not properly restoring registers after the 'CPUID' instruction +- Fixed the building issues of the user debugger with the 'bp' and the '.start' commands + +## [0.14.0.0] - 2025-07-23 +New release of the HyperDbg Debugger. + +### Added +- **microsleep(microseconds)** function in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/timings/microsleep)) +- **rdtsc()** and **rdtscp()** functions in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/timings/rdtsc))([link](https://docs.hyperdbg.org/commands/scripting-language/functions/timings/rdtscp)) +- Added functions to get system-call number from the running system ([link](https://github.com/HyperDbg/HyperDbg/commit/5d33cb7395c57fd6af170bfed90376598347679c)) +- Added the support for the '.start' command in the VMI mode ([link](https://docs.hyperdbg.org/commands/meta-commands/.start)) +- Added a new mechanism for finding the system-call number based on the running system ([link](https://github.com/HyperDbg/HyperDbg/commit/5d33cb7395c57fd6af170bfed90376598347679c)) +- Added hyperevade transparency project ([link](https://url.hyperdbg.org/hyperevade)) +- Added support to the '.attach' and '.detach' in the debugger mode ([link](https://docs.hyperdbg.org/commands/meta-commands/.attach))([link](https://docs.hyperdbg.org/commands/meta-commands/.detach)) +- Added support to the '.start' command in the VMI mode for the user debugger ([link](https://docs.hyperdbg.org/commands/meta-commands/.start)) +- Added support to setting the breakpoint using the 'bp' command in the VMI mode ([link](https://docs.hyperdbg.org/commands/debugging-commands/bp)) +- Added EPT page table support for MMIO addresses above 512 GB + +### Changed +- Redesigned the '!mode' extension command without extra EPTP ([link](https://github.com/HyperDbg/HyperDbg/commit/a93b78dfadbf94d2d69f24413170c983ec379f48)) +- The user mode debugger now uses MBEC for preventing user-mode code execution ([link](https://github.com/HyperDbg/HyperDbg/commit/6893c1b19f1edaf57d0074bd60abcd518bf77338)) +- Apply transparent-mode based on dynamic system-calls ([link](https://github.com/HyperDbg/HyperDbg/commit/1eb960607331fc0c2622804d7aff65702c155649)) +- Breakpoint initialization is changed from kernel debugger to the regular debugger ([link](https://github.com/HyperDbg/HyperDbg/commit/e5326f895dcddb1adbc873a9fecede7af7eb7651)) +- Fixed the build issue on new Windows SDK for Token structures ([link](https://github.com/HyperDbg/HyperDbg/pull/530)) +- Fixed retrieving valid watching process IDs for the execution trap and user-mode execution prevention +- Fixed crashing the driver if the hyperlog memory was not properly allocated +- The target runner image for deploying HyperDbg (CI/CD) changed from Windows Server 2019 to 2022 +- Restored the pid and the process name parameters of the '!hide' command ([link](https://docs.hyperdbg.org/commands/extension-commands/hide)) +- Fixed crashing Windows when using 'TPAUSE' instruction on bare metal Windows 11 24h2 +- Check to avoid putting EPT hooks on physical addresses greater than 512 GB + +## [0.13.2.0] - 2025-05-26 +New release of the HyperDbg Debugger. + +### Added +- Intercepting system-call return results using the TRAP flag for the transparent-mode +- Added optional parameters and context for the transparent-mode system-call return interceptions + +### Changed +- Set variable length (stack frames) for showing the callstack ([link](https://docs.hyperdbg.org/commands/debugging-commands/k)) +- Fixed VMCS layout corruption due to NMI injection (VMRESUME 0x7 error) in nested-virtualization on Meteor Lake processors +- Restore RDMSR handler for VM-exits + +## [0.13.1.0] - 2025-04-14 +New release of the HyperDbg Debugger. + +### Added +- Added new transparency methods for hiding nested virtualization environments thanks to [@CokeTree3](https://github.com/CokeTree3) ([link](https://github.com/HyperDbg/HyperDbg/pull/515)) + +### Changed +- Fix '.thread' command crash ([link](https://github.com/HyperDbg/HyperDbg/pull/510)) +- Update .clang-format format file based on the new version of LLVM +- Update the list of required contributions + +## [0.13.0.0] - 2025-02-25 +New release of the HyperDbg Debugger. + +### Added +- Added mitigation for the anti-hypervisor method in handling the trap flag for emulated instructions ([link](https://github.com/HyperDbg/HyperDbg/pull/497)) +- Export the SDK functions for enabling and disabling transparent mode ([link](https://docs.hyperdbg.org/commands/extension-commands/hide#sdk))([link](https://docs.hyperdbg.org/commands/extension-commands/unhide#sdk)) +- New description of changing script engine constants ([link](https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/change-script-engine-limitations)) +- Added the command for interpreting PCI CAM (PCI configuration space) fields ([link](https://docs.hyperdbg.org/commands/extension-commands/pcicam)) +- Added the command for dumping PCI CAM (PCI configuration space) memory ([link](https://docs.hyperdbg.org/commands/extension-commands/pcicam)) +- Checking for and unloading the older version of the driver (if it exists) ([link](https://github.com/HyperDbg/HyperDbg/pull/503)) +- **memcpy_pa()** function in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/memory/memcpy_pa)) +- **poi_pa**, **hi_pa**, **low_pa**, **db_pa**, **dd_pa**, **dw_pa**, and **dq_pa** keywords in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/assumptions-and-evaluations#keywords)) +- **eb_pa**, **ed_pa**, and **eq_pa** functions in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/memory/eb_pa-ed_pa-eq_pa)) + +### Changed +- Fix the 'lm' command issue of not showing kernel module addresses (KASLR leak mitigation) introduced in Windows 11 24h2 ([link](https://docs.hyperdbg.org/commands/debugging-commands/lm)) +- Deprecated TSC mitigation for the transparent mode ([link](https://docs.hyperdbg.org/commands/extension-commands/measure)) +- Changed the parameters of the '!hide' command ([link](https://docs.hyperdbg.org/commands/extension-commands/hide)) +- Changed the parameters of the '!unhide' command ([link](https://docs.hyperdbg.org/commands/extension-commands/unhide)) +- Fix containing backslash escape character in script strings ([link](https://github.com/HyperDbg/HyperDbg/pull/499)) +- Fix reading/writing into devices' physical memory (MMIO region) in VMI Mode ([link](https://github.com/HyperDbg/HyperDbg/pull/500)) +- All test cases for command parsing are now passed ([link](https://github.com/HyperDbg/HyperDbg/pull/504)) +- The '.sympath' command now requires the symbol server path to be within quotes, although it is not mandatory ([link](https://docs.hyperdbg.org/commands/meta-commands/.sympath)) + +## [0.12.0.0] - 2025-01-02 +New release of the HyperDbg Debugger. + +### Added +- Added the PCI tree command ([link](https://docs.hyperdbg.org/commands/extension-commands/pcitree)) +- Added the proper handling for the xsetbv VM exits thanks to [@Shtan7](https://github.com/Shtan7) ([link](https://github.com/HyperDbg/HyperDbg/pull/491)) +- Added the IDT command for interpreting Interrupt Descriptor Table (IDT) ([link](https://docs.hyperdbg.org/commands/extension-commands/idt)) +- Export SDK APIs for getting Interrupt Descriptor Table (IDT) entries + +### Changed +- Fix buffer overflow in the symbols path converter thanks to [@binophism](https://github.com/binophism) ([link](https://github.com/HyperDbg/HyperDbg/pull/490)) +- Fix script engine's "printf" function to improve safety thanks to [@Reodus](https://github.com/Reodus) ([link](https://github.com/HyperDbg/HyperDbg/pull/489)) + +## [0.11.0.0] - 2024-12-03 +New release of the HyperDbg Debugger. + +### Added +- Added the local APIC command (xAPIC and x2APIC modes) ([link](https://docs.hyperdbg.org/commands/extension-commands/apic)) +- Added the I/O APIC command ([link](https://docs.hyperdbg.org/commands/extension-commands/ioapic)) +- The new link is added to help increase the number of EPT hook breakpoints in a single page ([link](https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/number-of-ept-hooks-in-one-page)) +- Export SDK APIs for Local APIC and X2APIC + +### Changed +- The link for changing the communication buffer size is updated ([link](https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/increase-communication-buffer-size)) +- Update Microsoft's DIA SDK and symsrv + +## [0.10.2.0] - 2024-10-11 +New release of the HyperDbg Debugger. + +### Added +- Automated test case parsing and test case compilation (generation) for the hwdbg debugger +- Export hwdbg testing functions +- Automated test case interpretation and emulation of hwdbg hardware scripts +- Create JSON representation of hwdbg configs + +### Changed +- Fix main command parser bugs according to test cases +- Improvements in symbol structure, token structure, and stack buffer in the script engine +- Fix compatibility mode program crash when terminating 32-bit process (#479) ([link](https://github.com/HyperDbg/HyperDbg/pull/479)) +- Extensive refactor of chip instance info interpretation codes of hwdbg debugger +- Separating functions of hwdbg interpreter and script manager +- Fix synthesize inconsistencies between Icarus iVerilog and Xilinx ISim +- Fix runtime error for deallocating memory from separate DLLs +- Exporting standard functions (import/export) for the script engine +- Exporting standard functions (import/export) for the symbol parser +- Avoid passing signals once the stage is not configured + +## [0.10.1.0] - 2024-09-08 +New release of the HyperDbg Debugger. + +### Added +- Added feature to pause the debuggee immediately upon connection +- The '.debug' command now supports pausing the debuggee at startup ([link](https://docs.hyperdbg.org/commands/meta-commands/.debug)) +- Export SDK API for assembling instructions +- The 'struct' command now supports a path as output ([link](https://docs.hyperdbg.org/commands/debugging-commands/struct)) +- Export SDK API closing connection to the remote debuggee +- Automated tests for the main command parser +- Export SDK APIs for stepping and tracing instructions +- Export SDK APIs for tracking execution + +### Changed +- HyperDbg command-line comment sign is changed from '#' to C-like comments ('//' and '/**/') +- Integrating a new command parser for the regular HyperDbg commands +- Fix showing a list of active outputs using the 'output' command ([link](https://docs.hyperdbg.org/commands/debugging-commands/output)) +- Fix the issue of passing arguments to the '.start' command ([link](https://docs.hyperdbg.org/commands/meta-commands/.start)) +- Fix the problem with parsing multiple spaces within the events (#420) ([link](https://github.com/HyperDbg/HyperDbg/issues/420)) +- Fix the problem with escaping '{' in the command parser (#421) ([link](https://github.com/HyperDbg/HyperDbg/issues/421)) +- Fix nested brackets issues in the main command parser +- Fix script engine bugs on order of passing arguments to functions (#453) ([link](https://github.com/HyperDbg/HyperDbg/issues/453)) +- Fix the script test case for factorial computation ([link](https://github.com/HyperDbg/script-engine-test/blob/main/semantic-test-cases/manual-test-cases_60-69.ds)) +- Fix the script test case for computation iterative Fibonacci ([link](https://github.com/HyperDbg/script-engine-test/blob/main/semantic-test-cases/manual-test-cases_60-69.ds)) +- Fix miscomputation of physical address width for physical address validity checks (#469) ([link](https://github.com/HyperDbg/HyperDbg/issues/469)) + +## [0.10.0.0] - 2024-07-22 +New release of the HyperDbg Debugger. + +### Added +- Support using assembly conditions and codes in all events ([link](https://docs.hyperdbg.org/using-hyperdbg/prerequisites/how-to-create-a-condition))([link](https://docs.hyperdbg.org/using-hyperdbg/prerequisites/how-to-create-an-action)) +- Added support for forwarding events to binary (DLL) modules ([link](https://docs.hyperdbg.org/tips-and-tricks/misc/event-forwarding))([link](https://docs.hyperdbg.org/commands/debugging-commands/output))([link](https://github.com/HyperDbg/event-forwarding-examples)) +- Added the assembler command 'a' for virtual memory ([link](https://docs.hyperdbg.org/commands/debugging-commands/a)) +- Added the assembler command '!a' for physical memory ([link](https://docs.hyperdbg.org/commands/extension-commands/a)) +- Providing a unified SDK API for reading memory in the VMI Mode and the Debugger Mode +- Export SDK APIs for reading/writing into registers in the Debugger Mode +- Export SDK API for writing memory in the VMI Mode and the Debugger Mode +- Export SDK API for getting kernel base address +- Export SDK API for connecting to the debugger and from debuggee in the Debugger Mode +- Export SDK API for starting a new process +- Add and export SDK API for unsetting message callback +- Event commands are coming with more examples regarding scripts and assembly codes +- Add message callback using shared memory +- Add maximum execution limitation to the script IRs (#435) ([link](https://github.com/HyperDbg/HyperDbg/pull/435)) + +### Changed +- Fix clearing '!monitor' hooks on a different process or if the process is closed (#409) ([link](https://github.com/HyperDbg/HyperDbg/issues/409)) +- Fix triggering multiple '!monitor' hooks with different contexts (#415) ([link](https://github.com/HyperDbg/HyperDbg/issues/415)) +- Fix the problem of repeating commands once kHyperDbg is disconnected +- Fix step-over hangs if the process terminates/excepts within call instruction (#406) ([link](https://github.com/HyperDbg/HyperDbg/issues/406)) +- Fix crash on editing invalid physical addresses (#424) ([link](https://github.com/HyperDbg/HyperDbg/issues/424)) +- Fix exporting VMM module load and install it in the SDK +- Fix function interpretation issues and update the parser and the code execution (#435) ([link](https://github.com/HyperDbg/HyperDbg/pull/435)) + +## [0.9.1.0] - 2024-06-30 +New release of the HyperDbg Debugger. + +### Added +- Regular port/pin value read and modification in hwdbg +- Conditional statement evaluation in hwdbg +- Added automatic script buffer packet generator for hwdbg +- Added support for @hw_pinX and @hw_portX registers +- Added hwdbg instance information interpreter +- Added stack buffer in vmx-root ([link](https://github.com/HyperDbg/HyperDbg/commit/5df4d2a5268a6b190dc126bf6cfe0527703296eb)) +- Exporting functions to support loading drivers with different names +- Exporting function to connect and load HyperDbg drivers +- Exporting function to connect and load HyperDbg drivers +- **$date** and **$time** pseudo-registers are added ([link](https://docs.hyperdbg.org/commands/scripting-language/assumptions-and-evaluations#pseudo-registers))([link](https://github.com/HyperDbg/HyperDbg/issues/397)) + +### Changed +- Fix using constant WSTRINGs in the **wcsncmp** function ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/strings/wcsncmp)) +- Fix `phnt` build error with 24H2 SDK +- `hprdbgctrl.dll` changed to `libhyperdbg.dll` +- `hprdbgkd.sys` changed to `hyperkd.sys` +- `hprdbghv.dll` changed to `hyperhv.dll` +- Dividing user/kernel exported headers in the SDK + +## [0.9.0.0] - 2024-06-09 +New release of the HyperDbg Debugger. + +### Added +- The **!monitor** command now physical address hooking ([link](https://docs.hyperdbg.org/commands/extension-commands/monitor)) +- **hwdbg** is merged to HyperDbg codebase ([link](https://hwdbg.hyperdbg.org)) +- **strncmp(Str1, Str2, Num)**, and **wcsncmp(WStr1, WStr2, Num)** functions in script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/strings/strncmp))([link](https://docs.hyperdbg.org/commands/scripting-language/functions/strings/wcsncmp)) + +### Changed +- Using a separate HOST IDT in VMCS (not OS IDT) (fix to this [VM escape](https://www.unknowncheats.me/forum/c-and-c-/390593-vm-escape-via-nmi.html) issues) +- Using a dedicated HOST GDT and TSS Stack +- Checking for race-condition of not locked cores before applying instant-events and switching cores +- The error message for invalid address is changed ([more information](https://docs.hyperdbg.org/tips-and-tricks/considerations/accessing-invalid-address)) +- Fix the problem of not locking all cores after running the '.pagein' command + +## [0.8.4.0] - 2024-05-10 +New release of the HyperDbg Debugger. + +### Changed +- Fixed the signedness overflow of the command parser + ## [0.8.3.0] - 2024-05-03 New release of the HyperDbg Debugger. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 86595a5f..4b0d2c53 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,21 +2,19 @@ First off, thanks for taking the time to contribute! ❤️ -HyperDbg is a large-scale project that requires a lot of time and effort from the community. Given the current number of developers and their limited time and resources, we cannot develop every part simultaneously. Therefore, new developers are warmly welcomed to join and add their contributions to the project. Here, we made a list of potential improvements that you can contribute on. Feel free to open up an issue if you think you have any ideas that would make a good addition to the list, or if you want to implement one of the below items, or if you'd like to discuss a question you might have. +HyperDbg is a large-scale project that requires a lot of time and effort from the community. Given the current number of developers and their limited time and resources, we cannot develop every part simultaneously. Therefore, new developers are warmly welcomed to join and add their contributions to the project. Here, we made a list of potential improvements that you can contribute on. Feel free to open up an issue if you think you have any ideas that would make a good addition to the list. ## Things to Work on -- Writing blog posts about use-cases of HyperDbg -- Troubleshooting problems with running on Hyper-V's nested virtualization -- Troubleshooting problems with running on VirtualBox's nested virtualization -- Supporting kdnet (sending data over the net) -- Adding an assembler to the project -- Enhancing HyperDbg's [Transparent Mode](https://docs.hyperdbg.org/using-hyperdbg/prerequisites/operation-modes#transparent-mode), especially anti-hypervisor methods -- Making a SoftICE-style GUI -- Enhancing and adding more features to the ['.pe'](https://docs.hyperdbg.org/commands/meta-commands/.pe) command -- Anything else you might find interesting ;) +Please make sure to create a [discussion](https://github.com/orgs/HyperDbg/discussions) or an [issue](https://github.com/HyperDbg/HyperDbg/issues), or even better, join the HyperDbg groups ([Telegram](https://t.me/HyperDbg), [Discord](https://discord.gg/anSPsGUtzN), [Matrix](https://matrix.to/#/#hyperdbg-discussion:matrix.org)) on social media. Discuss the way you want to implement your changes and inform developers, because we often see people simultaneously working on the same issue. To avoid this collision, make sure to inform us before you start developing. -This list will be updated frequently. +### Working on an Idea or a Task +- We have a [wide range of ideas and tasks](https://github.com/orgs/HyperDbg/projects/2) that you might be interested in working on. You can choose a task and start working on it, and if you have any questions or need clarification, feel free to ask. This list will be updated frequently. + +### Other Things to Work on +- Writing blog posts and creating videos about use-cases of HyperDbg (make sure to add it to the [awesome](https://github.com/HyperDbg/awesome) repository). +- Fixing unresolved GitHub [issues](https://github.com/HyperDbg/HyperDbg/issues). +- Any other interesting ideas you might find! (Let's have a discussion before working on them.) ## Fixing Bugs diff --git a/CREDITS.md b/CREDITS.md index 36bfb4ad..0d39ff7b 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -4,7 +4,7 @@ The list provided comprises individuals who have made significant contributions ## Credits: -The attributions listed on this credits page are acknowledged without any particular order. +Just so you know – the attributions listed on this credits page are acknowledged without any particular order. - All of the [contributors](https://github.com/HyperDbg/HyperDbg/graphs/contributors) - Sina Karvandi ([@Intel80x86](https://twitter.com/Intel80x86)) @@ -21,4 +21,10 @@ The attributions listed on this credits page are acknowledged without any partic - Ddkwork ([@ddkwork](https://github.com/ddkwork)) for making GUI - Mohammad K. Fallah ([@mkfallah11](https://github.com/mkfallah11)) for implementing the optimization algorithms - Xandora Team ([xandora.io](https://www.xandora.io)) for [Keystone](https://github.com/keystone-engine/keystone) engine -- xmaple555 ([@xmaple555](https://github.com/xmaple555)) for contributions in HyperDbg core and the script engine \ No newline at end of file +- xmaple555 ([@xmaple555](https://github.com/xmaple555)) for contributions in HyperDbg core and the script engine +- Abbas Masoumi Gorji ([@AbbasMasoumiG](https://twitter.com/AbbasMasoumiG)) +- Björn Ruytenberg ([@0Xiphorus](https://twitter.com/0Xiphorus)) +- Marcis Zarins ([@CokeTree3](https://github.com/CokeTree3)) for his works on enhancing HyperEvade project +- Artem Shishkin ([@honorary_bot](https://twitter.com/honorary_bot)) for always answering our hypervisor questions +- unrustled.jimmies for helping us debug and fix issues, and his contributions in HyperDbg +- Hari Mishal ([@harimishal1](https://github.com/harimishal1)) for his works on the hypertrace project for supporting Last Branch Record (LBR) \ No newline at end of file diff --git a/README.md b/README.md index ef9a7374..fae0672e 100644 --- a/README.md +++ b/README.md @@ -6,25 +6,40 @@ License

- # HyperDbg Debugger HyperDbg Debugger
-HyperDbg Debugger is an open-source, community-driven, hypervisor-assisted, user-mode, and kernel-mode Windows debugger with a focus on using modern hardware technologies. It is a debugger designed for analyzing, fuzzing, and reversing. +**HyperDbg Debugger** is a free (as in free beer), open-source, community-driven, hypervisor-assisted, user-mode, and kernel-mode Windows debugger with a focus on using modern hardware technologies. It is a debugger designed for analyzing, fuzzing, and reversing. -You can follow **HyperDbg** on **[Twitter](https://twitter.com/HyperDbg)** to get notified about new releases, or join the HyperDbg **[Telegram](https://t.me/HyperDbg)** group, where you can ask developers and open-source reversing enthusiasts for help with setting up and running HyperDbg. +You can follow **HyperDbg** on **[Twitter](https://twitter.com/HyperDbg)** or **[Mastodon](https://infosec.exchange/@hyperdbg)** to get notified about new releases, or join any of the HyperDbg groups, where you can ask developers and open-source reversing enthusiasts for help setting up and using HyperDbg. + +- **[Telegram](https://t.me/HyperDbg)** +- **[Discord](https://discord.gg/anSPsGUtzN)** +- **[Matrix](https://matrix.to/#/#hyperdbg-discussion:matrix.org)** ## Description -**HyperDbg** is designed with a focus on using modern hardware technologies to provide new features to the debuggers' world. It operates on top of Windows by virtualizing an already running system using Intel VT-x and Intel PT. This debugger aims not to use any APIs and software debugging mechanisms, but instead, it uses Second Layer Page Table (a.k.a. Extended Page Table or EPT) extensively to monitor both kernel and user executions. +**HyperDbg** is designed with a focus on using modern hardware technologies to provide new features to the debuggers' world. It operates on top of Windows by virtualizing an already running system using Intel VT-x and EPT. This debugger aims not to use any APIs and software debugging mechanisms, but instead, it uses Second Layer Page Table (a.k.a. Extended Page Table or EPT) extensively to monitor both kernel and user executions.

HyperDbg Debugger

-HyperDbg comes with features like hidden hooks, which are as fast as old inline hooks, but also stealth. It mimics hardware debug registers for (read & write) to a specific location, but this time entirely invisible for both Windows kernel and the programs, and of course, without any limitation in size or count! +HyperDbg comes with features like hidden hooks, which are as fast as old inline hooks, but also stealth. It mimics hardware debug registers for (read & write) to a specific location, but this time invisible for both the Windows kernel and the programs, and of course, without any limitation in size or count! -Using TLB-splitting, and having features such as measuring code coverage and monitoring all mov(s) to/from memory by a function, makes HyperDbg a unique debugger. +Using TLB-splitting and having features such as measuring code coverage and monitoring all mov(s) to/from memory by a function, makes HyperDbg a unique debugger. Although it has novel features, HyperDbg tries to be as stealthy as possible. It doesn’t use any debugging APIs to debug Windows or any application, so classic anti-debugging methods won’t detect it. Also, it resists the exploitation of time delta methods (e.g., RDTSC/RDTSCP) to detect the presence of hypervisors, therefore making it much harder for applications, packers, protectors, malware, anti-cheat engines, etc. to discover the debugger. +## Why HyperDbg? + +HyperDbg is harder to set up and use, and also requires deeper low-level system knowledge compared to traditional debuggers. However, it provides two major advantages: + +1. **Full System & OS Control** +HyperDbg operates at the hypervisor level, giving you powerful capabilities that are simply not possible with classic debuggers. This allows you to leverage hardware-assisted [features](https://github.com/HyperDbg/HyperDbg?tab=readme-ov-file#unique-features) for advanced reverse engineering and debugging scenarios. + +2. **Stealth & Detection Resistance** +Since HyperDbg doesn't rely on standard OS debugging APIs, it is generally much harder (though not impossible) to detect. This makes it a strong choice when working against anti-debugging protections. + +These advantages open up entirely new debugging and reverse engineering techniques that go beyond what conventional debuggers can offer. + ## Build & Installation You can download the latest compiled binary files from **[releases](https://github.com/HyperDbg/HyperDbg/releases)**; otherwise, if you want to build HyperDbg, you should clone HyperDbg with the `--recursive` flag. @@ -35,7 +50,7 @@ Please visit **[Build & Install](https://docs.hyperdbg.org/getting-started/build ## Tutorials -The **[OpenSecurityTraining2's "Reversing with HyperDbg (Dbg3301)"](https://ost2.fyi/Dbg3301)** tutorial is the recommended way to get started with and learn HyperDbg, guiding you through the initial steps of using HyperDbg, covering essential concepts, principles, debugging functionalities, along with practical examples and numerous reverse engineering methods that are unique to HyperDbg. +The **OpenSecurityTraining2's "Reversing with HyperDbg (Dbg3301)**" tutorial series, available on [**OST2's website**](https://ost2.fyi/Dbg3301) (_preferred_) and [**YouTube**](https://www.youtube.com/playlist?list=PLUFkSN0XLZ-kF1f143wlw8ujlH2A45nZY) is the recommended way to get started with and learn HyperDbg. It guides you through the initial steps of using HyperDbg, covering essential concepts, principles, and debugging functionalities, along with practical examples and numerous reverse engineering methods that are unique to HyperDbg. If you're interested in understanding the internal design and architecture of hypervisors and HyperDbg, you can read the [**Hypervisor From Scratch**](https://rayanfam.com/tutorials) tutorials. @@ -54,26 +69,71 @@ In case you use one of **HyperDbg**'s components in your work, please consider c year={2022} } ``` +
-**2. [The Reversing Machine: Reconstructing Memory Assumptions](https://arxiv.org/pdf/2405.00298)** [[arXiv](https://arxiv.org/abs/2405.00298)] +Other paper built upon HyperDbg... + +**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)] ``` -@misc{karvandi2024reversing, - Author = {Mohammad Sina Karvandi and Soroush Meghdadizanjani and Sima Arasteh and Saleh Khalaj Monfared and Mohammad K. Fallah and Saeid Gorgin and Jeong-A Lee and Erik van der Kouwe}, - Title = {The Reversing Machine: Reconstructing Memory Assumptions}, - Year = {2024}, - Eprint = {arXiv:2405.00298}, +@inproceedings{karvandi2025hwdbg, + title={hwdbg: Debugging Hardware Like Software}, + author={Karvandi, Mohammad Sina and Meghdadizanjani, Soroush and Monfared, Saleh Khalaj and van der Kouwe, Erik and Slowinska, Asia}, + booktitle={Proceedings of the 18th European Workshop on Systems Security}, + pages={56--62}, + year={2025} } ``` -You can also read [this article](https://research.hyperdbg.org/debugger/kernel-debugger-design.html) as it describes the overall architecture, technical difficulties, design decisions, and internals of HyperDbg Debugger, [this article](https://research.hyperdbg.org/debugger/transparency.html) about our efforts on vm-exit transparency, and [this article](https://research.hyperdbg.org/debugger/chasing-bugs.html) about chasing bugs within hypervisors. 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. +**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, + title={HyperEvade: Countering Anti-Debugging Techniques and Enhancing Transparency in Nested Virtualization using HyperDbg}, + author={Ruytenberg, Bj{\"o}rn and Karvandi, Mohammad Sina}, + journal={Journal of Object Technology}, + volume={25}, + number={1}, + pages={1--3}, + year={2026}, + publisher={Association Internationale pour les Technologies Objets} +} +``` + +**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, + title={Digital Hole: Bypassing Commercial Audio DRM Solutions with DReaMcatcher}, + author={Ruytenberg, Bj{\"o}rn and Karvandi, Mohammad Sina and Bos, Herbert and van der Kouwe, Erik and Slowinska, Asia}, + booktitle={Proceedings of the 21st European Conference on Computer Systems}, + pages={484--496}, + year={2026} +} +``` + +**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} +} +``` + +
+ +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. ## Unique Features -### First Release (v0.1.0.0) + * Advanced Hypervisor-based Kernel Mode Debugger [link][link][link] * Classic EPT Hook (Hidden Breakpoint) [link][link][link] * Inline EPT Hook (Inline Hook) [link][link] -* Monitor Memory For R/W (Emulating Hardware Debug Registers Without Limitation) [link][link][link] +* Monitor Memory for R/W (Emulating Hardware Debug Registers Without Limitation) [link][link][link] * SYSCALL Hook (Disable EFER & Handle #UD) [link][link][link] * SYSRET Hook (Disable EFER & Handle #UD) [link][link] * CPUID Hook & Monitor [link][link] @@ -83,15 +143,15 @@ You can also read [this article](https://research.hyperdbg.org/debugger/kernel-d * RDPMC Hook & Monitor [link] * VMCALL Hook & Monitor [link] * Debug Registers Hook & Monitor [link] -* I/O Port (In Instruction) Hook & Monitor [link][link] -* I/O Port (Out Instruction) Hook & Monitor [link][link] +* I/O Port (IN Instruction) Hook & Monitor [link][link] +* I/O Port (OUT Instruction) Hook & Monitor [link][link] * MMIO Monitor [link] * Exception (IDT < 32) Monitor [link][link][link] * External-Interrupt (IDT > 32) Monitor [link][link][link] * Running Automated Scripts [link] -* Transparent-mode (Anti-debugging and Anti-hypervisor Resistance) [link][link] -* Running Custom Assembly In Both VMX-root, VMX non-root (Kernel & User) [link] -* Checking For Custom Conditions [link][link] +* Transparent-mode and Hyperevade Project (Anti-debugging and Anti-hypervisor Resistance) [link][link][link] +* Running Custom Assembly in Both VMX-root, VMX non-root (Kernel & User) [link] +* Checking for Custom Conditions [link][link] * Process-specific & Thread-specific Debugging [link][link][link] * VMX-root Compatible Message Tracing [link] * Powerful Kernel Side Scripting Engine [link][link] @@ -100,30 +160,26 @@ You can also read [this article](https://research.hyperdbg.org/debugger/kernel-d * Event Forwarding (#DFIR) [link][link] * Transparent Breakpoint Handler [link][link] * Various Custom Scripts [link] - -### Second Release (v0.2.0.0) * HyperDbg Software Development Kit (SDK) [link] - -### Third Release (v0.3.0.0) * Event Short-circuiting [link][link] -* Tracking records of function calls and return addresses [link] +* Tracking Records of Function Calls and Return Addresses [link] * Kernel-level Length Disassembler Engine (LDE) [link][link] - -### Fourth Release (v0.4.0.0) * Memory Execution Monitor & Execution Blocking [link] * Custom Page-fault Injection [link] - -### Fifth Release (v0.5.0.0) * Different Event Calling Stages [link] - -### Sixth Release (v0.6.0.0) * Injecting Custom Interrupts/Exceptions/Faults [link][link] - -### Seventh Release (v0.7.0.0) -* Instant events in the Debugger Mode [link] - -### Eighth Release (v0.8.0.0) -* Detect kernel-to-user and user-to-kernel transitions [link] +* Instant Events in the Debugger Mode [link] +* Detecting Kernel-to-user and User-to-kernel Transitions [link] +* Physical Memory Monitoring Hooks [link] +* Enumerating PCI/PCI-e Devices [link] +* Interpreting and Dumping PCI/PCI-e Configuration Space (CAM) [link] +* Dumping IDT Entries, I/O APIC, and Local APIC in XAPIC and X2APIC Modes [link][link][link] +* Triggering and Counting System Management Mode (SMM) Interrupts (SMIs) [link] +* Attaching to the User-mode Process and Preventing Execution [link] +* Intercepting Execution of XSETBV Instructions [link] +* Writing Library Script Files [link] +* Enhanced Portable Executable (PE) Parser [link] +* Tracing Branches using Last Branch Record (LBR) [link][link][link][link][link][link][link] ## How does it work? @@ -135,15 +191,17 @@ You can read about the internal design of HyperDbg and its features in the [docu
## Scripts + You can write your **[scripts](https://github.com/HyperDbg/scripts)** to automate your debugging journey. **HyperDbg** has a powerful, fast, and entirely kernel-side implemented [script engine](https://docs.hyperdbg.org/commands/scripting-language). ## Contributing + Contributing to HyperDbg is super appreciated. We have made a list of potential [tasks](https://github.com/HyperDbg/HyperDbg/blob/master/CONTRIBUTING.md#things-to-work-on) that you might be interested in contributing towards. If you want to contribute to HyperDbg, please read the [Contribution Guide](https://github.com/HyperDbg/HyperDbg/blob/master/CONTRIBUTING.md). - ## License + **HyperDbg**, and all its submodules and repos, unless a license is otherwise specified, are licensed under **GPLv3** LICENSE. Dependencies are licensed by their own. diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..47fa15b3 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,3 @@ +# User-Mode and Kernel-Mode Examples + +Examples for user-mode and kernel-mode are **NOT** yet completed and are currently **under construction**! diff --git a/examples/kernel/README.md b/examples/kernel/README.md new file mode 100644 index 00000000..e509023b --- /dev/null +++ b/examples/kernel/README.md @@ -0,0 +1,3 @@ +NOTE +============ +Build it directly from the main HyperDbg solution file. Do not build it independently, as it requires dependency files from the main HyperDbg libraries to be built first. \ No newline at end of file diff --git a/examples/kernel/hyperdbg_driver/CMakeLists.txt b/examples/kernel/hyperdbg_driver/CMakeLists.txt new file mode 100644 index 00000000..3b2ca0b2 --- /dev/null +++ b/examples/kernel/hyperdbg_driver/CMakeLists.txt @@ -0,0 +1,20 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "header/core/Core.h" + "header/driver/Driver.h" + "header/driver/Loader.h" + "header/misc/Global.h" + "header/pch.h" + "code/core/Core.c" + "code/driver/Driver.c" + "code/driver/Ioctl.c" + "code/driver/Loader.c" +) +include_directories( + "../../../hyperdbg/include" + "header" +) +wdk_add_driver(hyperdbg_driver + KMDF 1.15 + ${SourceFiles} +) diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/code/core/Core.c b/examples/kernel/hyperdbg_driver/code/core/Core.c similarity index 100% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/code/core/Core.c rename to examples/kernel/hyperdbg_driver/code/core/Core.c diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/code/driver/Driver.c b/examples/kernel/hyperdbg_driver/code/driver/Driver.c similarity index 99% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/code/driver/Driver.c rename to examples/kernel/hyperdbg_driver/code/driver/Driver.c index 44922817..b4092073 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_driver/code/driver/Driver.c +++ b/examples/kernel/hyperdbg_driver/code/driver/Driver.c @@ -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(); } /** diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/code/driver/Ioctl.c b/examples/kernel/hyperdbg_driver/code/driver/Ioctl.c similarity index 84% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/code/driver/Ioctl.c rename to examples/kernel/hyperdbg_driver/code/driver/Ioctl.c index f80b0c04..8d7b1c5c 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_driver/code/driver/Ioctl.c +++ b/examples/kernel/hyperdbg_driver/code/driver/Ioctl.c @@ -26,15 +26,17 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) PREGISTER_NOTIFY_BUFFER RegisterEventRequest; NTSTATUS Status; + UNREFERENCED_PARAMETER(DeviceObject); + // // Here's the best place to see if there is any allocation pending // to be allcated as we're in PASSIVE_LEVEL // // DO NOT CHANGE CALLING OF THE FOLLOWING FUNCTION // - PoolManagerCheckAndPerformAllocationAndDeallocation(); + // PoolManagerCheckAndPerformAllocationAndDeallocation(); - if (g_AllowIOCTLFromUsermode) + if (g_VmmInitialized) { IrpStack = IoGetCurrentIrpStackLocation(Irp); @@ -62,10 +64,21 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) switch (RegisterEventRequest->Type) { case IRP_BASED: - Status = LogRegisterIrpBasedNotification(DeviceObject, Irp); + + LogRegisterIrpBasedNotification((PVOID)Irp, &Status); + break; case EVENT_BASED: - Status = LogRegisterEventBasedNotification(DeviceObject, Irp); + + if (LogRegisterEventBasedNotification((PVOID)Irp)) + { + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_UNSUCCESSFUL; + } + break; default: LogError("Err, unknown notification type from user-mode"); diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/code/driver/Loader.c b/examples/kernel/hyperdbg_driver/code/driver/Loader.c similarity index 96% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/code/driver/Loader.c rename to examples/kernel/hyperdbg_driver/code/driver/Loader.c index a84a8f63..7a2ed944 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_driver/code/driver/Loader.c +++ b/examples/kernel/hyperdbg_driver/code/driver/Loader.c @@ -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"); diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/header/core/Core.h b/examples/kernel/hyperdbg_driver/header/core/Core.h similarity index 100% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/header/core/Core.h rename to examples/kernel/hyperdbg_driver/header/core/Core.h diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/header/driver/Driver.h b/examples/kernel/hyperdbg_driver/header/driver/Driver.h similarity index 100% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/header/driver/Driver.h rename to examples/kernel/hyperdbg_driver/header/driver/Driver.h diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/header/driver/Loader.h b/examples/kernel/hyperdbg_driver/header/driver/Loader.h similarity index 93% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/header/driver/Loader.h rename to examples/kernel/hyperdbg_driver/header/driver/Loader.h index c12b0d12..7ead903c 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_driver/header/driver/Loader.h +++ b/examples/kernel/hyperdbg_driver/header/driver/Loader.h @@ -17,7 +17,7 @@ ////////////////////////////////////////////////// VOID -LoaderUninitializeLogTracer(); +LoaderUninitLogTracer(); BOOLEAN LoaderInitVmmAndReversingMachine(); diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/header/misc/Global.h b/examples/kernel/hyperdbg_driver/header/misc/Global.h similarity index 77% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/header/misc/Global.h rename to examples/kernel/hyperdbg_driver/header/misc/Global.h index 77cf5e59..db81c9d8 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_driver/header/misc/Global.h +++ b/examples/kernel/hyperdbg_driver/header/misc/Global.h @@ -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; \ No newline at end of file diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/header/pch.h b/examples/kernel/hyperdbg_driver/header/pch.h similarity index 69% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/header/pch.h rename to examples/kernel/hyperdbg_driver/header/pch.h index ed1f5358..2d085776 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_driver/header/pch.h +++ b/examples/kernel/hyperdbg_driver/header/pch.h @@ -9,12 +9,6 @@ * @copyright This project is released under the GNU Public License v3. * */ -#include -#include -#include -#include -#include -#include // // Scope definitions @@ -23,14 +17,15 @@ #define HYPERDBG_RM // -// Definition of Intel primitives (External header) +// General WDK headers // -// #include "ia32-doc/out/ia32.h" +#include +#include // // Import Configuration and Definitions // -#include "Configuration.h" +#include "config/Configuration.h" // // Macros @@ -45,15 +40,15 @@ // // Import HyperLog Module // -#include "SDK/Modules/HyperLog.h" -#include "SDK/Imports/HyperDbgHyperLogImports.h" -#include "SDK/Imports/HyperDbgHyperLogIntrinsics.h" +#include "SDK/modules/HyperLog.h" +#include "SDK/imports/kernel/HyperDbgHyperLogImports.h" +#include "SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h" // // Import VMM Module // -#include "SDK/Modules/VMM.h" -#include "SDK/Imports/HyperDbgVmmImports.h" +#include "SDK/modules/VMM.h" +#include "SDK/imports/kernel/HyperDbgVmmImports.h" // // Local Driver headers diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/hyperdbg_driver.vcxproj b/examples/kernel/hyperdbg_driver/hyperdbg_driver.vcxproj similarity index 59% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/hyperdbg_driver.vcxproj rename to examples/kernel/hyperdbg_driver/hyperdbg_driver.vcxproj index a6cb2789..fd70d5dc 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_driver/hyperdbg_driver.vcxproj +++ b/examples/kernel/hyperdbg_driver/hyperdbg_driver.vcxproj @@ -1,5 +1,8 @@  + + + debug @@ -9,14 +12,6 @@ release x64 - - debug - ARM64 - - - release - ARM64 - {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5} @@ -47,22 +42,6 @@ Universal false - - Windows10 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - Windows10 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - @@ -81,18 +60,12 @@ $(SolutionDir)build\bin\$(Configuration)\ $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - - DbgengKernelDebugger - - - DbgengKernelDebugger - sha256 - $(SolutionDir)\include;$(ProjectDir)header;%(AdditionalIncludeDirectories) + $(SolutionDir)include;$(ProjectDir)header;%(AdditionalIncludeDirectories) true @@ -101,7 +74,7 @@ true - $(SolutionDir)build\bin\$(Configuration)\hyperlog.lib;$(SolutionDir)build\bin\$(Configuration)\hprdbghv.lib;%(AdditionalDependencies) + $(SolutionDir)build\bin\$(Configuration)\hyperlog.lib;$(SolutionDir)build\bin\$(Configuration)\hyperhv.lib;%(AdditionalDependencies) DriverEntry @@ -110,29 +83,20 @@ sha256 - $(SolutionDir)\include;$(ProjectDir)header;%(AdditionalIncludeDirectories) + $(SolutionDir)include;$(ProjectDir)header;%(AdditionalIncludeDirectories) true Create pch.h + Full true - $(SolutionDir)build\bin\$(Configuration)\hyperlog.lib;$(SolutionDir)build\bin\$(Configuration)\hprdbghv.lib;%(AdditionalDependencies) + $(SolutionDir)build\bin\$(Configuration)\hyperlog.lib;$(SolutionDir)build\bin\$(Configuration)\hyperhv.lib;%(AdditionalDependencies) DriverEntry - - - sha256 - - - - - sha256 - - @@ -149,7 +113,20 @@ + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_driver/hyperdbg_driver.vcxproj.filters b/examples/kernel/hyperdbg_driver/hyperdbg_driver.vcxproj.filters similarity index 96% rename from hyperdbg/include/SDK/Examples/hyperdbg_driver/hyperdbg_driver.vcxproj.filters rename to examples/kernel/hyperdbg_driver/hyperdbg_driver.vcxproj.filters index 2a6aa09a..3345321d 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_driver/hyperdbg_driver.vcxproj.filters +++ b/examples/kernel/hyperdbg_driver/hyperdbg_driver.vcxproj.filters @@ -56,4 +56,7 @@ code\driver + + + \ No newline at end of file diff --git a/examples/kernel/hyperdbg_driver/packages.config b/examples/kernel/hyperdbg_driver/packages.config new file mode 100644 index 00000000..eb276766 --- /dev/null +++ b/examples/kernel/hyperdbg_driver/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/examples/user/README.md b/examples/user/README.md new file mode 100644 index 00000000..e509023b --- /dev/null +++ b/examples/user/README.md @@ -0,0 +1,3 @@ +NOTE +============ +Build it directly from the main HyperDbg solution file. Do not build it independently, as it requires dependency files from the main HyperDbg libraries to be built first. \ No newline at end of file diff --git a/examples/user/hyperdbg_app/CMakeLists.txt b/examples/user/hyperdbg_app/CMakeLists.txt new file mode 100644 index 00000000..28460d83 --- /dev/null +++ b/examples/user/hyperdbg_app/CMakeLists.txt @@ -0,0 +1,11 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "../../../platform/user/header/Environment.h" + "header/pch.h" + "code/hyperdbg-app.cpp" +) +include_directories( + "../../../hyperdbg/include" + "header" +) +add_executable(hyperdbg_app ${SourceFiles}) diff --git a/examples/user/hyperdbg_app/code/hyperdbg-app.cpp b/examples/user/hyperdbg_app/code/hyperdbg-app.cpp new file mode 100644 index 00000000..095876bf --- /dev/null +++ b/examples/user/hyperdbg_app/code/hyperdbg-app.cpp @@ -0,0 +1,58 @@ +#include "pch.h" + +static int +ShowMessages(const char * Text) +{ + printf("%s", Text); + return 0; +} + +static int +LoadVmm() +{ + hyperdbg_u_set_text_message_callback((PVOID)ShowMessages); + + if (!hyperdbg_u_detect_vmx_support()) + { + printf("[-] VT-x (VMX) is not supported / enabled on this processor\n"); + return 1; + } + + printf("[*] loading HyperDbg VMM...\n"); + if (hyperdbg_u_install_kd_driver() == 1 || hyperdbg_u_load_vmm() == 1) + { + printf("[-] cannot load the HyperDbg VMM\n"); + return 1; + } + + printf("[+] HyperDbg VMM is running\n"); + + return 0; +} + +int +main(int argc, char ** argv) +{ + return main2(argc, argv); + + if (LoadVmm() != 0) + { + return 1; + } + + hyperdbg_u_run_command((CHAR*)"lm"); + + printf("[*] unloading HyperDbg VMM...\n"); + + // + // Unload the driver + // + hyperdbg_u_unload_vmm(); + hyperdbg_u_unload_kd(); + hyperdbg_u_stop_kd_driver(); + hyperdbg_u_uninstall_kd_driver(); + + printf("[+] done\n"); + + return 0; +} diff --git a/examples/user/hyperdbg_app/code/hyperdbg-ipt.cpp b/examples/user/hyperdbg_app/code/hyperdbg-ipt.cpp new file mode 100644 index 00000000..aacd776f --- /dev/null +++ b/examples/user/hyperdbg_app/code/hyperdbg-ipt.cpp @@ -0,0 +1,583 @@ +#include "pch.h" + +#include +#include +#include +#include "../dependencies/libipt/intel-pt.h" +#include + +#pragma comment(lib, "dbghelp.lib") + +static UINT64 g_ImageBase = 0; +static UINT64 g_CodeBase = 0; +static UINT64 g_CodeSize = 0; +static UINT8 * g_Code = NULL; + +static int +ShowMessages(const char * Text) +{ + printf("%s", Text); + return 0; +} + +static int +ReadImage(uint8_t * Buffer, size_t Size, const struct pt_asid * Asid, uint64_t Ip, void * Context) +{ + (void)Asid; + (void)Context; + + if (g_Code == NULL || Ip < g_CodeBase || Ip >= g_CodeBase + g_CodeSize) + return -pte_nomap; + + uint64_t Available = g_CodeBase + g_CodeSize - Ip; + size_t Count = (Size < Available) ? Size : (size_t)Available; + + memcpy(Buffer, g_Code + (Ip - g_CodeBase), Count); + return (int)Count; +} + +typedef struct _PROC_BASIC_INFO +{ + LONG ExitStatus; + PVOID PebBaseAddress; + ULONG_PTR Reserved[4]; +} PROC_BASIC_INFO; + +typedef LONG(NTAPI * PFN_NT_QIP)(HANDLE, ULONG, PVOID, ULONG, PULONG); + +static BOOLEAN +CaptureImage(HANDLE Process, UINT64 * TextStart, UINT64 * TextEnd) +{ + HMODULE Ntdll = GetModuleHandleA("ntdll.dll"); + PFN_NT_QIP NtQip = Ntdll ? (PFN_NT_QIP)GetProcAddress(Ntdll, "NtQueryInformationProcess") : NULL; + PROC_BASIC_INFO Pbi = {0}; + ULONG Ret = 0; + SIZE_T Got = 0; + UINT64 Base = 0; + IMAGE_DOS_HEADER Dos; + IMAGE_NT_HEADERS64 Nt; + UINT64 SectionBase; + + if (NtQip == NULL || NtQip(Process, 0, &Pbi, sizeof(Pbi), &Ret) < 0 || Pbi.PebBaseAddress == NULL) + return FALSE; + + if (!ReadProcessMemory(Process, (PBYTE)Pbi.PebBaseAddress + 0x10, &Base, sizeof(Base), &Got) || Base == 0) + return FALSE; + + if (!ReadProcessMemory(Process, (PVOID)Base, &Dos, sizeof(Dos), &Got) || Dos.e_magic != IMAGE_DOS_SIGNATURE) + return FALSE; + + if (!ReadProcessMemory(Process, (PBYTE)Base + Dos.e_lfanew, &Nt, sizeof(Nt), &Got) || Nt.Signature != IMAGE_NT_SIGNATURE) + return FALSE; + + g_ImageBase = Base; + SectionBase = Base + Dos.e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS64, OptionalHeader) + Nt.FileHeader.SizeOfOptionalHeader; + + for (WORD i = 0; i < Nt.FileHeader.NumberOfSections; i++) + { + IMAGE_SECTION_HEADER Section; + + if (!ReadProcessMemory(Process, (PBYTE)SectionBase + (UINT64)i * sizeof(Section), &Section, sizeof(Section), &Got)) + return FALSE; + + if (memcmp(Section.Name, ".text", 6) != 0) + continue; + + UINT64 Start = Base + Section.VirtualAddress; + UINT64 Size = Section.Misc.VirtualSize ? Section.Misc.VirtualSize : Section.SizeOfRawData; + + if (Size == 0) + return FALSE; + + g_Code = (UINT8 *)malloc((size_t)Size); + if (g_Code == NULL) + return FALSE; + + if (!ReadProcessMemory(Process, (PVOID)Start, g_Code, (SIZE_T)Size, &Got) || Got != Size) + { + free(g_Code); + g_Code = NULL; + return FALSE; + } + + g_CodeBase = Start; + g_CodeSize = Size; + *TextStart = Start; + *TextEnd = Start + Size - 1; + return TRUE; + } + + return FALSE; +} + +static BOOLEAN +ResolveFunction(HANDLE Process, const char * Path, const char * Name, UINT64 * Start, UINT64 * End) +{ + union + { + SYMBOL_INFO Info; + BYTE Buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; + } Symbol = {0}; + BOOLEAN Ok = FALSE; + + SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); + if (!SymInitialize(Process, NULL, FALSE)) + return FALSE; + + if (SymLoadModuleEx(Process, NULL, Path, NULL, (DWORD64)g_ImageBase, 0, NULL, 0) != 0) + { + Symbol.Info.SizeOfStruct = sizeof(SYMBOL_INFO); + Symbol.Info.MaxNameLen = MAX_SYM_NAME; + + if (SymFromName(Process, Name, &Symbol.Info) && Symbol.Info.Address != 0) + { + *Start = Symbol.Info.Address; + *End = Symbol.Info.Address + (Symbol.Info.Size ? Symbol.Info.Size : 0x200) - 1; + Ok = TRUE; + } + } + + SymCleanup(Process); + return Ok; +} + +static BOOLEAN +PtOperation(HYPERTRACE_PT_OPERATION_REQUEST_TYPE Type) +{ + HYPERTRACE_PT_OPERATION_PACKETS Op = {}; + Op.PtOperationType = Type; + return hyperdbg_u_pt_operation(&Op); +} + +static BOOLEAN +PtFilter(UINT32 ProcessId, UINT64 Start, UINT64 End) +{ + HYPERTRACE_PT_OPERATION_PACKETS Op = {}; + + Op.PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FILTER; + Op.FilterOptions.TraceUser = 1; + Op.EnableOptions.Pid = ProcessId; + + if (End > Start) + { + Op.FilterOptions.NumAddrRanges = 1; + Op.FilterOptions.AddrRanges[0].Start = Start; + Op.FilterOptions.AddrRanges[0].End = End; + } + + if (!hyperdbg_u_pt_operation(&Op)) + return FALSE; + + printf("[+] PT filter: cr3=0x%llx traceuser=%u ranges=%u buffer=0x%llx\n", + (unsigned long long)Op.EnableOptions.Cr3, + Op.FilterOptions.TraceUser, + Op.FilterOptions.NumAddrRanges, + (unsigned long long)Op.BufferSize); + return TRUE; +} + +static const char * +PacketName(enum pt_packet_type Type) +{ + switch (Type) + { + case ppt_psb: return "PSB"; case ppt_psbend: return "PSBEND"; case ppt_pad: return "PAD"; + case ppt_fup: return "FUP"; case ppt_tip: return "TIP"; case ppt_tip_pge: return "TIP.PGE"; + case ppt_tip_pgd: return "TIP.PGD"; case ppt_tnt_8: return "TNT8"; case ppt_tnt_64: return "TNT64"; + case ppt_mode: return "MODE"; case ppt_pip: return "PIP"; case ppt_vmcs: return "VMCS"; + case ppt_cbr: return "CBR"; case ppt_tsc: return "TSC"; case ppt_tma: return "TMA"; + case ppt_mtc: return "MTC"; case ppt_cyc: return "CYC"; case ppt_ovf: return "OVF"; + case ppt_stop: return "STOP"; case ppt_exstop: return "EXSTOP"; case ppt_mnt: return "MNT"; + case ppt_ptw: return "PTW"; default: return "?"; + } +} + +static uint64_t +ReconstructIp(const struct pt_packet_ip * Packet, uint64_t * LastIp) +{ + uint64_t Value = *LastIp; + + switch (Packet->ipc) + { + case pt_ipc_update_16: Value = (Value & ~0xffffull) | (Packet->ip & 0xffffull); break; + case pt_ipc_update_32: Value = (Value & ~0xffffffffull) | (Packet->ip & 0xffffffffull); break; + case pt_ipc_update_48: Value = (Value & ~0xffffffffffffull) | (Packet->ip & 0xffffffffffffull); break; + case pt_ipc_sext_48: + Value = Packet->ip & 0xffffffffffffull; + if (Value & 0x800000000000ull) + Value |= 0xffff000000000000ull; + break; + default: Value = Packet->ip; break; + } + + *LastIp = Value; + return Value; +} + +static UINT64 +DecodeCorePackets(UINT32 Cpu, const UINT8 * Buffer, UINT64 Size) +{ + struct pt_config Config; + struct pt_packet_decoder * Decoder; + UINT64 Count = 0; + uint64_t LastIp = 0; + int Status; + + pt_config_init(&Config); + Config.begin = (uint8_t *)Buffer; + Config.end = (uint8_t *)Buffer + Size; + + Decoder = pt_pkt_alloc_decoder(&Config); + if (Decoder == NULL) + { + printf("[-] core %u: cannot allocate packet decoder\n", Cpu); + return 0; + } + + for (;;) + { + Status = pt_pkt_sync_forward(Decoder); + if (Status < 0) + break; + + for (;;) + { + struct pt_packet Packet; + + Status = pt_pkt_next(Decoder, &Packet, sizeof(Packet)); + if (Status < 0) + break; + + Count++; + + switch (Packet.type) + { + case ppt_tnt_8: + case ppt_tnt_64: + printf(" %-8s %2u ", PacketName(Packet.type), Packet.payload.tnt.bit_size); + for (uint8_t Bit = 0; Bit < Packet.payload.tnt.bit_size && Bit < 64; Bit++) + putchar(((Packet.payload.tnt.payload >> (Packet.payload.tnt.bit_size - 1 - Bit)) & 1) ? 'T' : 'N'); + putchar('\n'); + break; + + case ppt_tip: + case ppt_fup: + case ppt_tip_pge: + case ppt_tip_pgd: + if (Packet.payload.ip.ipc == pt_ipc_suppressed) + printf(" %-8s (ip suppressed)\n", PacketName(Packet.type)); + else + { + uint64_t Ip = ReconstructIp(&Packet.payload.ip, &LastIp); + printf(" %-8s 0x%016llx exe+0x%llx\n", + PacketName(Packet.type), (unsigned long long)Ip, (unsigned long long)(Ip - g_ImageBase)); + } + break; + + case ppt_pip: + printf(" %-8s cr3=0x%llx\n", PacketName(Packet.type), (unsigned long long)Packet.payload.pip.cr3); + break; + + case ppt_cbr: + //printf(" %-8s ratio=%u\n", PacketName(Packet.type), Packet.payload.cbr.ratio); + break; + + case ppt_tsc: + printf(" %-8s tsc=0x%llx\n", PacketName(Packet.type), (unsigned long long)Packet.payload.tsc.tsc); + break; + + default: + //printf(" %-8s\n", PacketName(Packet.type)); + break; + } + } + } + + pt_pkt_free_decoder(Decoder); + return Count; +} + +static UINT64 +DecodeCore(UINT32 Cpu, const UINT8 * Buffer, UINT64 Size) +{ + struct pt_config Config; + struct pt_insn_decoder * Decoder; + struct pt_image * Image; + UINT64 Count = 0; + int Status; + + pt_config_init(&Config); + Config.begin = (uint8_t *)Buffer; + Config.end = (uint8_t *)Buffer + Size; + + Decoder = pt_insn_alloc_decoder(&Config); + if (Decoder == NULL) + { + printf("[-] core %u: cannot allocate instruction decoder\n", Cpu); + return 0; + } + + Image = pt_insn_get_image(Decoder); + pt_image_set_callback(Image, ReadImage, NULL); + + for (;;) + { + Status = pt_insn_sync_forward(Decoder); + if (Status < 0) + break; + + for (;;) + { + struct pt_insn Insn; + + while (Status & pts_event_pending) + { + struct pt_event Event; + Status = pt_insn_event(Decoder, &Event, sizeof(Event)); + if (Status < 0) + break; + } + + if (Status < 0 || (Status & pts_eos)) + break; + + Status = pt_insn_next(Decoder, &Insn, sizeof(Insn)); + if (Status < 0) + break; + + ZydisDisassembledInstruction Disasm; + ZydisMachineMode Mode = (Insn.mode == ptem_32bit) ? ZYDIS_MACHINE_MODE_LEGACY_32 : ZYDIS_MACHINE_MODE_LONG_64; + + if (ZYAN_SUCCESS(ZydisDisassembleIntel(Mode, Insn.ip, Insn.raw, Insn.size, &Disasm))) + printf(" 0x%016llx exe+0x%-6llx %s\n", + (unsigned long long)Insn.ip, + (unsigned long long)(Insn.ip - g_ImageBase), + Disasm.text); + else + printf(" 0x%016llx (undecodable)\n", (unsigned long long)Insn.ip); + + Count++; + } + + if (Status >= 0 && (Status & pts_eos)) + break; + } + + pt_insn_free_decoder(Decoder); + return Count; +} + +static void +RunAndTrace(const char * Path, const char * Function, BOOLEAN Packets, int PinCore) +{ + STARTUPINFOA Startup = {0}; + PROCESS_INFORMATION Process = {0}; + HYPERTRACE_PT_MMAP_PACKETS Mmap = {0}; + HYPERTRACE_PT_OPERATION_PACKETS Sizes = {0}; + UINT64 TextStart = 0; + UINT64 TextEnd = 0; + UINT64 FilterStart = 0; + UINT64 FilterEnd = 0; + UINT64 Total = 0; + + Startup.cb = sizeof(Startup); + + if (!CreateProcessA(Path, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &Startup, &Process)) + { + printf("[-] cannot launch '%s' (error 0x%x)\n", Path, GetLastError()); + return; + } + + printf("[+] launched '%s' (pid %u, suspended)\n", Path, Process.dwProcessId); + + if (PinCore >= 0) + { + DWORD_PTR Mask = (DWORD_PTR)1 << PinCore; + if (SetProcessAffinityMask(Process.hProcess, Mask)) + printf("[+] pinned target to core %d (all trace should land on this core)\n", PinCore); + else + printf("[!] could not pin to core %d (error 0x%x); running unpinned\n", PinCore, GetLastError()); + } + else + { + printf("[*] target unpinned (scheduler may migrate it across cores)\n"); + } + + if (!CaptureImage(Process.hProcess, &TextStart, &TextEnd)) + { + printf("[-] cannot read target image / .text section\n"); + TerminateProcess(Process.hProcess, 1); + goto Cleanup; + } + + printf("[+] image base 0x%llx, .text 0x%llx-0x%llx (%llu bytes)\n", + (unsigned long long)g_ImageBase, + (unsigned long long)TextStart, + (unsigned long long)TextEnd, + (unsigned long long)g_CodeSize); + + FilterStart = TextStart; + FilterEnd = TextEnd; + + if (Function != NULL && ResolveFunction(Process.hProcess, Path, Function, &FilterStart, &FilterEnd)) { + printf("[+] IP filter narrowed to '%s' 0x%llx-0x%llx (%llu bytes)\n", + Function, + (unsigned long long)FilterStart, + (unsigned long long)FilterEnd, + (unsigned long long)(FilterEnd - FilterStart + 1)); + } + else + { + printf("[!] IP filter: whole .text (symbol '%s' not found - build the target with a PDB)\n", + Function ? Function : "(none)"); + } + + if (!PtFilter(Process.dwProcessId, FilterStart, FilterEnd) || + !PtOperation(HYPERTRACE_PT_OPERATION_REQUEST_TYPE_ENABLE)) + { + printf("[-] cannot enable Intel PT\n"); + TerminateProcess(Process.hProcess, 1); + goto Cleanup; + } + + if (!hyperdbg_u_pt_mmap(&Mmap)) + { + printf("[-] pt_mmap failed\n"); + PtOperation(HYPERTRACE_PT_OPERATION_REQUEST_TYPE_DISABLE); + TerminateProcess(Process.hProcess, 1); + goto Cleanup; + } + + printf("[+] PT enabled, %u per-core buffers mapped\n", Mmap.NumCpus); + printf("[*] resuming target and waiting for it to exit...\n"); + + ResumeThread(Process.hThread); + WaitForSingleObject(Process.hProcess, INFINITE); + printf("[+] target exited, decoding trace\n"); + + PtOperation(HYPERTRACE_PT_OPERATION_REQUEST_TYPE_PAUSE); + + Sizes.PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_SIZE; + if (!hyperdbg_u_pt_operation(&Sizes)) + { + printf("[-] cannot query PT sizes\n"); + PtOperation(HYPERTRACE_PT_OPERATION_REQUEST_TYPE_DISABLE); + goto Cleanup; + } + + for (UINT32 i = 0; i < Mmap.NumCpus; i++) + { + UINT32 Cpu = Mmap.Cpus[i].CpuId; + UINT64 Bytes = (Cpu < Sizes.NumCpus) ? Sizes.BytesPerCpu[Cpu] : 0; + + if (Bytes == 0) + continue; + + if (Bytes > Mmap.Cpus[i].Size) + Bytes = Mmap.Cpus[i].Size; + + printf("\n[*] core %u: %llu bytes of trace\n", Cpu, (unsigned long long)Bytes); + Total += Packets + ? DecodeCorePackets(Cpu, (const UINT8 *)(ULONG_PTR)Mmap.Cpus[i].UserVa, Bytes) + : DecodeCore(Cpu, (const UINT8 *)(ULONG_PTR)Mmap.Cpus[i].UserVa, Bytes); + } + + printf("\n[+] decoded %llu %s total\n", (unsigned long long)Total, Packets ? "packet(s)" : "instruction(s)"); + + PtOperation(HYPERTRACE_PT_OPERATION_REQUEST_TYPE_DISABLE); + +Cleanup: + if (g_Code != NULL) + { + free(g_Code); + g_Code = NULL; + } + if (Process.hThread != NULL) + CloseHandle(Process.hThread); + if (Process.hProcess != NULL) + CloseHandle(Process.hProcess); +} + +static int +LoadVmmAndTrace() +{ + hyperdbg_u_set_text_message_callback((PVOID)ShowMessages); + + if (!hyperdbg_u_detect_vmx_support()) + { + printf("[-] VT-x (VMX) is not supported / enabled on this processor\n"); + return 1; + } + + printf("[*] loading HyperDbg VMM...\n"); + if (hyperdbg_u_install_kd_driver() == 1 || hyperdbg_u_load_vmm() == 1) + { + printf("[-] cannot load the HyperDbg VMM\n"); + return 1; + } + + printf("[+] HyperDbg VMM is running\n"); + + printf("[*] loading HyperTrace...\n"); + + if ( hyperdbg_u_load_hypertrace_module() == 1) + { + printf("[-] cannot load the HyperDbg HyperTrace\n"); + return 1; + } + + printf("[+] HyperDbg HyperTrace is running\n"); + + return 0; +} + +int +main2(int argc, char ** argv) +{ + const char * function = "main"; + BOOLEAN packets = FALSE; + int pinCore = 0; + + if (argc < 2) + { + printf("HyperDbg Intel PT tracer\n"); + printf("usage: %s [function] [-p] [-c core]\n", argv[0]); + printf(" [function] symbol to IP-filter (default 'main'; pass '*' for whole .text)\n"); + printf(" -p dump raw PT packets (TNT/TIP/FUP/PSB/...) instead of instructions\n"); + printf(" -c core pin the target to this logical core (default 0; -1 = unpinned)\n"); + return 1; + } + + for (int i = 2; i < argc; i++) + { + if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--packets") == 0) + packets = TRUE; + else if (strcmp(argv[i], "-c") == 0 && i + 1 < argc) + pinCore = atoi(argv[++i]); + else if (strcmp(argv[i], "*") == 0) + function = NULL; + else + function = argv[i]; + } + + if (LoadVmmAndTrace() != 0) + { + return 1; + } + + RunAndTrace(argv[1], function, packets, pinCore); + + printf("[*] unloading HyperDbg VMM...\n"); + + // + // Unload the driver + // + hyperdbg_u_unload_vmm(); + hyperdbg_u_unload_kd(); + hyperdbg_u_stop_kd_driver(); + hyperdbg_u_uninstall_kd_driver(); + + printf("[+] done\n"); + + return 0; +} diff --git a/examples/user/hyperdbg_app/header/example-ipt.h b/examples/user/hyperdbg_app/header/example-ipt.h new file mode 100644 index 00000000..90f00b87 --- /dev/null +++ b/examples/user/hyperdbg_app/header/example-ipt.h @@ -0,0 +1,16 @@ +/** + * @file example-ipt.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for Intel PT example + * @details + * + * @version 0.20 + * @date 2026-06-13 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +int +main2(int argc, char** argv); \ No newline at end of file diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_app/header/pch.h b/examples/user/hyperdbg_app/header/pch.h similarity index 75% rename from hyperdbg/include/SDK/Examples/hyperdbg_app/header/pch.h rename to examples/user/hyperdbg_app/header/pch.h index 80114722..d4bbf789 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_app/header/pch.h +++ b/examples/user/hyperdbg_app/header/pch.h @@ -12,14 +12,14 @@ */ #pragma once -// -// add headers that you want to pre-compile here -// + // + // Environment headers + // +#include "platform/general/header/Environment.h" // // Windows SDK headers // - #define WIN32_LEAN_AND_MEAN // @@ -36,6 +36,10 @@ // // HyperDbg SDK headers // -#include "Definition.h" #include "SDK/HyperDbgSdk.h" -#include "SDK/Imports/HyperDbgCtrlImports.h" +#include "SDK/imports/user/HyperDbgLibImports.h" + +// +// Other internal headers +// +#include "example-ipt.h" diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_app/hprdbgrev.vcxproj b/examples/user/hyperdbg_app/hyperdbg_app.vcxproj similarity index 56% rename from hyperdbg/include/SDK/Examples/hyperdbg_app/hprdbgrev.vcxproj rename to examples/user/hyperdbg_app/hyperdbg_app.vcxproj index 7a781963..3072d9ac 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_app/hprdbgrev.vcxproj +++ b/examples/user/hyperdbg_app/hyperdbg_app.vcxproj @@ -1,14 +1,6 @@ - - debug - Win32 - - - release - Win32 - debug x64 @@ -19,9 +11,11 @@ + + @@ -33,29 +27,16 @@ hyperdbg_app - - Application - true - v143 - Unicode - - - Application - false - v143 - true - Unicode - Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode @@ -64,73 +45,55 @@ - - - - - - - + + + C:\Users\masra\Desktop\libipt + $(SolutionDir)build\bin\$(Configuration)\ $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + false $(SolutionDir)build\bin\$(Configuration)\ $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + true - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - Level3 true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + _DEBUG;_CONSOLE;ZYCORE_STATIC_BUILD;ZYDIS_STATIC_BUILD;%(PreprocessorDefinitions) true MultiThreadedDebug Create pch.h - $(SolutionDir)\include;$(ProjectDir)\header;%(AdditionalIncludeDirectories) + $(LibIptDir)\include;$(SolutionDir)include;$(SolutionDir)dependencies\zydis\include;$(SolutionDir)dependencies\zydis\dependencies\zycore\include;$(ProjectDir)header;%(AdditionalIncludeDirectories) true Console true - $(SolutionDir)build\bin\$(Configuration)\hprdbgctrl.lib;%(AdditionalDependencies) - true + $(LibIptDir)\lib;%(AdditionalLibraryDirectories) + $(SolutionDir)build\bin\$(Configuration)\libhyperdbg.lib;$(SolutionDir)libraries\zydis\user\Zydis.lib;$(SolutionDir)libraries\zydis\user\Zycore.lib;$(SolutionDir)libraries\libipt\libipt.lib + false + + + + + + @@ -138,22 +101,30 @@ true true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + NDEBUG;_CONSOLE;ZYCORE_STATIC_BUILD;ZYDIS_STATIC_BUILD;%(PreprocessorDefinitions) true MultiThreaded Create pch.h - $(SolutionDir)\include;$(ProjectDir)\header;%(AdditionalIncludeDirectories) + $(LibIptDir)\include;$(SolutionDir)include;$(SolutionDir)dependencies\zydis\include;$(SolutionDir)dependencies\zydis\dependencies\zycore\include;$(ProjectDir)header;%(AdditionalIncludeDirectories) true + MaxSpeed Console true true true - $(SolutionDir)build\bin\$(Configuration)\hprdbgctrl.lib;%(AdditionalDependencies) + $(LibIptDir)\lib;%(AdditionalLibraryDirectories) + $(SolutionDir)build\bin\$(Configuration)\libhyperdbg.lib;$(SolutionDir)libraries\zydis\user\Zydis.lib;$(SolutionDir)libraries\zydis\user\Zycore.lib;$(SolutionDir)libraries\libipt\libipt.lib true + + + + + + diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_app/hprdbgrev.vcxproj.filters b/examples/user/hyperdbg_app/hyperdbg_app.vcxproj.filters similarity index 66% rename from hyperdbg/include/SDK/Examples/hyperdbg_app/hprdbgrev.vcxproj.filters rename to examples/user/hyperdbg_app/hyperdbg_app.vcxproj.filters index e6fb0974..d7dd0c26 100644 --- a/hyperdbg/include/SDK/Examples/hyperdbg_app/hprdbgrev.vcxproj.filters +++ b/examples/user/hyperdbg_app/hyperdbg_app.vcxproj.filters @@ -7,13 +7,22 @@ {c40916c8-414b-486b-bfd1-13bcbafd8fa1} + + {14cb7f22-aa90-410e-a333-f05e0ec7981f} + header + + header + + + code + code diff --git a/hwdbg/.github/workflows/test.yml b/hwdbg/.github/workflows/test.yml new file mode 100644 index 00000000..cbd456fa --- /dev/null +++ b/hwdbg/.github/workflows/test.yml @@ -0,0 +1,59 @@ +name: Continuous Integration + +on: + push: + tags: ['*'] + branches: ['main'] + pull_request: + workflow_dispatch: + +env: + verilator-version: v5.012 + verilator-install-dir: verilator-install + +jobs: + ci: + name: ci + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Cleanup + run: sed -i "s/%NAME%/test/g" build.sc + - name: Cache Scala + uses: coursier/cache-action@v6 + - name: Setup Scala + uses: coursier/setup-action@v1 + with: + jvm: adopt:11 + apps: sbt mill + - name: Setup Dependencies + run: | + sudo apt-get install ccache + - name: Get Cached Verilator + id: get-cached-verilator + uses: actions/cache@v4 + with: + path: ${{ env.verilator-install-dir }} + key: verilator-${{ env.verilator-version }} + - name: Install Verilator + if: steps.get-cached-verilator.outputs.cache-hit != 'true' + run: | + sudo apt-get install git help2man perl python3 make autoconf g++ flex bison numactl perl-doc libfl-dev + git clone https://github.com/verilator/verilator + unset VERILATOR_ROOT + cd verilator + git checkout ${{ env.verilator-version }} + autoconf + ./configure --prefix=$(pwd)/../${{ env.verilator-install-dir }} + make + make install + - name: Set PATH + run: | + echo "$(pwd)/${{ env.verilator-install-dir }}/bin" >> $GITHUB_PATH + echo VERILATOR_ROOT="$(pwd)/${{ env.verilator-install-dir }}/share/verilator" >> $GITHUB_ENV + ln -sf $(pwd)/${{ env.verilator-install-dir }}/bin/verilator_bin $(pwd)/${{ env.verilator-install-dir }}/share/verilator/verilator_bin + - name: SBT Test + run: sbt test + - name: mill Test + run: mill _.test diff --git a/hwdbg/.gitignore b/hwdbg/.gitignore new file mode 100644 index 00000000..6404852f --- /dev/null +++ b/hwdbg/.gitignore @@ -0,0 +1,366 @@ +### Project Specific stuff +test_run_dir/* +### XilinxISE template +# intermediate build files +*.bgn +*.bit +*.bld +*.cmd_log +*.drc +*.ll +*.lso +*.msd +*.msk +*.ncd +*.ngc +*.ngd +*.ngr +*.pad +*.par +*.pcf +*.prj +*.ptwx +*.rbb +*.rbd +*.stx +*.syr +*.twr +*.twx +*.unroutes +*.ut +*.xpi +*.xst +*_bitgen.xwbt +*_envsettings.html +*_map.map +*_map.mrp +*_map.ngm +*_map.xrpt +*_ngdbuild.xrpt +*_pad.csv +*_pad.txt +*_par.xrpt +*_summary.html +*_summary.xml +*_usage.xml +*_xst.xrpt + +# project-wide generated files +*.gise +par_usage_statistics.html +usage_statistics_webtalk.html +webtalk.log +webtalk_pn.xml + +# generated folders +iseconfig/ +xlnx_auto_0_xdb/ +xst/ +_ngo/ +_xmsgs/ +### Eclipse template +*.pydevproject +.metadata +.gradle +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific +.buildpath + +# sbteclipse plugin +.target + +# TeXlipse plugin +.texlipse +### C template +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +### SBT template +# Simple Build Tool +# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control + +target/ +lib_managed/ +src_managed/ +project/boot/ +.history +.cache +### Emacs template +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +### Vim template +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +### C++ template +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### OSX template +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +### Scala template +*.class +*.log +/.bsp + +# sbt specific +.cache +.history +.lib/ +dist/* +target/ +lib_managed/ +src_managed/ +project/boot/ +project/plugins/project/ + +# Scala-IDE specific +.scala_dependencies +.worksheet +### Java template +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# Visual Studio Code +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +# Scala metals +.metals/* + +# Scala metals +.bloop/ + +# Temporary disable the generated verilog files +generated/ + +# BRAM emulation content +# bram_instance_info.txt \ No newline at end of file diff --git a/hwdbg/.mill-version b/hwdbg/.mill-version new file mode 100644 index 00000000..62d5dbdf --- /dev/null +++ b/hwdbg/.mill-version @@ -0,0 +1 @@ +0.11.5 diff --git a/hwdbg/.scalafmt.conf b/hwdbg/.scalafmt.conf new file mode 100644 index 00000000..18f480ad --- /dev/null +++ b/hwdbg/.scalafmt.conf @@ -0,0 +1,5 @@ +version = "3.8.1" +runner.dialect = scala213 +maxColumn = 150 +docstrings.style = Asterisk +docstrings.oneline = unfold diff --git a/hwdbg/CODE_OF_CONDUCT.md b/hwdbg/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..b8d25f92 --- /dev/null +++ b/hwdbg/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at sina@rayanfam.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/hwdbg/LICENSE b/hwdbg/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/hwdbg/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/hwdbg/README.md b/hwdbg/README.md new file mode 100644 index 00000000..317a6f0a --- /dev/null +++ b/hwdbg/README.md @@ -0,0 +1,121 @@ +

+ hwdbg +

+ +

+Website +Docs +API +Published Researches +License +

+ +## Description +The **hwdbg** debugger chip generator is a gate-level debugging tool designed to make configurable and synthesizable hardware debuggers for white-box and black-box chip fuzzing, testing, and reverse engineering. The primary goal of **hwdbg** is to provide control over hardware, enabling monitoring and modification of signals down to the granular level of a single clock cycle. It is written in Chisel and Verilog. + +- ⚠️ This project is a work in progress and is not yet ready for testing. + +**hwdbg** is a highly customizable debugger designed to ease hardware debugging by bringing software debugging concepts into the hardware debugging domain. **hwdbg** aims to help with the complexities associated with debugging hardware, including chips and IP cores. Key features of **hwdbg** include the ability to step through the hardware design at the clock-cycle level, visualize waveforms, inspect values (e.g., like a logical analyzer), and modify signals. Moreover, it is synthesizable into [FPGAs](https://github.com/HyperDbg/hwdbg-fpga) and has the potential for fabrication into physical chips. + +``` + ┏━━━━━━━━━━━━━━━━━━━━━━━┓ + _ _ _ ┃ + | |_ _ _ _ _| || |_ ___ ┃ + | . || | | |/ . || . \/ . | ┃ + |_|_||__/_/ \___||___/\_. | ┃ + <___' ┃ + ┃ ╱|、 + HyperDbg's chip-level debugger ┃ (˚ˎ 。7 + ┃ |、 ˜〵 + ┗━━━━━━━━━━━━━━━━━━━━━━━┛ じしˍ,)ノ +``` +## Publications + +In case you use **hwdbg** in your work, please consider citing our paper. + +**[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, + title={hwdbg: Debugging Hardware Like Software}, + author={Karvandi, Mohammad Sina and Meghdadizanjani, Soroush and Monfared, Saleh Khalaj and van der Kouwe, Erik and Slowinska, Asia}, + booktitle={Proceedings of the 18th European Workshop on Systems Security}, + pages={56--62}, + year={2025} +} +``` + +## Deployment Board + +[This repository](https://github.com/HyperDbg/hwdbg-fpga) contains pre-built TCL files to facilitate project creation for running **hwdbg** on various FPGA development boards. + +## Output + +For generating SystemVerilog files, you need to install [Chisel](https://www.chisel-lang.org/docs/installation). Once installed, use the following commands: + +```sh +$ sbt run +``` + +This command prompts you to select a component. The `hwdbg.Main` class contains the debugger for synthesis purposes, while the `hwdbg.MainWithInitializedBRAM` class includes a pre-initialized Block RAM (BRAM), primarily for simulation and testing. + +After selecting the appropriate class for synthesis (option `1`) or simulation (option `2`), the output should look like this: + +```sh +$ sbt run +[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 17.0.10) +[info] loading settings for project -build-build-build from metals.sbt ... +[info] loading project definition from /home/sina/HyperDbg//project/project/project +[info] loading settings for project -build-build from metals.sbt ... +[info] loading project definition from /home/sina/HyperDbg//project/project +[success] Generated .bloop/-build-build.json +[success] Total time: 1 s, completed Apr 16, 2024, 1:49:05 PM +[info] loading settings for project -build from metals.sbt,plugins.sbt ... +[info] loading project definition from /home/sina/HyperDbg//project +[success] Total time: 0 s, completed Apr 16, 2024, 1:49:05 PM +[info] loading settings for project root from build.sbt ... +[info] set current project to hwdbg (in build file:/home/sina/HyperDbg/hwdbg/) + +Multiple main classes detected. Select one to run: + [1] hwdbg.Main + [2] hwdbg.MainWithInitializedBRAM + +Enter number: 2 +[info] running hwdbg.MainWithInitializedBRAM +``` + +The generated code for the debugger can be found in the `generated` directory. + +## Testbenches + +To test **hwdbg**, [cocotb](https://www.cocotb.org/) should be installed. After that, first, run the debugger (generated SystemVerilog files) and then run the following commands: + +```sh +cd sim/hwdbg/DebuggerModuleTestingBRAM +./test.sh +``` + +The above command generates a waves file at `./sim/hwdbg/DebuggerModuleTestingBRAM/sim_build/DebuggerModuleTestingBRAM.fst` which can be read using [GTKWave](https://gtkwave.sourceforge.net/). + +```sh +cd sim/hwdbg/DebuggerModuleTestingBRAM +gtkwave ./sim_build/DebuggerModuleTestingBRAM.fst +``` + +### ModelSim + +If you prefer to use ModelSim instead of GTKWave, you can configure the `modelsim.config` file. Please visit here for more information. + +## API + +If you want to create the latest version of API documentation, you can run the following command: + +```sh +$ sbt doc +``` + +This will generate documentation at `./target/scala-{version}/api/index.html`. + +## License + +**hwdbg** and all its submodules and repos, unless a license is otherwise specified, are licensed under **GPLv3** LICENSE. diff --git a/hwdbg/build.sbt b/hwdbg/build.sbt new file mode 100644 index 00000000..cf4b4ab5 --- /dev/null +++ b/hwdbg/build.sbt @@ -0,0 +1,29 @@ +// See README.md for license details. + +ThisBuild / scalaVersion := "2.13.12" +ThisBuild / version := "0.1.0" +ThisBuild / organization := "org.hyperdbg" + +val chiselVersion = "6.2.0" + +lazy val root = (project in file(".")) + .settings( + name := "hwdbg", + libraryDependencies ++= Seq( + "org.chipsalliance" %% "chisel" % chiselVersion, + "org.scalatest" %% "scalatest" % "3.2.16" % "test", + "io.circe" %% "circe-core" % "0.14.3", + "io.circe" %% "circe-generic" % "0.14.3", + "io.circe" %% "circe-parser" % "0.14.3" + ), + scalacOptions ++= Seq( + "-language:reflectiveCalls", + "-deprecation", + "-feature", + "-Xcheckinit", + "-Ymacro-annotations" + ), + addCompilerPlugin( + "org.chipsalliance" % "chisel-plugin" % chiselVersion cross CrossVersion.full + ) + ) diff --git a/hwdbg/build.sc b/hwdbg/build.sc new file mode 100644 index 00000000..1880b58f --- /dev/null +++ b/hwdbg/build.sc @@ -0,0 +1,30 @@ +// import Mill dependency +import mill._ +import mill.define.Sources +import mill.modules.Util +import mill.scalalib.TestModule.ScalaTest +import scalalib._ +// support BSP +import mill.bsp._ + +object hwdbg extends SbtModule { m => + override def millSourcePath = os.pwd + override def scalaVersion = "2.13.12" + override def scalacOptions = Seq( + "-language:reflectiveCalls", + "-deprecation", + "-feature", + "-Xcheckinit", + ) + override def ivyDeps = Agg( + ivy"org.chipsalliance::chisel:6.0.0", + ) + override def scalacPluginIvyDeps = Agg( + ivy"org.chipsalliance:::chisel-plugin:6.0.0", + ) + object test extends SbtModuleTests with TestModule.ScalaTest { + override def ivyDeps = m.ivyDeps() ++ Agg( + ivy"org.scalatest::scalatest::3.2.16" + ) + } +} diff --git a/hwdbg/project/build.properties b/hwdbg/project/build.properties new file mode 100644 index 00000000..b19d4e1e --- /dev/null +++ b/hwdbg/project/build.properties @@ -0,0 +1 @@ +sbt.version = 1.9.7 diff --git a/hwdbg/project/metals.sbt b/hwdbg/project/metals.sbt new file mode 100644 index 00000000..ac57eb45 --- /dev/null +++ b/hwdbg/project/metals.sbt @@ -0,0 +1,8 @@ +// format: off +// DO NOT EDIT! This file is auto-generated. + +// This file enables sbt-bloop to create bloop config files. + +addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.18") + +// format: on diff --git a/hwdbg/project/plugins.sbt b/hwdbg/project/plugins.sbt new file mode 100644 index 00000000..5708f81a --- /dev/null +++ b/hwdbg/project/plugins.sbt @@ -0,0 +1 @@ +logLevel := Level.Warn diff --git a/hwdbg/project/project/metals.sbt b/hwdbg/project/project/metals.sbt new file mode 100644 index 00000000..ac57eb45 --- /dev/null +++ b/hwdbg/project/project/metals.sbt @@ -0,0 +1,8 @@ +// format: off +// DO NOT EDIT! This file is auto-generated. + +// This file enables sbt-bloop to create bloop config files. + +addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.18") + +// format: on diff --git a/hwdbg/project/project/project/metals.sbt b/hwdbg/project/project/project/metals.sbt new file mode 100644 index 00000000..ac57eb45 --- /dev/null +++ b/hwdbg/project/project/project/metals.sbt @@ -0,0 +1,8 @@ +// format: off +// DO NOT EDIT! This file is auto-generated. + +// This file enables sbt-bloop to create bloop config files. + +addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.18") + +// format: on diff --git a/hwdbg/sim/.gitignore b/hwdbg/sim/.gitignore new file mode 100644 index 00000000..85f87a22 --- /dev/null +++ b/hwdbg/sim/.gitignore @@ -0,0 +1,164 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# cocotb folders and files +sim_build/ +results.xml \ No newline at end of file diff --git a/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/Makefile b/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/Makefile new file mode 100644 index 00000000..6f5989ca --- /dev/null +++ b/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/Makefile @@ -0,0 +1,23 @@ +# Makefile + +TOPLEVEL_LANG = verilog + +VERILOG_SOURCES += $(shell pwd)/../../../generated/DebuggerModuleTestingBRAM.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/InitRegMemFromFile.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/DebuggerMain.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/SendReceiveSynchronizer.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/DebuggerPacketReceiver.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/DebuggerPacketSender.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/DebuggerPacketInterpreter.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/InterpreterInstanceInfo.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/InterpreterSendSuccessOrError.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/ScriptExecutionEngine.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/InterpreterScriptBufferHandler.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/ScriptEngineGetValue.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/ScriptEngineSetValue.sv +VERILOG_SOURCES += $(shell pwd)/../../../generated/ScriptEngineEval.sv + +TOPLEVEL = DebuggerModuleTestingBRAM +MODULE = test_DebuggerModuleTestingBRAM + +include $(shell cocotb-config --makefiles)/Makefile.sim \ No newline at end of file diff --git a/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/bram_instance_info.txt b/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/bram_instance_info.txt new file mode 100644 index 00000000..f84b6a6e --- /dev/null +++ b/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/bram_instance_info.txt @@ -0,0 +1,261 @@ +Content of BRAM after emulation: + +PS to PL area: +mem_0: 0000005a | Checksum +mem_1: 00000000 | Checksum +mem_2: 52444247 | Indicator +mem_3: 48595045 | Indicator +mem_4: 00000004 | TypeOfThePacket +mem_5: 00000001 | RequestedActionOfThePacket +mem_6: 00000000 | Start of Optional Data +mem_7: 00000000 +mem_8: 00000000 +mem_9: 00000000 +mem_10: 00000000 +mem_11: 00000000 +mem_12: 00000000 +mem_13: 00000000 +mem_14: 00000000 +mem_15: 00000000 +mem_16: 00000000 +mem_17: 00000000 +mem_18: 00000000 +mem_19: 00000000 +mem_20: 00000000 +mem_21: 00000000 +mem_22: 00000000 +mem_23: 00000000 +mem_24: 00000000 +mem_25: 00000000 +mem_26: 00000000 +mem_27: 00000000 +mem_28: 00000000 +mem_29: 00000000 +mem_30: 00000000 +mem_31: 00000000 +mem_32: 00000000 +mem_33: 00000000 +mem_34: 00000000 +mem_35: 00000000 +mem_36: 00000000 +mem_37: 00000000 +mem_38: 00000000 +mem_39: 00000000 +mem_40: 00000000 +mem_41: 00000000 +mem_42: 00000000 +mem_43: 00000000 +mem_44: 00000000 +mem_45: 00000000 +mem_46: 00000000 +mem_47: 00000000 +mem_48: 00000000 +mem_49: 00000000 +mem_50: 00000000 +mem_51: 00000000 +mem_52: 00000000 +mem_53: 00000000 +mem_54: 00000000 +mem_55: 00000000 +mem_56: 00000000 +mem_57: 00000000 +mem_58: 00000000 +mem_59: 00000000 +mem_60: 00000000 +mem_61: 00000000 +mem_62: 00000000 +mem_63: 00000000 +mem_64: 00000000 +mem_65: 00000000 +mem_66: 00000000 +mem_67: 00000000 +mem_68: 00000000 +mem_69: 00000000 +mem_70: 00000000 +mem_71: 00000000 +mem_72: 00000000 +mem_73: 00000000 +mem_74: 00000000 +mem_75: 00000000 +mem_76: 00000000 +mem_77: 00000000 +mem_78: 00000000 +mem_79: 00000000 +mem_80: 00000000 +mem_81: 00000000 +mem_82: 00000000 +mem_83: 00000000 +mem_84: 00000000 +mem_85: 00000000 +mem_86: 00000000 +mem_87: 00000000 +mem_88: 00000000 +mem_89: 00000000 +mem_90: 00000000 +mem_91: 00000000 +mem_92: 00000000 +mem_93: 00000000 +mem_94: 00000000 +mem_95: 00000000 +mem_96: 00000000 +mem_97: 00000000 +mem_98: 00000000 +mem_99: 00000000 +mem_100: 00000000 +mem_101: 00000000 +mem_102: 00000000 +mem_103: 00000000 +mem_104: 00000000 +mem_105: 00000000 +mem_106: 00000000 +mem_107: 00000000 +mem_108: 00000000 +mem_109: 00000000 +mem_110: 00000000 +mem_111: 00000000 +mem_112: 00000000 +mem_113: 00000000 +mem_114: 00000000 +mem_115: 00000000 +mem_116: 00000000 +mem_117: 00000000 +mem_118: 00000000 +mem_119: 00000000 +mem_120: 00000000 +mem_121: 00000000 +mem_122: 00000000 +mem_123: 00000000 +mem_124: 00000000 +mem_125: 00000000 +mem_126: 00000000 +mem_127: 00000000 + +PL to PS area: +mem_128: 00000000 | Checksum +mem_129: 00000000 | Checksum +mem_130: 52444247 | Indicator +mem_131: 48595045 | Indicator +mem_132: 00000005 | TypeOfThePacket +mem_133: 00000002 | RequestedActionOfThePacket +mem_134: 00000100 | Start of Optional Data +mem_135: 00000020 +mem_136: 00000008 +mem_137: 00000002 +mem_138: 00000002 +mem_139: 00000002 +mem_140: 00000001 +mem_141: 00000400 +mem_142: 00000000 +mem_143: 00000200 +mem_144: 00000020 +mem_145: 00000002 +mem_146: 01ff9efb +mem_147: 00000000 +mem_148: 0000000d +mem_149: 00000020 +mem_150: 0000000c +mem_151: 00000014 +mem_152: 00000000 +mem_153: 00000000 +mem_154: 00000000 +mem_155: 00000000 +mem_156: 00000000 +mem_157: 00000000 +mem_158: 00000000 +mem_159: 00000000 +mem_160: 00000000 +mem_161: 00000000 +mem_162: 00000000 +mem_163: 00000000 +mem_164: 00000000 +mem_165: 00000000 +mem_166: 00000000 +mem_167: 00000000 +mem_168: 00000000 +mem_169: 00000000 +mem_170: 00000000 +mem_171: 00000000 +mem_172: 00000000 +mem_173: 00000000 +mem_174: 00000000 +mem_175: 00000000 +mem_176: 00000000 +mem_177: 00000000 +mem_178: 00000000 +mem_179: 00000000 +mem_180: 00000000 +mem_181: 00000000 +mem_182: 00000000 +mem_183: 00000000 +mem_184: 00000000 +mem_185: 00000000 +mem_186: 00000000 +mem_187: 00000000 +mem_188: 00000000 +mem_189: 00000000 +mem_190: 00000000 +mem_191: 00000000 +mem_192: 00000000 +mem_193: 00000000 +mem_194: 00000000 +mem_195: 00000000 +mem_196: 00000000 +mem_197: 00000000 +mem_198: 00000000 +mem_199: 00000000 +mem_200: 00000000 +mem_201: 00000000 +mem_202: 00000000 +mem_203: 00000000 +mem_204: 00000000 +mem_205: 00000000 +mem_206: 00000000 +mem_207: 00000000 +mem_208: 00000000 +mem_209: 00000000 +mem_210: 00000000 +mem_211: 00000000 +mem_212: 00000000 +mem_213: 00000000 +mem_214: 00000000 +mem_215: 00000000 +mem_216: 00000000 +mem_217: 00000000 +mem_218: 00000000 +mem_219: 00000000 +mem_220: 00000000 +mem_221: 00000000 +mem_222: 00000000 +mem_223: 00000000 +mem_224: 00000000 +mem_225: 00000000 +mem_226: 00000000 +mem_227: 00000000 +mem_228: 00000000 +mem_229: 00000000 +mem_230: 00000000 +mem_231: 00000000 +mem_232: 00000000 +mem_233: 00000000 +mem_234: 00000000 +mem_235: 00000000 +mem_236: 00000000 +mem_237: 00000000 +mem_238: 00000000 +mem_239: 00000000 +mem_240: 00000000 +mem_241: 00000000 +mem_242: 00000000 +mem_243: 00000000 +mem_244: 00000000 +mem_245: 00000000 +mem_246: 00000000 +mem_247: 00000000 +mem_248: 00000000 +mem_249: 00000000 +mem_250: 00000000 +mem_251: 00000000 +mem_252: 00000000 +mem_253: 00000000 +mem_254: 00000000 +mem_255: 00000000 diff --git a/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/script_buffer_response.txt b/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/script_buffer_response.txt new file mode 100644 index 00000000..3c75ec44 --- /dev/null +++ b/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/script_buffer_response.txt @@ -0,0 +1,261 @@ +Content of BRAM after emulation: + +PS to PL area: +mem_0: 00000017 | Checksum +mem_1: 00000000 | Checksum +mem_2: 52444247 | Indicator +mem_3: 48595045 | Indicator +mem_4: 00000004 | TypeOfThePacket +mem_5: 00000002 | RequestedActionOfThePacket +mem_6: 00000033 | Start of Optional Data +mem_7: 00000006 +mem_8: 0000000a +mem_9: 00000003 +mem_10: 00000001 +mem_11: 0000000f +mem_12: 00000000 +mem_13: 0000000f +mem_14: 00000000 +mem_15: 00000006 +mem_16: 00000013 +mem_17: 00000003 +mem_18: 00000001 +mem_19: 00000004 +mem_20: 00000000 +mem_21: 00000007 +mem_22: 00000000 +mem_23: 00000006 +mem_24: 00000016 +mem_25: 00000003 +mem_26: 00000013 +mem_27: 00000007 +mem_28: 00000000 +mem_29: 00000000 +mem_30: 00000000 +mem_31: 00000006 +mem_32: 00000018 +mem_33: 00000003 +mem_34: 00000000 +mem_35: 00000000 +mem_36: 00000000 +mem_37: 00000004 +mem_38: 00000002 +mem_39: 00000006 +mem_40: 00000018 +mem_41: 00000003 +mem_42: 00000000 +mem_43: 00000000 +mem_44: 00000000 +mem_45: 00000004 +mem_46: 00000003 +mem_47: 00000006 +mem_48: 00000015 +mem_49: 00000003 +mem_50: 00000028 +mem_51: 00000000 +mem_52: 00000000 +mem_53: 00000000 +mem_54: 00000000 +mem_55: 00000006 +mem_56: 00000013 +mem_57: 00000003 +mem_58: 00000001 +mem_59: 00000004 +mem_60: 00000001 +mem_61: 00000007 +mem_62: 00000000 +mem_63: 00000006 +mem_64: 00000016 +mem_65: 00000003 +mem_66: 00000022 +mem_67: 00000007 +mem_68: 00000000 +mem_69: 00000000 +mem_70: 00000000 +mem_71: 00000006 +mem_72: 00000018 +mem_73: 00000003 +mem_74: 00000000 +mem_75: 00000000 +mem_76: 00000000 +mem_77: 00000004 +mem_78: 00000004 +mem_79: 00000006 +mem_80: 00000018 +mem_81: 00000003 +mem_82: 00000000 +mem_83: 00000000 +mem_84: 00000000 +mem_85: 00000004 +mem_86: 00000005 +mem_87: 00000006 +mem_88: 00000015 +mem_89: 00000003 +mem_90: 00000028 +mem_91: 00000000 +mem_92: 00000000 +mem_93: 00000000 +mem_94: 00000000 +mem_95: 00000006 +mem_96: 00000018 +mem_97: 00000003 +mem_98: 00000000 +mem_99: 00000000 +mem_100: 00000000 +mem_101: 00000004 +mem_102: 00000006 +mem_103: 00000006 +mem_104: 00000018 +mem_105: 00000003 +mem_106: 00000000 +mem_107: 00000000 +mem_108: 00000000 +mem_109: 00000004 +mem_110: 00000007 +mem_111: 00000000 +mem_112: 00000000 +mem_113: 00000000 +mem_114: 00000000 +mem_115: 00000000 +mem_116: 00000000 +mem_117: 00000000 +mem_118: 00000000 +mem_119: 00000000 +mem_120: 00000000 +mem_121: 00000000 +mem_122: 00000000 +mem_123: 00000000 +mem_124: 00000000 +mem_125: 00000000 +mem_126: 00000000 +mem_127: 00000000 + +PL to PS area: +mem_128: 00000000 | Checksum +mem_129: 00000000 | Checksum +mem_130: 52444247 | Indicator +mem_131: 48595045 | Indicator +mem_132: 00000005 | TypeOfThePacket +mem_133: 00000001 | RequestedActionOfThePacket +mem_134: 7fffffff | Start of Optional Data +mem_135: 00000000 +mem_136: 00000000 +mem_137: 00000000 +mem_138: 00000000 +mem_139: 00000000 +mem_140: 00000000 +mem_141: 00000000 +mem_142: 00000000 +mem_143: 00000000 +mem_144: 00000000 +mem_145: 00000000 +mem_146: 00000000 +mem_147: 00000000 +mem_148: 00000000 +mem_149: 00000000 +mem_150: 00000000 +mem_151: 00000000 +mem_152: 00000000 +mem_153: 00000000 +mem_154: 00000000 +mem_155: 00000000 +mem_156: 00000000 +mem_157: 00000000 +mem_158: 00000000 +mem_159: 00000000 +mem_160: 00000000 +mem_161: 00000000 +mem_162: 00000000 +mem_163: 00000000 +mem_164: 00000000 +mem_165: 00000000 +mem_166: 00000000 +mem_167: 00000000 +mem_168: 00000000 +mem_169: 00000000 +mem_170: 00000000 +mem_171: 00000000 +mem_172: 00000000 +mem_173: 00000000 +mem_174: 00000000 +mem_175: 00000000 +mem_176: 00000000 +mem_177: 00000000 +mem_178: 00000000 +mem_179: 00000000 +mem_180: 00000000 +mem_181: 00000000 +mem_182: 00000000 +mem_183: 00000000 +mem_184: 00000000 +mem_185: 00000000 +mem_186: 00000000 +mem_187: 00000000 +mem_188: 00000000 +mem_189: 00000000 +mem_190: 00000000 +mem_191: 00000000 +mem_192: 00000000 +mem_193: 00000000 +mem_194: 00000000 +mem_195: 00000000 +mem_196: 00000000 +mem_197: 00000000 +mem_198: 00000000 +mem_199: 00000000 +mem_200: 00000000 +mem_201: 00000000 +mem_202: 00000000 +mem_203: 00000000 +mem_204: 00000000 +mem_205: 00000000 +mem_206: 00000000 +mem_207: 00000000 +mem_208: 00000000 +mem_209: 00000000 +mem_210: 00000000 +mem_211: 00000000 +mem_212: 00000000 +mem_213: 00000000 +mem_214: 00000000 +mem_215: 00000000 +mem_216: 00000000 +mem_217: 00000000 +mem_218: 00000000 +mem_219: 00000000 +mem_220: 00000000 +mem_221: 00000000 +mem_222: 00000000 +mem_223: 00000000 +mem_224: 00000000 +mem_225: 00000000 +mem_226: 00000000 +mem_227: 00000000 +mem_228: 00000000 +mem_229: 00000000 +mem_230: 00000000 +mem_231: 00000000 +mem_232: 00000000 +mem_233: 00000000 +mem_234: 00000000 +mem_235: 00000000 +mem_236: 00000000 +mem_237: 00000000 +mem_238: 00000000 +mem_239: 00000000 +mem_240: 00000000 +mem_241: 00000000 +mem_242: 00000000 +mem_243: 00000000 +mem_244: 00000000 +mem_245: 00000000 +mem_246: 00000000 +mem_247: 00000000 +mem_248: 00000000 +mem_249: 00000000 +mem_250: 00000000 +mem_251: 00000000 +mem_252: 00000000 +mem_253: 00000000 +mem_254: 00000000 +mem_255: 00000000 diff --git a/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/test.sh b/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/test.sh new file mode 100755 index 00000000..a83ca694 --- /dev/null +++ b/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/test.sh @@ -0,0 +1 @@ +make SIM=icarus WAVES=1 diff --git a/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/test_DebuggerModuleTestingBRAM.py b/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/test_DebuggerModuleTestingBRAM.py new file mode 100644 index 00000000..3d8323e7 --- /dev/null +++ b/hwdbg/sim/hwdbg/DebuggerModuleTestingBRAM/test_DebuggerModuleTestingBRAM.py @@ -0,0 +1,570 @@ +## +# @file test_DebuggerModuleTestingBRAM.py +# +# @author Sina Karvandi (sina@hyperdbg.org) +# +# @brief Testing module for DebuggerModuleTestingBRAM +# +# @details +# +# @version 0.1 +# +# @date 2024-04-21 +# +# @copyright This project is released under the GNU Public License v3. +# + +import random +import re + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import Timer +from cocotb.types import LogicArray + +maximum_number_of_clock_cycles = 1000 + +''' + input clock, + reset, + io_en, + io_inputPin_0, + io_inputPin_1, + io_inputPin_2, + io_inputPin_3, + io_inputPin_4, + io_inputPin_5, + io_inputPin_6, + io_inputPin_7, + io_inputPin_8, + io_inputPin_9, + io_inputPin_10, + io_inputPin_11, + io_inputPin_12, + io_inputPin_13, + io_inputPin_14, + io_inputPin_15, + io_inputPin_16, + io_inputPin_17, + io_inputPin_18, + io_inputPin_19, + io_inputPin_20, + io_inputPin_21, + io_inputPin_22, + io_inputPin_23, + io_inputPin_24, + io_inputPin_25, + io_inputPin_26, + io_inputPin_27, + io_inputPin_28, + io_inputPin_29, + io_inputPin_30, + io_inputPin_31, + output io_outputPin_0, + io_outputPin_1, + io_outputPin_2, + io_outputPin_3, + io_outputPin_4, + io_outputPin_5, + io_outputPin_6, + io_outputPin_7, + io_outputPin_8, + io_outputPin_9, + io_outputPin_10, + io_outputPin_11, + io_outputPin_12, + io_outputPin_13, + io_outputPin_14, + io_outputPin_15, + io_outputPin_16, + io_outputPin_17, + io_outputPin_18, + io_outputPin_19, + io_outputPin_20, + io_outputPin_21, + io_outputPin_22, + io_outputPin_23, + io_outputPin_24, + io_outputPin_25, + io_outputPin_26, + io_outputPin_27, + io_outputPin_28, + io_outputPin_29, + io_outputPin_30, + io_outputPin_31, + input io_plInSignal, + output io_psOutInterrupt +''' + +# +# Define a function to extract the numeric part of the string +# +def extract_number(s): + return int(s.split('_')[1]) + +def print_bram_content(dut): + """Printing contents of Block RAM and saving them to a file""" + + # + # Print the instances and signals (which includes the ports) of the design's toplevel + # + print("===================================================================") + # print("Onstances and signals (which includes the ports) of the design's toplevel:") + # print(dir(dut)) + # print("===================================================================") + + # + # Print the instances and signals of "inst_sub_block" under the toplevel + # which is the instance name of a Verilog module or VHDL entity/component + # + # print("Onstances and signals of 'dataOut_initRegMemFromFileModule' under the toplevel:") + # print(dir(dut.dataOut_initRegMemFromFileModule)) + + items_inside_bram_emulator = dir(dut.dataOut_initRegMemFromFileModule) + mem_items = [] + + for item in items_inside_bram_emulator: + if item.startswith("mem_"): + mem_items.append(item) + + # + # Sort the list using the custom key function + # + sorted_list = sorted(mem_items, key=extract_number) + + with open("script_buffer_response.txt", "w") as file: + # with open("bram_instance_info.txt", "w") as file: + file.write("Content of BRAM after emulation:\n") + print("Content of BRAM after emulation:") + + # + # The second half of the BRAM is used for PL to PS communication + # + address_of_ps_to_pl_communication = "mem_0" + address_of_ps_to_pl_communication_checksum1 = "mem_0" + address_of_ps_to_pl_communication_checksum2 = "mem_1" + address_of_ps_to_pl_communication_indicator1 = "mem_2" + address_of_ps_to_pl_communication_indicator2 = "mem_3" + address_of_ps_to_pl_communication_type_of_packet = "mem_4" + address_of_ps_to_pl_communication_requested_action_of_the_packet = "mem_5" + address_of_ps_to_pl_communication_start_of_data = "mem_6" + + len_of_sorted_list_div_by_2 = int(len(sorted_list) / 2) + address_of_pl_to_ps_communication = "mem_" + str(len_of_sorted_list_div_by_2) + address_of_pl_to_ps_communication_checksum1 = "mem_" + str(len_of_sorted_list_div_by_2 + 0) + address_of_pl_to_ps_communication_checksum2 = "mem_" + str(len_of_sorted_list_div_by_2 + 1) + address_of_pl_to_ps_communication_indicator1 = "mem_" + str(len_of_sorted_list_div_by_2 + 2) + address_of_pl_to_ps_communication_indicator2 = "mem_" + str(len_of_sorted_list_div_by_2 + 3) + address_of_pl_to_ps_communication_type_of_packet = "mem_" + str(len_of_sorted_list_div_by_2 + 4) + address_of_pl_to_ps_communication_requested_action_of_the_packet = "mem_" + str(len_of_sorted_list_div_by_2 + 5) + address_of_pl_to_ps_communication_start_of_data = "mem_" + str(len_of_sorted_list_div_by_2 + 6) + + print("Address of PL to PS communication: " + address_of_pl_to_ps_communication) + + for item in sorted_list: + element = getattr(dut.dataOut_initRegMemFromFileModule, item) + + # + # Print the target register in binary format + # + # print(str(element)) + + # + # Convert binary to int + # + int_content = int(str(element.value), 2) + + # + # Convert integer to hexadecimal string with at least 8 characters + # + hex_string = f'{int_content:08x}' + + final_string = "" + if len(item) == 5: + final_string = item + ": " + hex_string + elif len(item) == 6: + final_string = item + ": " + hex_string + else: + final_string = item + ": " + hex_string + + # + # Make a separation between PS and PL area + # + if item == address_of_ps_to_pl_communication: + file.write("\nPS to PL area:\n") + print("\nPS to PL area:") + elif item == address_of_pl_to_ps_communication: + file.write("\nPL to PS area:\n") + print("\nPL to PS area:") + + if item == address_of_ps_to_pl_communication_checksum1 or \ + item == address_of_ps_to_pl_communication_checksum2 or \ + item == address_of_pl_to_ps_communication_checksum1 or \ + item == address_of_pl_to_ps_communication_checksum2: + final_string = final_string + " | Checksum" + elif item == address_of_ps_to_pl_communication_indicator1 or \ + item == address_of_ps_to_pl_communication_indicator2 or \ + item == address_of_pl_to_ps_communication_indicator1 or \ + item == address_of_pl_to_ps_communication_indicator2: + final_string = final_string + " | Indicator" + elif item == address_of_ps_to_pl_communication_type_of_packet or \ + item == address_of_pl_to_ps_communication_type_of_packet: + final_string = final_string + " | TypeOfThePacket" + elif item == address_of_ps_to_pl_communication_requested_action_of_the_packet or \ + item == address_of_pl_to_ps_communication_requested_action_of_the_packet: + final_string = final_string + " | RequestedActionOfThePacket" + elif item == address_of_ps_to_pl_communication_start_of_data or \ + item == address_of_pl_to_ps_communication_start_of_data: + final_string = final_string + " | Start of Optional Data" + + # + # Print contents of BRAM + # + file.write(final_string + "\n") + print(final_string) + + print("\n===================================================================\n") + + +# +# Define a function to extract value of symbol +# +def get_symbol_value(dut, value): + element_value = getattr(dut.debuggerMainModule.outputPin_scriptExecutionEngineModule, value) + hex_string_value = "" + try: + int_content_value = int(str(element_value.value), 2) + hex_string_value = f'{int_content_value:x}' + except: + hex_string_value = str(element_value.value) + + final_string_value = f'{value}: 0x{hex_string_value}' + " (bin: " + str(element_value.value) + ")" + return final_string_value + +# +# Define a function to extract type of symbol +# +def get_symbol_type(dut, type): + element_type = getattr(dut.debuggerMainModule.outputPin_scriptExecutionEngineModule, type) + hex_string_type = "" + try: + int_content_type = int(str(element_type.value), 2) + hex_string_type = f'{int_content_type:x}' + except: + hex_string_type = str(element_type.value) + + final_string_type = f'{type} : 0x{hex_string_type}' + " (bin: " + str(element_type.value) + ")" + return final_string_type + +# +# Define a function to extract stage index +# +def get_stage_index(dut, stage_index): + stage_index_str = "stageRegs_" + str(stage_index) + "_stageIndex" + element_stage_index = getattr(dut.debuggerMainModule.outputPin_scriptExecutionEngineModule, stage_index_str) + hex_string_stage_index = "" + try: + int_content_stage_index = int(str(element_stage_index.value), 2) + hex_string_stage_index = f'{int_content_stage_index:x}' + except: + hex_string_stage_index = str(element_stage_index.value) + + final_string_stage_index = f'{stage_index}: 0x{hex_string_stage_index}' + " (bin: " + str(element_stage_index.value) + ")" + return final_string_stage_index + +# +# Define a function to extract content of stages +# +def extract_stage_details(dut): + + print("Script Stage Registers Configuration:\n") + all_elements = dir(dut.debuggerMainModule.outputPin_scriptExecutionEngineModule) + + # + # Define the pattern to match + # + pattern_value = re.compile(r'stageRegs_\d+_stageSymbol_Value') + pattern_type = re.compile(r'stageRegs_\d+_stageSymbol_Type') + pattern_stage_index = re.compile(r'stageRegs_\d+_stageIndex') + + # + # Filter the list using the patterns + # + filtered_strings_values = [s for s in all_elements if pattern_value.match(s)] + filtered_strings_types = [s for s in all_elements if pattern_type.match(s)] + filtered_strings_stage_index = [s for s in all_elements if pattern_stage_index.match(s)] + + # + # Sort the lists + # + sorted_values = sorted(filtered_strings_values, key=extract_number) + sorted_types = sorted(filtered_strings_types, key=extract_number) + sorted_stage_index = sorted(filtered_strings_stage_index, key=extract_number) + + # + # Print the filtered strings + # + # print(sorted_values) + # print(sorted_types) + # print(sorted_stage_index) + + for index, element in enumerate(sorted_values): + + try: + final_string_type = get_symbol_type(dut, sorted_types[index]) + + # + # Print the type + # + print(final_string_type) + except: + print("This stage does not contain a 'type'") + + try: + final_string_value = get_symbol_value(dut, sorted_values[index]) + + # + # Print the value + # + print(final_string_value) + except: + print("Unable to get stage 'value' configuration details") + + try: + final_string_stage_index = get_stage_index(dut, index) + + # + # Print the stage index + # + print("index: " + final_string_stage_index) + + except: + print("index: " + str(index) +": This stage does not contain a 'stage index'") + + print("\n") + + + # + # Check stage enable bit + # + try: + stage_enabled = "stageRegs_" + str(index) + "_stageEnable" + is_stage_enabled = getattr(dut.debuggerMainModule.outputPin_scriptExecutionEngineModule, stage_enabled) + print("\t Stage enabled bit: " + str(is_stage_enabled)) + except: + print("\t Stage enabled bit: (unavailable)") + + try: + final_string_value = get_symbol_value(dut, "stageRegs_" + str(index) + "_getOperatorSymbol_0_Value") + final_string_type = get_symbol_type(dut, "stageRegs_" + str(index) + "_getOperatorSymbol_0_Type") + + print("\t Get (0) | " + final_string_type) + print("\t Get (0) | " + final_string_value) + except: + print("\t stage at:" + str(index) + " does not contain a Get (0) buffer") + + print("\n") + + try: + final_string_value = get_symbol_value(dut, "stageRegs_" + str(index) + "_getOperatorSymbol_1_Value") + final_string_type = get_symbol_type(dut, "stageRegs_" + str(index) + "_getOperatorSymbol_1_Type") + + print("\t Get (1) | " + final_string_type) + print("\t Get (1) | " + final_string_value) + except: + print("\t stage at:" + str(index) + " does not contain a Get (1) buffer") + + print("\n") + + try: + final_string_value = get_symbol_value(dut, "stageRegs_" + str(index) + "_setOperatorSymbol_0_Value") + final_string_type = get_symbol_type(dut, "stageRegs_" + str(index) + "_setOperatorSymbol_0_Type") + + print("\t Set (0) | " + final_string_type) + print("\t Set (0) | " + final_string_value) + except: + print("\t stage at:" + str(index) + " does not contain a Set (0) buffer") + + print("\n\n") + +def set_input_pins(dut): + dut.io_inputPin_0.value = 1 + dut.io_inputPin_1.value = 1 + dut.io_inputPin_2.value = 1 + dut.io_inputPin_3.value = 1 + dut.io_inputPin_4.value = 1 + dut.io_inputPin_5.value = 1 + dut.io_inputPin_6.value = 1 + dut.io_inputPin_7.value = 1 + dut.io_inputPin_8.value = 1 + dut.io_inputPin_9.value = 1 + dut.io_inputPin_10.value = 1 + dut.io_inputPin_11.value = 1 + dut.io_inputPin_12.value = 1 + dut.io_inputPin_13.value = 1 + dut.io_inputPin_14.value = 1 + dut.io_inputPin_15.value = 1 + dut.io_inputPin_16.value = 1 + dut.io_inputPin_17.value = 1 + dut.io_inputPin_18.value = 1 + dut.io_inputPin_19.value = 1 + dut.io_inputPin_20.value = 1 + dut.io_inputPin_21.value = 1 + dut.io_inputPin_22.value = 1 + dut.io_inputPin_23.value = 1 + dut.io_inputPin_24.value = 1 + dut.io_inputPin_25.value = 1 + dut.io_inputPin_26.value = 1 + dut.io_inputPin_27.value = 1 + dut.io_inputPin_28.value = 1 + dut.io_inputPin_29.value = 1 + dut.io_inputPin_30.value = 1 + dut.io_inputPin_31.value = 1 + +@cocotb.test() +async def DebuggerModuleTestingBRAM_test(dut): + """Test hwdbg module (with pre-defined BRAM)""" + + # + # Assert initial output is unknown + # + assert LogicArray(dut.io_outputPin_0.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_1.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_2.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_3.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_4.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_5.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_6.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_7.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_8.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_9.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_10.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_11.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_12.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_13.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_14.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_15.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_16.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_17.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_18.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_19.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_20.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_21.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_22.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_23.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_24.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_25.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_26.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_27.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_28.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_29.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_30.value) == LogicArray("X") + assert LogicArray(dut.io_outputPin_31.value) == LogicArray("X") + + # + # Create a 10ns period clock on port clock + # + clock = Clock(dut.clock, 10, units="ns") + + # + # Start the clock. Start it low to avoid issues on the first RisingEdge + # + cocotb.start_soon(clock.start(start_high=False)) + + dut._log.info("Initialize and reset module") + + # + # Initial values + # + dut.io_en.value = 0 + dut.io_plInSignal.value = 0 + + # + # Reset DUT + # + dut.reset.value = 1 + for _ in range(10): + await Timer(10, units="ns") + dut.reset.value = 0 + + + dut._log.info("Enabling an interrupting chip to receive commands from BRAM") + + # + # Enable chip + # + dut.io_en.value = 1 + + # + # Set initial input value to prevent it from floating + # + dut._log.info("Initializing input pins") + # set_input_pins(dut) + + # + # Tell the hwdbg to receive BRAM results + # + dut.io_plInSignal.value = 1 + await Timer(10, units="ns") + dut.io_plInSignal.value = 0 + + # + # Synchronize with the clock. This will regisiter the initial `inputPinX` value + # + await Timer(10, units="ns") + + # + # Wait until the debuggee sends an interrupt to debugger + # + clock_counter = 0 + interrupt_not_delivered = False + + while str(dut.io_psOutInterrupt) != "1": + + # print("State of interrupt: '" + str(dut.io_psOutInterrupt) + "'") + + if clock_counter % 10 == 0: + print("Number of clock cycles spent in debuggee (PL): " + str(clock_counter)) + + clock_counter = clock_counter + 1 + await Timer(10, units="ns") + + # + # Apply a limitation to the number of clock cycles that + # can be executed to avoid infinite time + # + if (clock_counter >= maximum_number_of_clock_cycles): + interrupt_not_delivered = True + break + + # + # Being here means either the debuggee sent an interrupt to the PS + # or the maximum clock cycles reached + # + if interrupt_not_delivered: + print("Maximum clock cycles reached") + else: + print("Debuggee (PL) interrupted Debugger (PS)") + + # + # Run one more clock cycle to apply the latest BRAM modifications + # + await Timer(10, units="ns") + + # + # Print contents of BRAM + # + print_bram_content(dut) + + # + # Print the script stage configuration + # + extract_stage_details(dut) + + # + # Check the final input on the next clock and run the circuit for a couple + # of more clock cycles + # + for _ in range(100): + set_input_pins(dut) + await Timer(10, units="ns") diff --git a/hwdbg/sim/hwdbg/communication/DebuggerPacketReceiver/Makefile b/hwdbg/sim/hwdbg/communication/DebuggerPacketReceiver/Makefile new file mode 100644 index 00000000..8678f015 --- /dev/null +++ b/hwdbg/sim/hwdbg/communication/DebuggerPacketReceiver/Makefile @@ -0,0 +1,8 @@ +# Makefile + +TOPLEVEL_LANG = verilog +VERILOG_SOURCES = $(shell pwd)/../../../../generated/DebuggerPacketReceiver.sv +TOPLEVEL = DebuggerPacketReceiver +MODULE = test_DebuggerPacketReceiver + +include $(shell cocotb-config --makefiles)/Makefile.sim diff --git a/hwdbg/sim/hwdbg/communication/DebuggerPacketReceiver/test.sh b/hwdbg/sim/hwdbg/communication/DebuggerPacketReceiver/test.sh new file mode 100644 index 00000000..a83ca694 --- /dev/null +++ b/hwdbg/sim/hwdbg/communication/DebuggerPacketReceiver/test.sh @@ -0,0 +1 @@ +make SIM=icarus WAVES=1 diff --git a/hwdbg/sim/hwdbg/communication/DebuggerPacketReceiver/test_DebuggerPacketReceiver.py b/hwdbg/sim/hwdbg/communication/DebuggerPacketReceiver/test_DebuggerPacketReceiver.py new file mode 100644 index 00000000..e3c19085 --- /dev/null +++ b/hwdbg/sim/hwdbg/communication/DebuggerPacketReceiver/test_DebuggerPacketReceiver.py @@ -0,0 +1,187 @@ +## +# @file test_DebuggerPacketReceiver.py +# +# @author Sina Karvandi (sina@hyperdbg.org) +# +# @brief Testing module for DebuggerPacketReceiver +# +# @details +# +# @version 0.1 +# +# @date 2024-04-22 +# +# @copyright This project is released under the GNU Public License v3. +# + +import random + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import Timer +from cocotb.types import LogicArray + +''' + input clock, + reset, + io_en, + io_plInSignal, + output [12:0] io_rdWrAddr, + input [31:0] io_rdData, + output [31:0] io_requestedActionOfThePacketOutput, + output io_requestedActionOfThePacketOutputValid, + input io_noNewDataReceiver, + io_readNextData, + output io_dataValidOutput, + output [31:0] io_receivingData, + output io_finishedReceivingBuffer +''' + +@cocotb.test() +async def DebuggerPacketReceiver_test(dut): + """Test DebuggerPacketReceiver module""" + + # + # Assert initial output is unknown + # + assert LogicArray(dut.io_rdWrAddr.value) == LogicArray("XXXXXXXXXXXXX") + assert LogicArray(dut.io_requestedActionOfThePacketOutput.value) == LogicArray("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") + assert LogicArray(dut.io_requestedActionOfThePacketOutputValid.value) == LogicArray("X") + assert LogicArray(dut.io_dataValidOutput.value) == LogicArray("X") + assert LogicArray(dut.io_receivingData.value) == LogicArray("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") + assert LogicArray(dut.io_finishedReceivingBuffer.value) == LogicArray("X") + + clock = Clock(dut.clock, 10, units="ns") # Create a 10ns period clock on port clock + + # + # Start the clock. Start it low to avoid issues on the first RisingEdge + # + cocotb.start_soon(clock.start(start_high=False)) + + dut._log.info("Initialize and reset module") + + # + # Initial values + # + dut.io_en.value = 0 + dut.io_readNextData.value = 0 + dut.io_noNewDataReceiver.value = 0 + dut.io_plInSignal.value = 0 + + # + # Reset DUT + # + dut.reset.value = 1 + for _ in range(10): + await Timer(10, units="ns") + dut.reset.value = 0 + + dut._log.info("Enabling chip") + + # + # Enable chip + # + dut.io_en.value = 1 + + for test_number in range(10): + + dut._log.info("Enable receiving data on the chip (" + str(test_number) + ")") + + # + # Tell the receiver to start receiving data (This mainly operates based on + # a rising-edge detector, so we'll need to make it low) + # + dut.io_plInSignal.value = 1 + await Timer(10, units="ns") + dut.io_plInSignal.value = 0 + + # + # Wait until the receive operation is done (finished) + # + for i in range(30): + + if (dut.io_finishedReceivingBuffer.value == 1): + break + else: + match dut.io_rdWrAddr.value: + case 0x0: # checksum + dut.io_rdData.value = 0x00001234 + case 0x8: # indicator + dut.io_rdData.value = 0x48595045 # first 32 bits of the indicator + case 0x10: # type + dut.io_rdData.value = 0x4 # debugger to hardware packet (DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL) + case 0x14: # requested action + dut.io_rdData.value = 0x14141414 + case 0x18: # General output + dut.io_rdData.value = 0x18181818 + case 0x1c: # General output + dut.io_rdData.value = 0x1c1c1c1c + case 0x20: # General output + dut.io_rdData.value = 0x20202020 + case 0x24: # General output + dut.io_rdData.value = 0x24242424 + case 0x28: # General output + dut.io_rdData.value = 0x28282828 + case 0x2c: # General output + dut.io_rdData.value = 0x2c2c2c2c + case 0x30: # General output + dut.io_rdData.value = 0x30303030 + case 0x34: # General output + dut.io_rdData.value = 0x34343434 + case 0x38: # General output + dut.io_rdData.value = 0x38383838 + case 0x3c: # General output + dut.io_rdData.value = 0x3c3c3c3c + case 0x40: # General output + dut.io_rdData.value = 0x40404040 + case 0x44: # General output + dut.io_rdData.value = 0x44444444 + case 0x48: # General output + dut.io_rdData.value = 0x48484848 + case 0x4c: # General output + dut.io_rdData.value = 0x4c4c4c4c + case 0x50: # General output + dut.io_rdData.value = 0x50505050 + case _: + assert "invalid address in the address line" + + if dut.io_requestedActionOfThePacketOutputValid.value == 1: + + # + # No new data needed to be received + # + if test_number % 3 == 0: + dut.io_noNewDataReceiver.value = 1 + await Timer(10, units="ns") + dut.io_noNewDataReceiver.value = 0 + else: + # + # Make change to the io_readNextData signal as it operates mainly + # based on a rising-edge detector + # + if dut.io_readNextData.value == 0: + dut.io_readNextData.value = 1 + else: + dut.io_readNextData.value = 0 + + + # + # Go to the next clock cycle + # + await Timer(10, units="ns") + + if test_number % 3 != 0: + dut.io_noNewDataReceiver.value = 1 + await Timer(10, units="ns") + dut.io_noNewDataReceiver.value = 0 + + # + # Run extra waiting clocks + # + for _ in range(10): + await Timer(10, units="ns") + + # + # Check the final input on the next clock + # + await Timer(10, units="ns") diff --git a/hwdbg/sim/hwdbg/communication/DebuggerPacketSender/Makefile b/hwdbg/sim/hwdbg/communication/DebuggerPacketSender/Makefile new file mode 100644 index 00000000..16ee52f3 --- /dev/null +++ b/hwdbg/sim/hwdbg/communication/DebuggerPacketSender/Makefile @@ -0,0 +1,8 @@ +# Makefile + +TOPLEVEL_LANG = verilog +VERILOG_SOURCES = $(shell pwd)/../../../../generated/DebuggerPacketSender.sv +TOPLEVEL = DebuggerPacketSender +MODULE = test_DebuggerPacketSender + +include $(shell cocotb-config --makefiles)/Makefile.sim diff --git a/hwdbg/sim/hwdbg/communication/DebuggerPacketSender/test.sh b/hwdbg/sim/hwdbg/communication/DebuggerPacketSender/test.sh new file mode 100644 index 00000000..a83ca694 --- /dev/null +++ b/hwdbg/sim/hwdbg/communication/DebuggerPacketSender/test.sh @@ -0,0 +1 @@ +make SIM=icarus WAVES=1 diff --git a/hwdbg/sim/hwdbg/communication/DebuggerPacketSender/test_DebuggerPacketSender.py b/hwdbg/sim/hwdbg/communication/DebuggerPacketSender/test_DebuggerPacketSender.py new file mode 100644 index 00000000..f2b77f1f --- /dev/null +++ b/hwdbg/sim/hwdbg/communication/DebuggerPacketSender/test_DebuggerPacketSender.py @@ -0,0 +1,165 @@ +## +# @file test_DebuggerPacketSender.py +# +# @author Sina Karvandi (sina@hyperdbg.org) +# +# @brief Testing module for DebuggerPacketSender +# +# @details +# +# @version 0.1 +# +# @date 2024-04-21 +# +# @copyright This project is released under the GNU Public License v3. +# + +import random + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import Timer +from cocotb.types import LogicArray + +''' + input clock, + reset, + io_en, + output io_psOutInterrupt, + output [12:0] io_rdWrAddr, + output io_wrEna, + output [31:0] io_wrData, + input io_beginSendingBuffer, + io_noNewDataSender, + io_dataValidInput, + output io_sendWaitForBuffer, + io_finishedSendingBuffer, + input [31:0] io_requestedActionOfThePacketInput, + io_sendingData +''' + +@cocotb.test() +async def DebuggerPacketSender_test(dut): + """Test DebuggerPacketSender module""" + + # + # Assert initial output is unknown + # + assert LogicArray(dut.io_psOutInterrupt.value) == LogicArray("X") + assert LogicArray(dut.io_rdWrAddr.value) == LogicArray("XXXXXXXXXXXXX") + assert LogicArray(dut.io_wrEna.value) == LogicArray("X") + assert LogicArray(dut.io_wrData.value) == LogicArray("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") + assert LogicArray(dut.io_sendWaitForBuffer.value) == LogicArray("X") + assert LogicArray(dut.io_finishedSendingBuffer.value) == LogicArray("X") + + clock = Clock(dut.clock, 10, units="ns") # Create a 10ns period clock on port clock + + # + # Start the clock. Start it low to avoid issues on the first RisingEdge + # + cocotb.start_soon(clock.start(start_high=False)) + + dut._log.info("Initialize and reset module") + + # + # Initial values + # + dut.io_en.value = 0 + dut.io_beginSendingBuffer.value = 0 + + # + # Reset DUT + # + dut.reset.value = 1 + for _ in range(10): + await Timer(10, units="ns") + dut.reset.value = 0 + + dut._log.info("Enabling chip") + + # + # Enable chip + # + dut.io_en.value = 1 + + for test_number in range(10): + + dut._log.info("Enable sending data on the chip (" + str(test_number) + ")") + + # + # Still there is data to send + # + dut.io_noNewDataSender.value = 0 + + # + # Tell the sender to start sending data (This mainly operates based on + # a rising-edge detector, so we'll need to make it low) + # + dut.io_beginSendingBuffer.value = 1 + await Timer(10, units="ns") + dut.io_beginSendingBuffer.value = 0 + + # + # No new data at this stage + # + dut.io_dataValidInput.value = 0 + dut.io_sendingData.value = 0 + + # + # Adjust the requested action of the packet + # + dut.io_requestedActionOfThePacketInput.value = 0x55859555 + + # + # Synchronize with the clock. This will apply the initial values + # + await Timer(10, units="ns") + + # + # This will change the behavior of the data producer to only + # generate extra data for 2 of the test case rounds, the third + # test case doesn't have any extra data + # + if test_number % 3 != 0 : + # + # Run until the module asks for further buffers + # + for i in range(100): + if dut.io_sendWaitForBuffer.value == 1: + val = random.randint(0, 0xffffffff) + + # + # Indicate that the data is valid + # + dut.io_dataValidInput.value = 1 + + # + # Assign the random value to send as the data + # + dut.io_sendingData.value = val + + await Timer(10, units="ns") + + # + # Now, tell the sender module that there is no longer needed to send data + # + for i in range(100): + if dut.io_sendWaitForBuffer.value == 1: + dut.io_noNewDataSender.value = 1 + await Timer(10, units="ns") + dut.io_noNewDataSender.value = 0 + break + + await Timer(10, units="ns") + + + # + # Run extra waiting clocks + # + for _ in range(10): + await Timer(10, units="ns") + + # + # Check the final input on the next clock + # + await Timer(10, units="ns") diff --git a/hwdbg/sim/hwdbg/communication/SendReceiveSynchronizer/Makefile b/hwdbg/sim/hwdbg/communication/SendReceiveSynchronizer/Makefile new file mode 100644 index 00000000..425db36d --- /dev/null +++ b/hwdbg/sim/hwdbg/communication/SendReceiveSynchronizer/Makefile @@ -0,0 +1,10 @@ +# Makefile + +TOPLEVEL_LANG = verilog +VERILOG_SOURCES += $(shell pwd)/../../../../generated/SendReceiveSynchronizer.sv +VERILOG_SOURCES += $(shell pwd)/../../../../generated/DebuggerPacketReceiver.sv +VERILOG_SOURCES += $(shell pwd)/../../../../generated/DebuggerPacketSender.sv +TOPLEVEL = SendReceiveSynchronizer +MODULE = test_SendReceiveSynchronizer + +include $(shell cocotb-config --makefiles)/Makefile.sim diff --git a/hwdbg/sim/hwdbg/communication/SendReceiveSynchronizer/test.sh b/hwdbg/sim/hwdbg/communication/SendReceiveSynchronizer/test.sh new file mode 100644 index 00000000..a83ca694 --- /dev/null +++ b/hwdbg/sim/hwdbg/communication/SendReceiveSynchronizer/test.sh @@ -0,0 +1 @@ +make SIM=icarus WAVES=1 diff --git a/hwdbg/sim/hwdbg/communication/SendReceiveSynchronizer/test_SendReceiveSynchronizer.py b/hwdbg/sim/hwdbg/communication/SendReceiveSynchronizer/test_SendReceiveSynchronizer.py new file mode 100644 index 00000000..a9b0f2b7 --- /dev/null +++ b/hwdbg/sim/hwdbg/communication/SendReceiveSynchronizer/test_SendReceiveSynchronizer.py @@ -0,0 +1,352 @@ +## +# @file test_SendReceiveSynchronizer.py +# +# @author Sina Karvandi (sina@hyperdbg.org) +# +# @brief Testing module for SendReceiveSynchronizer +# +# @details +# +# @version 0.1 +# +# @date 2024-04-23 +# +# @copyright This project is released under the GNU Public License v3. +# + +import random + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import Timer +from cocotb.types import LogicArray + +''' + input clock, + reset, + io_en, + io_plInSignal, + output io_psOutInterrupt, + output [12:0] io_rdWrAddr, + input [31:0] io_rdData, + output io_wrEna, + output [31:0] io_wrData, + io_requestedActionOfThePacketOutput, + output io_requestedActionOfThePacketOutputValid, + input io_noNewDataReceiver, + io_readNextData, + output io_dataValidOutput, + output [31:0] io_receivingData, + input io_beginSendingBuffer, + io_noNewDataSender, + io_dataValidInput, + output io_sendWaitForBuffer, + input [31:0] io_requestedActionOfThePacketInput, + io_sendingData +''' + +@cocotb.test() +async def SendReceiveSynchronizer_test(dut): + """Test SendReceiveSynchronizer module""" + + global DEFAULT_CONFIGURATION_INITIALIZED_MEMORY_SIZE + + # + # Assert initial output is unknown + # + assert LogicArray(dut.io_psOutInterrupt.value) == LogicArray("X") + assert LogicArray(dut.io_rdWrAddr.value) == LogicArray("XXXXXXXXXXXXX") + assert LogicArray(dut.io_wrEna.value) == LogicArray("X") + assert LogicArray(dut.io_wrData.value) == LogicArray("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") + assert LogicArray(dut.io_requestedActionOfThePacketOutput.value) == LogicArray("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") + assert LogicArray(dut.io_requestedActionOfThePacketOutputValid.value) == LogicArray("X") + assert LogicArray(dut.io_dataValidOutput.value) == LogicArray("X") + assert LogicArray(dut.io_receivingData.value) == LogicArray("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") + assert LogicArray(dut.io_sendWaitForBuffer.value) == LogicArray("X") + + clock = Clock(dut.clock, 10, units="ns") # Create a 10ns period clock on port clock + + # + # Start the clock. Start it low to avoid issues on the first RisingEdge + # + cocotb.start_soon(clock.start(start_high=False)) + + dut._log.info("Initialize and reset module") + + # + # Initial values + # + dut.io_en.value = 0 + dut.io_beginSendingBuffer.value = 0 + dut.io_noNewDataSender.value = 0 + dut.io_dataValidInput.value = 0 + dut.io_readNextData.value = 0 + dut.io_noNewDataReceiver.value = 0 + dut.io_plInSignal.value = 0 + dut.io_requestedActionOfThePacketInput.value = 0 + dut.io_requestedActionOfThePacketInput.value = 0 + + # + # Reset DUT + # + dut.reset.value = 1 + for _ in range(10): + await Timer(10, units="ns") + dut.reset.value = 0 + + dut._log.info("Enabling chip") + + # + # Enable chip + # + dut.io_en.value = 1 + + for test_number in range(10): + + ############################################################### + # # + # Receiving Logic # + # # + ############################################################### + + dut._log.info("Enable receiving data on the chip (" + str(test_number) + ")") + + # + # Tell the receiver to start receiving data (This mainly operates based on + # a rising-edge detector, so we'll need to make it low) + # + dut.io_plInSignal.value = 1 + await Timer(10, units="ns") + dut.io_plInSignal.value = 0 + + # + # Activate sending logic to test whether the chip fails synchronizing signals or not + # + dut.io_beginSendingBuffer.value = 1 + await Timer(10, units="ns") + dut.io_beginSendingBuffer.value = 0 + + # + # Wait until the receive operation is done (finished) + # + for i in range(30): + + match dut.io_rdWrAddr.value: + + # + # For the PS data range + # + case 0x0: # checksum + dut.io_rdData.value = 0x00001234 + case 0x8: # indicator + dut.io_rdData.value = 0x48595045 # first 32 bits of the indicator + case 0x10: # type + dut.io_rdData.value = 0x4 # debugger to hardware packet (DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL) + case 0x14: # requested action + dut.io_rdData.value = 0x14141414 + case 0x18: # General output + dut.io_rdData.value = 0x18181818 + case 0x1c: # General output + dut.io_rdData.value = 0x1c1c1c1c + case 0x20: # General output + dut.io_rdData.value = 0x20202020 + case 0x24: # General output + dut.io_rdData.value = 0x24242424 + case 0x28: # General output + dut.io_rdData.value = 0x28282828 + case 0x2c: # General output + dut.io_rdData.value = 0x2c2c2c2c + case 0x30: # General output + dut.io_rdData.value = 0x30303030 + case 0x34: # General output + dut.io_rdData.value = 0x34343434 + case 0x38: # General output + dut.io_rdData.value = 0x38383838 + case 0x3c: # General output + dut.io_rdData.value = 0x3c3c3c3c + case 0x40: # General output + dut.io_rdData.value = 0x40404040 + case 0x44: # General output + dut.io_rdData.value = 0x44444444 + case 0x48: # General output + dut.io_rdData.value = 0x48484848 + case 0x4c: # General output + dut.io_rdData.value = 0x4c4c4c4c + case 0x50: # General output + dut.io_rdData.value = 0x50505050 + + # + # For the PL data range + # + case 0x1000: # checksum + dut.io_rdData.value = 0x10001000 + case 0x1008: # indicator 1 + dut.io_rdData.value = 0x48595045 # The first 32 bits of the indicator + case 0x100c: # indicator 2 + dut.io_rdData.value = 0x100c100c # The second 32 bits of the indicator + case 0x1010: # type + dut.io_rdData.value = 0x4 # debugger to hardware packet (DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL) + case 0x1014: # requested action + dut.io_rdData.value = 0x10141014 + case 0x1018: # General output + dut.io_rdData.value = 0x10181018 + case 0x101c: # General output + dut.io_rdData.value = 0x101c101c + case 0x1020: # General output + dut.io_rdData.value = 0x10201020 + case 0x1024: # General output + dut.io_rdData.value = 0x10241024 + case 0x1028: # General output + dut.io_rdData.value = 0x10281028 + case 0x102c: # General output + dut.io_rdData.value = 0x102c102c + case 0x1030: # General output + dut.io_rdData.value = 0x10301030 + case 0x1034: # General output + dut.io_rdData.value = 0x10341034 + case 0x1038: # General output + dut.io_rdData.value = 0x10381038 + case 0x103c: # General output + dut.io_rdData.value = 0x103c103c + case 0x1040: # General output + dut.io_rdData.value = 0x10401040 + case 0x1044: # General output + dut.io_rdData.value = 0x10441044 + case 0x1048: # General output + dut.io_rdData.value = 0x10481048 + case 0x104c: # General output + dut.io_rdData.value = 0x104c104c + case 0x1050: # General output + dut.io_rdData.value = 0x10501050 + case _: + assert 1 == 2, "invalid address in the address line" + + if dut.io_requestedActionOfThePacketOutputValid.value == 1: + + # + # No new data needed to be received + # + if test_number % 3 == 0: + dut.io_noNewDataReceiver.value = 1 + await Timer(10, units="ns") + dut.io_noNewDataReceiver.value = 0 + else: + # + # Make change to the io_readNextData signal as it operates mainly + # based on a rising-edge detector + # + if dut.io_readNextData.value == 0: + dut.io_readNextData.value = 1 + else: + dut.io_readNextData.value = 0 + + # + # Go to the next clock cycle + # + await Timer(10, units="ns") + + + if test_number % 3 != 0: + dut.io_noNewDataReceiver.value = 1 + await Timer(10, units="ns") + dut.io_noNewDataReceiver.value = 0 + + # + # Run extra waiting clocks + # + for _ in range(10): + await Timer(10, units="ns") + + ############################################################### + # # + # Sending Logic # + # # + ############################################################### + + dut._log.info("Enable sending data on the chip (" + str(test_number) + ")") + + # + # There is data to send + # + dut.io_noNewDataSender.value = 0 + dut.io_beginSendingBuffer.value = 0 + + # + # Tell the sender to start sending data (This mainly operates based on + # a rising-edge detector, so we'll need to make it low) + # + dut.io_beginSendingBuffer.value = 1 + await Timer(10, units="ns") + dut.io_beginSendingBuffer.value = 0 + + # + # Activate receiving logic to test whether the chip fails synchronizing signals or not + # + dut.io_plInSignal.value = 1 + await Timer(10, units="ns") + dut.io_plInSignal.value = 0 + + # + # No new data at this stage + # + dut.io_dataValidInput.value = 0 + dut.io_sendingData.value = 0 + + # + # Adjust the requested action of the packet + # + dut.io_requestedActionOfThePacketInput.value = 0x55859555 + + # + # Synchronize with the clock. This will apply the initial values + # + await Timer(10, units="ns") + + # + # This will change the behavior of the data producer to only + # generate extra data for 2 of the test case rounds, the third + # test case doesn't have any extra data + # + if test_number % 3 != 0 : + # + # Run until the module asks for further buffers + # + for i in range(100): + if dut.io_sendWaitForBuffer.value == 1: + val = random.randint(0, 0xffffffff) + + # + # Indicate that the data is valid + # + dut.io_dataValidInput.value = 1 + + # + # Assign the random value to send as the data + # + dut.io_sendingData.value = val + + await Timer(10, units="ns") + + # + # Now, tell the sender module that there is no longer needed to send data + # + for i in range(100): + if dut.io_sendWaitForBuffer.value == 1: + dut.io_noNewDataSender.value = 1 + await Timer(10, units="ns") + dut.io_noNewDataSender.value = 0 + break + + await Timer(10, units="ns") + + + # + # Run extra waiting clocks + # + for _ in range(10): + await Timer(10, units="ns") + + # + # Check the final input on the next clock + # + await Timer(10, units="ns") diff --git a/hwdbg/sim/modelsim/README.md b/hwdbg/sim/modelsim/README.md new file mode 100644 index 00000000..f511e03c --- /dev/null +++ b/hwdbg/sim/modelsim/README.md @@ -0,0 +1,32 @@ +# Automated ModelSim Viewer + +First of all, make sure to edit the address of the "ModelSim" directory in **modelsim.py**. + +After that, only modify the "modelsim.config" file. + +In the "modelsim.config" file, the first line that starts with "module:" is the name of the target module's **Tester** class. The rest of the lines are signals to be shown. + +For example: +``` +module:DebuggerModuleTest +clock +inputPin +``` + +If you don't specify the signals to be filtered, then **ALL** signals will be shown. + +For example: +``` +module:DebuggerModuleTest +``` + +At last, run it with the following command: +``` +python3 modelsim.py +``` + +or, +``` +python3 sim/modelsim.py +``` + diff --git a/hwdbg/sim/modelsim/modelsim.config b/hwdbg/sim/modelsim/modelsim.config new file mode 100644 index 00000000..cc537f5f --- /dev/null +++ b/hwdbg/sim/modelsim/modelsim.config @@ -0,0 +1,3 @@ +module:DebuggerModuleTest +io_inputPin +io_outputPin \ No newline at end of file diff --git a/hwdbg/sim/modelsim/modelsim.py b/hwdbg/sim/modelsim/modelsim.py new file mode 100644 index 00000000..e3c90db1 --- /dev/null +++ b/hwdbg/sim/modelsim/modelsim.py @@ -0,0 +1,157 @@ +import os +import subprocess +import glob + +MODELSIM = "/home/sina/intelFPGA/20.1/modelsim_ase/bin" + +# +# Check modelsim directory +# +if not os.path.exists(MODELSIM): + print("[x] Error: The path does not exist") + exit() +else: + print("[*] Oh, the modelsim path found :)") + +MODELSIM_VCD2WLF = MODELSIM + "/vcd2wlf" +MODELSIM_VSIM = MODELSIM + "/vsim" + +# +# Config file variables +# +CONFIG_TEST_MODULE_CLASS = "" +CONFIG_SHOW_ALL_WAVES = True +CONFIG_WAVES_LIST = [] + +# +# Check if user is root or not +# +if os.geteuid() != 0: + print("[x] you should run this script with root (sudo) user permission") + exit() +else: + print("[*] user is root") + +# +# Get the current script's directory +# +current_script_path = os.path.dirname(os.path.abspath(__file__)) + +WAVE_OUTPUT_FILES_PATH = current_script_path + \ + "/../test_run_dir/DUT_should_pass/" +CONFIG_FILE_PATH = current_script_path + "/modelsim.config" +print("[*] current script path:", WAVE_OUTPUT_FILES_PATH) + +# +# Check config file +# +if os.path.exists(CONFIG_FILE_PATH) == False: + print("[x] config file not found") + exit() + +# +# Interpreting config file +# +with open(CONFIG_FILE_PATH, 'r') as file: + for line in file: + + if line.lower().startswith("module:") or line.lower().startswith("module :"): + # it's the test module name + CONFIG_TEST_MODULE_CLASS = line.split(":")[1] + print("[*] found module name:", CONFIG_TEST_MODULE_CLASS) + else: + # it's a wave, so no longer need to show all waves + if line.isspace() == False: + CONFIG_SHOW_ALL_WAVES = False + CONFIG_WAVES_LIST.append(line) + print("[*] signal filter for:", line) + +# +# Show message if all signals need to be shown +# +if CONFIG_SHOW_ALL_WAVES == True: + print("[*] no signal filter found, assuming all signals to be shown!") + +# +# Check if test module is empty or not +# +if CONFIG_TEST_MODULE_CLASS.isspace() == True: + print("[x] main test module not found, please add 'module:' to the config file") + exit() + +# +# Set the current working directory +# +os.chdir(current_script_path + "/..") +print("[*] current working directory: " + format(os.getcwd())) + +# +# Create TCL config file +# +print("[*] writing to TCL config file: " + + current_script_path + '/modelsim.tcl') +if CONFIG_SHOW_ALL_WAVES: + with open(current_script_path + '/modelsim.tcl', 'w') as f: + # add the clock at top of the signals by default + f.write("add wave -position insertpoint clock\n") + f.write("add wave -position insertpoint *\n") +else: + with open(current_script_path + '/modelsim.tcl', 'w') as f: + for item in CONFIG_WAVES_LIST: + f.write("add wave -position insertpoint {*" + item.replace('\n','').replace('\r', '') + '*}\n') + +# +# Remove all the previous *.wlf, *.vcd, *.fir files +# +print("[*] removing previously generated files") +for file_name in os.listdir(WAVE_OUTPUT_FILES_PATH): + if file_name.endswith('.wlf') or file_name.endswith('.vcd') or file_name.endswith('.fir'): + os.remove(os.path.join(WAVE_OUTPUT_FILES_PATH, file_name)) + +# +# Run the VCD wave generator +# +print("[*] running chisel VCD file generator for module: " + + CONFIG_TEST_MODULE_CLASS) +print("running command: '" + "sbt testOnly " + CONFIG_TEST_MODULE_CLASS + " -- -DwriteVcd=1" + "'") +result = subprocess.run( + ["sbt", "testOnly " + CONFIG_TEST_MODULE_CLASS + " -- -DwriteVcd=1"], stdout=subprocess.PIPE) +print(result.stdout.decode()) + +# +# Get all files in directory +# +files = glob.glob(WAVE_OUTPUT_FILES_PATH + "/*") + +# +# Sort files by last modified time +# +files.sort(key=lambda x: os.path.getmtime(x)) + +# +# Check if the list is empty or not +# +if not files or not files[-1].endswith('.vcd') : + print("[x] there was an error in generating VCD files") + exit() + +# +# Get the latest modified file +# +latest_vcd_file = files[-1] +print("[*] latest generated VCD file: " + latest_vcd_file) + +# +# Converting VCD to WLF +# +print("[*] converting VCD file to WLF file") +result = subprocess.run( + [MODELSIM_VCD2WLF, latest_vcd_file, latest_vcd_file + ".wlf"], stdout=subprocess.PIPE) +print(result.stdout.decode()) + +# +# Run the generated WLF file +# +print("[*] opening file in vsim: " + latest_vcd_file + ".wlf") +subprocess.run([MODELSIM_VSIM, latest_vcd_file + ".wlf", + "-do", current_script_path + '/modelsim.tcl']) diff --git a/hwdbg/sim/modelsim/modelsim.tcl b/hwdbg/sim/modelsim/modelsim.tcl new file mode 100644 index 00000000..59c53356 --- /dev/null +++ b/hwdbg/sim/modelsim/modelsim.tcl @@ -0,0 +1,2 @@ +add wave -position insertpoint {*io_inputPin*} +add wave -position insertpoint {*io_outputPin*} diff --git a/hwdbg/sim/plain-sv/PlainSystemVerilogDUT.sv b/hwdbg/sim/plain-sv/PlainSystemVerilogDUT.sv new file mode 100644 index 00000000..12c7fa1f --- /dev/null +++ b/hwdbg/sim/plain-sv/PlainSystemVerilogDUT.sv @@ -0,0 +1,162 @@ +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: Sina Karvandi (sina@hyperdbg.org) +// +// Create Date: 09/18/2024 +// Design Name: +// Module Name: PlainSystemVerilogDUT +// Project Name: PlainSystemVerilogDUT +// Target Devices: +// Tool Versions: +// Description: This code is used for plain simulation of the top-level +// design of hwdbg debugger +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + +module PlainSystemVerilogDUT; + + // + // Parameters + // + parameter CLK_PERIOD = 10; // Clock period + + // + // Signal Declarations + // + logic clock; + logic reset; + logic io_en; + logic [31:0] io_inputPin; // Array for input pins + logic [31:0] io_outputPin; // Array for output pins + logic io_plInSignal; + logic io_psOutInterrupt; + + // + // Instantiate the DUT (Device Under Test) + // + DebuggerModuleTestingBRAM uut ( + .clock(clock), + .reset(reset), + .io_en(io_en), + .io_inputPin_0(io_inputPin[0]), + .io_inputPin_1(io_inputPin[1]), + .io_inputPin_2(io_inputPin[2]), + .io_inputPin_3(io_inputPin[3]), + .io_inputPin_4(io_inputPin[4]), + .io_inputPin_5(io_inputPin[5]), + .io_inputPin_6(io_inputPin[6]), + .io_inputPin_7(io_inputPin[7]), + .io_inputPin_8(io_inputPin[8]), + .io_inputPin_9(io_inputPin[9]), + .io_inputPin_10(io_inputPin[10]), + .io_inputPin_11(io_inputPin[11]), + .io_inputPin_12(io_inputPin[12]), + .io_inputPin_13(io_inputPin[13]), + .io_inputPin_14(io_inputPin[14]), + .io_inputPin_15(io_inputPin[15]), + .io_inputPin_16(io_inputPin[16]), + .io_inputPin_17(io_inputPin[17]), + .io_inputPin_18(io_inputPin[18]), + .io_inputPin_19(io_inputPin[19]), + .io_inputPin_20(io_inputPin[20]), + .io_inputPin_21(io_inputPin[21]), + .io_inputPin_22(io_inputPin[22]), + .io_inputPin_23(io_inputPin[23]), + .io_inputPin_24(io_inputPin[24]), + .io_inputPin_25(io_inputPin[25]), + .io_inputPin_26(io_inputPin[26]), + .io_inputPin_27(io_inputPin[27]), + .io_inputPin_28(io_inputPin[28]), + .io_inputPin_29(io_inputPin[29]), + .io_inputPin_30(io_inputPin[30]), + .io_inputPin_31(io_inputPin[31]), + .io_outputPin_0(io_outputPin[0]), + .io_outputPin_1(io_outputPin[1]), + .io_outputPin_2(io_outputPin[2]), + .io_outputPin_3(io_outputPin[3]), + .io_outputPin_4(io_outputPin[4]), + .io_outputPin_5(io_outputPin[5]), + .io_outputPin_6(io_outputPin[6]), + .io_outputPin_7(io_outputPin[7]), + .io_outputPin_8(io_outputPin[8]), + .io_outputPin_9(io_outputPin[9]), + .io_outputPin_10(io_outputPin[10]), + .io_outputPin_11(io_outputPin[11]), + .io_outputPin_12(io_outputPin[12]), + .io_outputPin_13(io_outputPin[13]), + .io_outputPin_14(io_outputPin[14]), + .io_outputPin_15(io_outputPin[15]), + .io_outputPin_16(io_outputPin[16]), + .io_outputPin_17(io_outputPin[17]), + .io_outputPin_18(io_outputPin[18]), + .io_outputPin_19(io_outputPin[19]), + .io_outputPin_20(io_outputPin[20]), + .io_outputPin_21(io_outputPin[21]), + .io_outputPin_22(io_outputPin[22]), + .io_outputPin_23(io_outputPin[23]), + .io_outputPin_24(io_outputPin[24]), + .io_outputPin_25(io_outputPin[25]), + .io_outputPin_26(io_outputPin[26]), + .io_outputPin_27(io_outputPin[27]), + .io_outputPin_28(io_outputPin[28]), + .io_outputPin_29(io_outputPin[29]), + .io_outputPin_30(io_outputPin[30]), + .io_outputPin_31(io_outputPin[31]), + .io_plInSignal(io_plInSignal), + .io_psOutInterrupt(io_psOutInterrupt) + ); + + // + // Clock generation + // + initial begin + clock = 0; + forever #(CLK_PERIOD / 2) clock = ~clock; + end + + // + // Test procedure + // + initial begin + // Initialize signals + reset = 1; + io_en = 1; + io_plInSignal = 0; + io_inputPin = 32'h0; // Initialize all input pins to 0 + + #100; // Hold reset for 100 ns + + // Apply reset + @(posedge clock); + reset = 0; // Release reset + @(posedge clock); + + // + // Example input stimulus + // + io_inputPin = 32'hFFFF_FFFF; // Apply some input pattern + + // + // Enable PL input signal + // + io_plInSignal = 1; + + // + // Wait for a few clock cycles + // + repeat (10000) @(posedge clock); + + // + // Finish the simulation after some time + // + repeat (20) @(posedge clock); + $finish; + end + +endmodule diff --git a/hwdbg/src/main/scala/hwdbg/communication/interpreter.scala b/hwdbg/src/main/scala/hwdbg/communication/interpreter.scala new file mode 100644 index 00000000..e682e612 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/communication/interpreter.scala @@ -0,0 +1,515 @@ +/** + * @file + * interpreter.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Remote debugger packet interpreter module + * @details + * @version 0.1 + * @date + * 2024-04-19 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.communication.interpreter + +import chisel3._ +import chisel3.util.{switch, is} +import circt.stage.ChiselStage + +import hwdbg.configs._ +import hwdbg.types._ +import hwdbg.script._ + +object DebuggerPacketInterpreterEnums { + object State extends ChiselEnum { + val sIdle, sNewActionReceived, sSendResponse, sDone = Value + } +} + +class DebuggerPacketInterpreter( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + // + // Import state enum + // + import DebuggerPacketInterpreterEnums.State + import DebuggerPacketInterpreterEnums.State._ + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Receiving signals + // + val requestedActionOfThePacketInput = Input(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) // the requested action + val requestedActionOfThePacketInputValid = Input(Bool()) // whether data on the requested action is valid or not + + val noNewDataReceiver = Output(Bool()) // are interpreter expects more data? + val readNextData = Output(Bool()) // whether the next data should be read or not? + + val dataValidInput = Input(Bool()) // whether data on the receiving data line is valid or not? + val receivingData = Input(UInt(instanceInfo.bramDataWidth.W)) // data to be received in interpreter + + // + // Sending signals + // + val beginSendingBuffer = Output(Bool()) // should sender start sending buffers or not? + val noNewDataSender = Output(Bool()) // should sender finish sending buffers or not? + val dataValidOutput = Output(Bool()) // should sender send next buffer or not? + + val sendWaitForBuffer = Input(Bool()) // should the interpreter send next buffer or not? + + val requestedActionOfThePacketOutput = Output(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) // the requested action + val sendingData = Output(UInt(instanceInfo.bramDataWidth.W)) // data to be sent to the debugger + + // + // Script stage configuration signals + // + val finishedScriptConfiguration = Output(Bool()) // whether script configuration finished or not? + val configureStage = Output(Bool()) // whether the configuration of stage should start or not? + val targetOperator = Output(new HwdbgShortSymbol(instanceInfo.scriptVariableLength)) // Current operator to be configured + }) + + // + // State registers + // + val state = RegInit(sIdle) + + // + // Last error register + // + val lastSuccesOrErrorMessage = RegInit(0.U(instanceInfo.bramDataWidth.W)) + + // + // Last error register + // + val enablePinOfScriptBufferHandler = RegInit(false.B) + + // + // Output pins + // + val noNewDataReceiver = WireInit(false.B) + val readNextData = WireInit(false.B) + + val regBeginSendingBuffer = RegInit(false.B) + val noNewDataSender = WireInit(false.B) + val dataValidOutput = WireInit(false.B) + val sendingData = WireInit(0.U(instanceInfo.bramDataWidth.W)) + + val regRequestedActionOfThePacketOutput = RegInit(0.U(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) + + val finishedScriptConfiguration = WireInit(false.B) + val configureStage = WireInit(false.B) + val initialSymbol = Wire(new HwdbgShortSymbol(instanceInfo.scriptVariableLength)) + initialSymbol.Type := 0.U + initialSymbol.Value := 0.U + val targetOperator = WireInit(initialSymbol) + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + switch(state) { + + is(sIdle) { + + // + // Check if the debugger need a new action (a new command is received) + // + when(io.requestedActionOfThePacketInputValid) { + + // + // An action is received + // + state := sNewActionReceived + + }.otherwise { + + // + // Remain at the same state (no action) + // + state := sIdle + } + + } + is(sNewActionReceived) { + + // ------------------------------------------------------------------------- + // Now, the action needs to be dispatched + // + val inputAction = io.requestedActionOfThePacketInput + + when(inputAction === HwdbgActionEnums.hwdbgActionSendInstanceInfo.id.U) { + + // + // *** Configure sending instance info *** + // + + // + // Set the response packet type + // + regRequestedActionOfThePacketOutput := HwdbgResponseEnums.hwdbgResponseInstanceInfo.id.U + + // + // This action needs a response + // + state := sSendResponse + + }.elsewhen(inputAction === HwdbgActionEnums.hwdbgActionConfigureScriptBuffer.id.U) { + + // + // *** Configure the internal buffer with script *** + // + + // + // Enable the buffer config module + // + enablePinOfScriptBufferHandler := true.B + + val ( + moduleReadNextData, + moduleFinishedScriptConfiguration, + moduleConfigureStage, + moduleTargetOperator + ) = + InterpreterScriptBufferHandler( + debug, + instanceInfo + )( + enablePinOfScriptBufferHandler, + io.dataValidInput, + io.receivingData + ) + + // + // Connect the script stage configuration signals + // + readNextData := moduleReadNextData + configureStage := moduleConfigureStage + finishedScriptConfiguration := moduleFinishedScriptConfiguration + targetOperator := moduleTargetOperator + + when(moduleFinishedScriptConfiguration === true.B) { + + // + // *** Script stage buffer configuration finished! *** + // + + // + // Disable the buffer config module + // + enablePinOfScriptBufferHandler := false.B + + // + // Set the response packet type + // + regRequestedActionOfThePacketOutput := HwdbgResponseEnums.hwdbgResponseSuccessOrErrorMessage.id.U + + // + // Set the success message + // + lastSuccesOrErrorMessage := HwdbgSuccessOrErrorEnums.hwdbgOperationWasSuccessful.id.U + + // + // This action needs a response + // + state := sSendResponse + + }.otherwise { + + // + // *** Script stage buffer configuration NOT finished, read the buffer *** + // + + // + // Stay at the same state + // + state := sNewActionReceived + } + + }.otherwise { + + // + // *** Invalid action *** + // + + // + // Set the response packet type + // + regRequestedActionOfThePacketOutput := HwdbgResponseEnums.hwdbgResponseSuccessOrErrorMessage.id.U + + // + // Set the latest error + // + lastSuccesOrErrorMessage := HwdbgSuccessOrErrorEnums.hwdbgErrorInvalidPacket.id.U + + // + // This action needs a response + // + state := sSendResponse + + } + + // + // ------------------------------------------------------------------------- + // + + } + is(sSendResponse) { + + // + // Finish the receiving + // + noNewDataReceiver := true.B + + // + // Begin sending response + // + regBeginSendingBuffer := true.B + + // + // Wait until the sender module is reading to send data + // + when(io.sendWaitForBuffer === true.B) { + + // ------------------------------------------------------------------------- + // Now, the response needs to be sent + // + when(regRequestedActionOfThePacketOutput === HwdbgResponseEnums.hwdbgResponseInstanceInfo.id.U) { + + // + // *** Send instance information *** + // + + // + // Instantiate the instance info module + // + + val ( + noNewDataSenderModule, + dataValidOutputModule, + sendingDataModule + ) = + InterpreterInstanceInfo( + debug, + instanceInfo + )( + io.sendWaitForBuffer // send waiting for buffer as an activation signal to the module + ) + + // + // Set data validity + // + dataValidOutput := dataValidOutputModule + + // + // Set data + // + sendingData := sendingDataModule + + // + // Once sending data is done, we'll go to the Done state + // + when(noNewDataSenderModule === true.B) { + state := sDone + } + + }.elsewhen(regRequestedActionOfThePacketOutput === HwdbgResponseEnums.hwdbgResponseSuccessOrErrorMessage.id.U) { + + // + // *** Send result of applying command (and errors) *** + // + + // + // Instantiate the invalid packet module + // + val ( + noNewDataSenderModule, + dataValidOutputModule, + sendingDataModule + ) = + InterpreterSendSuccessOrError( + debug, + instanceInfo + )( + io.sendWaitForBuffer, // send waiting for buffer as an activation signal to the module + lastSuccesOrErrorMessage + ) + + // + // Set data validity + // + dataValidOutput := dataValidOutputModule + + // + // Set data + // + sendingData := sendingDataModule + + // + // Once sending data is done, we'll go to the Done state + // + when(noNewDataSenderModule === true.B) { + state := sDone + } + } + + // + // ------------------------------------------------------------------------- + // + + }.otherwise { + + // + // The sender module is not ready for sending buffer + // so, we need to stay at this state + // + state := sSendResponse + } + } + is(sDone) { + + // + // Finish the receiving, sending communication + // + noNewDataReceiver := true.B + noNewDataSender := true.B + + // + // No longer need to begin sending data + // + regBeginSendingBuffer := false.B + + // + // Go to the idle state + // + state := sIdle + } + } + } + + // --------------------------------------------------------------------- + + // + // Connect output pins + // + io.noNewDataReceiver := noNewDataReceiver + io.readNextData := readNextData + + io.beginSendingBuffer := regBeginSendingBuffer + io.noNewDataSender := noNewDataSender + io.dataValidOutput := dataValidOutput + io.requestedActionOfThePacketOutput := regRequestedActionOfThePacketOutput + io.sendingData := sendingData + + io.configureStage := configureStage + io.finishedScriptConfiguration := finishedScriptConfiguration + io.targetOperator := targetOperator +} + +object DebuggerPacketInterpreter { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool, + requestedActionOfThePacketInput: UInt, + requestedActionOfThePacketInputValid: Bool, + dataValidInput: Bool, + receivingData: UInt, + sendWaitForBuffer: Bool + ): (Bool, Bool, Bool, Bool, Bool, UInt, UInt, Bool, Bool, HwdbgShortSymbol) = { + + val debuggerPacketInterpreter = Module( + new DebuggerPacketInterpreter( + debug, + instanceInfo + ) + ) + + val noNewDataReceiver = Wire(Bool()) + val readNextData = Wire(Bool()) + + val beginSendingBuffer = Wire(Bool()) + val noNewDataSender = Wire(Bool()) + val dataValidOutput = Wire(Bool()) + + val requestedActionOfThePacketOutput = Wire(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) + val sendingData = Wire(UInt(instanceInfo.bramDataWidth.W)) + + val finishedScriptConfiguration = Wire(Bool()) + val configureStage = Wire(Bool()) + val targetOperator = Wire(new HwdbgShortSymbol(instanceInfo.scriptVariableLength)) + + // + // Configure the input signals + // + debuggerPacketInterpreter.io.en := en + + // + // Configure the input signals related to the receiving signals + // + debuggerPacketInterpreter.io.requestedActionOfThePacketInput := requestedActionOfThePacketInput + debuggerPacketInterpreter.io.requestedActionOfThePacketInputValid := requestedActionOfThePacketInputValid + debuggerPacketInterpreter.io.dataValidInput := dataValidInput + debuggerPacketInterpreter.io.receivingData := receivingData + + // + // Configure the input signals related to the sending signals + // + debuggerPacketInterpreter.io.sendWaitForBuffer := sendWaitForBuffer + + // + // Configure the output signals + // + noNewDataReceiver := debuggerPacketInterpreter.io.noNewDataReceiver + readNextData := debuggerPacketInterpreter.io.readNextData + + // + // Configure the output signals related to sending packets + // + beginSendingBuffer := debuggerPacketInterpreter.io.beginSendingBuffer + noNewDataSender := debuggerPacketInterpreter.io.noNewDataSender + dataValidOutput := debuggerPacketInterpreter.io.dataValidOutput + + // + // Configure the output signals related to received packets + // + requestedActionOfThePacketOutput := debuggerPacketInterpreter.io.requestedActionOfThePacketOutput + sendingData := debuggerPacketInterpreter.io.sendingData + + // + // Configure the output signals related to stage configuration + // + finishedScriptConfiguration := debuggerPacketInterpreter.io.finishedScriptConfiguration + configureStage := debuggerPacketInterpreter.io.configureStage + targetOperator := debuggerPacketInterpreter.io.targetOperator + + // + // Return the output result + // + ( + noNewDataReceiver, + readNextData, + beginSendingBuffer, + noNewDataSender, + dataValidOutput, + requestedActionOfThePacketOutput, + sendingData, + finishedScriptConfiguration, + configureStage, + targetOperator + ) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/communication/interpreter/instance_info.scala b/hwdbg/src/main/scala/hwdbg/communication/interpreter/instance_info.scala new file mode 100644 index 00000000..f84df188 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/communication/interpreter/instance_info.scala @@ -0,0 +1,462 @@ +/** + * @file + * port_information.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Send port information (in interpreter) + * @details + * @version 0.1 + * @date + * 2024-05-04 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.communication.interpreter + +import chisel3._ +import chisel3.util.{switch, is, log2Ceil} +import circt.stage.ChiselStage + +import hwdbg.configs._ +import hwdbg.utils._ + +object InterpreterInstanceInfoEnums { + object State extends ChiselEnum { + val sIdle, sSendVersion, sSendMaximumNumberOfStages, sSendScriptVariableLength, sSendNumberOfSupportedLocalAndGlobalVariables, + sSendNumberOfSupportedTemporaryVariables, sSendMaximumNumberOfSupportedGetScriptOperators, sSendMaximumNumberOfSupportedSetScriptOperators, + sSendSharedMemorySize, sSendDebuggerAreaOffset, sSendDebuggeeAreaOffset, sSendNumberOfPins, sSendNumberOfPorts, sSendScriptCapabilities1, + sSendScriptCapabilities2, sSendBramAddrWidth, sSendBramDataWidth, sSendPortsConfiguration, sDone = Value + } +} + +class InterpreterInstanceInfo( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + // + // Import state enum + // + import InterpreterInstanceInfoEnums.State + import InterpreterInstanceInfoEnums.State._ + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Sending signals + // + val noNewDataSender = Output(Bool()) // should sender finish sending buffers or not? + val dataValidOutput = Output(Bool()) // should sender send next buffer or not? + val sendingData = Output(UInt(instanceInfo.bramDataWidth.W)) // data to be sent to the debugger + + }) + + // + // State registers + // + val state = RegInit(sIdle) + + // + // Get number of input/output ports + // + val numberOfPorts = instanceInfo.portsConfiguration.size + + // + // Convert input port pins into vector + // + // val pinsVec = RegInit(VecInit(Seq.fill(numberOfPorts)(0.U(instanceInfo.bramDataWidth.W)))) + val pinsVec = VecInit(instanceInfo.portsConfiguration.map(_.U)) + + // + // Determine the width for numberOfSentPins + // + val numberOfSentPinsWidth = log2Ceil(numberOfPorts) + + // + // Registers for keeping track of sent pin details + // + val numberOfSentPins = RegInit(0.U(numberOfSentPinsWidth.W)) + + // + // Output pins + // + val noNewDataSender = WireInit(false.B) + val dataValidOutput = WireInit(false.B) + val sendingData = WireInit(0.U(instanceInfo.bramDataWidth.W)) + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + switch(state) { + + is(sIdle) { + + // + // Going to the next state (sending the version of the debugger) + // + state := sSendVersion + } + is(sSendVersion) { + + // + // Set the version + // + sendingData := instanceInfo.version.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendMaximumNumberOfStages + + } + is(sSendMaximumNumberOfStages) { + + // + // Set the maximum number of stages supported by this instance of the debugger + // + sendingData := instanceInfo.maximumNumberOfStages.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendScriptVariableLength + + } + is(sSendScriptVariableLength) { + + // + // Set the script variable length of this instance of the debugger + // + sendingData := instanceInfo.scriptVariableLength.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendNumberOfSupportedLocalAndGlobalVariables + + } + is(sSendNumberOfSupportedLocalAndGlobalVariables) { + + // + // Set the number of supported local variables for this instance of the debugger + // + sendingData := instanceInfo.numberOfSupportedLocalAndGlobalVariables.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendNumberOfSupportedTemporaryVariables + + } + is(sSendNumberOfSupportedTemporaryVariables) { + + // + // Set the number of supported temporary variables for this instance of the debugger + // + sendingData := instanceInfo.numberOfSupportedTemporaryVariables.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendMaximumNumberOfSupportedGetScriptOperators + + } + is(sSendMaximumNumberOfSupportedGetScriptOperators) { + + // + // Set the maximum number of supported GET operators by this instance of the + // debugger in the script engine + // + sendingData := instanceInfo.maximumNumberOfSupportedGetScriptOperators.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendMaximumNumberOfSupportedSetScriptOperators + + } + is(sSendMaximumNumberOfSupportedSetScriptOperators) { + + // + // Set the maximum number of supported SET operators by this instance of the + // debugger in the script engine + // + sendingData := instanceInfo.maximumNumberOfSupportedSetScriptOperators.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendSharedMemorySize + + } + is(sSendSharedMemorySize) { + + // + // Set the shared memory size used by this instance of the debugger + // + sendingData := instanceInfo.sharedMemorySize.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendDebuggerAreaOffset + + } + is(sSendDebuggerAreaOffset) { + + // + // Set the start offset of the debugger to the debuggee memory for this + // instance of the debugger + // + sendingData := instanceInfo.debuggerAreaOffset.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendDebuggeeAreaOffset + + } + is(sSendDebuggeeAreaOffset) { + + // + // Set the start offset of the debuggee to the debugger memory for this + // instance of the debugger + // + sendingData := instanceInfo.debuggeeAreaOffset.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendNumberOfPins + + } + is(sSendNumberOfPins) { + + // + // Set the number of pins in this instance of the debugger + // + sendingData := instanceInfo.numberOfPins.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendNumberOfPorts + + } + is(sSendNumberOfPorts) { + + // + // Set the number of ports in this instance of the debugger + // + sendingData := instanceInfo.numberOfPorts.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendScriptCapabilities1 + + } + is(sSendScriptCapabilities1) { + + // + // Set the first bits (most significant) of the supported operators capabilities of this instance + // of the debugger + // + sendingData := BitwiseFunction + .getBitsInRange(instanceInfo.scriptCapabilities, instanceInfo.bramDataWidth, instanceInfo.bramDataWidth + instanceInfo.bramDataWidth - 1) + .U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendScriptCapabilities2 + + } + is(sSendScriptCapabilities2) { + + // + // Set the second bits (least significant) of the supported operators capabilities of this instance + // of the debugger + // + sendingData := BitwiseFunction.getBitsInRange(instanceInfo.scriptCapabilities, 0, instanceInfo.bramDataWidth - 1).U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendBramAddrWidth + + } + is(sSendBramAddrWidth) { + + // + // Set the BRAM address width in this instance of the debugger + // + sendingData := instanceInfo.bramAddrWidth.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendBramDataWidth + + } + is(sSendBramDataWidth) { + + // + // Set the BRAM data width in this instance of the debugger + // + sendingData := instanceInfo.bramDataWidth.U + + // + // The output is valid + // + dataValidOutput := true.B + + state := sSendPortsConfiguration + + } + is(sSendPortsConfiguration) { + + // + // Send input port items + // + + // + // Adjust data + // + sendingData := pinsVec(numberOfSentPins) + + // + // Data is valid + // + dataValidOutput := true.B + + when(numberOfSentPins === (numberOfPorts - 1).U) { + + // + // Reset the pins sent for sending details + // + numberOfSentPins := 0.U + + state := sDone + + }.otherwise { + + // + // Send next index + // + numberOfSentPins := numberOfSentPins + 1.U + + // + // Stay at the same state + // + state := sSendPortsConfiguration + } + } + is(sDone) { + + // + // Indicate that sending data is done + // + noNewDataSender := true.B + + // + // Goto the idle state + // + state := sIdle + } + } + + } + + // --------------------------------------------------------------------- + + // + // Connect output pins + // + io.noNewDataSender := noNewDataSender + io.dataValidOutput := dataValidOutput + io.sendingData := sendingData + +} + +object InterpreterInstanceInfo { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool + ): (Bool, Bool, UInt) = { + + val interpreterInstanceInfo = Module( + new InterpreterInstanceInfo( + debug, + instanceInfo + ) + ) + + val noNewDataSender = Wire(Bool()) + val dataValidOutput = Wire(Bool()) + val sendingData = Wire(UInt(instanceInfo.bramDataWidth.W)) + + // + // Configure the input signals + // + interpreterInstanceInfo.io.en := en + + // + // Configure the output signals + // + noNewDataSender := interpreterInstanceInfo.io.noNewDataSender + dataValidOutput := interpreterInstanceInfo.io.dataValidOutput + sendingData := interpreterInstanceInfo.io.sendingData + + // + // Return the output result + // + ( + noNewDataSender, + dataValidOutput, + sendingData + ) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/communication/interpreter/script_buffer_handler.scala b/hwdbg/src/main/scala/hwdbg/communication/interpreter/script_buffer_handler.scala new file mode 100644 index 00000000..ee7462f9 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/communication/interpreter/script_buffer_handler.scala @@ -0,0 +1,301 @@ +/** + * @file + * script_buffer_handler.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Configures the script stages from shared memory + * @details + * @version 0.1 + * @date + * 2024-06-14 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.communication.interpreter + +import chisel3._ +import chisel3.util.{switch, is} +import circt.stage.ChiselStage + +import hwdbg.configs._ +import hwdbg.types._ +import hwdbg.script._ + +object InterpreterScriptBufferHandlerEnums { + object State extends ChiselEnum { + val sIdle, sReadSizeOfBuffer, sReadTypeOfOperator, sReadValueOfOperator, sDone = Value + } +} + +class InterpreterScriptBufferHandler( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + // + // Import state enum + // + import InterpreterScriptBufferHandlerEnums.State + import InterpreterScriptBufferHandlerEnums.State._ + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Receiving signals + // + val readNextData = Output(Bool()) // whether the next data should be read or not? + + val dataValidInput = Input(Bool()) // whether data on the receiving data line is valid or not? + val receivingData = Input(UInt(instanceInfo.bramDataWidth.W)) // data to be received in interpreter + + // + // Script stage configuration signals + // + val finishedScriptConfiguration = Output(Bool()) // whether configuration finished or not? + val configureStage = Output(Bool()) // whether the configuration of stage should start or not? + val targetOperator = Output(new HwdbgShortSymbol(instanceInfo.scriptVariableLength)) // Current operator to be configured + }) + + // + // State registers + // + val state = RegInit(sIdle) + + // + // Internal registers + // + val regScriptNumberOfSymbols = Reg(UInt(instanceInfo.bramDataWidth.W)) + + // + // Output pins + // + val readNextData = WireInit(false.B) + + val finishedScriptConfiguration = WireInit(false.B) + val configureStage = RegInit(false.B) + + val regTargetOperator = Reg(new HwdbgShortSymbol(instanceInfo.scriptVariableLength)) + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + switch(state) { + + is(sIdle) { + + // + // Read next data for the size of the buffer + // + readNextData := true.B + + // + // Move to the next state + // + state := sReadSizeOfBuffer + } + is(sReadSizeOfBuffer) { + + when(io.dataValidInput) { + + // + // Data is valid and number of symbols is now available + // + regScriptNumberOfSymbols := io.receivingData + + // + // Request next data + // + readNextData := true.B + + // + // Move to the configuration state + // + state := sReadTypeOfOperator + + }.otherwise { + + // + // Stay at the same state since the data is not yet received + // + state := sReadSizeOfBuffer + } + } + is(sReadTypeOfOperator) { + + // + // Not valid for configuring yet + // + configureStage := false.B + + when(io.dataValidInput) { + + // + // Request next data + // + readNextData := true.B + + // + // Read the operator's "Type" data + // + regTargetOperator.Type := io.receivingData + + // + // Next, we need to read "Value" + // + state := sReadValueOfOperator + + }.otherwise { + + // + // Stay at the same state since the data is not received yet + // + state := sReadTypeOfOperator + } + } + is(sReadValueOfOperator) { + + when(io.dataValidInput) { + + // + // Configure the stages + // + configureStage := true.B + + // + // Read the operator's "Value" data + // + regTargetOperator.Value := io.receivingData + + // + // Decrement the remaining symbols + // + regScriptNumberOfSymbols := regScriptNumberOfSymbols - 1.U + + // + // Check if reading is scripts are finished or not + // + when(regScriptNumberOfSymbols === 0.U) { + + // + // Configurartion was done + // + state := sDone + + }.otherwise { + + // + // Request next data + // + readNextData := true.B + + // + // Again, read the next type + // + state := sReadTypeOfOperator + } + }.otherwise { + + // + // Stay at the same state since the data is not received yet + // + state := sReadValueOfOperator + } + } + is(sDone) { + + // + // Not valid for configuring anymore + // + configureStage := false.B + + // + // Finished configuration + // + finishedScriptConfiguration := true.B + + // + // Move to the idle state + // + state := sIdle + } + } + } + + // + // Connect output pins + // + io.readNextData := readNextData + + io.finishedScriptConfiguration := finishedScriptConfiguration + io.configureStage := configureStage + io.targetOperator := regTargetOperator + +} + +object InterpreterScriptBufferHandler { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool, + dataValidInput: Bool, + receivingData: UInt + ): (Bool, Bool, Bool, HwdbgShortSymbol) = { + + val interpreterScriptBufferHandler = Module( + new InterpreterScriptBufferHandler( + debug, + instanceInfo + ) + ) + + val readNextData = Wire(Bool()) + + val finishedScriptConfiguration = Wire(Bool()) + val configureStage = Wire(Bool()) + val targetOperator = Wire(new HwdbgShortSymbol(instanceInfo.scriptVariableLength)) + + // + // Configure the input signals + // + interpreterScriptBufferHandler.io.en := en + + // + // Configure the input signals related to the receiving signals + // + interpreterScriptBufferHandler.io.dataValidInput := dataValidInput + interpreterScriptBufferHandler.io.receivingData := receivingData + + // + // Configure the output signals + // + readNextData := interpreterScriptBufferHandler.io.readNextData + + // + // Configure the output signals related to configuring stage operators + // + finishedScriptConfiguration := interpreterScriptBufferHandler.io.finishedScriptConfiguration + configureStage := interpreterScriptBufferHandler.io.configureStage + targetOperator := interpreterScriptBufferHandler.io.targetOperator + + // + // Return the output result + // + ( + readNextData, + finishedScriptConfiguration, + configureStage, + targetOperator + ) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/communication/interpreter/send_success_or_error.scala b/hwdbg/src/main/scala/hwdbg/communication/interpreter/send_success_or_error.scala new file mode 100644 index 00000000..5ae70121 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/communication/interpreter/send_success_or_error.scala @@ -0,0 +1,125 @@ +/** + * @file + * send_success_or_error.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Send an indication of invalid packet error or success message (in the interpreter) + * @details + * @version 0.1 + * @date + * 2024-05-04 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.communication.interpreter + +import chisel3._ +import chisel3.util.{switch, is} +import circt.stage.ChiselStage + +import hwdbg.configs._ + +class InterpreterSendSuccessOrError( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + val lastSuccessOrError = Input(UInt(instanceInfo.bramDataWidth.W)) // input last error + + // + // Sending signals + // + val noNewDataSender = Output(Bool()) // should sender finish sending buffers or not? + val dataValidOutput = Output(Bool()) // should sender send next buffer or not? + val sendingData = Output(UInt(instanceInfo.bramDataWidth.W)) // data to be sent to the debugger + + }) + + // + // Output pins + // + val noNewDataSender = WireInit(false.B) + val dataValidOutput = WireInit(false.B) + val sendingData = WireInit(0.U(instanceInfo.bramDataWidth.W)) + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + // + // Set the version + // + sendingData := io.lastSuccessOrError + + // + // Sending the version in one clock cycle + // + noNewDataSender := true.B + dataValidOutput := true.B + + } + + // --------------------------------------------------------------------- + + // + // Connect output pins + // + io.noNewDataSender := noNewDataSender + io.dataValidOutput := dataValidOutput + io.sendingData := sendingData + +} + +object InterpreterSendSuccessOrError { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool, + lastSuccessOrError: UInt + ): (Bool, Bool, UInt) = { + + val interpreterSendSuccessOrError = Module( + new InterpreterSendSuccessOrError( + debug, + instanceInfo + ) + ) + + val noNewDataSender = Wire(Bool()) + val dataValidOutput = Wire(Bool()) + val sendingData = Wire(UInt(instanceInfo.bramDataWidth.W)) + + // + // Configure the input signals + // + interpreterSendSuccessOrError.io.en := en + interpreterSendSuccessOrError.io.lastSuccessOrError := lastSuccessOrError + + // + // Configure the output signals + // + noNewDataSender := interpreterSendSuccessOrError.io.noNewDataSender + dataValidOutput := interpreterSendSuccessOrError.io.dataValidOutput + sendingData := interpreterSendSuccessOrError.io.sendingData + + // + // Return the output result + // + ( + noNewDataSender, + dataValidOutput, + sendingData + ) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/communication/receiver.scala b/hwdbg/src/main/scala/hwdbg/communication/receiver.scala new file mode 100644 index 00000000..e27f9635 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/communication/receiver.scala @@ -0,0 +1,444 @@ +/** + * @file + * receiver.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Remote debugger packet receiver module + * @details + * @version 0.1 + * @date + * 2024-04-08 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.communication + +import chisel3._ +import chisel3.util.{switch, is} +import circt.stage.ChiselStage + +import hwdbg.configs._ +import hwdbg.types._ +import hwdbg.utils._ +import hwdbg.constants._ + +object DebuggerPacketReceiverEnums { + object State extends ChiselEnum { + val sIdle, sReadChecksum, sReadIndicator, sReadTypeOfThePacket, sReadRequestedActionOfThePacket, sRequestedActionIsValid, sWaitToReadActionBuffer, + sReadActionBuffer, sDone = Value + } +} + +class DebuggerPacketReceiver( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + // + // Import state enum + // + import DebuggerPacketReceiverEnums.State + import DebuggerPacketReceiverEnums.State._ + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Interrupt signals (lines) + // Note: Only PL input signal is received here, + // a separate module will control the PS signal + // + val plInSignal = Input(Bool()) // PS to PL signal + + // + // BRAM (Block RAM) ports + // + val rdWrAddr = Output(UInt(instanceInfo.bramAddrWidth.W)) // read/write address + val rdData = Input(UInt(instanceInfo.bramDataWidth.W)) // read data + + // + // Receiving signals + // + val requestedActionOfThePacketOutput = Output(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) // the requested action + val requestedActionOfThePacketOutputValid = Output(Bool()) // whether data on the requested action is valid or not + val noNewDataReceiver = Input(Bool()) // receive done or not? + + // this contains and edge-detection mechanism, which means reader should make it low after reading the data + val readNextData = Input(Bool()) // whether the next data should be read or not? + + val dataValidOutput = Output(Bool()) // whether data on the receiving data line is valid or not? + val receivingData = Output(UInt(instanceInfo.bramDataWidth.W)) // data to be sent to the reader + + val finishedReceivingBuffer = Output(Bool()) // Receiving is done or not? + + }) + + // + // State registers + // + val state = RegInit(sIdle) + + // + // Output pins + // + val rdWrAddr = WireInit(0.U(instanceInfo.bramAddrWidth.W)) + val regRdWrAddr = RegInit(0.U(instanceInfo.bramAddrWidth.W)) + val finishedReceivingBuffer = WireInit(false.B) + val regRequestedActionOfThePacketOutput = RegInit(0.U(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) + val regRequestedActionOfThePacketOutputValid = RegInit(false.B) + val regDataValidOutput = RegInit(false.B) + val regReceivingData = RegInit(0.U(instanceInfo.bramDataWidth.W)) + + // + // Rising-edge detector for start receiving signal + // + val risingEdgePlInSignal = io.plInSignal & !RegNext(io.plInSignal) + + // + // Rising-edge detector for reading next data signal + // + val risingEdgeReadNextData = io.readNextData & !RegNext(io.readNextData) + + // + // Structure (as wire) of the received packet buffer + // + val receivedPacketBuffer = WireInit(0.U.asTypeOf(new DebuggerRemotePacket())) // here the wire is not used + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + switch(state) { + + is(sIdle) { + + // + // Create logs from communication structure offsets + // + LogInfo(debug)(f"The offset of Checksum is 0x${receivedPacketBuffer.Offset.checksum}%x") + LogInfo(debug)(f"The offset of Indicator is 0x${receivedPacketBuffer.Offset.indicator}%x") + LogInfo(debug)(f"The offset of TypeOfThePacket is 0x${receivedPacketBuffer.Offset.typeOfThePacket}%x") + LogInfo(debug)(f"The offset of requestedActionOfThePacketOutput is 0x${receivedPacketBuffer.Offset.requestedActionOfThePacket}%x") + + // + // Check whether the interrupt from the PS is received or not + // + when(risingEdgePlInSignal === true.B) { + state := sReadChecksum + } + + // + // Configure the output pins in case of sIdle + // + rdWrAddr := 0.U + regRequestedActionOfThePacketOutput := 0.U + regRequestedActionOfThePacketOutputValid := false.B + regDataValidOutput := false.B + regReceivingData := 0.U + finishedReceivingBuffer := false.B + + } + is(sReadChecksum) { + + // + // Adjust address to read Checksum from BRAM (Not Used) + // + rdWrAddr := (instanceInfo.debuggerAreaOffset + receivedPacketBuffer.Offset.checksum).U + + // + // Goes to the next section + // + state := sReadIndicator + + } + is(sReadIndicator) { + + // + // Adjust address to read Indicator from BRAM + // + rdWrAddr := (instanceInfo.debuggerAreaOffset + receivedPacketBuffer.Offset.indicator).U + + // + // Goes to the next section + // + state := sReadTypeOfThePacket + + } + is(sReadTypeOfThePacket) { + + // + // Adjust address to read TypeOfThePacket from BRAM + // + rdWrAddr := (instanceInfo.debuggerAreaOffset + receivedPacketBuffer.Offset.typeOfThePacket).U + + // + // Check whether the indicator is valid or not + // + LogInfo(debug)( + f"Comparing first 0x${BitwiseFunction.getBitsInRange(HyperDbgSharedConstants.INDICATOR_OF_HYPERDBG_PACKET, 32, (32 + instanceInfo.bramDataWidth - 1))}%x number of the indicator (little-endian)" + ) + + when( + io.rdData === BitwiseFunction + .getBitsInRange(HyperDbgSharedConstants.INDICATOR_OF_HYPERDBG_PACKET, 32, (32 + instanceInfo.bramDataWidth - 1)) + .U + ) { + + // + // Indicator of packet is valid + // (Goes to the next section) + // + state := sReadRequestedActionOfThePacket + + }.otherwise { + + // + // Indicator of packet is not valid + // (Receiving was done but not found a valid packet, + // so, go to the idle state) + // + state := sDone + } + } + is(sReadRequestedActionOfThePacket) { + + // + // Adjust address to read RequestedActionOfThePacket from BRAM + // + rdWrAddr := (instanceInfo.debuggerAreaOffset + receivedPacketBuffer.Offset.requestedActionOfThePacket).U + + // + // Save the address into a register + // + regRdWrAddr := (instanceInfo.debuggerAreaOffset + receivedPacketBuffer.Offset.requestedActionOfThePacket + (instanceInfo.bramDataWidth >> 3)).U + + // + // Check whether the type of the packet is valid or not + // + val packetType: DebuggerRemotePacketType.Value = DebuggerRemotePacketType.DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL + LogInfo(debug)( + f"Check packet type with DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL (0x${packetType.id}%x)" + ) + when(io.rdData === packetType.id.U) { + + // + // Type of packet is valid + // (Goes to the next section) + // + state := sRequestedActionIsValid + + }.otherwise { + + // + // Type of packet is not valid + // (Receiving was done but not found a valid packet, + // so, go to the idle state) + // + state := sDone + } + + } + is(sRequestedActionIsValid) { + + // + // Read the RequestedActionOfThePacket + // + regRequestedActionOfThePacketOutput := io.rdData + + // + // The RequestedActionOfThePacketOutput is valid from now + // + regRequestedActionOfThePacketOutputValid := true.B + + // + // Goes to the next section + // + state := sWaitToReadActionBuffer + + } + is(sWaitToReadActionBuffer) { + + // + // The value of the received buffer is valid here, however, + // in order to make difference when a new value is read, the + // following signals goes to the off state + // + regDataValidOutput := false.B + + // + // Check if the caller needs to read the next part of + // the block RAM or the receiving data should be finished + // + when(io.noNewDataReceiver === true.B) { + + // + // No new data, the receiving is done + // + state := sDone + + }.elsewhen(risingEdgeReadNextData === true.B) { + + // + // Adjust address to read next data to BRAM + // + rdWrAddr := regRdWrAddr + regRdWrAddr := regRdWrAddr + (instanceInfo.bramDataWidth >> 3).U + + // + // Read the next offset of the buffer + // + state := sReadActionBuffer + + }.otherwise { + + // + // Stay at the same state + // + state := sWaitToReadActionBuffer + } + + } + is(sReadActionBuffer) { + + // + // Data outputs are now valid + // + regDataValidOutput := true.B + + // + // Adjust the read buffer data + // + regReceivingData := io.rdData + + when(io.noNewDataReceiver === true.B) { + + // + // No new data, the receiving is done + // + state := sDone + + }.otherwise { + + // + // Return to the previous state of action + // + state := sWaitToReadActionBuffer + + } + + } + is(sDone) { + + // + // Reset the temporary address holder + // + regRdWrAddr := 0.U + + // + // Requested action buffer and the receiving buffer is no longer valid + // + regRequestedActionOfThePacketOutput := 0.U + regRequestedActionOfThePacketOutputValid := false.B + regReceivingData := 0.U + regDataValidOutput := false.B + + // + // The receiving is done at this stage, either + // was successful or unsuccessful, we'll release the + // sharing bram resource by indicating that the receiving + // module is no longer using the bram line + // + finishedReceivingBuffer := true.B + + // + // Go to the idle state + // + state := sIdle + } + } + } + + // --------------------------------------------------------------------- + + // + // Connect output pins + // + io.rdWrAddr := rdWrAddr + io.requestedActionOfThePacketOutput := regRequestedActionOfThePacketOutput + io.requestedActionOfThePacketOutputValid := regRequestedActionOfThePacketOutputValid + io.dataValidOutput := regDataValidOutput + io.receivingData := regReceivingData + io.finishedReceivingBuffer := finishedReceivingBuffer + +} + +object DebuggerPacketReceiver { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool, + plInSignal: Bool, + rdData: UInt, + noNewDataReceiver: Bool, + readNextData: Bool + ): (UInt, UInt, Bool, Bool, UInt, Bool) = { + + val debuggerPacketReceiver = Module( + new DebuggerPacketReceiver( + debug, + instanceInfo + ) + ) + + val rdWrAddr = Wire(UInt(instanceInfo.bramAddrWidth.W)) + val requestedActionOfThePacketOutput = Wire(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) + val requestedActionOfThePacketOutputValid = Wire(Bool()) + val dataValidOutput = Wire(Bool()) + val receivingData = Wire(UInt(instanceInfo.bramDataWidth.W)) + val finishedReceivingBuffer = Wire(Bool()) + + // + // Configure the input signals + // + debuggerPacketReceiver.io.en := en + debuggerPacketReceiver.io.plInSignal := plInSignal + debuggerPacketReceiver.io.rdData := rdData + debuggerPacketReceiver.io.noNewDataReceiver := noNewDataReceiver + debuggerPacketReceiver.io.readNextData := readNextData + + // + // Configure the output signals + // + rdWrAddr := debuggerPacketReceiver.io.rdWrAddr + + // + // Configure the output signals related to received packets + // + requestedActionOfThePacketOutput := debuggerPacketReceiver.io.requestedActionOfThePacketOutput + requestedActionOfThePacketOutputValid := debuggerPacketReceiver.io.requestedActionOfThePacketOutputValid + dataValidOutput := debuggerPacketReceiver.io.dataValidOutput + receivingData := debuggerPacketReceiver.io.receivingData + finishedReceivingBuffer := debuggerPacketReceiver.io.finishedReceivingBuffer + + // + // Return the output result + // + ( + rdWrAddr, + requestedActionOfThePacketOutput, + requestedActionOfThePacketOutputValid, + dataValidOutput, + receivingData, + finishedReceivingBuffer + ) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/communication/send_receive_synchronizer.scala b/hwdbg/src/main/scala/hwdbg/communication/send_receive_synchronizer.scala new file mode 100644 index 00000000..4ebf5a74 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/communication/send_receive_synchronizer.scala @@ -0,0 +1,383 @@ +/** + * @file + * send_receive_synchronizer.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Send and receive synchronizer module + * @details + * @version 0.1 + * @date + * 2024-04-17 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.communication + +import chisel3._ +import chisel3.util.{switch, is} +import circt.stage.ChiselStage + +import hwdbg.configs._ +import hwdbg.types._ + +object SendReceiveSynchronizerEnums { + object State extends ChiselEnum { + val sIdle, sReceiver, sSender = Value + } +} + +class SendReceiveSynchronizer( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + // + // Import state enum + // + import SendReceiveSynchronizerEnums.State + import SendReceiveSynchronizerEnums.State._ + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Interrupt signals (lines) + // + val plInSignal = Input(Bool()) // PS to PL signal + val psOutInterrupt = Output(Bool()) // PL to PS interrupt + + // + // BRAM (Block RAM) ports + // + val rdWrAddr = Output(UInt(instanceInfo.bramAddrWidth.W)) // read/write address + val rdData = Input(UInt(instanceInfo.bramDataWidth.W)) // read data + val wrEna = Output(Bool()) // enable writing + val wrData = Output(UInt(instanceInfo.bramDataWidth.W)) // write data + + // + // Receiver ports + // + val requestedActionOfThePacketOutput = Output(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) // the requested action + val requestedActionOfThePacketOutputValid = Output(Bool()) // whether data on the requested action is valid or not + + val noNewDataReceiver = Input(Bool()) // receive done or not? + val readNextData = Input(Bool()) // whether the next data should be read or not? + + val dataValidOutput = Output(Bool()) // whether data on the receiving data line is valid or not? + val receivingData = Output(UInt(instanceInfo.bramDataWidth.W)) // data to be sent to the reader + + // + // Sender ports + // + val beginSendingBuffer = Input(Bool()) // should sender start sending buffers or not? + val noNewDataSender = Input(Bool()) // should sender finish sending buffers or not? + val dataValidInput = Input(Bool()) // should sender send next buffer or not? + + val sendWaitForBuffer = Output(Bool()) // should the external module send next buffer or not? + + val requestedActionOfThePacketInput = Input(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) // the requested action + val sendingData = Input(UInt(instanceInfo.bramDataWidth.W)) // data to be sent to the debugger + + }) + + // + // State registers + // + val state = RegInit(sIdle) + + // + // Saving state of the controlling pins + // + val regPlInSignal = RegInit(false.B) + val regBeginSendingBuffer = RegInit(false.B) + + // + // Shared BRAM pins + // + val sharedRdWrAddr = WireInit(0.U(instanceInfo.bramAddrWidth.W)) // read/write address + val sharedRdData = WireInit(0.U(instanceInfo.bramDataWidth.W)) // read data + val sharedWrEna = WireInit(false.B) // enable writing + val sharedWrData = WireInit(0.U(instanceInfo.bramDataWidth.W)) // write data + + // + // Instantiate the packet receiver module + // + val ( + receiverRdWrAddr, + requestedActionOfThePacketOutput, + requestedActionOfThePacketOutputValid, + dataValidOutput, + receivingData, + finishedReceivingBuffer + ) = + DebuggerPacketReceiver( + debug, + instanceInfo + )( + io.en, + regPlInSignal, + io.rdData, + io.noNewDataReceiver, + io.readNextData + ) + + // + // Instantiate the packet sender module + // + val ( + psOutInterrupt, + senderRdWrAddr, + wrEna, + wrData, + sendWaitForBuffer, + finishedSendingBuffer + ) = + DebuggerPacketSender( + debug, + instanceInfo + )( + io.en, + regBeginSendingBuffer, + io.noNewDataSender, + io.dataValidInput, + io.requestedActionOfThePacketInput, + io.sendingData + ) + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + switch(state) { + + is(sIdle) { + + // + // Perform the resource separation of shared BRAM + // and apply priority to receive over send + // + when(io.plInSignal === true.B) { + + // + // Activate the receiver module + // + regPlInSignal := true.B + + // + // Go to the receiver state + // + state := sReceiver + + }.elsewhen(io.beginSendingBuffer === true.B && io.plInSignal === false.B) { + + // + // Activate the sender module + // + regBeginSendingBuffer := true.B + + // + // Go to the sender state + // + state := sSender + + }.otherwise { + + // + // Stay at the same state as there is no communication + // + state := sIdle + + } + + } + is(sReceiver) { + + // + // Check whether the receiving is finished + // + when(finishedReceivingBuffer === true.B) { + + // + // No longer in the receiver state + // + regPlInSignal := false.B + + // + // Go to the idle state + // + state := sIdle + + }.otherwise { + + // + // Connect the address of BRAM reader to the receiver address + // + sharedRdWrAddr := receiverRdWrAddr + + // + // On the receiver, writing is not allowed + // + sharedWrEna := false.B + + // + // Stay at the same state + // + state := sReceiver + + } + } + is(sSender) { + + // + // Check whether sending data is finished + // + when(finishedSendingBuffer === true.B) { + + // + // No longer in the sender state + // + regBeginSendingBuffer := false.B + + // + // Go to the idle state + // + state := sIdle + + }.otherwise { + + // + // Connect shared BRAM signals to the sender + // + sharedRdWrAddr := senderRdWrAddr + sharedWrEna := wrEna + sharedWrData := wrData + + // + // Stay at the same state + // + state := sSender + + } + } + } + } + + // --------------------------------------------------------------------- + + // + // Connect output pins (Interrupt) + // + io.psOutInterrupt := psOutInterrupt + + // + // Connect output pins (BRAM) + // + io.rdWrAddr := sharedRdWrAddr + io.wrEna := wrEna + io.wrData := wrData + + // + // Connect output pins (Receiver) + // + io.requestedActionOfThePacketOutput := requestedActionOfThePacketOutput + io.requestedActionOfThePacketOutputValid := requestedActionOfThePacketOutputValid + io.dataValidOutput := dataValidOutput + io.receivingData := receivingData + + // + // Connect output pins (Sender) + // + io.sendWaitForBuffer := sendWaitForBuffer + +} + +object SendReceiveSynchronizer { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool, + plInSignal: Bool, + rdData: UInt, + noNewDataReceiver: Bool, + readNextData: Bool, + beginSendingBuffer: Bool, + noNewDataSender: Bool, + dataValidInput: Bool, + requestedActionOfThePacketInput: UInt, + sendingData: UInt + ): (Bool, UInt, Bool, UInt, UInt, Bool, Bool, UInt, Bool) = { + + val sendReceiveSynchronizerModule = Module( + new SendReceiveSynchronizer( + debug, + instanceInfo + ) + ) + + val psOutInterrupt = Wire(Bool()) + + val rdWrAddr = Wire(UInt(instanceInfo.bramAddrWidth.W)) + val wrEna = Wire(Bool()) + val wrData = Wire(UInt(instanceInfo.bramDataWidth.W)) + + val requestedActionOfThePacketOutput = Wire(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) + val requestedActionOfThePacketOutputValid = Wire(Bool()) + val dataValidOutput = Wire(Bool()) + val receivingData = Wire(UInt(instanceInfo.bramDataWidth.W)) + + val sendWaitForBuffer = Wire(Bool()) + + // + // Configure the input signals + // + sendReceiveSynchronizerModule.io.en := en + sendReceiveSynchronizerModule.io.plInSignal := plInSignal + sendReceiveSynchronizerModule.io.rdData := rdData + sendReceiveSynchronizerModule.io.noNewDataReceiver := noNewDataReceiver + sendReceiveSynchronizerModule.io.readNextData := readNextData + sendReceiveSynchronizerModule.io.beginSendingBuffer := beginSendingBuffer + sendReceiveSynchronizerModule.io.noNewDataSender := noNewDataSender + sendReceiveSynchronizerModule.io.dataValidInput := dataValidInput + sendReceiveSynchronizerModule.io.requestedActionOfThePacketInput := requestedActionOfThePacketInput + sendReceiveSynchronizerModule.io.sendingData := sendingData + + // + // Configure the output signals + // + psOutInterrupt := sendReceiveSynchronizerModule.io.psOutInterrupt + rdWrAddr := sendReceiveSynchronizerModule.io.rdWrAddr + wrEna := sendReceiveSynchronizerModule.io.wrEna + wrData := sendReceiveSynchronizerModule.io.wrData + + requestedActionOfThePacketOutput := sendReceiveSynchronizerModule.io.requestedActionOfThePacketOutput + requestedActionOfThePacketOutputValid := sendReceiveSynchronizerModule.io.requestedActionOfThePacketOutputValid + dataValidOutput := sendReceiveSynchronizerModule.io.dataValidOutput + receivingData := sendReceiveSynchronizerModule.io.receivingData + + sendWaitForBuffer := sendReceiveSynchronizerModule.io.sendWaitForBuffer + + // + // Return the output result + // + ( + psOutInterrupt, + rdWrAddr, + wrEna, + wrData, + requestedActionOfThePacketOutput, + requestedActionOfThePacketOutputValid, + dataValidOutput, + receivingData, + sendWaitForBuffer + ) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/communication/sender.scala b/hwdbg/src/main/scala/hwdbg/communication/sender.scala new file mode 100644 index 00000000..e1c049d9 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/communication/sender.scala @@ -0,0 +1,494 @@ +/** + * @file + * sender.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Remote debugger packet sender module + * @details + * @version 0.1 + * @date + * 2024-04-16 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.communication + +import chisel3._ +import chisel3.util.{switch, is, log2Ceil} +import circt.stage.ChiselStage + +import hwdbg.configs._ +import hwdbg.types._ +import hwdbg.constants._ + +object DebuggerPacketSenderEnums { + object State extends ChiselEnum { + val sIdle, sWriteChecksum, sWriteIndicator, sWriteTypeOfThePacket, sWriteRequestedActionOfThePacket, sWaitToGetData, sSendData, sDone = Value + } +} + +class DebuggerPacketSender( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + // + // Import state enum + // + import DebuggerPacketSenderEnums.State + import DebuggerPacketSenderEnums.State._ + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Interrupt signals (lines) + // Note: Only PS output signal is exported here, + // a separate module will control the PL signal + // + val psOutInterrupt = Output(Bool()) // PL to PS interrupt + + // + // BRAM (Block RAM) ports + // + val rdWrAddr = Output(UInt(instanceInfo.bramAddrWidth.W)) // read/write address + val wrEna = Output(Bool()) // enable writing + val wrData = Output(UInt(instanceInfo.bramDataWidth.W)) // write data + + // + // Sending signals + // + val beginSendingBuffer = Input(Bool()) // should sender start sending buffers or not? + val noNewDataSender = Input(Bool()) // should sender finish sending buffers or not? + val dataValidInput = Input(Bool()) // should sender send next buffer or not? + + val sendWaitForBuffer = Output(Bool()) // should the external module send next buffer or not? + val finishedSendingBuffer = Output(Bool()) // indicate that the sender finished sending buffers and ready to send next packet + + val requestedActionOfThePacketInput = Input(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) // the requested action + val sendingData = Input(UInt(instanceInfo.bramDataWidth.W)) // data to be sent to the debugger + + }) + + // + // State registers + // + val state = RegInit(sIdle) + + // + // Output pins + // + val psOutInterrupt = WireInit(false.B) + val wrEna = WireInit(false.B) + val wrData = WireInit(0.U(instanceInfo.bramDataWidth.W)) + val sendWaitForBuffer = WireInit(false.B) + val finishedSendingBuffer = WireInit(false.B) + val rdWrAddr = WireInit(0.U(instanceInfo.bramAddrWidth.W)) + + // + // Temporary address and data holder (register) + // + val regRdWrAddr = RegInit(0.U(instanceInfo.bramAddrWidth.W)) + val regDataToSend = RegInit(0.U(instanceInfo.bramDataWidth.W)) + + // + // Rising-edge detector for start sending signal + // + val risingEdgeBeginSendingBuffer = io.beginSendingBuffer & !RegNext(io.beginSendingBuffer) + + // + // Keeping the state of whether sending data has been started or not + // Means that if the sender is in the middle of sending the headers + // of the packet or the actual data + // + val regIsSendingDataStarted = RegInit(false.B) + + // + // Used to hold the transferred length of the indicator + // + val lengthOfIndicator: Int = new DebuggerRemotePacket().Indicator.getWidth + val regTransferredIndicatorLength = RegInit(0.U((log2Ceil(lengthOfIndicator) + 1).W)) + + // + // Structure (as wire) of the received packet buffer + // + val sendingPacketBuffer = WireInit(0.U.asTypeOf(new DebuggerRemotePacket())) + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + switch(state) { + + is(sIdle) { + + // + // Check whether the interrupt from the PS is received or not + // + when(risingEdgeBeginSendingBuffer === true.B) { + state := sWriteChecksum + } + + // + // Configure the outputs in case of sIdle + // + psOutInterrupt := false.B + rdWrAddr := 0.U + regRdWrAddr := 0.U + wrEna := false.B + wrData := 0.U + sendWaitForBuffer := false.B + finishedSendingBuffer := false.B + + // + // Sending data has not been started + // + regIsSendingDataStarted := false.B + + } + is(sWriteChecksum) { + + // + // Enable writing to the BRAM + // + wrEna := true.B + + // + // Adjust address to write Checksum to BRAM (Not Used) + // + rdWrAddr := (instanceInfo.debuggeeAreaOffset + sendingPacketBuffer.Offset.checksum).U + + // + // Adjust data to write Checksum + // + wrData := 0.U // Checksum is ignored + + // + // Reset the transferred bytes of the indicator + // + regTransferredIndicatorLength := 0.U + + // + // Goes to the next section + // + state := sWriteIndicator + } + is(sWriteIndicator) { + + if (instanceInfo.bramDataWidth >= lengthOfIndicator) { + + // + // Enable writing to the BRAM + // + wrEna := true.B + + // + // Adjust address to write Indicator to BRAM + // + rdWrAddr := (instanceInfo.debuggeeAreaOffset + sendingPacketBuffer.Offset.indicator).U + + // + // Adjust data to write Indicator + // + wrData := HyperDbgSharedConstants.INDICATOR_OF_HYPERDBG_PACKET.U + + // + // Goes to the next section + // + state := sWriteTypeOfThePacket + + } else { + + // + // Enable writing to the BRAM + // + wrEna := true.B + + // + // Adjust address to write Indicator to BRAM (Address granularity is in the byte format so, + // it'll be divided by 8 or shift to right by 3) + // + rdWrAddr := (instanceInfo.debuggeeAreaOffset + sendingPacketBuffer.Offset.indicator).U + (regTransferredIndicatorLength >> 3) + + // + // Adjust data to write Indicator + // + wrData := HyperDbgSharedConstants.INDICATOR_OF_HYPERDBG_PACKET.U >> regTransferredIndicatorLength + + // + // Add to the transferred length + // + regTransferredIndicatorLength := regTransferredIndicatorLength + instanceInfo.bramDataWidth.U + + when(regTransferredIndicatorLength >= lengthOfIndicator.U) { + + // + // Disable writing to the BRAM + // + wrEna := false.B + + // + // Goes to the next section + // + state := sWriteTypeOfThePacket + + }.otherwise { + + // + // Stay at the same state + // + state := sWriteIndicator + } + } + } + is(sWriteTypeOfThePacket) { + + // + // Enable writing to the BRAM + // + wrEna := true.B + + // + // Adjust address to write type of packet to BRAM + // + rdWrAddr := (instanceInfo.debuggeeAreaOffset + sendingPacketBuffer.Offset.typeOfThePacket).U + + // + // Adjust data to write type of packet + // + val packetType: DebuggerRemotePacketType.Value = DebuggerRemotePacketType.DEBUGGEE_TO_DEBUGGER_HARDWARE_LEVEL + wrData := packetType.id.U + + // + // Goes to the next section + // + state := sWriteRequestedActionOfThePacket + + } + is(sWriteRequestedActionOfThePacket) { + + // + // Enable writing to the BRAM + // + wrEna := true.B + + // + // Adjust address to write requested action of packet to BRAM + // + rdWrAddr := (instanceInfo.debuggeeAreaOffset + sendingPacketBuffer.Offset.requestedActionOfThePacket).U + + // + // Adjust data to write requested action of packet + // + wrData := io.requestedActionOfThePacketInput + + // + // Goes to the next section + // + state := sWaitToGetData + + } + is(sWaitToGetData) { + + // + // Disable writing to the BRAM + // + wrEna := false.B + + // + // Indicate that the module is waiting for data + // + sendWaitForBuffer := true.B + + // + // Check whether sending actual data already started or not + // + when(regIsSendingDataStarted === false.B) { + + // + // It's not yet started, so we adjust the address to the start + // of the buffer after the last field of the header + // + regRdWrAddr := (instanceInfo.debuggeeAreaOffset + sendingPacketBuffer.Offset.startOfDataBuffer).U + + // + // Indicate that sending data already started + // + regIsSendingDataStarted := true.B + } + + // + // Wait to receive the data or check whether sending was done at this state + // (Two states will go us to the 'done' state) + // + when(io.noNewDataSender === true.B) { + + // + // Sending data was done + // + state := sDone + + }.elsewhen(io.dataValidInput === true.B) { + + // + // Store the data to send in a register + // + regDataToSend := io.sendingData + + // + // The data is valid, so let's send it + // + state := sSendData + + }.otherwise { + + // + // Stay in the same state as the data is not ready (valid) + // + state := sWaitToGetData + } + + } + is(sSendData) { + + // + // Not waiting for the buffer at this state + // + sendWaitForBuffer := false.B + + // + // Enable writing to the BRAM + // + wrEna := true.B + + // + // Adjust address to write next data to BRAM (Address granularity is in the byte format so, + // it'll be divided by 8 or shift to right by 3) + // + rdWrAddr := regRdWrAddr + regRdWrAddr := regRdWrAddr + (instanceInfo.bramDataWidth >> 3).U + + // + // Adjust data to write as the sending data + // + wrData := regDataToSend + + // + // Check whether sending was done at this state (Two states will go us to the 'done' state) + // + when(io.noNewDataSender === true.B) { + + // + // Sending data was done + // + state := sDone + + }.otherwise { + + // + // Again go to the state for waiting for new data + // + state := sWaitToGetData + + } + + } + is(sDone) { + + // + // Adjust the output bits + // + finishedSendingBuffer := true.B + + // + // Interrupt the PS + // + psOutInterrupt := true.B + + // + // Go to the idle state + // + state := sIdle + } + } + } + + // --------------------------------------------------------------------- + + // + // Connect output pins to internal registers + // + io.psOutInterrupt := psOutInterrupt + io.rdWrAddr := rdWrAddr + io.wrEna := wrEna + io.wrData := wrData + io.sendWaitForBuffer := sendWaitForBuffer + io.finishedSendingBuffer := finishedSendingBuffer + +} + +object DebuggerPacketSender { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool, + beginSendingBuffer: Bool, + noNewDataSender: Bool, + dataValidInput: Bool, + requestedActionOfThePacketInput: UInt, + sendingData: UInt + ): (Bool, UInt, Bool, UInt, Bool, Bool) = { + + val debuggerPacketSender = Module( + new DebuggerPacketSender( + debug, + instanceInfo + ) + ) + + val psOutInterrupt = Wire(Bool()) + val rdWrAddr = Wire(UInt(instanceInfo.bramAddrWidth.W)) + val wrEna = Wire(Bool()) + val wrData = Wire(UInt(instanceInfo.bramDataWidth.W)) + val sendWaitForBuffer = Wire(Bool()) + val finishedSendingBuffer = Wire(Bool()) + + // + // Configure the input signals + // + debuggerPacketSender.io.en := en + debuggerPacketSender.io.beginSendingBuffer := beginSendingBuffer + debuggerPacketSender.io.noNewDataSender := noNewDataSender + debuggerPacketSender.io.dataValidInput := dataValidInput + debuggerPacketSender.io.requestedActionOfThePacketInput := requestedActionOfThePacketInput + debuggerPacketSender.io.sendingData := sendingData + + // + // Configure the output signals + // + psOutInterrupt := debuggerPacketSender.io.psOutInterrupt + rdWrAddr := debuggerPacketSender.io.rdWrAddr + wrEna := debuggerPacketSender.io.wrEna + wrData := debuggerPacketSender.io.wrData + + // + // Configure the output signals related to sending packets + // + sendWaitForBuffer := debuggerPacketSender.io.sendWaitForBuffer + finishedSendingBuffer := debuggerPacketSender.io.finishedSendingBuffer + + // + // Return the output result + // + (psOutInterrupt, rdWrAddr, wrEna, wrData, sendWaitForBuffer, finishedSendingBuffer) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/configs/config.json b/hwdbg/src/main/scala/hwdbg/configs/config.json new file mode 100644 index 00000000..b2fb33f2 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/configs/config.json @@ -0,0 +1,52 @@ +{ + "Version": { + "VERSION_MAJOR": 0, + "VERSION_MINOR": 2, + "VERSION_PATCH": 0 + }, + "DebuggerConfigurations": { + "ENABLE_DEBUG": true, + "NUMBER_OF_PINS": 32, + "PORT_PINS_MAP": [12, 20] + }, + "ScriptEngineConfigurations": { + "MAXIMUM_NUMBER_OF_STAGES": 32, + "MAXIMUM_NUMBER_OF_SUPPORTED_GET_SCRIPT_OPERATORS": 2, + "MAXIMUM_NUMBER_OF_SUPPORTED_SET_SCRIPT_OPERATORS": 1, + "SCRIPT_VARIABLE_LENGTH": 8, + "NUMBER_OF_SUPPORTED_LOCAL_AND_GLOBAL_VARIABLES": 2, + "NUMBER_OF_SUPPORTED_TEMPORARY_VARIABLES": 2, + "SCRIPT_ENGINE_EVAL_CAPABILITIES": [ + "assign_local_global_var", + "assign_registers", + "conditional_statements_and_comparison_operators", + "stack_assignments", + "func_or", + "func_xor", + "func_and", + "func_asl", + "func_add", + "func_sub", + "func_mul", + "func_gt", + "func_lt", + "func_egt", + "func_elt", + "func_equal", + "func_neq", + "func_jmp", + "func_jz", + "func_jnz", + "func_mov" + ] + }, + "MemoryCommunicationConfigurations": { + "BLOCK_RAM_ADDR_WIDTH": 13, + "BLOCK_RAM_DATA_WIDTH": 32, + "ENABLE_BLOCK_RAM_DELAY": true, + "DEFAULT_CONFIGURATION_INITIALIZED_MEMORY_SIZE": 1024, + "BASE_ADDRESS_OF_PS_TO_PL_COMMUNICATION": 0, + "BASE_ADDRESS_OF_PL_TO_PS_COMMUNICATION": 512 + } + } + \ No newline at end of file diff --git a/hwdbg/src/main/scala/hwdbg/configs/configs.scala b/hwdbg/src/main/scala/hwdbg/configs/configs.scala new file mode 100644 index 00000000..a315055b --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/configs/configs.scala @@ -0,0 +1,500 @@ +/** + * @file + * configs.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Configuration files + * @details + * @version 0.1 + * @date + * 2024-04-03 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.configs + +import io.circe._ +import io.circe.parser._ +import io.circe.generic.auto._ +import scala.io.Source + +import chisel3._ +import chisel3.util._ + +import hwdbg.utils._ + +/** + * @brief + * Version of hwdbg (Definition and Default Values) + * @warning + * will be checked with HyperDbg + */ +object Version { + + // + // Constant version info + // + var VERSION_MAJOR: Int = 0 + var VERSION_MINOR: Int = 1 + var VERSION_PATCH: Int = 0 + + def getEncodedVersion: Int = { + (VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | VERSION_PATCH + } + + def extractMajor(encodedVersion: Int): Int = { + encodedVersion >> 16 + } + + def extractMinor(encodedVersion: Int): Int = { + (encodedVersion >> 8) & 0xff // Masking to get only the 8 bits + } + + def extractPatch(encodedVersion: Int): Int = { + encodedVersion & 0xff // Masking to get only the 8 bits + } +} + +/** + * @brief + * Design constants (Definition and Default Values) + */ +object DebuggerConfigurations { + + // + // whether to enable debug or not + // + var ENABLE_DEBUG: Boolean = true + + // + // Number of input/output pins + // + var NUMBER_OF_PINS: Int = 32 + + // + // The configuration of ports and pins + // + // The following constant shows the key value object of the mappings + // of pins to ports (used for inputs/outputs) + // For example, + // port 0 (in) -> contains 12 pins + // port 1 (in) -> contains 20 pins + // + // var PORT_PINS_MAP: Array[Int] = Array(12, 18, 2) + // var PORT_PINS_MAP: Array[Int] = Array(12, 10, 5, 3, 2) + var PORT_PINS_MAP: Array[Int] = Array(12, 20) +} + +/** + * @brief + * Design constants for script engine (Definition and Default Values) + */ +object ScriptEngineConfigurations { + + // + // Maximum number of stages + // + var MAXIMUM_NUMBER_OF_STAGES: Int = 32 + + // + // Maximum number of stages + // + var MAXIMUM_NUMBER_OF_SUPPORTED_GET_SCRIPT_OPERATORS: Int = 2 // for get values + + // + // Maximum number of stages + // + var MAXIMUM_NUMBER_OF_SUPPORTED_SET_SCRIPT_OPERATORS: Int = 1 // for get value + + // + // Script variable length + // + var SCRIPT_VARIABLE_LENGTH: Int = 8 + + // + // Number supported of local and global variables + // + var NUMBER_OF_SUPPORTED_LOCAL_AND_GLOBAL_VARIABLES: Int = 2 + + // + // Number supported of temporary variables + // + var NUMBER_OF_SUPPORTED_TEMPORARY_VARIABLES: Int = 2 + + // + // Define the capabilities you want to enable + // + var SCRIPT_ENGINE_EVAL_CAPABILITIES = Seq( + // + // Statements and expressions + // + HwdbgScriptCapabilities.assign_local_global_var, + HwdbgScriptCapabilities.assign_registers, + // HwdbgScriptCapabilities.assign_pseudo_registers, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators, + HwdbgScriptCapabilities.stack_assignments, + + // + // Operators + // + HwdbgScriptCapabilities.func_or, + HwdbgScriptCapabilities.func_xor, + HwdbgScriptCapabilities.func_and, + HwdbgScriptCapabilities.func_asl, + HwdbgScriptCapabilities.func_add, + HwdbgScriptCapabilities.func_sub, + HwdbgScriptCapabilities.func_mul, + // HwdbgScriptCapabilities.func_div, + // HwdbgScriptCapabilities.func_mod, + HwdbgScriptCapabilities.func_gt, + HwdbgScriptCapabilities.func_lt, + HwdbgScriptCapabilities.func_egt, + HwdbgScriptCapabilities.func_elt, + HwdbgScriptCapabilities.func_equal, + HwdbgScriptCapabilities.func_neq, + HwdbgScriptCapabilities.func_jmp, + HwdbgScriptCapabilities.func_jz, + HwdbgScriptCapabilities.func_jnz, + HwdbgScriptCapabilities.func_mov + // HwdbgScriptCapabilities.func_printf, + ) +} + +/** + * @brief + * The constants for memory communication (Definition and Default Values) + */ +object MemoryCommunicationConfigurations { + + // + // Address width of the Block RAM (BRAM) + // + var BLOCK_RAM_ADDR_WIDTH: Int = 13 + + // + // Data width of the Block RAM (BRAM) + // + var BLOCK_RAM_DATA_WIDTH: Int = 32 + + // + // Emulate block RAM by inferring a register to delay one clock cycle + // + var ENABLE_BLOCK_RAM_DELAY: Boolean = true + + // + // Default number of bytes used in initialized SRAM memory + // + var DEFAULT_CONFIGURATION_INITIALIZED_MEMORY_SIZE: Int = 8192 / 8 // 8 Kilobits + + // + // Base address of PS to PL SRAM communication memory + // + var BASE_ADDRESS_OF_PS_TO_PL_COMMUNICATION: Int = 0 + + // + // Base address of PL to PS SRAM communication memory + // + var BASE_ADDRESS_OF_PL_TO_PS_COMMUNICATION: Int = DEFAULT_CONFIGURATION_INITIALIZED_MEMORY_SIZE / 2 +} + +/** + * @brief + * The structure of script capabilities information in hwdbg + * @details + * Same as _HWDBG_INSTANCE_INFORMATION in HyperDbg + */ +case class HwdbgInstanceInformation( + version: Int, // Target version of HyperDbg (same as hwdbg) + maximumNumberOfStages: Int, // Number of stages that this instance of hwdbg supports (NumberOfSupportedStages == 0 means script engine is disabled) + scriptVariableLength: Int, // Maximum length of variables (and other script elements) + numberOfSupportedLocalAndGlobalVariables: Int, // Number of supported local (and global) variables + numberOfSupportedTemporaryVariables: Int, // Number of supported temporary variables + maximumNumberOfSupportedGetScriptOperators: Int, // Maximum supported GET operators in a single func + maximumNumberOfSupportedSetScriptOperators: Int, // Maximum supported SET operators in a single func + sharedMemorySize: Int, // Size of shared memory + debuggerAreaOffset: Int, // The memory offset of debugger + debuggeeAreaOffset: Int, // The memory offset of debuggee + numberOfPins: Int, // Number of pins + numberOfPorts: Int, // Number of ports + scriptCapabilities: Long, // Capabilities bitmask + bramAddrWidth: Int, // BRAM address width + bramDataWidth: Int, // BRAM data width + portsConfiguration: Array[Int] // Port arrangement +) + +/** + * @brief + * The script engine capabilities (Definition and Default Values) + */ +object HwdbgScriptCapabilities { + + // + // Statements and expressions + // + val assign_local_global_var: Long = 1L << 0 + val assign_registers: Long = 1L << 1 + val assign_pseudo_registers: Long = 1L << 2 + val conditional_statements_and_comparison_operators: Long = 1L << 3 + val stack_assignments: Long = 1L << 4 + + // + // Operators + // + val func_or: Long = 1L << 5 + val func_xor: Long = 1L << 6 + val func_and: Long = 1L << 7 + val func_asr: Long = 1L << 8 + val func_asl: Long = 1L << 9 + val func_add: Long = 1L << 10 + val func_sub: Long = 1L << 11 + val func_mul: Long = 1L << 12 + val func_div: Long = 1L << 13 + val func_mod: Long = 1L << 14 + val func_gt: Long = 1L << 15 + val func_lt: Long = 1L << 16 + val func_egt: Long = 1L << 17 + val func_elt: Long = 1L << 18 + val func_equal: Long = 1L << 19 + val func_neq: Long = 1L << 20 + val func_jmp: Long = 1L << 21 + val func_jz: Long = 1L << 22 + val func_jnz: Long = 1L << 23 + val func_mov: Long = 1L << 24 + val func_printf: Long = 1L << 25 + + def allCapabilities: Seq[Long] = Seq( + assign_local_global_var, + assign_registers, + assign_pseudo_registers, + conditional_statements_and_comparison_operators, + stack_assignments, + func_or, + func_xor, + func_and, + func_asr, + func_asl, + func_add, + func_sub, + func_mul, + func_div, + func_mod, + func_gt, + func_lt, + func_egt, + func_elt, + func_equal, + func_neq, + func_jmp, + func_jz, + func_jnz, + func_mov, + func_printf + ) + + // + // Utility method to create a bitmask from a sequence of capabilities + // + def createCapabilitiesMask(capabilities: Seq[Long]): Long = { + capabilities.foldLeft(0L)(_ | _) + } + + // + // Function to check if a capability is supported + // + def isCapabilitySupported(supportedCapabilities: Long, capability: Long): Boolean = { + (supportedCapabilities & capability) != 0 + } + +} + +object HwdbgInstanceInformation { + + // + // Function to create an instance of HwdbgInstanceInformation + // + def createInstanceInformation( + version: Int, + maximumNumberOfStages: Int, + scriptVariableLength: Int, + numberOfSupportedLocalAndGlobalVariables: Int, + numberOfSupportedTemporaryVariables: Int, + maximumNumberOfSupportedGetScriptOperators: Int, + maximumNumberOfSupportedSetScriptOperators: Int, + sharedMemorySize: Int, + debuggerAreaOffset: Int, + debuggeeAreaOffset: Int, + numberOfPins: Int, + numberOfPorts: Int, + enabledCapabilities: Seq[Long], + bramAddrWidth: Int, + bramDataWidth: Int, + portsConfiguration: Array[Int] + ): HwdbgInstanceInformation = { + + val capabilitiesMask = HwdbgScriptCapabilities.createCapabilitiesMask(enabledCapabilities) + + // + // Printing the versioning info + // + LogInfo(true)("=======================================================================") + LogInfo(true)( + s"Generating code for hwdbg v${Version.extractMajor(version)}.${Version.extractMinor(version)}.${Version.extractPatch(version)} ($version)" + ) + LogInfo(true)("Please visit https://hwdbg.hyperdbg.org/docs for more information...") + LogInfo(true)("hwdbg is released under the GNU Public License v3 (GPLv3).") + LogInfo(true)("=======================================================================") + + HwdbgInstanceInformation( + version = version, + maximumNumberOfStages = maximumNumberOfStages, + scriptVariableLength = scriptVariableLength, + numberOfSupportedLocalAndGlobalVariables = numberOfSupportedLocalAndGlobalVariables, + numberOfSupportedTemporaryVariables = numberOfSupportedTemporaryVariables, + maximumNumberOfSupportedGetScriptOperators = maximumNumberOfSupportedGetScriptOperators, + maximumNumberOfSupportedSetScriptOperators = maximumNumberOfSupportedSetScriptOperators, + sharedMemorySize = sharedMemorySize, + debuggerAreaOffset = debuggerAreaOffset, + debuggeeAreaOffset = debuggeeAreaOffset, + numberOfPins = numberOfPins, + numberOfPorts = numberOfPorts, + scriptCapabilities = capabilitiesMask, + bramAddrWidth = bramAddrWidth, + bramDataWidth = bramDataWidth, + portsConfiguration = portsConfiguration + ) + } +} + +object ConfigLoader { + + // + // Case classes for each configuration section + // + case class VersionConfig( + VERSION_MAJOR: Int, + VERSION_MINOR: Int, + VERSION_PATCH: Int + ) + case class DebuggerConfigurationsConfig( + ENABLE_DEBUG: Boolean, + NUMBER_OF_PINS: Int, + PORT_PINS_MAP: Array[Int] + ) + case class ScriptEngineConfigurationsConfig( + MAXIMUM_NUMBER_OF_STAGES: Int, + MAXIMUM_NUMBER_OF_SUPPORTED_GET_SCRIPT_OPERATORS: Int, + MAXIMUM_NUMBER_OF_SUPPORTED_SET_SCRIPT_OPERATORS: Int, + SCRIPT_VARIABLE_LENGTH: Int, + NUMBER_OF_SUPPORTED_LOCAL_AND_GLOBAL_VARIABLES: Int, + NUMBER_OF_SUPPORTED_TEMPORARY_VARIABLES: Int, + SCRIPT_ENGINE_EVAL_CAPABILITIES: Seq[String] + ) + case class MemoryCommunicationConfigurationsConfig( + BLOCK_RAM_ADDR_WIDTH: Int, + BLOCK_RAM_DATA_WIDTH: Int, + ENABLE_BLOCK_RAM_DELAY: Boolean, + DEFAULT_CONFIGURATION_INITIALIZED_MEMORY_SIZE: Int, + BASE_ADDRESS_OF_PS_TO_PL_COMMUNICATION: Int, + BASE_ADDRESS_OF_PL_TO_PS_COMMUNICATION: Int + ) + case class FullConfig( + Version: VersionConfig, + DebuggerConfigurations: DebuggerConfigurationsConfig, + ScriptEngineConfigurations: ScriptEngineConfigurationsConfig, + MemoryCommunicationConfigurations: MemoryCommunicationConfigurationsConfig + ) + + // + // Function to load configuration from a JSON file + // + def loadConfig(filePath: String): Option[FullConfig] = { + val source = Source.fromFile(filePath) + val jsonString = try source.getLines().mkString("\n") finally source.close() + + decode[FullConfig](jsonString) match { + case Right(config) => Some(config) + case Left(error) => + println(s"Failed to parse JSON configuration: $error") + None + } + } +} + +object LoadConfiguration { + + def loadFromJson(configPath: String): Unit = { + + val configOpt = ConfigLoader.loadConfig(configPath) + + configOpt.foreach { config => + + // + // *** Set the values in the respective objects *** + // + + // + // Read the version + // + Version.VERSION_MAJOR = config.Version.VERSION_MAJOR + Version.VERSION_MINOR = config.Version.VERSION_MINOR + Version.VERSION_PATCH = config.Version.VERSION_PATCH + + // + // Read the debugger configurations + // + DebuggerConfigurations.ENABLE_DEBUG = config.DebuggerConfigurations.ENABLE_DEBUG + DebuggerConfigurations.NUMBER_OF_PINS = config.DebuggerConfigurations.NUMBER_OF_PINS + DebuggerConfigurations.PORT_PINS_MAP = config.DebuggerConfigurations.PORT_PINS_MAP + + // + // Read the script engine configurations + // + ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_STAGES = config.ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_STAGES + ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_SUPPORTED_GET_SCRIPT_OPERATORS = config.ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_SUPPORTED_GET_SCRIPT_OPERATORS + ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_SUPPORTED_SET_SCRIPT_OPERATORS = config.ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_SUPPORTED_SET_SCRIPT_OPERATORS + ScriptEngineConfigurations.SCRIPT_VARIABLE_LENGTH = config.ScriptEngineConfigurations.SCRIPT_VARIABLE_LENGTH + ScriptEngineConfigurations.NUMBER_OF_SUPPORTED_LOCAL_AND_GLOBAL_VARIABLES = config.ScriptEngineConfigurations.NUMBER_OF_SUPPORTED_LOCAL_AND_GLOBAL_VARIABLES + ScriptEngineConfigurations.NUMBER_OF_SUPPORTED_TEMPORARY_VARIABLES = config.ScriptEngineConfigurations.NUMBER_OF_SUPPORTED_TEMPORARY_VARIABLES + + // + // Convert string capability names to the corresponding values in HwdbgScriptCapabilities + // + ScriptEngineConfigurations.SCRIPT_ENGINE_EVAL_CAPABILITIES = config.ScriptEngineConfigurations.SCRIPT_ENGINE_EVAL_CAPABILITIES.flatMap { + case "assign_local_global_var" => Some(HwdbgScriptCapabilities.assign_local_global_var) + case "assign_registers" => Some(HwdbgScriptCapabilities.assign_registers) + case "conditional_statements_and_comparison_operators" => Some(HwdbgScriptCapabilities.conditional_statements_and_comparison_operators) + case "stack_assignments" => Some(HwdbgScriptCapabilities.stack_assignments) + case "func_or" => Some(HwdbgScriptCapabilities.func_or) + case "func_xor" => Some(HwdbgScriptCapabilities.func_xor) + case "func_and" => Some(HwdbgScriptCapabilities.func_and) + case "func_asl" => Some(HwdbgScriptCapabilities.func_asl) + case "func_add" => Some(HwdbgScriptCapabilities.func_add) + case "func_sub" => Some(HwdbgScriptCapabilities.func_sub) + case "func_mul" => Some(HwdbgScriptCapabilities.func_mul) + case "func_gt" => Some(HwdbgScriptCapabilities.func_gt) + case "func_lt" => Some(HwdbgScriptCapabilities.func_lt) + case "func_egt" => Some(HwdbgScriptCapabilities.func_egt) + case "func_elt" => Some(HwdbgScriptCapabilities.func_elt) + case "func_equal" => Some(HwdbgScriptCapabilities.func_equal) + case "func_neq" => Some(HwdbgScriptCapabilities.func_neq) + case "func_jmp" => Some(HwdbgScriptCapabilities.func_jmp) + case "func_jz" => Some(HwdbgScriptCapabilities.func_jz) + case "func_jnz" => Some(HwdbgScriptCapabilities.func_jnz) + case "func_mov" => Some(HwdbgScriptCapabilities.func_mov) + case _ => None + } + + // + // Read memory communication configurations + // + MemoryCommunicationConfigurations.BLOCK_RAM_ADDR_WIDTH = config.MemoryCommunicationConfigurations.BLOCK_RAM_ADDR_WIDTH + MemoryCommunicationConfigurations.BLOCK_RAM_DATA_WIDTH = config.MemoryCommunicationConfigurations.BLOCK_RAM_DATA_WIDTH + MemoryCommunicationConfigurations.ENABLE_BLOCK_RAM_DELAY = config.MemoryCommunicationConfigurations.ENABLE_BLOCK_RAM_DELAY + MemoryCommunicationConfigurations.DEFAULT_CONFIGURATION_INITIALIZED_MEMORY_SIZE = config.MemoryCommunicationConfigurations.DEFAULT_CONFIGURATION_INITIALIZED_MEMORY_SIZE + MemoryCommunicationConfigurations.BASE_ADDRESS_OF_PS_TO_PL_COMMUNICATION = config.MemoryCommunicationConfigurations.BASE_ADDRESS_OF_PS_TO_PL_COMMUNICATION + MemoryCommunicationConfigurations.BASE_ADDRESS_OF_PL_TO_PS_COMMUNICATION = config.MemoryCommunicationConfigurations.BASE_ADDRESS_OF_PL_TO_PS_COMMUNICATION + } + } +} \ No newline at end of file diff --git a/hwdbg/src/main/scala/hwdbg/configs/constants.scala b/hwdbg/src/main/scala/hwdbg/configs/constants.scala new file mode 100644 index 00000000..9a4e219d --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/configs/constants.scala @@ -0,0 +1,68 @@ +/** + * @file + * constants.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Constant values + * @details + * @version 0.1 + * @date + * 2024-04-16 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.constants + +import chisel3._ +import chisel3.util._ + +/** + * @brief + * Shared value with HyperDbg + * @warning + * used in HyperDbg + */ +object HyperDbgSharedConstants { + + // + // Constant indicator of a HyperDbg packet + // + val INDICATOR_OF_HYPERDBG_PACKET: Long = 0x4859504552444247L // HYPERDBG = 0x4859504552444247 + +} + +/** + * @brief + * Enumeration for different packet types in HyperDbg packets (DEBUGGER_REMOTE_PACKET_TYPE) + * @warning + * Used in HyperDbg + */ +object DebuggerRemotePacketType extends Enumeration { + + // + // Debugger to debuggee (vmx-root) + // + val DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT = Value(1) + + // + // Debugger to debuggee (user-mode) + // + val DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_USER_MODE = Value(2) + + // + // Debuggee to debugger (user-mode and kernel-mode, vmx-root mode) + // + val DEBUGGEE_TO_DEBUGGER = Value(3) + + // + // Debugger to debuggee (hardware), used in hwdbg + // + val DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL = Value(4) + + // + // Debuggee to debugger (hardware), used in hwdbg + // + val DEBUGGEE_TO_DEBUGGER_HARDWARE_LEVEL = Value(5) +} diff --git a/hwdbg/src/main/scala/hwdbg/configs/test_configs.scala b/hwdbg/src/main/scala/hwdbg/configs/test_configs.scala new file mode 100644 index 00000000..f34ba50e --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/configs/test_configs.scala @@ -0,0 +1,36 @@ +/** + * @file + * configs.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Configuration files for testing hwdbg + * @details + * @version 0.1 + * @date + * 2024-04-15 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.configs + +import chisel3._ +import chisel3.util._ + +/** + * @brief + * The configuration constants for testing + */ +object TestingConfigurations { + + // val BRAM_INITIALIZATION_FILE_PATH: String = "./src/test/bram/instance_info.hex.txt" + val BRAM_INITIALIZATION_FILE_PATH: String = "./src/test/bram/script_buffer.hex.txt" + // val BRAM_INITIALIZATION_FILE_PATH: String = "./src/test/bram/script_conditional_statements_pins.hex.txt" + // val BRAM_INITIALIZATION_FILE_PATH: String = "./src/test/bram/script_simple_pin_assignments.hex.txt" + // val BRAM_INITIALIZATION_FILE_PATH: String = "./src/test/bram/script_simple_port_assignments.hex.txt" + // val BRAM_INITIALIZATION_FILE_PATH: String = "./src/test/bram/script_conditional_statements_ports.hex.txt" + // val BRAM_INITIALIZATION_FILE_PATH: String = "./src/test/bram/script_conditional_statements_ports_with_port_assignments.hex.txt" + // val BRAM_INITIALIZATION_FILE_PATH: String = "./src/test/bram/script_conditional_statement_global_var.txt" + +} diff --git a/hwdbg/src/main/scala/hwdbg/libs/mem/init_mem.scala b/hwdbg/src/main/scala/hwdbg/libs/mem/init_mem.scala new file mode 100644 index 00000000..ba957a7b --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/libs/mem/init_mem.scala @@ -0,0 +1,105 @@ +/** + * @file + * init_mem.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Initialize SRAM memory from a file + * @details + * @version 0.1 + * @date + * 2024-04-03 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.libs.mem + +import chisel3._ +import chisel3.util.experimental.loadMemoryFromFileInline + +import hwdbg.configs._ + +class InitMemInline( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + memoryFile: String, + addrWidth: Int, + width: Int, + size: Int +) extends Module { + + val io = IO(new Bundle { + val enable = Input(Bool()) + val write = Input(Bool()) + val addr = Input(UInt(addrWidth.W)) + val dataIn = Input(UInt(width.W)) + val dataOut = Output(UInt(width.W)) + }) + + val mem = SyncReadMem(size / width, UInt(width.W)) + + // + // Initialize memory + // + if (memoryFile.trim().nonEmpty) { + loadMemoryFromFileInline(mem, memoryFile) + } + + io.dataOut := DontCare + + when(io.enable) { + val rdwrPort = mem(io.addr) + when(io.write) { + rdwrPort := io.dataIn + }.otherwise { + io.dataOut := rdwrPort + } + } +} + +object InitMemInline { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + memoryFile: String, + addrWidth: Int, + width: Int, + size: Int + )( + enable: Bool, + write: Bool, + addr: UInt, + dataIn: UInt + ): UInt = { + + val initMemInlineModule = Module( + new InitMemInline( + debug, + memoryFile, + addrWidth, + width, + size + ) + ) + + val dataOut = Wire(UInt(width.W)) + + // + // Configure the input signals + // + initMemInlineModule.io.enable := enable + initMemInlineModule.io.write := write + initMemInlineModule.io.addr := addr + initMemInlineModule.io.dataIn := dataIn + + // + // Configure the output signals + // + dataOut := initMemInlineModule.io.dataOut + + // + // Return the output result + // + dataOut + } +} diff --git a/hwdbg/src/main/scala/hwdbg/libs/mem/init_reg_mem_from_file.scala b/hwdbg/src/main/scala/hwdbg/libs/mem/init_reg_mem_from_file.scala new file mode 100644 index 00000000..0c5c2475 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/libs/mem/init_reg_mem_from_file.scala @@ -0,0 +1,159 @@ +/** + * @file + * init_reg_mem_from_file.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Initialize registers from a file + * @details + * @version 0.1 + * @date + * 2024-04-14 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.libs.mem + +import scala.collection.mutable.ArrayBuffer +import scala.io.Source + +import chisel3._ + +import hwdbg.utils._ +import hwdbg.configs._ + +object InitRegMemFromFileTools { + def readmemh( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + path: String, + width: Int + ): Seq[UInt] = { + + var counter: Int = 0 + val buffer = new ArrayBuffer[UInt] + for (line <- Source.fromFile(path).getLines()) { + + val tokens: Array[String] = line.split("(//)").map(_.trim) + + if (tokens.nonEmpty && tokens.head != "" && tokens.head.split(";")(0).trim != "") { + + val i = Integer.parseInt(tokens.head.split(";")(0).trim, 16) + + LogInfo(debug)( + f"Initialize memory [${counter}%x]: 0x${i}%x" + ) + + counter = counter + 4 + buffer.append(i.U(width.W)) + } + } + + buffer.toSeq + + } +} + +class InitRegMemFromFile( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + emulateBlockRamDelay: Boolean, + memoryFile: String, + addrWidth: Int, + width: Int, + size: Int +) extends Module { + + val io = IO(new Bundle { + val enable = Input(Bool()) + val write = Input(Bool()) + val addr = Input(UInt(addrWidth.W)) + val dataIn = Input(UInt(width.W)) + val dataOut = Output(UInt(width.W)) + }) + + // + // Not needed to show the BRAM information + // + val mem = RegInit(VecInit(InitRegMemFromFileTools.readmemh(false, memoryFile, width))) + + val actualAddr = Wire(UInt(addrWidth.W)) + val actualData = Wire(UInt(width.W)) + val actualWrite = Wire(Bool()) + + // + // This because the address of the saved registers are using 4 bytes granularities + // E.g., 4 Rsh 2 = 1 | 8 Rsh 2 = 2 | 12 Rsh 2 = 3 + // + if (emulateBlockRamDelay) { + // + // In case, if it is an emulation of BRAM, a one clock delay is injected + // + actualAddr := RegNext(io.addr >> 2) + actualData := RegNext(io.dataIn) + actualWrite := RegNext(io.write) + } else { + actualAddr := io.addr >> 2 + actualData := io.dataIn + actualWrite := io.write + } + + when(io.enable) { + val rdwrPort = mem(actualAddr) + io.dataOut := rdwrPort + + when(actualWrite) { + mem(actualAddr) := actualData + } + }.otherwise { + io.dataOut := 0.U + } +} + +object InitRegMemFromFile { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + emulateBlockRamDelay: Boolean, + memoryFile: String, + addrWidth: Int, + width: Int, + size: Int + )( + enable: Bool, + write: Bool, + addr: UInt, + dataIn: UInt + ): UInt = { + + val initRegMemFromFileModule = Module( + new InitRegMemFromFile( + debug, + emulateBlockRamDelay, + memoryFile, + addrWidth, + width, + size + ) + ) + + val dataOut = Wire(UInt(width.W)) + + // + // Configure the input signals + // + initRegMemFromFileModule.io.enable := enable + initRegMemFromFileModule.io.write := write + initRegMemFromFileModule.io.addr := addr + initRegMemFromFileModule.io.dataIn := dataIn + + // + // Configure the output signals + // + dataOut := initRegMemFromFileModule.io.dataOut + + // + // Return the output result + // + dataOut + } +} diff --git a/hwdbg/src/main/scala/hwdbg/libs/mux/mux_2_to_1_io.scala b/hwdbg/src/main/scala/hwdbg/libs/mux/mux_2_to_1_io.scala new file mode 100644 index 00000000..a011d9c5 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/libs/mux/mux_2_to_1_io.scala @@ -0,0 +1,73 @@ +/** + * @file + * mux_2_to_1_io.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Implementation of MUX 2 to 1 (I/O) + * @details + * @version 0.1 + * @date + * 2024-05-05 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.libs.mux + +import chisel3._ + +import hwdbg.configs._ + +class Mux2To1IO( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG +) extends Module { + + val io = IO(new Bundle { + + val a = Input(Bool()) + val b = Input(Bool()) + val select = Input(Bool()) + val out = Output(Bool()) + + }) + io.out := io.a & io.select | io.b & (~io.select) + +} + +object Mux2To1IO { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG + )( + a: Bool, + b: Bool, + select: Bool + ): (Bool) = { + + val mux2To1IO = Module( + new Mux2To1IO( + debug + ) + ) + + val out = Wire(Bool()) + + // + // Configure the input signals + // + mux2To1IO.io.a := a + mux2To1IO.io.b := b + mux2To1IO.io.select := select + + // + // Configure the output signals + // + out := mux2To1IO.io.out + + // + // Return the output result + // + out + } +} diff --git a/hwdbg/src/main/scala/hwdbg/libs/mux/mux_2_to_1_lookup.scala b/hwdbg/src/main/scala/hwdbg/libs/mux/mux_2_to_1_lookup.scala new file mode 100644 index 00000000..eeebef43 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/libs/mux/mux_2_to_1_lookup.scala @@ -0,0 +1,80 @@ +/** + * @file + * mux_2_to_1_lookup.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Implementation of MUX 2 to 1 (Mux-Lookup) + * @details + * @version 0.1 + * @date + * 2024-05-05 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.libs.mux + +import chisel3._ +import chisel3.util._ + +import hwdbg.configs._ + +class Mux2To1Lookup( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG +) extends Module { + + val io = IO(new Bundle { + + val a = Input(Bool()) + val b = Input(Bool()) + val select = Input(Bool()) + val out = Output(Bool()) + + }) + + val inputs = Array( + false.B -> io.a, + true.B -> io.b + ) + + io.out := MuxLookup(io.select, io.a)(inputs) + +} + +object Mux2To1Lookup { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG + )( + a: Bool, + b: Bool, + select: Bool + ): (Bool) = { + + val mux2To1Lookup = Module( + new Mux2To1Lookup( + debug + ) + ) + + val out = Wire(Bool()) + + // + // Configure the input signals + // + mux2To1Lookup.io.a := a + mux2To1Lookup.io.b := b + mux2To1Lookup.io.select := select + + // + // Configure the output signals + // + out := mux2To1Lookup.io.out + + // + // Return the output result + // + out + } +} diff --git a/hwdbg/src/main/scala/hwdbg/libs/mux/mux_4_to_1_onehot.scala b/hwdbg/src/main/scala/hwdbg/libs/mux/mux_4_to_1_onehot.scala new file mode 100644 index 00000000..dfa9e0b9 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/libs/mux/mux_4_to_1_onehot.scala @@ -0,0 +1,83 @@ +/** + * @file + * mux_4_to_1_onehot.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Implementation of MUX 4 to 1 (One Hot) + * @details + * @version 0.1 + * @date + * 2024-05-05 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.libs.mux + +import chisel3._ +import chisel3.util._ + +import hwdbg.configs._ + +class Mux4To1OneHot( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + width: Int = 32 +) extends Module { + + val io = IO(new Bundle { + + val in0 = Input(UInt(width.W)) + val in1 = Input(UInt(width.W)) + val in2 = Input(UInt(width.W)) + val in3 = Input(UInt(width.W)) + val sel = Input(UInt(log2Ceil(width).W)) + val out = Output(UInt(width.W)) + + }) + + io.out := Mux1H(io.sel, Seq(io.in0, io.in1, io.in2, io.in3)) + +} + +object Mux4To1OneHot { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + width: Int = 32 + )( + in0: UInt, + in1: UInt, + in2: UInt, + in3: UInt, + sel: UInt + ): (UInt) = { + + val mux4To1OneHot = Module( + new Mux4To1OneHot( + debug + ) + ) + + val out = Wire(UInt(width.W)) + + // + // Configure the input signals + // + mux4To1OneHot.io.in0 := in0 + mux4To1OneHot.io.in1 := in1 + mux4To1OneHot.io.in2 := in2 + mux4To1OneHot.io.in3 := in3 + mux4To1OneHot.io.sel := sel + + // + // Configure the output signals + // + out := mux4To1OneHot.io.out + + // + // Return the output result + // + out + } +} diff --git a/hwdbg/src/main/scala/hwdbg/main.scala b/hwdbg/src/main/scala/hwdbg/main.scala new file mode 100644 index 00000000..87955c35 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/main.scala @@ -0,0 +1,320 @@ +/** + * @file + * main.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * hwdbg's main debugger module + * @details + * @version 0.1 + * @date + * 2024-04-04 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg + +import chisel3._ +import circt.stage.ChiselStage + +import hwdbg.configs._ +import hwdbg.types._ +import hwdbg.utils._ +import hwdbg.script._ +import hwdbg.communication._ +import hwdbg.communication.interpreter._ + +class DebuggerMain( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + numberOfPins: Int, + maximumNumberOfStages: Int, + maximumNumberOfSupportedGetScriptOperators: Int, + maximumNumberOfSupportedSetScriptOperators: Int, + sharedMemorySize: Int, + debuggerAreaOffset: Int, + debuggeeAreaOffset: Int, + scriptVariableLength: Int, + numberOfSupportedLocalAndGlobalVariables: Int, + numberOfSupportedTemporaryVariables: Int, + scriptCapabilities: Seq[Long], + bramAddrWidth: Int, + bramDataWidth: Int, + portsConfiguration: Array[Int] +) extends Module { + + // + // Ensure sum of input port values equals numberOfPins (NUMBER_OF_PINS) + // + require( + portsConfiguration.sum == numberOfPins, + "err, the sum of the portsConfiguration (PORT_PINS_MAP) values must equal the numberOfPins (NUMBER_OF_PINS)." + ) + + // + // Ensure script variable length is not bigger than BRAM data width + // + require( + bramDataWidth >= scriptVariableLength, + "err, the script variable length should not be bigger than BRAM data width." + ) + + // + // Ensure the maximum number of stages is not bigger than the maximum number + // that can be stored within the script variable length. This is because + // if a JUMP for conditional statements wants to set the target location, + // it cannot store its destination in a script variable. + // + require( + maximumNumberOfStages < math.pow(2, scriptVariableLength), + "err, the maximum number of stages should be less than 2 to the power of the script variable length." + ) + + // + // Ensure the number of pin + ports is not bigger than the maximum number + // that can be stored within the script variable length. This is because + // for setting and getting pins/ports values, hwdbg uses an index which + // should fit within a variable size. + // + require( + numberOfPins + portsConfiguration.size < math.pow(2, scriptVariableLength), + "err, the maximum number of pins + ports should be less than 2 to the power of the script variable length." + ) + + // + // Ensure the number of set operators are equal to 1 since otherwise two variables (local, global and + // temp) might be written simultaneously. + // + require( + maximumNumberOfSupportedSetScriptOperators == 1, + "err, the supported number of SET operators can be only 1." + ) + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Input/Output signals + // + val inputPin = Input(Vec(numberOfPins, UInt(1.W))) // input pins + val outputPin = Output(Vec(numberOfPins, UInt(1.W))) // output pins + + // + // Interrupt signals (lines) + // + val plInSignal = Input(Bool()) // PS to PL signal + val psOutInterrupt = Output(Bool()) // PL to PS interrupt + + // + // BRAM (Block RAM) ports + // + val rdWrAddr = Output(UInt(bramAddrWidth.W)) // read/write address + val rdData = Input(UInt(bramDataWidth.W)) // read data + val wrEna = Output(Bool()) // enable writing + val wrData = Output(UInt(bramDataWidth.W)) // write data + + }) + + // + // *** Create an instance of the debugger *** + // + val instanceInfo = HwdbgInstanceInformation.createInstanceInformation( + version = Version.getEncodedVersion, + maximumNumberOfStages = maximumNumberOfStages, + scriptVariableLength = scriptVariableLength, + numberOfSupportedLocalAndGlobalVariables = numberOfSupportedLocalAndGlobalVariables, + numberOfSupportedTemporaryVariables = numberOfSupportedTemporaryVariables, + maximumNumberOfSupportedGetScriptOperators = maximumNumberOfSupportedGetScriptOperators, + maximumNumberOfSupportedSetScriptOperators = maximumNumberOfSupportedSetScriptOperators, + sharedMemorySize = sharedMemorySize, + debuggerAreaOffset = debuggerAreaOffset, + debuggeeAreaOffset = debuggeeAreaOffset, + numberOfPins = numberOfPins, + numberOfPorts = portsConfiguration.size, + enabledCapabilities = scriptCapabilities, + bramAddrWidth = bramAddrWidth, + bramDataWidth = bramDataWidth, + portsConfiguration = portsConfiguration + ) + + // + // Wire signals for the synchronizer + // + val requestedActionOfThePacketOutput = Wire(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) + val requestedActionOfThePacketOutputValid = Wire(Bool()) + val dataValidOutput = Wire(Bool()) + val receivingData = Wire(UInt(bramDataWidth.W)) + val sendWaitForBuffer = Wire(Bool()) + + // ----------------------------------------------------------------------- + // Create instance from interpreter + // + val ( + noNewDataReceiver, + readNextData, + beginSendingBuffer, + noNewDataSender, + dataValidInterpreterOutput, + requestedActionOfThePacketInterpreterOutput, + sendingData, + finishedScriptConfiguration, + configureStage, + targetOperator + ) = + DebuggerPacketInterpreter( + debug, + instanceInfo + )( + io.en, + requestedActionOfThePacketOutput, + requestedActionOfThePacketOutputValid, + dataValidOutput, + receivingData, + sendWaitForBuffer + ) + + // ----------------------------------------------------------------------- + // Create instance from script execution engine + // + val (outputPin) = + ScriptExecutionEngine( + debug, + instanceInfo + )( + io.en, + finishedScriptConfiguration, + configureStage, + targetOperator, + io.inputPin + ) + + // ----------------------------------------------------------------------- + // Create instance from synchronizer + // + val ( + psOutInterrupt, + rdWrAddr, + wrEna, + wrData, + outRequestedActionOfThePacketOutput, + outRequestedActionOfThePacketOutputValid, + outDataValidOutput, + outReceivingData, + outSendWaitForBuffer + ) = + SendReceiveSynchronizer( + debug, + instanceInfo + )( + io.en, + io.plInSignal, + io.rdData, + noNewDataReceiver, + readNextData, + beginSendingBuffer, + noNewDataSender, + dataValidInterpreterOutput, + requestedActionOfThePacketInterpreterOutput, + sendingData + ) + + // ----------------------------------------------------------------------- + // Connect synchronizer signals to wires + // + requestedActionOfThePacketOutput := outRequestedActionOfThePacketOutput + requestedActionOfThePacketOutputValid := outRequestedActionOfThePacketOutputValid + dataValidOutput := outDataValidOutput + receivingData := outReceivingData + sendWaitForBuffer := outSendWaitForBuffer + + // ----------------------------------------------------------------------- + // Configure the output signals + // + io.wrEna := wrEna + io.wrData := wrData + io.rdWrAddr := rdWrAddr + + io.outputPin := outputPin + + io.psOutInterrupt := psOutInterrupt + +} + +object DebuggerMain { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + numberOfPins: Int, + maximumNumberOfStages: Int, + maximumNumberOfSupportedGetScriptOperators: Int, + maximumNumberOfSupportedSetScriptOperators: Int, + sharedMemorySize: Int, + debuggerAreaOffset: Int, + debuggeeAreaOffset: Int, + scriptVariableLength: Int, + numberOfSupportedLocalAndGlobalVariables: Int, + numberOfSupportedTemporaryVariables: Int, + scriptCapabilities: Seq[Long], + bramAddrWidth: Int, + bramDataWidth: Int, + portsConfiguration: Array[Int] + )( + en: Bool, + inputPin: Vec[UInt], + plInSignal: Bool, + rdData: UInt + ): (Vec[UInt], Bool, UInt, Bool, UInt) = { + + val debuggerMainModule = Module( + new DebuggerMain( + debug, + numberOfPins, + maximumNumberOfStages, + maximumNumberOfSupportedGetScriptOperators, + maximumNumberOfSupportedSetScriptOperators, + sharedMemorySize, + debuggerAreaOffset, + debuggeeAreaOffset, + scriptVariableLength, + numberOfSupportedLocalAndGlobalVariables, + numberOfSupportedTemporaryVariables, + scriptCapabilities, + bramAddrWidth, + bramDataWidth, + portsConfiguration + ) + ) + + val outputPin = Wire(Vec(numberOfPins, UInt(1.W))) + val psOutInterrupt = Wire(Bool()) + val rdWrAddr = Wire(UInt(bramAddrWidth.W)) + val wrEna = Wire(Bool()) + val wrData = Wire(UInt(bramDataWidth.W)) + + // + // Configure the input signals + // + debuggerMainModule.io.en := en + debuggerMainModule.io.inputPin := inputPin + debuggerMainModule.io.plInSignal := plInSignal + debuggerMainModule.io.rdData := rdData + + // + // Configure the output signals + // + outputPin := debuggerMainModule.io.outputPin + psOutInterrupt := debuggerMainModule.io.psOutInterrupt + rdWrAddr := debuggerMainModule.io.rdWrAddr + wrEna := debuggerMainModule.io.wrEna + wrData := debuggerMainModule.io.wrData + + // + // Return the output result + // + (outputPin, psOutInterrupt, rdWrAddr, wrEna, wrData) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/script/eval.scala b/hwdbg/src/main/scala/hwdbg/script/eval.scala new file mode 100644 index 00000000..2fbb89e9 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/script/eval.scala @@ -0,0 +1,507 @@ +/** + * @file + * eval.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Script execution engine + * @details + * @version 0.1 + * @date + * 2024-05-17 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.script + +import chisel3._ +import chisel3.util._ + +import hwdbg.configs._ +import hwdbg.utils._ +import hwdbg.stage._ + +class ScriptEngineEval( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + // + // Import operators enum + // + import hwdbg.script.ScriptEvalFunc.ScriptOperators + import hwdbg.script.ScriptEvalFunc.ScriptOperators._ + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Stage configuration signals + // + val stageConfig = Input(new Stage(debug, instanceInfo)) + val nextStage = Output( + UInt( + log2Ceil( + instanceInfo.maximumNumberOfStages * (instanceInfo.maximumNumberOfSupportedGetScriptOperators + instanceInfo.maximumNumberOfSupportedSetScriptOperators + 1) + ).W + ) + ) + + // + // Output signals + // + val outputPin = Output(Vec(instanceInfo.numberOfPins, UInt(1.W))) // output pins + val resultingLocalGlobalVariables = Output( + Vec(instanceInfo.numberOfSupportedLocalAndGlobalVariables, UInt(instanceInfo.scriptVariableLength.W)) + ) // output of local (and global) variables + val resultingTempVariables = + Output(Vec(instanceInfo.numberOfSupportedTemporaryVariables, UInt(instanceInfo.scriptVariableLength.W))) // output of temporary variables + }) + + // + // Output pins + // + val nextStage = WireInit( + 0.U( + log2Ceil( + instanceInfo.maximumNumberOfStages * (instanceInfo.maximumNumberOfSupportedGetScriptOperators + instanceInfo.maximumNumberOfSupportedSetScriptOperators + 1) + ).W + ) + ) + + // + // Assign operator value (split the signal into only usable part) + // + LogInfo(debug)("Usable size of Value in the SYMBOL: " + ScriptOperators().getWidth) + val mainOperatorValue = io.stageConfig.stageSymbol.Value(ScriptOperators().getWidth - 1, 0).asTypeOf(ScriptOperators()) + + // ------------------------------------------------------------------------- + // Get value module + // + val getValueModuleOutput = Wire(Vec(instanceInfo.maximumNumberOfSupportedGetScriptOperators, UInt(instanceInfo.scriptVariableLength.W))) + + for (i <- 0 until instanceInfo.maximumNumberOfSupportedGetScriptOperators) { + + getValueModuleOutput(i) := ScriptEngineGetValue( + debug, + instanceInfo + )( + io.en, + io.stageConfig.getOperatorSymbol(i), + io.stageConfig.localGlobalVariables, + io.stageConfig.tempVariables, + io.stageConfig.pinValues + ) + } + + // ------------------------------------------------------------------------- + // *** Implementing the evaluation engine *** + // + // + val srcVal = WireInit(VecInit(Seq.fill(instanceInfo.maximumNumberOfSupportedGetScriptOperators)(0.U(instanceInfo.scriptVariableLength.W)))) + val desVal = WireInit(VecInit(Seq.fill(instanceInfo.maximumNumberOfSupportedSetScriptOperators)(0.U(instanceInfo.scriptVariableLength.W)))) + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + switch(mainOperatorValue) { + + is(sFuncOr) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_or) == true) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) | srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncXor) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_xor) == true) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) ^ srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncAnd) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_and) == true) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) & srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncAsr) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_asr) == true) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) >> srcVal(1)(log2Ceil(instanceInfo.scriptVariableLength), 0) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncAsl) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_asl) == true) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) << srcVal(1)(log2Ceil(instanceInfo.scriptVariableLength), 0) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncAdd) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_add) == true) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) + srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncSub) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_sub) == true) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) - srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncMul) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_mul) == true) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) * srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncDiv) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_div) == true) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) / srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncMod) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_mod) == true) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) % srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncGt) { + if ( + HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_gt) == true && + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) > srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncLt) { + if ( + HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_lt) == true && + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) < srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncEgt) { + if ( + HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_egt) == true && + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) >= srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncElt) { + if ( + HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_egt) == true && + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) <= srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncEqual) { + if ( + HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_equal) == true && + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) === srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncNeq) { + if ( + HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_neq) == true && + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + desVal(0) := srcVal(0) =/= srcVal(1) + + nextStage := io.stageConfig.stageIndex + 4.U // one main operator + two GET operators + one SET operator + } + } + is(sFuncJmp) { + if ( + HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_jmp) == true && + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + + srcVal(0) := getValueModuleOutput(0) + nextStage := srcVal(0) + } + } + is(sFuncJz) { + if ( + HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_jz) == true && + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + when(srcVal(1) === 0.U) { + nextStage := srcVal(0) + }.otherwise { + nextStage := io.stageConfig.stageIndex + 3.U // one main operator + two GET operators + } + } + } + is(sFuncJnz) { + if ( + HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_jnz) == true && + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + + srcVal(0) := getValueModuleOutput(0) + srcVal(1) := getValueModuleOutput(1) + + when(srcVal(1) =/= 0.U) { + nextStage := srcVal(0) + }.otherwise { + nextStage := io.stageConfig.stageIndex + 3.U // one main operator + two GET operators + } + + } + } + is(sFuncMov) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_mov) == true) { + + srcVal(0) := getValueModuleOutput(0) + + desVal(0) := srcVal(0) + + nextStage := io.stageConfig.stageIndex + 3.U // one main operator + one GET operators + one SET operator + } + } + is(sFuncPrintf) { + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.func_printf) == true) { + + // + // To be implemented + // + } + } + } + } + + // ------------------------------------------------------------------------- + // Set value module + // + val setValueModuleInput = Wire(Vec(instanceInfo.maximumNumberOfSupportedSetScriptOperators, Vec(instanceInfo.numberOfPins, UInt(1.W)))) + val outputLocalGlobalVariables = Wire( + Vec( + instanceInfo.maximumNumberOfSupportedSetScriptOperators, + Vec(instanceInfo.numberOfSupportedLocalAndGlobalVariables, UInt(instanceInfo.scriptVariableLength.W)) + ) + ) + val outputTempVariables = Wire( + Vec( + instanceInfo.maximumNumberOfSupportedSetScriptOperators, + Vec(instanceInfo.numberOfSupportedTemporaryVariables, UInt(instanceInfo.scriptVariableLength.W)) + ) + ) + + for (i <- 0 until instanceInfo.maximumNumberOfSupportedSetScriptOperators) { + + val ( + outputPin, + resultingLocalGlobalVariables, + resultingTempVariables + ) = ScriptEngineSetValue( + debug, + instanceInfo + )( + io.en, + io.stageConfig.setOperatorSymbol(i), + io.stageConfig.localGlobalVariables, + io.stageConfig.tempVariables, + desVal(i), + io.stageConfig.pinValues + ) + + // + // Connect SET output pins + // + setValueModuleInput(i) := outputPin + outputLocalGlobalVariables(i) := resultingLocalGlobalVariables + outputTempVariables(i) := resultingTempVariables + } + + // --------------------------------------------------------------------- + + // + // Connect the output signals + // + io.outputPin := setValueModuleInput(0) + io.resultingLocalGlobalVariables := outputLocalGlobalVariables(0) + io.resultingTempVariables := outputTempVariables(0) + io.nextStage := nextStage +} + +object ScriptEngineEval { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool, + stageConfig: Stage + ): (UInt, Vec[UInt], Vec[UInt], Vec[UInt]) = { + + val scriptEngineEvalModule = Module( + new ScriptEngineEval( + debug, + instanceInfo + ) + ) + + val outputPin = Wire(Vec(instanceInfo.numberOfPins, UInt(1.W))) + val resultingLocalGlobalVariables = Wire(Vec(instanceInfo.numberOfSupportedLocalAndGlobalVariables, UInt(instanceInfo.scriptVariableLength.W))) + val resultingTempVariables = Wire(Vec(instanceInfo.numberOfSupportedTemporaryVariables, UInt(instanceInfo.scriptVariableLength.W))) + val nextStage = Wire( + UInt( + log2Ceil( + instanceInfo.maximumNumberOfStages * (instanceInfo.maximumNumberOfSupportedGetScriptOperators + instanceInfo.maximumNumberOfSupportedSetScriptOperators + 1) + ).W + ) + ) + + // + // Configure the input signals + // + scriptEngineEvalModule.io.en := en + scriptEngineEvalModule.io.stageConfig := stageConfig + + // + // Configure the output signals + // + nextStage := scriptEngineEvalModule.io.nextStage + outputPin := scriptEngineEvalModule.io.outputPin + resultingLocalGlobalVariables := scriptEngineEvalModule.io.resultingLocalGlobalVariables + resultingTempVariables := scriptEngineEvalModule.io.resultingTempVariables + + // + // Return the output result + // + ( + nextStage, + outputPin, + resultingLocalGlobalVariables, + resultingTempVariables + ) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/script/exec.scala b/hwdbg/src/main/scala/hwdbg/script/exec.scala new file mode 100644 index 00000000..1fb91e6c --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/script/exec.scala @@ -0,0 +1,373 @@ +/** + * @file + * exec.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Script execution engine + * @details + * @version 0.1 + * @date + * 2024-05-07 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.script + +import chisel3._ +import chisel3.util._ + +import hwdbg.configs._ +import hwdbg.stage._ + +object ScriptExecutionEngineConfigStage { + object State extends ChiselEnum { + val sConfigStageSymbol, sConfigGetSymbol, sConfigSetSymbol = Value + } +} + +class ScriptExecutionEngine( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + // + // Import state enum + // + import ScriptExecutionEngineConfigStage.State + import ScriptExecutionEngineConfigStage.State._ + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Script stage configuration signals + // + val finishedScriptConfiguration = Input(Bool()) // whether script configuration finished or not? + val configureStage = Input(Bool()) // whether the configuration of stage should start or not? + val targetOperator = Input(new HwdbgShortSymbol(instanceInfo.scriptVariableLength)) // Current operator to be configured + + // + // Input/Output signals + // + val inputPin = Input(Vec(instanceInfo.numberOfPins, UInt(1.W))) // input pins + val outputPin = Output(Vec(instanceInfo.numberOfPins, UInt(1.W))) // output pins + }) + + // + // Output pins + // + val outputPin = Wire(Vec(instanceInfo.numberOfPins, UInt(1.W))) + + // + // Stage registers + // + val stageRegs = Reg(Vec(instanceInfo.maximumNumberOfStages, new Stage(debug, instanceInfo))) + + // + // Stage configuration done + // Whether the state are configured or not + // + val stageConfigurationValid = RegInit(false.B) + + // + // Stage configuration registers + // + val configState = RegInit(sConfigStageSymbol) + val configStageNumber = RegInit(0.U(log2Ceil(instanceInfo.maximumNumberOfStages).W)) + + // + // Calculate the maximum of the two values since we only want to use one register for + // both GET and SET + // + val maxOperators = math.max(instanceInfo.maximumNumberOfSupportedGetScriptOperators, instanceInfo.maximumNumberOfSupportedSetScriptOperators) + + // + // Create a register with the width based on the maximum value + // + val configGetSetOperatorNumber = RegInit(0.U(log2Ceil(maxOperators).W)) + val stageIndex = RegInit( + 0.U( + log2Ceil( + instanceInfo.maximumNumberOfStages * (instanceInfo.maximumNumberOfSupportedGetScriptOperators + instanceInfo.maximumNumberOfSupportedSetScriptOperators + 1) + ).W + ) + ) + + // ----------------------------------------------------------------------- + // + // *** Configure stage buffers *** + // + when(io.configureStage === true.B) { + + switch(configState) { + + is(sConfigStageSymbol) { + + // + // Since the chip is in the configuring status, just pass all the input + // to output since the stage data is not valid at this stage + // + stageConfigurationValid := false.B + + // + // Configure the stage symbol (The first symbol is the stage operator) + // + stageRegs(configStageNumber).stageSymbol := io.targetOperator + + // + // Set the stage index + // + stageRegs(configStageNumber).stageIndex := stageIndex // store the stage index + stageRegs(configStageNumber).targetStage := 0.U // reset the target stage + stageIndex := stageIndex + 1.U // increment stage index + + // + // If it is the very first configuration symbol, then we disable all stages + // + when(configStageNumber === 0.U) { + for (i <- 0 until instanceInfo.maximumNumberOfStages) { + stageRegs(i).stageEnable := false.B + } + } + + // + // Going to the next state + // + configState := sConfigGetSymbol + } + is(sConfigGetSymbol) { + + // + // Config GET operator + // + stageRegs(configStageNumber).getOperatorSymbol(configGetSetOperatorNumber) := io.targetOperator + configGetSetOperatorNumber := configGetSetOperatorNumber + 1.U + + // + // Check whether this stage number should be counted in stage indexes or its empty + // + when(io.targetOperator.Type =/= 0.U) { + stageIndex := stageIndex + 1.U + } + + when(configGetSetOperatorNumber === (instanceInfo.maximumNumberOfSupportedGetScriptOperators - 1).U) { + + configGetSetOperatorNumber := 0.U // reset the counter + configState := sConfigSetSymbol // go to the next state + }.otherwise { + configState := sConfigGetSymbol // stay at the same state + } + } + is(sConfigSetSymbol) { + + // + // Config SET operator + // + stageRegs(configStageNumber).setOperatorSymbol(configGetSetOperatorNumber) := io.targetOperator + stageRegs(configStageNumber).stageEnable := true.B // this stage is enabled + configGetSetOperatorNumber := configGetSetOperatorNumber + 1.U + + when(io.targetOperator.Type =/= 0.U) { + stageIndex := stageIndex + 1.U + } + + when(configGetSetOperatorNumber === (instanceInfo.maximumNumberOfSupportedSetScriptOperators - 1).U) { + + configGetSetOperatorNumber := 0.U // reset the counter + + when(io.finishedScriptConfiguration === true.B) { + + // + // Not configuring anymore, reset the stage number + // + configStageNumber := 0.U // reset the stage number + stageIndex := 0.U // reset the stage index + configState := sConfigStageSymbol + + // + // Stage data is now valid and can be used (scripts can apply from now on) + // + stageConfigurationValid := true.B + + }.otherwise { + configStageNumber := configStageNumber + 1.U // Increment the stage number holder of current configuration + configState := sConfigStageSymbol // the next state is again a stage symbol + } + }.otherwise { + configState := sConfigSetSymbol // stay at the same state + } + } + } + } + + // ----------------------------------------------------------------------- + // + // *** Move each register (input vector) to the next stage at each clock *** + // + for (i <- 0 until instanceInfo.maximumNumberOfStages) { + + if (i == 0) { + + // + // At the first stage, the input registers should be passed to the + // first registers set of the stage registers + // + stageRegs(0).pinValues := io.inputPin + + // + // Each pin start initially start from 0th target stage + // + stageRegs(0).targetStage := 0.U + + } else if (i == (instanceInfo.maximumNumberOfStages - 1)) { + + // + // At the last stage, the state registers should be passed to the output + // Note: At this stage script symbol is useless + // + outputPin := stageRegs(i - 1).pinValues + + } else { + + // + // Check if this stage should be ignored (passed to the next stage) or be evaluated + // (i - 1) is because the 0th index registers are used for storing data but the + // script engine assumes that the symbols start from 0, so -1 is used here + // + // Also, if the stage data is valid (configuration applied at least once) + // + when(stageConfigurationValid === true.B && stageRegs(i - 1).stageIndex === stageRegs(i - 1).targetStage && stageRegs(i - 1).stageEnable === true.B) { + + // + // *** Based on target stage, this stage needs evaluation *** + // + + // + // Instantiate an eval engine for this stage + // + val ( + nextStage, + outputPin, + resultingLocalGlobalVariables, + resultingTempVariables + ) = ScriptEngineEval( + debug, + instanceInfo + )( + stageRegs(i - 1).stageEnable, + stageRegs(i - 1) + ) + + // + // At the normal (middle) stage, the result of state registers should be passed to + // the next level of stage registers + // + stageRegs(i).pinValues := outputPin + + // + // Pass the target stage symbol number to the next stage + // + stageRegs(i).targetStage := nextStage + + // + // Pass the local (and global) and temporary variables to the next stage + // + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.assign_local_global_var) == true) { + stageRegs(i).localGlobalVariables := resultingLocalGlobalVariables + } + + if ( + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + stageRegs(i).tempVariables := resultingTempVariables + } + + }.otherwise { + + // + // *** Based on target stage, this stage should be ignore *** + // + + // + // Just pass all the values to the next stage + // + stageRegs(i).pinValues := stageRegs(i - 1).pinValues + stageRegs(i).targetStage := stageRegs(i - 1).targetStage + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.assign_local_global_var) == true) { + stageRegs(i).localGlobalVariables := stageRegs(i - 1).localGlobalVariables + } + + if ( + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + stageRegs(i).tempVariables := stageRegs(i - 1).tempVariables + } + + } + } + } + + // ----------------------------------------------------------------------- + + // + // Connect the output signals + // + io.outputPin := outputPin + +} + +object ScriptExecutionEngine { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool, + finishedScriptConfiguration: Bool, + configureStage: Bool, + targetOperator: HwdbgShortSymbol, + inputPin: Vec[UInt] + ): (Vec[UInt]) = { + + val scriptExecutionEngineModule = Module( + new ScriptExecutionEngine( + debug, + instanceInfo + ) + ) + + val outputPin = Wire(Vec(instanceInfo.numberOfPins, UInt(1.W))) + + // + // Configure the input signals + // + scriptExecutionEngineModule.io.en := en + scriptExecutionEngineModule.io.finishedScriptConfiguration := finishedScriptConfiguration + scriptExecutionEngineModule.io.configureStage := configureStage + scriptExecutionEngineModule.io.targetOperator := targetOperator + scriptExecutionEngineModule.io.inputPin := inputPin + + // + // Configure the output signals + // + outputPin := scriptExecutionEngineModule.io.outputPin + + // + // Return the output result + // + (outputPin) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/script/get_value.scala b/hwdbg/src/main/scala/hwdbg/script/get_value.scala new file mode 100644 index 00000000..a81f475e --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/script/get_value.scala @@ -0,0 +1,238 @@ +/** + * @file + * get_value.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Script engine get value + * @details + * @version 0.1 + * @date + * 2024-05-29 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.script + +import chisel3._ +import chisel3.util._ + +import hwdbg.configs._ +import hwdbg.utils._ +import hwdbg.stage._ + +class ScriptEngineGetValue( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + // + // Import script data types enum + // + import hwdbg.script.ScriptConstantTypes.ScriptDataTypes + import hwdbg.script.ScriptConstantTypes.ScriptDataTypes._ + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Evaluation operator symbol + // + val operator = Input(new HwdbgShortSymbol(instanceInfo.scriptVariableLength)) + + // + // Input variables + // + val localGlobalVariables = + Input(Vec(instanceInfo.numberOfSupportedLocalAndGlobalVariables, UInt(instanceInfo.scriptVariableLength.W))) // Local (and Global) variables + val tempVariables = Input(Vec(instanceInfo.numberOfSupportedTemporaryVariables, UInt(instanceInfo.scriptVariableLength.W))) // Temporary variables + + // + // Input signals + // + val inputPin = Input(Vec(instanceInfo.numberOfPins, UInt(1.W))) // input pins + + // + // Output value + // + val outputValue = Output(UInt(instanceInfo.scriptVariableLength.W)) // output value + }) + + val outputValue = WireInit(0.U(instanceInfo.scriptVariableLength.W)) + + // + // Assign operator type (split the signal into only usable part) + // + LogInfo(debug)("Usable size of Type in the SYMBOL: " + ScriptDataTypes().getWidth) + val mainOperatorType = io.operator.Type(ScriptDataTypes().getWidth - 1, 0).asTypeOf(ScriptDataTypes()) + + // + // *** Implementing the getting data logic *** + // + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + switch(mainOperatorType) { + + is(symbolGlobalIdType) { + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.assign_local_global_var) == true) { + // + // Set output to local (and global) variables + // + outputValue := io.localGlobalVariables(io.operator.Value) + } + } + is(symbolLocalIdType) { + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.assign_local_global_var) == true) { + // + // Set output to local (and global) variables + // + outputValue := io.localGlobalVariables(io.operator.Value) + } + } + is(symbolNumType) { + + // + // Constant value + // + outputValue := io.operator.Value + } + is(symbolRegisterType) { + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.assign_registers) == true) { + + // + // Registers are pins and ports + // + when(instanceInfo.numberOfPins.U > io.operator.Value) { + + // + // *** Used for getting the pin value *** + // + outputValue := io.inputPin(io.operator.Value) + }.otherwise { + + // + // *** Used for getting the port value *** + // + + // + // Create a vector of wires + // + val ports = Wire(Vec(instanceInfo.numberOfPorts, UInt(instanceInfo.scriptVariableLength.W))) + var currentPortIndex: Int = 0 + var currentPortNum: Int = 0 + + // + // Iterate based on port configuration + // + for (port <- instanceInfo.portsConfiguration) { + + LogInfo(debug)(f"connect port(${currentPortIndex}) to inputPin(${currentPortNum} to ${currentPortNum + port}) for SET") + ports(currentPortIndex) := io.inputPin.asUInt(currentPortNum + port - 1, currentPortNum) + + currentPortNum += port + currentPortIndex += 1 + } + + // + // Set the output + // + outputValue := ports(io.operator.Value - instanceInfo.numberOfPins.U) + } + } + } + is(symbolPseudoRegType) { + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.assign_pseudo_registers) == true) { + // + // To be implemented + // + outputValue := 0.U + } + } + is(symbolStackIndexType) { + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.stack_assignments) == true) { + // + // To be implemented + // + outputValue := 0.U // io.inputPin.asUInt + } + } + is(symbolTempType) { + + if ( + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + // + // Set output to temporary variables + // + outputValue := io.tempVariables(io.operator.Value) + } + } + } + } + + // + // Connect the output signals + // + io.outputValue := outputValue + +} + +object ScriptEngineGetValue { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool, + operator: HwdbgShortSymbol, + localGlobalVariables: Vec[UInt], + tempVariables: Vec[UInt], + inputPin: Vec[UInt] + ): (UInt) = { + + val scriptEngineGetValueModule = Module( + new ScriptEngineGetValue( + debug, + instanceInfo + ) + ) + + val outputValue = Wire(UInt(instanceInfo.scriptVariableLength.W)) + + // + // Configure the input signals + // + scriptEngineGetValueModule.io.en := en + scriptEngineGetValueModule.io.operator := operator + scriptEngineGetValueModule.io.localGlobalVariables := localGlobalVariables + scriptEngineGetValueModule.io.tempVariables := tempVariables + scriptEngineGetValueModule.io.inputPin := inputPin + + // + // Configure the output signal + // + outputValue := scriptEngineGetValueModule.io.outputValue + + // + // Return the output result + // + (outputValue) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/script/script_definitions.scala b/hwdbg/src/main/scala/hwdbg/script/script_definitions.scala new file mode 100644 index 00000000..5471e834 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/script/script_definitions.scala @@ -0,0 +1,50 @@ +package hwdbg.script + +import chisel3._ +import chisel3.util._ + +/** + * @brief + * The structure of HWDBG_SHORT_SYMBOL used in script engine of HyperDbg + */ +class HwdbgShortSymbol( + scriptVariableLength: Int +) extends Bundle { + + // + // Ensure that the script variable length is at least 8 bits or 1 byte + // + require( + scriptVariableLength >= 8, + f"err, the minimum script variable length is 8 bits (1 byte)." + ) + + val Type = UInt(scriptVariableLength.W) // long long unsigned is 64 bits but it can be dynamic + val Value = UInt(scriptVariableLength.W) // long long unsigned is 64 bits but it can be dynamic +} + +/** + * @brief + * Constant values for the script engine + */ +object ScriptConstants { + val SYMBOL_MEM_VALID_CHECK_MASK = 1 << 31 + val INVALID = 0x80000000 + val LALR_ACCEPT = 0x7fffffff +} + +/** + * @brief + * Constant type values for the script engine + */ +object ScriptConstantTypes { + object ScriptDataTypes extends ChiselEnum { + val symbolUndefined, symbolGlobalIdType, symbolLocalIdType, symbolNumType, symbolRegisterType, symbolPseudoRegType, symbolSemanticRuleType, symbolTempType, symbolStringType, symbolVariableCountType, symbolInvalid, symbolWstringType, symbolFunctionParameterIdType, symbolReturnAddressType, symbolFunctionParameterType, symbolStackIndexType, symbolStackBaseIndexType, symbolReturnValueType = Value + } +} + +object ScriptEvalFunc { + object ScriptOperators extends ChiselEnum { + val sFuncUndefined, sFuncInc, sFuncDec, sFuncReference, sFuncOr, sFuncXor, sFuncAnd, sFuncAsr, sFuncAsl, sFuncAdd, sFuncSub, sFuncMul, sFuncDiv, sFuncMod, sFuncGt, sFuncLt, sFuncEgt, sFuncElt, sFuncEqual, sFuncNeq, sFuncJmp, sFuncJz, sFuncJnz, sFuncMov, sFuncStart_of_do_while, sFuncStart_of_do_while_commands, sFuncEnd_of_do_while, sFuncStart_of_for, sFuncFor_inc_dec, sFuncStart_of_for_ommands, sFuncEnd_of_if, sFuncIgnore_lvalue, sFuncPush, sFuncPop, sFuncCall, sFuncRet, sFuncPrint, sFuncFormats, sFuncEvent_enable, sFuncEvent_disable, sFuncEvent_clear, sFuncTest_statement, sFuncSpinlock_lock, sFuncSpinlock_unlock, sFuncEvent_sc, sFuncMicrosleep, sFuncPrintf, sFuncPause, sFuncFlush, sFuncEvent_trace_step, sFuncEvent_trace_step_in, sFuncEvent_trace_step_out, sFuncEvent_trace_instrumentation_step, sFuncEvent_trace_instrumentation_step_in, sFuncRdtsc, sFuncRdtscp, sFuncLbr_save, sFuncLbr_dump, sFuncLbr_print, sFuncLbr_restore, sFuncLbr_check, sFuncSpinlock_lock_custom_wait, sFuncEvent_inject, sFuncPoi, sFuncDb, sFuncDd, sFuncDw, sFuncDq, sFuncNeg, sFuncHi, sFuncLow, sFuncNot, sFuncCheck_address, sFuncDisassemble_len, sFuncDisassemble_len32, sFuncDisassemble_len64, sFuncInterlocked_increment, sFuncInterlocked_decrement, sFuncPhysical_to_virtual, sFuncVirtual_to_physical, sFuncPoi_pa, sFuncHi_pa, sFuncLow_pa, sFuncDb_pa, sFuncDd_pa, sFuncDw_pa, sFuncDq_pa, sFuncLbr_restore_by_filter, sFuncEd, sFuncEb, sFuncEq, sFuncInterlocked_exchange, sFuncInterlocked_exchange_add, sFuncEb_pa, sFuncEd_pa, sFuncEq_pa, sFuncInterlocked_compare_exchange, sFuncStrlen, sFuncStrcmp, sFuncMemcmp, sFuncStrncmp, sFuncWcslen, sFuncWcscmp, sFuncEvent_inject_error_code, sFuncMemcpy, sFuncMemcpy_pa, sFuncWcsncmp = Value + } +} \ No newline at end of file diff --git a/hwdbg/src/main/scala/hwdbg/script/set_value.scala b/hwdbg/src/main/scala/hwdbg/script/set_value.scala new file mode 100644 index 00000000..9b5f554d --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/script/set_value.scala @@ -0,0 +1,389 @@ +/** + * @file + * set_value.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Script engine set value + * @details + * @version 0.1 + * @date + * 2024-05-29 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.script + +import chisel3._ +import chisel3.util._ + +import hwdbg.configs._ +import hwdbg.utils._ +import hwdbg.stage._ + +class ScriptEngineSetValue( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Module { + + // + // Import script data types enum + // + import hwdbg.script.ScriptConstantTypes.ScriptDataTypes + import hwdbg.script.ScriptConstantTypes.ScriptDataTypes._ + + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Evaluation operator symbol + // + val operator = Input(new HwdbgShortSymbol(instanceInfo.scriptVariableLength)) + + // + // Input variables + // + val inputLocalGlobalVariables = + Input(Vec(instanceInfo.numberOfSupportedLocalAndGlobalVariables, UInt(instanceInfo.scriptVariableLength.W))) // Local (and Global) variables + val inputTempVariables = + Input(Vec(instanceInfo.numberOfSupportedTemporaryVariables, UInt(instanceInfo.scriptVariableLength.W))) // Temporary variables + + // + // Input value + // + val inputValue = Input(UInt(instanceInfo.scriptVariableLength.W)) // input value + + // + // Output signals + // + val inputPin = Input(Vec(instanceInfo.numberOfPins, UInt(1.W))) // output pins + val outputPin = Output(Vec(instanceInfo.numberOfPins, UInt(1.W))) // output pins + + // + // Output variables + // + val outputLocalGlobalVariables = + Output(Vec(instanceInfo.numberOfSupportedLocalAndGlobalVariables, UInt(instanceInfo.scriptVariableLength.W))) // Local (and Global) variables + val outputTempVariables = + Output(Vec(instanceInfo.numberOfSupportedTemporaryVariables, UInt(instanceInfo.scriptVariableLength.W))) // Temporary variables + + }) + + // + // Temp input + // + val inputLocalGlobalVariables = io.inputLocalGlobalVariables + val inputTempVariables = io.inputTempVariables + val inputPin = io.inputPin.asUInt + + // + // Output pins + // + val outputPin = WireInit(0.U(instanceInfo.numberOfPins.W)) + val outputLocalGlobalVariables = WireInit( + VecInit(Seq.fill(instanceInfo.numberOfSupportedLocalAndGlobalVariables)(0.U(instanceInfo.scriptVariableLength.W))) + ) // Local (and Global) variables + val outputTempVariables = WireInit( + VecInit(Seq.fill(instanceInfo.numberOfSupportedTemporaryVariables)(0.U(instanceInfo.scriptVariableLength.W))) + ) // Temporary variables + + // + // Assign operator type (split the signal into only usable part) + // + LogInfo(debug)("Usable size of Type in the SYMBOL: " + ScriptDataTypes().getWidth) + val mainOperatorType = io.operator.Type(ScriptDataTypes().getWidth - 1, 0).asTypeOf(ScriptDataTypes()) + + // + // *** Implementing the setting data logic *** + // + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + switch(mainOperatorType) { + + is(symbolUndefined) { + + // + // In case of undefined SET value, just pass every input to the next step + // + outputPin := inputPin + outputLocalGlobalVariables := inputLocalGlobalVariables + outputTempVariables := inputTempVariables + + } + is(symbolGlobalIdType) { + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.assign_local_global_var) == true) { + + // + // Set the local (and global) variables + // + outputPin := inputPin + outputLocalGlobalVariables := inputLocalGlobalVariables + outputTempVariables := inputTempVariables + + // + // Set the target variable + // + outputLocalGlobalVariables(io.operator.Value) := io.inputValue + } + + } + is(symbolLocalIdType) { + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.assign_local_global_var) == true) { + // + // Set the target local/global variable + // + outputPin := inputPin + outputLocalGlobalVariables := inputLocalGlobalVariables + outputTempVariables := inputTempVariables + + // + // Set the target local/global variable + // + outputLocalGlobalVariables(io.operator.Value) := io.inputValue + } + + } + is(symbolRegisterType) { + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.assign_registers) == true) { + + when(instanceInfo.numberOfPins.U > io.operator.Value) { + + // + // *** Used for setting the pin value *** + // + + // + // Registers are pins (set the value based on less significant bit) + // + val tempShiftedBit = (1.U << io.operator.Value) + + when(io.inputValue(0) === 1.U) { + outputPin := inputPin | tempShiftedBit; // Set the N-th bit to 1 + }.otherwise { + outputPin := inputPin & ~tempShiftedBit; // Clear the N-th bit to 0 + } + + }.otherwise { + + // + // *** Used for setting the port value *** + // + + // + // Iterate based on port configuration + // + var currentPortNum: Int = 0 + val numPorts = instanceInfo.portsConfiguration.length + + for ((port, index) <- instanceInfo.portsConfiguration.zipWithIndex) { + + LogInfo(debug)(f"========================= port assignment (${index} - port size: ${port}) =========================") + + when(io.operator.Value === (index + instanceInfo.numberOfPins).U) { + + // + // If the current port's bit width is bigger than the script variable length, + // we need to append zero + // + val targetInputValue = WireInit(0.U(port.W)) + + if (port > instanceInfo.scriptVariableLength) { + + // + // Since the port size is bigger than the variable size, + // we need to append zeros to the target value + // + LogInfo(debug)( + f"Appending zeros (${port - instanceInfo.scriptVariableLength}) to input variable (targetInputValue) to support port num: ${index}" + ) + targetInputValue := Cat(io.inputValue, 0.U((port - instanceInfo.scriptVariableLength).W)) + } else { + // + // Since the variable size is bigger than the port size, + // we need only a portion of the input value + // + targetInputValue := io.inputValue(port - 1, 0) + } + + // + // Determine the range of bits to be modified + // + val high = currentPortNum + port - 1 + val low = currentPortNum + + // Create the modified outputPin based on whether it's the first, last or a middle port + val modifiedOutputPin = if (index == 0) { + + // + // First port: keep higher bits unchanged, set lower bits to input value + // + LogInfo(debug)( + f"Set connecting index=${index} - inputPin(${instanceInfo.numberOfPins - 1}, ${high + 1}) + targetInputValue(${port - 1}, 0)" + ) + Cat( + inputPin(instanceInfo.numberOfPins - 1, high + 1), // Bits above the range to keep unchanged + targetInputValue // New value for the specified range + ) + } else if (index == numPorts - 1) { + + // + // Last port: keep lower bits unchanged, set higher bits to input value + // + LogInfo(debug)(f"Set connecting index=${index} - targetInputValue(${port - 1}, 0) + inputPin(${low - 1}, 0)") + Cat( + targetInputValue, // New value for the specified range + inputPin(low - 1, 0) // Bits below the range to keep unchanged + ) + } else { + + // + // Middle port: keep both higher and lower bits unchanged + // + LogInfo(debug)( + f"Set connecting index=${index} - inputPin(${instanceInfo.numberOfPins - 1}, ${high + 1}) + targetInputValue(${port - 1}, 0) + inputPin(${low - 1}, 0)" + ) + Cat( + inputPin(instanceInfo.numberOfPins - 1, high + 1), // Bits above the range to keep unchanged + targetInputValue, // New value for the specified range + inputPin(low - 1, 0) // Bits below the range to keep unchanged + ) + } + + // + // Assign the modified outputPin back to outputPin + // + outputPin := modifiedOutputPin + } + + currentPortNum += port + } + } + + outputLocalGlobalVariables := inputLocalGlobalVariables + outputTempVariables := inputTempVariables + } + } + is(symbolPseudoRegType) { + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.assign_pseudo_registers) == true) { + // + // To be implemented + // + outputPin := 0.U + outputLocalGlobalVariables := inputLocalGlobalVariables + outputTempVariables := inputTempVariables + } + + } + is(symbolStackIndexType) { + + if (HwdbgScriptCapabilities.isCapabilitySupported(instanceInfo.scriptCapabilities, HwdbgScriptCapabilities.stack_assignments) == true) { + // + // To be implemented + // + outputPin := inputPin + outputLocalGlobalVariables := inputLocalGlobalVariables + outputTempVariables := inputTempVariables + } + + } + is(symbolTempType) { + + if ( + HwdbgScriptCapabilities.isCapabilitySupported( + instanceInfo.scriptCapabilities, + HwdbgScriptCapabilities.conditional_statements_and_comparison_operators + ) == true + ) { + // + // Set the temporary variables + // + outputPin := inputPin + outputLocalGlobalVariables := inputLocalGlobalVariables + outputTempVariables := inputTempVariables + + // + // Set the target temporary variable + // + outputTempVariables(io.operator.Value) := io.inputValue + } + } + } + } + + // + // Connect the output signals + // + io.outputLocalGlobalVariables := outputLocalGlobalVariables + io.outputTempVariables := outputTempVariables + + for (i <- 0 until instanceInfo.numberOfPins) { + io.outputPin(i) := outputPin(i) + } + +} + +object ScriptEngineSetValue { + + def apply( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation + )( + en: Bool, + operator: HwdbgShortSymbol, + inputLocalGlobalVariables: Vec[UInt], + inputTempVariables: Vec[UInt], + inputValue: UInt, + inputPin: Vec[UInt] + ): (Vec[UInt], Vec[UInt], Vec[UInt]) = { + + val scriptEngineSetValueModule = Module( + new ScriptEngineSetValue( + debug, + instanceInfo + ) + ) + + val outputPin = Wire(Vec(instanceInfo.numberOfPins, UInt(1.W))) + val outputLocalGlobalVariables = Wire(Vec(instanceInfo.numberOfSupportedLocalAndGlobalVariables, UInt(instanceInfo.scriptVariableLength.W))) + val outputTempVariables = Wire(Vec(instanceInfo.numberOfSupportedTemporaryVariables, UInt(instanceInfo.scriptVariableLength.W))) + + // + // Configure the input signals + // + scriptEngineSetValueModule.io.en := en + scriptEngineSetValueModule.io.operator := operator + scriptEngineSetValueModule.io.inputLocalGlobalVariables := inputLocalGlobalVariables + scriptEngineSetValueModule.io.inputTempVariables := inputTempVariables + scriptEngineSetValueModule.io.inputValue := inputValue + scriptEngineSetValueModule.io.inputPin := inputPin + + // + // Configure the output signal + // + outputPin := scriptEngineSetValueModule.io.outputPin + outputLocalGlobalVariables := scriptEngineSetValueModule.io.outputLocalGlobalVariables + outputTempVariables := scriptEngineSetValueModule.io.outputTempVariables + + // + // Return the output result + // + ( + outputPin, + outputLocalGlobalVariables, + outputTempVariables + ) + } +} diff --git a/hwdbg/src/main/scala/hwdbg/types/communication.scala b/hwdbg/src/main/scala/hwdbg/types/communication.scala new file mode 100644 index 00000000..c0b8ef6b --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/types/communication.scala @@ -0,0 +1,183 @@ +/** + * @file + * communication.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Data types for the communication + * @details + * @version 0.1 + * @date + * 2024-04-08 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.types + +import chisel3._ + +// ----------------------------------------------------------------------- + +// +// Structure in C: +// +// typedef struct _DEBUGGER_REMOTE_PACKET +// { +// BYTE Checksum; +// UINT64 Indicator; /* Shows the type of the packet */ +// DEBUGGER_REMOTE_PACKET_TYPE TypeOfThePacket; +// DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION RequestedActionOfThePacket; +// +// } DEBUGGER_REMOTE_PACKET, *PDEBUGGER_REMOTE_PACKET; +// + +/** + * @brief + * The packet used for communication with the remote debugger + */ +class DebuggerRemotePacket() extends Bundle { + + // + // Structure fields + // + val Checksum = UInt(8.W) // 1 bytes + val Alignment0 = UInt((64 - 8).W) // 7 bytes + val Indicator = UInt(64.W) // 8 bytes + val TypeOfThePacket = UInt(32.W) // 4 bytes + val RequestedActionOfThePacket = UInt(32.W) // 4 bytes + + // + // Offset of structure fields + // + object Offset { + + val checksum = (0) / 8 + + val indicator = (Checksum.getWidth + Alignment0.getWidth) / 8 + + val typeOfThePacket = (Checksum.getWidth + Alignment0.getWidth + Indicator.getWidth) / 8 + + val requestedActionOfThePacket = (Checksum.getWidth + Alignment0.getWidth + Indicator.getWidth + TypeOfThePacket.getWidth) / 8 + + val startOfDataBuffer = + (Checksum.getWidth + Alignment0.getWidth + Indicator.getWidth + TypeOfThePacket.getWidth + RequestedActionOfThePacket.getWidth) / 8 + } +} + +// ----------------------------------------------------------------------- + +// +// Structure in C: +// +// typedef struct _HWDBG_PORT_INFORMATION +// { +// UINT32 CountOfPorts; +// +// /* +// +// Here the pin information details will be available. +// +// UINT32 +// Port Size +// +// */ +// +// } HWDBG_PORT_INFORMATION, *PHWDBG_PORT_INFORMATION; + +/** + * @brief + * The structure of port information in hwdbg + */ +class HwdbgPortInformation() extends Bundle { + + // + // Structure fields + // + val CountOfPorts = UInt(32.W) // 4 bytes + + // + // Offset of structure fields + // + object Offset { + + val countOfPorts = (0) / 8 + } +} + +// ----------------------------------------------------------------------- + +// +// Structure in C: +// +// typedef struct _HWDBG_PORT_INFORMATION_ITEMS +// { +// UINT32 PortIndex; +// +// } HWDBG_PORT_INFORMATION_ITEMS, *PHWDBG_PORT_INFORMATION_ITEMS; + +/** + * @brief + * The structure of port information (each item) in hwdbg + */ +class HwdbgPortInformationItems() extends Bundle { + + // + // Structure fields + // + val PortSize = UInt(32.W) // 4 bytes + + // + // Offset of structure fields + // + object Offset { + + val portSize = (0) / 8 + } +} + +// ----------------------------------------------------------------------- + +/** + * @brief + * Different action of hwdbg (SHARED WITH HYPERDBG) (HWDBG_ACTION_ENUMS) + * @warning + * Used in HyperDbg + */ +object HwdbgActionEnums extends Enumeration { + + val hwdbgActionSendInstanceInfo = Value(1) + val hwdbgActionConfigureScriptBuffer = Value(2) + +} + +// ----------------------------------------------------------------------- + +/** + * @brief + * Different responses of hwdbg (SHARED WITH HYPERDBG) (HWDBG_RESPONSE_ENUMS) + * @warning + * Used in HyperDbg + */ +object HwdbgResponseEnums extends Enumeration { + + val hwdbgResponseSuccessOrErrorMessage = Value(1) + val hwdbgResponseInstanceInfo = Value(2) + +} + +// ----------------------------------------------------------------------- + +/** + * @brief + * Different responses of hwdbg (SHARED WITH HYPERDBG) (HWDBG_ERROR_ENUMS) + * @warning + */ +object HwdbgSuccessOrErrorEnums extends Enumeration { + + val hwdbgOperationWasSuccessful = Value(0x7fffffff) + val hwdbgErrorInvalidPacket = Value(1) + +} + +// ----------------------------------------------------------------------- diff --git a/hwdbg/src/main/scala/hwdbg/types/stage.scala b/hwdbg/src/main/scala/hwdbg/types/stage.scala new file mode 100644 index 00000000..78d0fa39 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/types/stage.scala @@ -0,0 +1,71 @@ +/** + * @file + * stage.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Data types related to stage registers + * @details + * @version 0.1 + * @date + * 2024-05-07 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.stage + +import chisel3._ +import chisel3.util.log2Ceil + +import hwdbg.configs._ +import hwdbg.script._ + +class Stage( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + instanceInfo: HwdbgInstanceInformation +) extends Bundle { + + val pinValues = Vec( + instanceInfo.numberOfPins, + UInt(1.W) + ) // The value of each pin in each stage (should be passed to the next stage) + + val stageSymbol = new HwdbgShortSymbol( + instanceInfo.scriptVariableLength + ) // Interpreted script symbol for the target stage (should NOT be passed to the next stage) + + val getOperatorSymbol = Vec( + instanceInfo.maximumNumberOfSupportedGetScriptOperators, + new HwdbgShortSymbol(instanceInfo.scriptVariableLength) + ) // GET symbol operand (should NOT be passed to the next stage) + + val setOperatorSymbol = Vec( + instanceInfo.maximumNumberOfSupportedSetScriptOperators, + new HwdbgShortSymbol(instanceInfo.scriptVariableLength) + ) // SET symbol operand (should NOT be passed to the next stage) + + val targetStage = UInt( + log2Ceil( + instanceInfo.maximumNumberOfStages * (instanceInfo.maximumNumberOfSupportedGetScriptOperators + instanceInfo.maximumNumberOfSupportedSetScriptOperators + 1) + ).W + ) // Target stage that needs to be executed for the current pin values (should be passed to the next stage) + + val tempVariables = Vec( + instanceInfo.numberOfSupportedTemporaryVariables, + UInt(instanceInfo.scriptVariableLength.W) + ) // Temporary variables + + val localGlobalVariables = Vec( + instanceInfo.numberOfSupportedLocalAndGlobalVariables, + UInt(instanceInfo.scriptVariableLength.W) + ) // Local (and Global) variables + + val stageIndex = UInt( + log2Ceil( + instanceInfo.maximumNumberOfStages * (instanceInfo.maximumNumberOfSupportedGetScriptOperators + instanceInfo.maximumNumberOfSupportedSetScriptOperators + 1) + ).W + ) // Target stage index of the current stage (configured with script configuration and remains constant during execution) + + val stageEnable = Bool() // Target stage is enabled (configured) or not +} diff --git a/hwdbg/src/main/scala/hwdbg/utils/utils.scala b/hwdbg/src/main/scala/hwdbg/utils/utils.scala new file mode 100644 index 00000000..162107d0 --- /dev/null +++ b/hwdbg/src/main/scala/hwdbg/utils/utils.scala @@ -0,0 +1,59 @@ +/** + * @file + * utils.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Different utilities and functionalities + * @details + * @version 0.1 + * @date + * 2024-04-12 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.utils + +import chisel3._ +import chisel3.util._ + +/** + * @brief + * Create logs and debug messages + */ +object LogInfo { + + def apply(debug: Boolean)(message: String): Unit = { + if (debug) { + println("[*] debug msg: " + message) + } + } +} + +object BitwiseFunction { + + def getFirstNBits(num: Long, n: Int): Long = { + + val mask = (1L << n) - 1 // Create a bitmask with the first 'n' bits set to 1 + val shifted = num >>> (java.lang.Long.SIZE - n) // Shift the bits to the right to keep the first 'n' bits + val firstNBits = shifted & mask // Extract the first 'n' bits by performing a bitwise AND operation + + firstNBits + } + + def getBitsInRange(num: Long, start: Int, end: Int): Long = { + + require(start >= 0 && start <= 63, "Starting point must be between 0 and 63") + require(end >= 0 && end <= 63, "Ending point must be between 0 and 63") + require(start <= end, "Starting point must be less than or equal to ending point") + + val numBits = end - start + 1 // Number of bits in the range + val mask = (1L << numBits) - 1 // Create a bitmask with 'numBits' bits set to 1 + val shifted = num >>> (java.lang.Long.SIZE - end - 1) // Shift the bits to the right to align the range with the rightmost position + val bitsInRange = shifted & mask // Extract the bits within the specified range + + bitsInRange + } + +} diff --git a/hwdbg/src/main/scala/top.scala b/hwdbg/src/main/scala/top.scala new file mode 100644 index 00000000..619fe296 --- /dev/null +++ b/hwdbg/src/main/scala/top.scala @@ -0,0 +1,143 @@ +/** + * @file + * top.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * hwdbg's top module + * @details + * @version 0.1 + * @date + * 2024-04-03 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg + +import chisel3._ +import circt.stage.ChiselStage + +import hwdbg._ +import hwdbg.configs._ + +class DebuggerModule( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + numberOfPins: Int, + maximumNumberOfStages: Int, + maximumNumberOfSupportedGetScriptOperators: Int, + maximumNumberOfSupportedSetScriptOperators: Int, + sharedMemorySize: Int, + debuggerAreaOffset: Int, + debuggeeAreaOffset: Int, + scriptVariableLength: Int, + numberOfSupportedLocalAndGlobalVariables: Int, + numberOfSupportedTemporaryVariables: Int, + scriptCapabilities: Seq[Long], + bramAddrWidth: Int, + bramDataWidth: Int, + portsConfiguration: Array[Int] +) extends Module { + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Input/Output signals + // + val inputPin = Input(Vec(numberOfPins, UInt(1.W))) // input pins + val outputPin = Output(Vec(numberOfPins, UInt(1.W))) // output pins + + // + // Interrupt signals (lines) + // + val plInSignal = Input(Bool()) // PS to PL signal + val psOutInterrupt = Output(Bool()) // PL to PS interrupt + + // + // BRAM (Block RAM) ports + // + val rdWrAddr = Output(UInt(bramAddrWidth.W)) // read/write address + val rdData = Input(UInt(bramDataWidth.W)) // read data + val wrEna = Output(Bool()) // enable writing + val wrData = Output(UInt(bramDataWidth.W)) // write data + + }) + + // + // Instantiate the debugger's main module + // + val (outputPin, psOutInterrupt, rdWrAddr, wrEna, wrData) = + DebuggerMain( + debug, + numberOfPins, + maximumNumberOfStages, + maximumNumberOfSupportedGetScriptOperators, + maximumNumberOfSupportedSetScriptOperators, + sharedMemorySize, + debuggerAreaOffset, + debuggeeAreaOffset, + scriptVariableLength, + numberOfSupportedLocalAndGlobalVariables, + numberOfSupportedTemporaryVariables, + scriptCapabilities, + bramAddrWidth, + bramDataWidth, + portsConfiguration + )( + io.en, + io.inputPin, + io.plInSignal, + io.rdData + ) + + io.outputPin := outputPin + io.psOutInterrupt := psOutInterrupt + io.rdWrAddr := rdWrAddr + io.wrEna := wrEna + io.wrData := wrData + +} + +object Main extends App { + + // + // Load configuration from JSON file + // + LoadConfiguration.loadFromJson("src/main/scala/hwdbg/configs/config.json") + + // + // Generate hwdbg verilog files + // + println( + ChiselStage.emitSystemVerilog( + new DebuggerModule( + DebuggerConfigurations.ENABLE_DEBUG, + DebuggerConfigurations.NUMBER_OF_PINS, + ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_STAGES, + ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_SUPPORTED_GET_SCRIPT_OPERATORS, + ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_SUPPORTED_SET_SCRIPT_OPERATORS, + MemoryCommunicationConfigurations.DEFAULT_CONFIGURATION_INITIALIZED_MEMORY_SIZE, + MemoryCommunicationConfigurations.BASE_ADDRESS_OF_PS_TO_PL_COMMUNICATION, + MemoryCommunicationConfigurations.BASE_ADDRESS_OF_PL_TO_PS_COMMUNICATION, + ScriptEngineConfigurations.SCRIPT_VARIABLE_LENGTH, + ScriptEngineConfigurations.NUMBER_OF_SUPPORTED_LOCAL_AND_GLOBAL_VARIABLES, + ScriptEngineConfigurations.NUMBER_OF_SUPPORTED_TEMPORARY_VARIABLES, + ScriptEngineConfigurations.SCRIPT_ENGINE_EVAL_CAPABILITIES, + MemoryCommunicationConfigurations.BLOCK_RAM_ADDR_WIDTH, + MemoryCommunicationConfigurations.BLOCK_RAM_DATA_WIDTH, + DebuggerConfigurations.PORT_PINS_MAP + ), + firtoolOpts = Array( + "-disable-all-randomization", + // "-strip-debug-info", + "--split-verilog", // The intention for this argument (and next argument) is to separate generated files. + "-o", + "generated/" + ) + ) + ) +} diff --git a/hwdbg/src/main/scala/top_test.scala b/hwdbg/src/main/scala/top_test.scala new file mode 100644 index 00000000..dabe92d7 --- /dev/null +++ b/hwdbg/src/main/scala/top_test.scala @@ -0,0 +1,176 @@ +/** + * @file + * top_test.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * hwdbg's top module (with BRAM) for testing + * @details + * @version 0.1 + * @date + * 2024-04-04 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg + +import chisel3._ +import circt.stage.ChiselStage + +import hwdbg._ +import hwdbg.configs._ +import hwdbg.libs.mem._ + +class DebuggerModuleTestingBRAM( + debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, + numberOfPins: Int, + maximumNumberOfStages: Int, + maximumNumberOfSupportedGetScriptOperators: Int, + maximumNumberOfSupportedSetScriptOperators: Int, + sharedMemorySize: Int, + debuggerAreaOffset: Int, + debuggeeAreaOffset: Int, + scriptVariableLength: Int, + numberOfSupportedLocalAndGlobalVariables: Int, + numberOfSupportedTemporaryVariables: Int, + scriptCapabilities: Seq[Long], + bramAddrWidth: Int, + bramDataWidth: Int, + portsConfiguration: Array[Int] +) extends Module { + val io = IO(new Bundle { + + // + // Chip signals + // + val en = Input(Bool()) // chip enable signal + + // + // Input/Output signals + // + val inputPin = Input(Vec(numberOfPins, UInt(1.W))) // input pins + val outputPin = Output(Vec(numberOfPins, UInt(1.W))) // output pins + + // + // Interrupt signals (lines) + // + val plInSignal = Input(Bool()) // PS to PL signal + val psOutInterrupt = Output(Bool()) // PL to PS interrupt + + // + // *** BRAM (Block RAM) ports are initialized from an external file *** + // + + }) + + val bramEn = WireInit(false.B) + val bramWrite = WireInit(false.B) + val bramAddr = WireInit(0.U(bramAddrWidth.W)) + val bramDataIn = WireInit(0.U(bramDataWidth.W)) + + val bramDataOut = WireInit(0.U(bramDataWidth.W)) + + // + // Instantiate the BRAM memory initializer module + // + val dataOut = + InitRegMemFromFile( + debug, + MemoryCommunicationConfigurations.ENABLE_BLOCK_RAM_DELAY, + TestingConfigurations.BRAM_INITIALIZATION_FILE_PATH, + bramAddrWidth, + bramDataWidth, + MemoryCommunicationConfigurations.DEFAULT_CONFIGURATION_INITIALIZED_MEMORY_SIZE + )( + bramEn, + bramWrite, + bramAddr, + bramDataIn + ) + + bramDataOut := dataOut + + // + // Instantiate the debugger's main module + // + val (outputPin, psOutInterrupt, rdWrAddr, wrEna, wrData) = + DebuggerMain( + debug, + numberOfPins, + maximumNumberOfStages, + maximumNumberOfSupportedGetScriptOperators, + maximumNumberOfSupportedSetScriptOperators, + sharedMemorySize, + debuggerAreaOffset, + debuggeeAreaOffset, + scriptVariableLength, + numberOfSupportedLocalAndGlobalVariables, + numberOfSupportedTemporaryVariables, + scriptCapabilities, + bramAddrWidth, + bramDataWidth, + portsConfiguration + )( + io.en, + io.inputPin, + io.plInSignal, + bramDataOut + ) + + // + // Connect BRAM Pins + // + bramEn := io.en // enable BRAM when the main chip enabled + bramAddr := rdWrAddr + bramWrite := wrEna + bramDataIn := wrData + + // + // Connect I/O pins + // + io.outputPin := outputPin + io.psOutInterrupt := psOutInterrupt + +} + +object MainWithInitializedBRAM extends App { + + // + // Load configuration from JSON file + // + LoadConfiguration.loadFromJson("src/main/scala/hwdbg/configs/config.json") + + // + // Generate hwdbg verilog files + // + println( + ChiselStage.emitSystemVerilog( + new DebuggerModuleTestingBRAM( + DebuggerConfigurations.ENABLE_DEBUG, + DebuggerConfigurations.NUMBER_OF_PINS, + ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_STAGES, + ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_SUPPORTED_GET_SCRIPT_OPERATORS, + ScriptEngineConfigurations.MAXIMUM_NUMBER_OF_SUPPORTED_SET_SCRIPT_OPERATORS, + MemoryCommunicationConfigurations.DEFAULT_CONFIGURATION_INITIALIZED_MEMORY_SIZE, + MemoryCommunicationConfigurations.BASE_ADDRESS_OF_PS_TO_PL_COMMUNICATION, + MemoryCommunicationConfigurations.BASE_ADDRESS_OF_PL_TO_PS_COMMUNICATION, + ScriptEngineConfigurations.SCRIPT_VARIABLE_LENGTH, + ScriptEngineConfigurations.NUMBER_OF_SUPPORTED_LOCAL_AND_GLOBAL_VARIABLES, + ScriptEngineConfigurations.NUMBER_OF_SUPPORTED_TEMPORARY_VARIABLES, + ScriptEngineConfigurations.SCRIPT_ENGINE_EVAL_CAPABILITIES, + MemoryCommunicationConfigurations.BLOCK_RAM_ADDR_WIDTH, + MemoryCommunicationConfigurations.BLOCK_RAM_DATA_WIDTH, + DebuggerConfigurations.PORT_PINS_MAP + ), + firtoolOpts = Array( + "-disable-all-randomization", + // "-strip-debug-info", + "--lowering-options=disallowLocalVariables", // because icarus doesn't support 'automatic logic', this option prevents such logics + "--split-verilog", // The intention for this argument (and next argument) is to separate generated files. + "-o", + "generated/" + ) + ) + ) +} diff --git a/hwdbg/src/main/systemverilog/sensors/constraints/top.xdc b/hwdbg/src/main/systemverilog/sensors/constraints/top.xdc new file mode 100644 index 00000000..1c85485d --- /dev/null +++ b/hwdbg/src/main/systemverilog/sensors/constraints/top.xdc @@ -0,0 +1,4620 @@ +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[0]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[10]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[11]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[12]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[13]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[14]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[15]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[16]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[17]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[18]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[19]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[1]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[20]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[21]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[22]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[23]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[24]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[25]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[26]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[27]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[28]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[29]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[2]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[30]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[31]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[3]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[4]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[5]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[6]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[7]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[8]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets UART_FF_INS/RO[9]/ro_fanout_ins[0]/ro_inst[0]/x[2]] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/RO_SENS[5]/FSM_onehot_next_state[1]_i_1__0] +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets {UART_FF_INS/RO[0]/ro_fanout_ins[0]/ro_inst[0]/a}] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[0]/ro_fanout_ins[0]/ro_inst[0]/*] + + +set_property IOSTANDARD DIFF_SSTL12 [get_ports QDR4_CLK_100MHZ_N] +set_property PACKAGE_PIN BJ4 [get_ports QDR4_CLK_100MHZ_P] +set_property PACKAGE_PIN BK3 [get_ports QDR4_CLK_100MHZ_N] +set_property IOSTANDARD DIFF_SSTL12 [get_ports QDR4_CLK_100MHZ_P] + + + +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[0]/ro_inst[0]/a] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[0]/ro_inst[0]/b] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[0]/ro_inst[0]/b_inferred_i_1__510_0[0]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[0]/ro_inst[0]/x[0]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[0]/ro_inst[0]/x[1]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[0]/ro_inst[0]/x[2]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[1]/ro_inst[0]/a] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[1]/ro_inst[0]/b] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[1]/ro_inst[0]/b_inferred_i_1__382_0[0]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[1]/ro_inst[0]/x[0]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[1]/ro_inst[0]/x[1]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[1]/ro_inst[0]/x[2]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[2]/ro_inst[0]/a] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[2]/ro_inst[0]/b] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[2]/ro_inst[0]/b_inferred_i_1__254_0[0]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[2]/ro_inst[0]/x[0]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[2]/ro_inst[0]/x[1]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[2]/ro_inst[0]/x[2]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[3]/ro_inst[0]/a] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[3]/ro_inst[0]/b] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[3]/ro_inst[0]/b_inferred_i_1__126_0[0]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[3]/ro_inst[0]/x[0]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[3]/ro_inst[0]/x[1]] +#set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets design_1_i/PL_CORE_0/inst/UART_FF_INS/RO[3]/ro_inst[0]/x[2]] + + + + +set_property PACKAGE_PIN BH24 [get_ports {led_out_ff[0]}] +set_property IOSTANDARD LVCMOS18 [get_ports {led_out_ff[0]}] +set_property PACKAGE_PIN BG24 [get_ports {led_out_ff[1]}] +set_property IOSTANDARD LVCMOS18 [get_ports {led_out_ff[1]}] +set_property PACKAGE_PIN BG25 [get_ports {led_out_ff[2]}] +set_property IOSTANDARD LVCMOS18 [get_ports {led_out_ff[2]}] +set_property PACKAGE_PIN BF25 [get_ports {led_out_ff[3]}] +set_property IOSTANDARD LVCMOS18 [get_ports {led_out_ff[3]}] + + +#set_property PACKAGE_PIN BP26 [get_ports uart_rx_line_0] +#set_property IOSTANDARD LVCMOS18 [get_ports uart_rx_line_0] +#set_property PACKAGE_PIN BN26 [get_ports uart_tx_line_0] +#set_property IOSTANDARD LVCMOS18 [get_ports uart_tx_line_0] + + + +set_property PACKAGE_PIN BK28 [get_ports uart_rx_line] +set_property IOSTANDARD LVCMOS18 [get_ports uart_rx_line] +set_property PACKAGE_PIN BJ28 [get_ports uart_tx_line] +set_property IOSTANDARD LVCMOS18 [get_ports uart_tx_line] +#set_property PACKAGE_PIN BL26 [get_ports "UART1_RTS_B"] ;# Bank 67 VCCO - VCC1V8 - IO_L8N_T1L_N3_AD5N_67 +#set_property IOSTANDARD LVCMOS18 [get_ports "UART1_RTS_B"] ;# Bank 67 VCCO - VCC1V8 - IO_L8N_T1L_N3_AD5N_67 +#set_property PACKAGE_PIN BL27 [get_ports "UART1_CTS_B"] ;# Bank 67 VCCO - VCC1V8 - IO_L8P_T1L_N2_AD5P_67 +#set_property IOSTANDARD LVCMOS18 [get_ports "UART1_CTS_B"] ;# Bank 67 VCCO - VCC1V8 - IO_L8P_T1L_N2_AD5P_67 + + +#set_property PACKAGE_PIN BP26 [get_ports uart_tx_line_0] +#set_property IOSTANDARD LVCMOS18 [get_ports uart_tx_line_0] +#set_property PACKAGE_PIN BN26 [get_ports uart_rx_line_0] +#set_property IOSTANDARD LVCMOS18 [get_ports uart_rx_line_0] + + + +#set_property USER_SLR_ASSIGNMENT SLR1 [get_cells -hier {*/aes_ht_free/*}] + +#set_property USER_SLR_ASSIGNMENT SLR1 [get_cells -hier -filter {NAME =~ */aes_ht_free}] + +#set_property USER_SLR_ASSIGNMENT SLR1 [get_cells -hier -filter {NAME =~ */aes_ht}] + + +#set_property USER_SLR_ASSIGNMENT SLR2 [get_cells -hier -filter {NAME =~ */ff[0]}] +#set_property USER_SLR_ASSIGNMENT SLR2 [get_cells -hier -filter {NAME =~ */ff[1]}] +#set_property USER_SLR_ASSIGNMENT SLR2 [get_cells -hier -filter {NAME =~ */ff[2]}] +#set_property USER_SLR_ASSIGNMENT SLR2 [get_cells -hier -filter {NAME =~ */ff[3]}] + +#set_property USER_SLR_ASSIGNMENT SLR0 [get_cells -hier -filter {NAME =~ */RO[0]}] +#set_property USER_SLR_ASSIGNMENT SLR0 [get_cells -hier -filter {NAME =~ */RO[1]}] +#set_property USER_SLR_ASSIGNMENT SLR0 [get_cells -hier -filter {NAME =~ */RO[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells -hier -filter {NAME =~ */RO_SENS*}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells uart_rx_line_IBUF_inst] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells uart_tx_line_OBUF_inst] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][0]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][0]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][0]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][0]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][1]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][1]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][1]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][1]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][2]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][2]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][2]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][2]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][3]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][3]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][3]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][3]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][4]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][4]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][4]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][4]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][5]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][5]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][5]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][5]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][6]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][6]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][6]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][6]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_10}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_11}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_12}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_13}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_14}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_15}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_18}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_31}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_32}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_33}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_34}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_37}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_38}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_39}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_40}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_49}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_50}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_51}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_52}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_53}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_54}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_55}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_56}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[0][7]_i_9}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[10][0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[10][1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[10][2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[10][3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[10][4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[10][5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[10][6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[10][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[11][0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[11][1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[11][2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[11][3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[11][4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[11][5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[11][6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[11][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[12][0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[12][1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[12][2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[12][3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[12][4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[12][5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[12][6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[12][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[13][0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[13][1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[13][2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[13][3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[13][4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[13][5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[13][6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[13][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[14][0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[14][1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[14][2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[14][3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[14][4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[14][5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[14][6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[14][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[15][0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[15][1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[15][2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[15][3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[15][4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[15][5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[15][6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[15][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][0]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][0]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][1]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][1]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][2]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][2]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][3]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][3]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][4]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][4]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][5]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][5]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][6]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][6]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][7]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][7]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[1][7]_i_8}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[2][0]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[2][1]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[2][2]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[2][3]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[2][4]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[2][5]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[2][6]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[2][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[3][0]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[3][1]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[3][2]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[3][3]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[3][4]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[3][5]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[3][6]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[3][7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[3][7]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[4][0]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[4][1]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[4][2]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[4][3]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[4][4]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[4][5]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[4][6]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[4][7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[5][0]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[5][1]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[5][2]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[5][3]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[5][4]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[5][5]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[5][6]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[5][7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[6][0]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[6][1]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[6][2]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[6][3]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[6][4]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[6][5]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[6][6]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[6][7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[7][0]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[7][1]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[7][2]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[7][3]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[7][4]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[7][5]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[7][6]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[7][7]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[8][0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[8][1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[8][2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[8][3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[8][4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[8][5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[8][6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[8][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[9][0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[9][1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[9][2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[9][3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[9][4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[9][5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[9][6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data[9][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_length[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_length[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_length[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_length[3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_length[4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_length_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_length_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_length_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_length_reg[3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_length_reg[4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]_i_19}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]_i_20}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]_i_21}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]_i_22}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]_i_23}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]_i_24}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]_i_29}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]_i_30}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]_i_35}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[0][7]_i_36}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[10][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[10][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[10][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[10][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[10][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[10][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[10][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[10][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[11][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[11][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[11][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[11][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[11][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[11][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[11][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[11][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[12][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[12][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[12][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[12][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[12][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[12][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[12][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[12][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[13][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[13][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[13][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[13][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[13][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[13][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[13][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[13][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[14][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[14][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[14][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[14][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[14][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[14][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[14][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[14][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[15][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[15][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[15][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[15][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[15][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[15][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[15][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[15][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[1][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[1][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[1][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[1][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[1][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[1][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[1][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[1][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[2][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[2][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[2][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[2][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[2][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[2][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[2][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[2][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[3][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[3][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[3][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[3][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[3][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[3][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[3][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[3][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[4][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[4][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[4][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[4][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[4][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[4][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[4][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[4][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[5][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[5][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[5][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[5][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[5][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[5][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[5][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[5][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[6][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[6][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[6][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[6][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[6][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[6][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[6][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[6][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[7][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[7][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[7][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[7][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[7][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[7][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[7][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[7][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[8][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[8][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[8][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[8][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[8][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[8][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[8][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[8][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[9][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[9][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[9][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[9][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[9][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[9][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[9][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/uart_tx_data_reg[9][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/uart_tx_en_reg] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[10]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[11]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[12]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[13]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[14]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[15]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[15]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[15]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[16]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[17]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[18]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[19]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[1]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[1]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[20]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[21]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[22]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[24]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[25]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[26]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[27]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[28]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[29]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[30]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[30]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[31]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[31]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[32]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[33]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[34]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[34]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[34]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[35]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[35]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_10}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_11}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_12}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_13}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_14}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_15}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_16}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_166}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_167}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_168}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_169}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_17}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_170}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_171}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_172}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_173}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_174}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_175}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_176}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_177}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_178}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_179}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_18}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_180}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_181}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_182}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_183}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_184}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_185}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_186}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_187}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_188}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_189}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_190}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_191}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_192}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_193}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_194}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_195}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_196}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_197}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_198}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_199}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_20}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_200}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_201}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_202}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_203}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_204}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_205}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_206}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_207}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_208}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_209}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_21}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_210}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_211}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_212}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_213}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_214}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_215}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_216}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_217}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_218}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_219}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_22}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_220}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_221}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_222}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_223}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_224}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_225}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_226}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_227}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_228}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_229}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_230}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_231}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_232}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_233}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_234}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_235}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_236}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_237}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_238}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_239}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_240}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_241}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_242}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_243}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_244}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_245}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_246}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_247}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_248}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_249}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_25}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_250}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_251}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_252}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_253}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_254}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_255}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_256}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_257}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_258}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_259}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_26}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_260}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_261}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_262}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_263}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_264}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_265}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_266}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_267}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_268}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_269}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_27}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_270}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_271}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_272}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_273}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_274}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_275}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_276}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_277}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_278}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_279}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_28}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_280}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_281}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_282}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_283}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_284}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_285}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_286}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_287}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_288}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_289}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_29}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_290}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_291}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_292}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_293}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_30}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_31}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_32}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_33}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_38}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_43}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_54}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_55}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_57}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_58}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_59}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_60}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_61}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_62}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_63}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_64}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_65}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_66}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_8}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[36]_i_9}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[37]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[37]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[8]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state[9]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_100}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_101}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_102}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_103}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_104}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_105}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_106}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_107}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_108}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_109}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_110}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_111}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_112}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_113}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_114}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_115}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_116}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_117}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_118}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_119}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_120}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_121}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_122}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_123}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_124}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_125}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_126}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_127}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_128}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_129}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_130}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_131}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_132}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_133}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_134}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_135}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_136}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_137}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_138}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_139}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_140}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_141}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_142}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_143}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_144}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_145}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_146}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_147}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_148}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_149}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_150}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_151}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_152}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_153}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_154}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_155}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_156}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_157}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_158}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_159}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_160}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_161}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_162}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_163}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_164}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_165}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_34}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_35}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_36}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_37}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_70}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_71}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_72}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_73}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_74}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_75}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_76}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_77}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_78}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_79}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_80}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_81}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_82}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_83}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_84}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_85}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_86}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_87}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_88}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_89}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_90}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_91}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_92}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_93}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_94}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_95}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_96}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_97}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_98}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/FSM_onehot_current_state_reg[36]_i_99}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/GND] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/VCC] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/aes_key[127]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/aes_ptx[127]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/aes_ptx[127]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[10]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[11]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[12]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[13]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[14]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[15]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[16]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[17]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[18]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[19]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[20]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[21]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[22]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[23]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[24]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[25]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[26]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[27]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[28]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[29]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[30]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[31]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[8]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_en[9]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/chain_id_reg[7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/div_frac[31]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/div_int[31]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/div_int[31]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_1] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_10] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_100] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_101] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_102] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_103] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_104] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_105] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_106] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_107] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_108] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_109] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_11] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_110] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_111] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_112] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_113] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_114] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_115] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_116] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_117] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_118] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_119] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_12] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_120] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_121] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_122] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_123] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_124] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_125] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_126] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_127] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_128] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_129] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_13] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_130] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_131] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_132] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_133] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_134] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_135] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_136] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_137] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_138] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_139] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_14] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_140] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_141] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_142] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_143] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_144] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_145] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_146] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_147] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_148] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_149] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_15] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_150] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_151] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_152] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_153] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_154] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_155] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_156] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_157] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_158] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_159] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_16] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_160] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_161] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_162] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_163] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_164] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_165] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_166] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_167] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_168] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_169] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_17] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_170] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_171] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_172] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_173] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_174] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_175] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_176] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_177] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_178] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_179] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_18] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_180] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_181] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_182] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_183] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_184] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_185] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_186] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_187] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_188] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_189] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_19] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_190] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_191] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_192] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_193] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_194] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_195] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_196] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_197] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_198] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_199] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_2] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_20] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_200] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_201] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_202] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_203] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_204] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_205] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_206] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_207] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_208] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_209] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_21] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_210] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_211] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_212] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_213] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_214] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_215] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_216] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_217] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_218] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_219] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_22] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_220] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_221] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_222] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_223] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_224] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_225] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_226] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_227] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_228] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_229] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_23] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_230] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_231] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_232] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_233] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_234] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_235] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_236] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_237] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_238] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_239] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_24] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_240] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_241] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_242] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_243] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_244] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_245] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_246] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_247] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_248] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_249] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_25] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_250] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_251] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_252] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_253] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_254] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_255] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_256] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_257] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_258] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_259] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_26] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_260] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_261] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_262] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_263] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_264] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_265] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_266] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_267] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_268] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_269] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_27] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_270] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_271] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_272] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_273] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_274] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_275] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_276] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_277] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_278] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_279] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_28] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_280] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_281] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_282] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_283] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_284] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_285] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_286] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_287] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_288] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_289] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_29] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_290] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_291] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_292] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_293] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_294] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_295] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_296] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_297] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_298] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_299] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_3] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_30] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_300] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_301] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_302] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_303] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_304] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_305] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_306] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_307] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_308] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_309] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_31] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_310] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_311] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_312] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_313] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_314] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_315] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_316] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_317] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_318] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_319] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_32] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_320] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_321] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_322] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_323] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_324] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_325] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_326] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_327] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_328] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_329] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_33] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_330] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_331] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_332] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_333] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_334] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_335] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_336] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_337] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_338] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_339] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_34] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_340] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_341] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_342] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_343] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_344] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_345] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_346] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_347] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_348] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_349] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_35] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_350] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_351] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_352] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_353] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_354] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_355] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_356] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_357] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_358] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_359] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_36] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_360] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_361] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_362] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_363] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_364] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_365] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_366] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_367] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_368] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_369] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_37] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_370] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_371] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_372] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_373] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_374] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_375] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_376] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_377] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_378] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_379] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_38] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_380] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_381] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_382] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_383] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_384] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_385] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_386] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_387] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_388] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_389] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_39] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_390] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_391] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_392] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_393] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_394] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_395] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_396] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_397] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_398] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_399] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_4] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_40] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_400] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_401] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_402] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_403] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_404] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_405] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_406] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_407] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_408] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_409] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_41] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_410] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_411] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_412] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_413] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_414] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_415] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_416] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_417] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_418] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_419] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_42] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_420] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_421] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_422] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_423] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_424] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_425] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_426] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_427] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_428] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_429] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_43] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_430] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_431] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_432] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_433] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_434] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_435] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_436] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_437] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_438] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_439] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_44] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_440] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_441] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_442] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_443] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_444] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_445] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_446] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_447] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_448] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_449] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_45] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_450] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_451] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_452] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_453] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_454] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_455] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_456] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_457] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_458] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_459] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_46] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_460] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_461] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_462] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_463] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_464] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_465] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_466] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_467] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_468] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_469] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_47] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_470] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_471] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_472] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_473] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_474] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_475] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_476] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_477] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_478] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_479] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_48] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_480] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_481] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_482] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_483] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_484] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_485] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_486] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_487] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_488] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_489] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_49] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_490] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_491] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_492] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_493] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_494] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_495] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_496] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_497] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_498] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_499] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_5] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_50] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_500] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_501] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_502] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_503] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_504] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_505] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_506] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_507] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_508] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_509] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_51] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_510] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_511] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_512] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_513] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_514] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_515] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_516] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_517] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_518] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_519] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_52] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_520] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_521] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_522] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_523] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_524] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_525] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_526] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_527] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_528] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_529] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_53] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_530] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_531] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_532] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_533] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_534] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_535] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_536] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_537] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_538] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_539] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_54] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_540] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_541] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_542] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_543] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_544] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_545] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_546] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_547] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_548] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_549] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_55] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_550] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_551] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_552] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_553] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_554] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_555] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_556] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_557] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_558] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_559] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_56] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_560] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_561] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_562] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_563] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_564] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_565] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_566] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_567] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_568] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_569] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_57] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_570] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_571] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_572] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_573] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_574] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_575] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_576] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_577] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_578] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_579] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_58] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_580] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_581] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_582] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_583] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_584] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_585] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_586] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_587] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_588] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_589] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_59] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_590] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_591] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_592] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_593] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_594] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_595] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_596] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_597] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_598] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_599] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_6] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_60] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_600] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_601] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_602] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_603] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_604] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_605] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_606] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_607] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_608] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_609] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_61] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_610] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_611] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_612] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_613] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_614] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_615] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_616] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_617] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_618] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_619] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_62] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_620] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_621] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_622] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_623] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_624] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_625] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_626] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_627] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_628] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_629] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_63] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_630] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_631] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_632] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_633] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_634] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_635] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_636] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_637] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_638] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_639] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_64] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_640] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_641] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_642] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_643] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_644] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_645] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_646] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_647] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_648] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_649] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_65] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_650] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_651] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_652] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_653] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_654] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_655] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_656] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_657] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_658] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_659] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_66] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_660] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_661] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_662] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_663] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_664] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_665] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_666] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_667] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_668] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_669] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_67] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_670] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_671] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_672] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_673] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_674] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_675] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_676] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_677] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_678] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_679] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_68] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_680] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_681] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_682] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_683] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_684] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_685] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_686] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_687] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_688] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_689] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_69] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_690] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_691] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_692] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_693] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_694] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_695] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_696] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_697] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_698] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_699] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_7] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_70] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_700] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_701] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_702] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_703] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_704] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_705] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_706] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_707] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_708] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_709] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_71] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_710] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_711] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_712] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_713] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_714] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_72] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_73] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_74] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_75] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_76] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_77] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_78] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_79] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_8] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_80] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_81] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_82] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_83] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_84] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_85] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_86] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_87] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_88] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_89] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_9] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_90] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_91] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_92] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_93] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_94] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_95] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_96] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_97] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_98] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/g0_b0_i_99] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/receiver] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[10]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[11]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[12]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[13]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[14]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[15]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[16]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[17]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[18]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[19]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[20]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[21]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[22]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[23]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[24]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[25]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[26]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[27]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[28]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[29]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[30]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[31]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[8]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_en[9]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_id_reg[7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_id_reg[7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_id_reg[7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_meas_time[63]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_meas_time[63]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/ro_meas_time[63]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[118][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[122][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[126][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[138][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[139][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[139][7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[154][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[163][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[170][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[176][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[179][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[183][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[187][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[190][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[194][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[202][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[216][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[224][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[232][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[36][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[37][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[38][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[62][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data[67][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[0]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[0]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[0]_rep__2_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[0]_rep__3_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[0]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[1]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[1]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[1]_rep__2_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[1]_rep__3_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[1]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[2]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[2]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[2]_rep__2_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[2]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[3]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[3]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[4]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[4]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[5]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[6]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[8]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length[8]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[0]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[0]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[0]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[0]_rep__2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[0]_rep__3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[1]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[1]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[1]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[1]_rep__2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[1]_rep__3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[2]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[2]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[2]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[2]_rep__2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[3]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[3]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[4]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[4]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[5]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[6]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_length_reg[8]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[0][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[0][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[0][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[0][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[0][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[0][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[0][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[0][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[100][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[100][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[100][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[100][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[100][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[100][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[100][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[100][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[101][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[101][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[101][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[101][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[101][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[101][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[101][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[101][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[102][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[102][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[102][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[102][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[102][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[102][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[102][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[102][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[103][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[103][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[103][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[103][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[103][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[103][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[103][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[103][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[104][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[104][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[104][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[104][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[104][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[104][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[104][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[104][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[105][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[105][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[105][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[105][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[105][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[105][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[105][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[105][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[106][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[106][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[106][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[106][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[106][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[106][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[106][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[106][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[107][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[107][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[107][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[107][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[107][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[107][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[107][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[107][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[108][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[108][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[108][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[108][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[108][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[108][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[108][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[108][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[109][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[109][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[109][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[109][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[109][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[109][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[109][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[109][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[10][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[10][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[10][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[10][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[10][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[10][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[10][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[10][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[110][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[110][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[110][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[110][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[110][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[110][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[110][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[110][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[111][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[111][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[111][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[111][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[111][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[111][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[111][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[111][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[112][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[112][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[112][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[112][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[112][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[112][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[112][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[112][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[113][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[113][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[113][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[113][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[113][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[113][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[113][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[113][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[114][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[114][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[114][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[114][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[114][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[114][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[114][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[114][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[115][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[115][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[115][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[115][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[115][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[115][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[115][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[115][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[116][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[116][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[116][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[116][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[116][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[116][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[116][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[116][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[117][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[117][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[117][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[117][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[117][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[117][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[117][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[117][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[118][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[118][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[118][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[118][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[118][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[118][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[118][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[118][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[119][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[119][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[119][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[119][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[119][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[119][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[119][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[119][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[11][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[11][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[11][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[11][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[11][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[11][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[11][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[11][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[120][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[120][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[120][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[120][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[120][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[120][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[120][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[120][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[121][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[121][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[121][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[121][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[121][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[121][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[121][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[121][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[122][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[122][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[122][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[122][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[122][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[122][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[122][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[122][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[123][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[123][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[123][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[123][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[123][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[123][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[123][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[123][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[124][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[124][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[124][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[124][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[124][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[124][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[124][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[124][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[125][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[125][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[125][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[125][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[125][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[125][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[125][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[125][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[126][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[126][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[126][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[126][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[126][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[126][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[126][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[126][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[127][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[127][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[127][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[127][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[127][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[127][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[127][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[127][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[128][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[128][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[128][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[128][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[128][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[128][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[128][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[128][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[129][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[129][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[129][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[129][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[129][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[129][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[129][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[129][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[12][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[12][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[12][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[12][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[12][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[12][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[12][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[12][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[130][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[130][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[130][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[130][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[130][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[130][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[130][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[130][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[131][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[131][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[131][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[131][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[131][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[131][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[131][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[131][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[132][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[132][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[132][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[132][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[132][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[132][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[132][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[132][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[133][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[133][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[133][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[133][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[133][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[133][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[133][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[133][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[134][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[134][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[134][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[134][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[134][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[134][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[134][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[134][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[135][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[135][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[135][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[135][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[135][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[135][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[135][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[135][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[136][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[136][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[136][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[136][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[136][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[136][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[136][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[136][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[137][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[137][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[137][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[137][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[137][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[137][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[137][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[137][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[138][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[138][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[138][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[138][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[138][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[138][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[138][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[138][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[139][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[139][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[139][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[139][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[139][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[139][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[139][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[139][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[13][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[13][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[13][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[13][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[13][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[13][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[13][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[13][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[140][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[140][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[140][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[140][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[140][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[140][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[140][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[140][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[141][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[141][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[141][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[141][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[141][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[141][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[141][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[141][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[142][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[142][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[142][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[142][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[142][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[142][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[142][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[142][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[143][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[143][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[143][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[143][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[143][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[143][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[143][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[143][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[144][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[144][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[144][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[144][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[144][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[144][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[144][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[144][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[145][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[145][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[145][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[145][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[145][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[145][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[145][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[145][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[146][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[146][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[146][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[146][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[146][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[146][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[146][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[146][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[147][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[147][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[147][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[147][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[147][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[147][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[147][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[147][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[148][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[148][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[148][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[148][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[148][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[148][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[148][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[148][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[149][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[149][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[149][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[149][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[149][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[149][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[149][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[149][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[14][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[14][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[14][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[14][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[14][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[14][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[14][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[14][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[150][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[150][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[150][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[150][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[150][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[150][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[150][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[150][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[151][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[151][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[151][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[151][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[151][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[151][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[151][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[151][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[152][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[152][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[152][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[152][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[152][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[152][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[152][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[152][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[153][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[153][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[153][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[153][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[153][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[153][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[153][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[153][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[154][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[154][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[154][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[154][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[154][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[154][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[154][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[154][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[155][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[155][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[155][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[155][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[155][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[155][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[155][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[155][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[156][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[156][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[156][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[156][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[156][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[156][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[156][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[156][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[157][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[157][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[157][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[157][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[157][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[157][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[157][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[157][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[158][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[158][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[158][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[158][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[158][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[158][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[158][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[158][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[159][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[159][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[159][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[159][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[159][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[159][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[159][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[159][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[15][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[15][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[15][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[15][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[15][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[15][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[15][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[15][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[160][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[160][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[160][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[160][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[160][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[160][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[160][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[160][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[161][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[161][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[161][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[161][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[161][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[161][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[161][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[161][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[162][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[162][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[162][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[162][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[162][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[162][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[162][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[162][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[163][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[163][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[163][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[163][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[163][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[163][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[163][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[163][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[164][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[164][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[164][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[164][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[164][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[164][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[164][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[164][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[165][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[165][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[165][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[165][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[165][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[165][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[165][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[165][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[166][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[166][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[166][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[166][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[166][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[166][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[166][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[166][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[167][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[167][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[167][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[167][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[167][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[167][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[167][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[167][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[168][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[168][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[168][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[168][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[168][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[168][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[168][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[168][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[169][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[169][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[169][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[169][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[169][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[169][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[169][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[169][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[16][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[16][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[16][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[16][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[16][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[16][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[16][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[16][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[170][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[170][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[170][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[170][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[170][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[170][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[170][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[170][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[171][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[171][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[171][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[171][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[171][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[171][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[171][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[171][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[172][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[172][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[172][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[172][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[172][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[172][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[172][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[172][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[173][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[173][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[173][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[173][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[173][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[173][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[173][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[173][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[174][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[174][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[174][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[174][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[174][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[174][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[174][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[174][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[175][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[175][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[175][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[175][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[175][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[175][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[175][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[175][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[176][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[176][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[176][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[176][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[176][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[176][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[176][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[176][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[177][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[177][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[177][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[177][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[177][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[177][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[177][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[177][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[178][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[178][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[178][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[178][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[178][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[178][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[178][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[178][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[179][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[179][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[179][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[179][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[179][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[179][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[179][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[179][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[17][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[17][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[17][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[17][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[17][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[17][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[17][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[17][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[180][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[180][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[180][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[180][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[180][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[180][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[180][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[180][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[181][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[181][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[181][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[181][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[181][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[181][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[181][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[181][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[182][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[182][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[182][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[182][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[182][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[182][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[182][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[182][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[183][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[183][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[183][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[183][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[183][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[183][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[183][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[183][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[184][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[184][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[184][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[184][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[184][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[184][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[184][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[184][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[185][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[185][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[185][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[185][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[185][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[185][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[185][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[185][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[186][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[186][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[186][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[186][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[186][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[186][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[186][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[186][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[187][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[187][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[187][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[187][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[187][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[187][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[187][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[187][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[188][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[188][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[188][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[188][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[188][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[188][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[188][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[188][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[189][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[189][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[189][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[189][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[189][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[189][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[189][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[189][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[18][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[18][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[18][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[18][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[18][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[18][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[18][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[18][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[190][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[190][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[190][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[190][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[190][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[190][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[190][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[190][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[191][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[191][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[191][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[191][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[191][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[191][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[191][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[191][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[192][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[192][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[192][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[192][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[192][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[192][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[192][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[192][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[193][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[193][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[193][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[193][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[193][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[193][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[193][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[193][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[194][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[194][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[194][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[194][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[194][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[194][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[194][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[194][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[195][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[195][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[195][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[195][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[195][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[195][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[195][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[195][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[196][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[196][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[196][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[196][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[196][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[196][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[196][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[196][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[197][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[197][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[197][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[197][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[197][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[197][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[197][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[197][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[198][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[198][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[198][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[198][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[198][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[198][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[198][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[198][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[199][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[199][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[199][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[199][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[199][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[199][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[199][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[199][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[19][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[19][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[19][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[19][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[19][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[19][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[19][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[19][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[1][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[1][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[1][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[1][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[1][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[1][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[1][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[1][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[200][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[200][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[200][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[200][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[200][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[200][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[200][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[200][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[201][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[201][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[201][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[201][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[201][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[201][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[201][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[201][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[202][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[202][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[202][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[202][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[202][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[202][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[202][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[202][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[203][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[203][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[203][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[203][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[203][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[203][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[203][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[203][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[204][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[204][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[204][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[204][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[204][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[204][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[204][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[204][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[205][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[205][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[205][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[205][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[205][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[205][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[205][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[205][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[206][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[206][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[206][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[206][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[206][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[206][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[206][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[206][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[207][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[207][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[207][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[207][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[207][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[207][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[207][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[207][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[208][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[208][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[208][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[208][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[208][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[208][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[208][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[208][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[209][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[209][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[209][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[209][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[209][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[209][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[209][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[209][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[20][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[20][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[20][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[20][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[20][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[20][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[20][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[20][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[210][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[210][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[210][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[210][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[210][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[210][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[210][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[210][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[211][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[211][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[211][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[211][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[211][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[211][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[211][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[211][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[212][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[212][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[212][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[212][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[212][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[212][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[212][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[212][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[213][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[213][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[213][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[213][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[213][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[213][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[213][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[213][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[214][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[214][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[214][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[214][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[214][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[214][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[214][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[214][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[215][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[215][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[215][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[215][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[215][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[215][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[215][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[215][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[216][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[216][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[216][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[216][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[216][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[216][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[216][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[216][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[217][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[217][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[217][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[217][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[217][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[217][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[217][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[217][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[218][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[218][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[218][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[218][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[218][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[218][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[218][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[218][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[219][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[219][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[219][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[219][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[219][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[219][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[219][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[219][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[21][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[21][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[21][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[21][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[21][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[21][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[21][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[21][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[220][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[220][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[220][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[220][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[220][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[220][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[220][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[220][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[221][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[221][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[221][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[221][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[221][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[221][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[221][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[221][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[222][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[222][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[222][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[222][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[222][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[222][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[222][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[222][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[223][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[223][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[223][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[223][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[223][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[223][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[223][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[223][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[224][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[224][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[224][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[224][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[224][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[224][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[224][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[224][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[225][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[225][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[225][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[225][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[225][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[225][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[225][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[225][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[226][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[226][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[226][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[226][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[226][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[226][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[226][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[226][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[227][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[227][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[227][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[227][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[227][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[227][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[227][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[227][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[228][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[228][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[228][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[228][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[228][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[228][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[228][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[228][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[229][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[229][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[229][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[229][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[229][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[229][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[229][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[229][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[22][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[22][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[22][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[22][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[22][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[22][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[22][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[22][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[230][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[230][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[230][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[230][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[230][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[230][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[230][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[230][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[231][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[231][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[231][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[231][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[231][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[231][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[231][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[231][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[232][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[232][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[232][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[232][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[232][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[232][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[232][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[232][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[233][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[233][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[233][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[233][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[233][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[233][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[233][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[233][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[234][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[234][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[234][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[234][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[234][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[234][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[234][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[234][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[235][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[235][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[235][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[235][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[235][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[235][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[235][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[235][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[236][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[236][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[236][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[236][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[236][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[236][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[236][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[236][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[237][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[237][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[237][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[237][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[237][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[237][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[237][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[237][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[238][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[238][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[238][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[238][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[238][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[238][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[238][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[238][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[239][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[239][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[239][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[239][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[239][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[239][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[239][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[239][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[23][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[23][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[23][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[23][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[23][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[23][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[23][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[23][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[240][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[240][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[240][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[240][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[240][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[240][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[240][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[240][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[241][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[241][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[241][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[241][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[241][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[241][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[241][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[241][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[242][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[242][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[242][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[242][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[242][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[242][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[242][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[242][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[243][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[243][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[243][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[243][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[243][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[243][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[243][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[243][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[244][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[244][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[244][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[244][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[244][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[244][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[244][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[244][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[245][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[245][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[245][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[245][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[245][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[245][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[245][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[245][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[246][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[246][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[246][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[246][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[246][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[246][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[246][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[246][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[247][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[247][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[247][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[247][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[247][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[247][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[247][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[247][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[248][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[248][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[248][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[248][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[248][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[248][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[248][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[248][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[249][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[249][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[249][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[249][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[249][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[249][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[249][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[249][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[24][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[24][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[24][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[24][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[24][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[24][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[24][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[24][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[250][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[250][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[250][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[250][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[250][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[250][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[250][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[250][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[251][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[251][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[251][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[251][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[251][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[251][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[251][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[251][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[252][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[252][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[252][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[252][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[252][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[252][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[252][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[252][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[253][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[253][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[253][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[253][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[253][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[253][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[253][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[253][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[254][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[254][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[254][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[254][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[254][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[254][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[254][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[254][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[255][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[255][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[255][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[255][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[255][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[255][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[255][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[255][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[25][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[25][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[25][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[25][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[25][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[25][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[25][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[25][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[26][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[26][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[26][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[26][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[26][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[26][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[26][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[26][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[27][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[27][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[27][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[27][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[27][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[27][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[27][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[27][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[28][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[28][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[28][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[28][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[28][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[28][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[28][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[28][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[29][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[29][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[29][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[29][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[29][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[29][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[29][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[29][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[2][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[2][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[2][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[2][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[2][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[2][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[2][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[2][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[30][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[30][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[30][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[30][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[30][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[30][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[30][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[30][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[31][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[31][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[31][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[31][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[31][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[31][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[31][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[31][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[32][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[32][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[32][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[32][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[32][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[32][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[32][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[32][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[33][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[33][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[33][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[33][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[33][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[33][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[33][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[33][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[34][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[34][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[34][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[34][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[34][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[34][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[34][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[34][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[35][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[35][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[35][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[35][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[35][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[35][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[35][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[35][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[36][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[36][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[36][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[36][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[36][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[36][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[36][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[36][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[37][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[37][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[37][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[37][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[37][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[37][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[37][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[37][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[38][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[38][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[38][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[38][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[38][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[38][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[38][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[38][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[39][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[39][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[39][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[39][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[39][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[39][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[39][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[39][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[3][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[3][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[3][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[3][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[3][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[3][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[3][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[3][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[40][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[40][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[40][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[40][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[40][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[40][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[40][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[40][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[41][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[41][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[41][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[41][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[41][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[41][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[41][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[41][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[42][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[42][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[42][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[42][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[42][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[42][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[42][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[42][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[43][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[43][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[43][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[43][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[43][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[43][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[43][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[43][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[44][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[44][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[44][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[44][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[44][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[44][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[44][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[44][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[45][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[45][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[45][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[45][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[45][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[45][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[45][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[45][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[46][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[46][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[46][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[46][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[46][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[46][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[46][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[46][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[47][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[47][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[47][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[47][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[47][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[47][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[47][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[47][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[48][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[48][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[48][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[48][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[48][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[48][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[48][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[48][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[49][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[49][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[49][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[49][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[49][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[49][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[49][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[49][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[4][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[4][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[4][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[4][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[4][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[4][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[4][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[4][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[50][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[50][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[50][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[50][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[50][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[50][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[50][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[50][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[51][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[51][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[51][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[51][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[51][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[51][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[51][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[51][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[52][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[52][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[52][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[52][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[52][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[52][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[52][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[52][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[53][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[53][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[53][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[53][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[53][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[53][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[53][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[53][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[54][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[54][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[54][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[54][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[54][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[54][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[54][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[54][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[55][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[55][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[55][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[55][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[55][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[55][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[55][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[55][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[56][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[56][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[56][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[56][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[56][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[56][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[56][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[56][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[57][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[57][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[57][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[57][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[57][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[57][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[57][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[57][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[58][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[58][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[58][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[58][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[58][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[58][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[58][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[58][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[59][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[59][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[59][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[59][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[59][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[59][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[59][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[59][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[5][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[5][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[5][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[5][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[5][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[5][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[5][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[5][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[60][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[60][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[60][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[60][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[60][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[60][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[60][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[60][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[61][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[61][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[61][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[61][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[61][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[61][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[61][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[61][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[62][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[62][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[62][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[62][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[62][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[62][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[62][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[62][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[63][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[63][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[63][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[63][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[63][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[63][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[63][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[63][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[64][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[64][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[64][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[64][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[64][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[64][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[64][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[64][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[65][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[65][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[65][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[65][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[65][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[65][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[65][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[65][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[66][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[66][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[66][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[66][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[66][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[66][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[66][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[66][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[67][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[67][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[67][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[67][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[67][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[67][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[67][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[67][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[68][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[68][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[68][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[68][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[68][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[68][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[68][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[68][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[69][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[69][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[69][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[69][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[69][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[69][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[69][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[69][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[6][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[6][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[6][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[6][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[6][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[6][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[6][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[6][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[70][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[70][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[70][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[70][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[70][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[70][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[70][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[70][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[71][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[71][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[71][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[71][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[71][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[71][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[71][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[71][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[72][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[72][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[72][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[72][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[72][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[72][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[72][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[72][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[73][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[73][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[73][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[73][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[73][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[73][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[73][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[73][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[74][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[74][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[74][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[74][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[74][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[74][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[74][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[74][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[75][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[75][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[75][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[75][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[75][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[75][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[75][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[75][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[76][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[76][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[76][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[76][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[76][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[76][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[76][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[76][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[77][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[77][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[77][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[77][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[77][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[77][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[77][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[77][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[78][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[78][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[78][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[78][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[78][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[78][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[78][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[78][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[79][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[79][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[79][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[79][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[79][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[79][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[79][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[79][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[7][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[7][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[7][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[7][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[7][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[7][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[7][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[7][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[80][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[80][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[80][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[80][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[80][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[80][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[80][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[80][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[81][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[81][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[81][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[81][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[81][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[81][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[81][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[81][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[82][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[82][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[82][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[82][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[82][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[82][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[82][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[82][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[83][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[83][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[83][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[83][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[83][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[83][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[83][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[83][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[84][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[84][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[84][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[84][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[84][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[84][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[84][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[84][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[85][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[85][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[85][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[85][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[85][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[85][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[85][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[85][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[86][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[86][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[86][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[86][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[86][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[86][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[86][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[86][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[87][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[87][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[87][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[87][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[87][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[87][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[87][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[87][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[88][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[88][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[88][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[88][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[88][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[88][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[88][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[88][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[89][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[89][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[89][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[89][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[89][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[89][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[89][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[89][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[8][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[8][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[8][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[8][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[8][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[8][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[8][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[8][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[90][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[90][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[90][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[90][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[90][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[90][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[90][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[90][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[91][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[91][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[91][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[91][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[91][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[91][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[91][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[91][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[92][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[92][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[92][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[92][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[92][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[92][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[92][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[92][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[93][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[93][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[93][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[93][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[93][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[93][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[93][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[93][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[94][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[94][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[94][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[94][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[94][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[94][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[94][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[94][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[95][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[95][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[95][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[95][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[95][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[95][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[95][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[95][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[96][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[96][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[96][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[96][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[96][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[96][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[96][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[96][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[97][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[97][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[97][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[97][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[97][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[97][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[97][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[97][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[98][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[98][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[98][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[98][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[98][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[98][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[98][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[98][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[99][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[99][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[99][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[99][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[99][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[99][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[99][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[99][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[9][0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[9][1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[9][2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[9][3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[9][4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[9][5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[9][6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/rx_data_reg[9][7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_10}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_11}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_12}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_13}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_14}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_1__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_8}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state[2]_i_9}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/FSM_sequential_current_state_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/receiver/GND] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/receiver/GND_1] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/receiver/VCC] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter0_carry] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter0_carry__0] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter0_carry__1] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter0_carry__2] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter[31]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[10]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[11]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[12]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[13]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[14]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[15]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[16]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[17]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[18]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[19]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[20]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[21]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[22]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[23]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[24]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[25]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[26]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[27]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[28]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[29]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[30]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[31]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[8]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/clock_counter_reg[9]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/current_bit[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/current_bit[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/current_bit[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/current_bit[3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/current_bit[3]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/current_bit_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/current_bit_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/current_bit_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/current_bit_reg[3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[0][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[0][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[0]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[0]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[0]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[0]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[0]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[100][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[101][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[102][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[103][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[104][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[105][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[106][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[107][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[108][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[109][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[10][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[110][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[111][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[112][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[113][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[113][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[114][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[114][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[115][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[116][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[117][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[118][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[119][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[11][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[120][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[120][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[121][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[122][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[123][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[123][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[124][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[125][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[126][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[127][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[127][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[128][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[129][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[12][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[130][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[131][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[132][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[133][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[134][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[135][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[136][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[137][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[138][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[139][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[13][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[140][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[141][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[142][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[143][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[144][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[145][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[146][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[147][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[148][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[149][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[14][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[150][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[151][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[152][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[153][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[154][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[155][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[156][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[157][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[158][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[159][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[15][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[15][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[160][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[161][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[162][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[163][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[164][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[165][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[166][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[167][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[168][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[169][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[16][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[170][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[171][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[172][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[173][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[174][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[175][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[176][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[177][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[178][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[179][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[17][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[180][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[181][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[182][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[183][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[184][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[184][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[185][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[186][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[187][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[188][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[189][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[18][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[190][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[191][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[192][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[193][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[194][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[195][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[195][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[196][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[197][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[198][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[199][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[19][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[1][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[1]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[1]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[1]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[200][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[201][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[202][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[203][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[204][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[205][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[206][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[207][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[208][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[209][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[20][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[210][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[211][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[212][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[213][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[214][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[215][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[216][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[217][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[218][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[219][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[21][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[220][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[221][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[222][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[223][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[224][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[225][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[226][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[227][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[228][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[229][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[22][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[230][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[231][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[232][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[233][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[234][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[235][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[236][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[237][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[238][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[239][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[23][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[240][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[241][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[242][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[243][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[244][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[245][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[246][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[247][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[248][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[249][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[24][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[250][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[251][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[252][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[252][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[253][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[253][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[254][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[254][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[255][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[255][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[25][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[26][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[27][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[28][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[29][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[2][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[2]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[2]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[2]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[2]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[2]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[30][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[30][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[31][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[32][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[33][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[34][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[35][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[36][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[37][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[38][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[38][7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[39][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[3][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[3]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[3]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[3]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[3]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[40][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[41][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[42][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[43][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[44][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[45][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[46][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[46][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[47][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[48][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[49][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[4][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[4]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[4]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[4]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[4]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[4]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[4]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[50][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[51][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[52][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[53][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[54][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[55][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[56][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[57][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[58][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[59][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[5][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[5]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[5]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[5]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[5]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[60][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[60][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[61][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[62][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[63][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[64][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[65][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[66][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[67][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[68][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[69][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[6][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[6]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[6]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[6]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[6]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[6]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[6]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[6]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[6]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[70][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[71][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[72][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[73][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[74][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[75][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[76][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[77][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[78][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[79][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[7][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[7][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[7]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[7]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[7]_rep__0_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[7]_rep__1_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[7]_rep_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[80][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[81][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[82][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[83][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[84][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[85][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[86][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[87][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[88][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[89][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[8][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[90][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[91][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[92][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[93][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[94][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[95][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[96][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[97][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[98][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[99][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[99][7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data[9][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_length[8]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[0]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[0]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[0]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[1]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[1]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[1]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[2]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[2]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[2]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[3]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[3]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[3]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[4]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[4]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[4]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[5]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[5]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[5]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[6]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[6]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[6]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[7]_rep}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[7]_rep__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_rxer/receiver/rx_data_reg[7]_rep__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_onehot_current_state[36]_i_19}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_onehot_current_state[36]_i_56}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[0]_i_10}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[0]_i_1__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[0]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[0]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[0]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[0]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[0]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[0]_i_8}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[0]_i_9}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_10}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_11}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_12}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_13}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_14}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_15}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_16}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_17}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_18}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_19}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_20}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_21}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_22}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_23}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_24}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_25}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_26}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_27}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_28}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_29}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_30}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_31}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_32}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_33}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_34}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_35}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_36}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_8}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state[1]_i_9}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state_reg[0]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state_reg[1]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/FSM_sequential_current_state_reg[1]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/GND] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/GND_1] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/VCC] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[10]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[11]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[12]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[13]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[14]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[15]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[16]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[16]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[17]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[18]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[19]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[20]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[21]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[22]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[23]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[24]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[24]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[25]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[26]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[27]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[28]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[29]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[30]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[31]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[31]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[8]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[8]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/delay_counter_reg[9]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter[3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter[4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter[5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter[5]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter[6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter[7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter[7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter_reg[3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter_reg[4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter_reg[5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter_reg[6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/transfer_counter_reg[7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/tx_ready_i_1__0] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/tx_ready_reg] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[0][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[0]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[0]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[0]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[0]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[15][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[1][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[1]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[1]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[1]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[1]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[2]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[2]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[2]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[2]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[3][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[3]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[3]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[3]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[3]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[4]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[4]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[4]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[4]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[4]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[5]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[5]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[5]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[5]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[5]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[6]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[6]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[6]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[6]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[6]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[7][7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[7]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[7]_i_6}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[7]_i_7}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[7]_i_8}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data[7]_i_9}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[0]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[0]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[1]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[1]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[2]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[2]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[3]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[3]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[4]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[4]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[5]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[5]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[6]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[6]_i_3}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[7]_i_4}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/uart_tx_data_reg[7]_i_5}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/uart_tx_en_reg] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[0]_i_1__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[1]_i_1__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[1]_i_1__1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[2]_i_10__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[2]_i_2__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[2]_i_3__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[2]_i_4__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[2]_i_5__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[2]_i_6__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[2]_i_7__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[2]_i_8__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state[2]_i_9__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/FSM_sequential_current_state_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/GND] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/GND_1] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/VCC] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/bit_counter[0]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/bit_counter[1]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/bit_counter[2]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/bit_counter[3]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/bit_counter[3]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/bit_counter_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/bit_counter_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/bit_counter_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/bit_counter_reg[3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/clock_counter0_carry] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/clock_counter0_carry__0] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/clock_counter0_carry__1] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/clock_counter0_carry__2] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter[0]_i_1__0}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter[32]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[0]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[10]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[11]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[12]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[13]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[14]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[15]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[16]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[17]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[18]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[19]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[1]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[20]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[21]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[22]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[23]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[24]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[25]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[26]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[27]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[28]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[29]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[2]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[30]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[31]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[32]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[3]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[4]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[5]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[6]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[7]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[8]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/clock_counter_reg[9]}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/delay_counter[31]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/delay_counter[31]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/transfer_counter[7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/tx_line_i_1] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/tx_line_i_2] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/tx_line_i_3] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/tx_line_i_4] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/tx_line_i_5] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/tx_line_reg] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/tx_ready_i_1] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells UART_FF_INS/multibyte_uart_txer/sender/tx_ready_reg] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/uart_tx_data[7]_i_1}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells {UART_FF_INS/multibyte_uart_txer/sender/uart_tx_data[7]_i_2}] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells uart_rx_line_IBUF_inst/IBUFCTRL_INST] +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells uart_rx_line_IBUF_inst/INBUF_INST] + +#create_pblock pb_ff_0 +#set_property IS_SOFT FALSE [get_pblocks pb_ff_0] +#resize_pblock [get_pblocks pb_ff_0] -add {CLOCKREGION_X6Y1:CLOCKREGION_X6Y1} +#add_cells_to_pblock {pb_ff_0} [get_cells -hier -filter {NAME =~ */ff[0]}] + + +create_pblock pb_ro_0 +add_cells_to_pblock [get_pblocks pb_ro_0] [get_cells -quiet [list {UART_FF_INS/RO[0]} {UART_FF_INS/chain[0]}]] +resize_pblock [get_pblocks pb_ro_0] -add {CLOCKREGION_X0Y3:CLOCKREGION_X0Y3} +set_property IS_SOFT FALSE [get_pblocks pb_ro_0] +#resize_pblock [get_pblocks pb_ro_0] -add {SLICE_X117Y0:SLICE_X145Y59} + + + +create_pblock pb_ro_1 +add_cells_to_pblock [get_pblocks pb_ro_1] [get_cells -quiet [list {UART_FF_INS/RO[1]} {UART_FF_INS/chain[1]}]] +resize_pblock [get_pblocks pb_ro_1] -add {CLOCKREGION_X1Y3:CLOCKREGION_X1Y3} +set_property IS_SOFT FALSE [get_pblocks pb_ro_1] + +create_pblock pb_ro_2 +add_cells_to_pblock [get_pblocks pb_ro_2] [get_cells -quiet [list {UART_FF_INS/RO[2]} {UART_FF_INS/chain[2]}]] +resize_pblock [get_pblocks pb_ro_2] -add {CLOCKREGION_X2Y3:CLOCKREGION_X2Y3} +set_property IS_SOFT FALSE [get_pblocks pb_ro_2] + +create_pblock pb_ro_3 +add_cells_to_pblock [get_pblocks pb_ro_3] [get_cells -quiet [list {UART_FF_INS/RO[3]} {UART_FF_INS/chain[3]}]] +resize_pblock [get_pblocks pb_ro_3] -add {CLOCKREGION_X3Y3:CLOCKREGION_X3Y3} +set_property IS_SOFT FALSE [get_pblocks pb_ro_3] + +create_pblock pb_ro_4 +add_cells_to_pblock [get_pblocks pb_ro_4] [get_cells -quiet [list {UART_FF_INS/RO[4]} {UART_FF_INS/chain[4]}]] +resize_pblock [get_pblocks pb_ro_4] -add {CLOCKREGION_X4Y3:CLOCKREGION_X4Y3} +set_property IS_SOFT FALSE [get_pblocks pb_ro_4] + +create_pblock pb_ro_5 +add_cells_to_pblock [get_pblocks pb_ro_5] [get_cells -quiet [list {UART_FF_INS/RO[5]} {UART_FF_INS/chain[5]}]] +resize_pblock [get_pblocks pb_ro_5] -add {CLOCKREGION_X5Y3:CLOCKREGION_X5Y3} +set_property IS_SOFT FALSE [get_pblocks pb_ro_5] + +create_pblock pb_ro_6 +add_cells_to_pblock [get_pblocks pb_ro_6] [get_cells -quiet [list {UART_FF_INS/RO[6]} {UART_FF_INS/chain[6]}]] +resize_pblock [get_pblocks pb_ro_6] -add {CLOCKREGION_X6Y3:CLOCKREGION_X6Y3} +set_property IS_SOFT FALSE [get_pblocks pb_ro_6] + +create_pblock pb_ro_7 +add_cells_to_pblock [get_pblocks pb_ro_7] [get_cells -quiet [list {UART_FF_INS/RO[7]} {UART_FF_INS/chain[7]}]] +resize_pblock [get_pblocks pb_ro_7] -add {CLOCKREGION_X7Y3:CLOCKREGION_X7Y3} +set_property IS_SOFT FALSE [get_pblocks pb_ro_7] + + +create_pblock pb_ro_8 +add_cells_to_pblock [get_pblocks pb_ro_8] [get_cells -quiet [list {UART_FF_INS/RO[8]} {UART_FF_INS/chain[8]}]] +resize_pblock [get_pblocks pb_ro_8] -add {CLOCKREGION_X0Y2:CLOCKREGION_X0Y2} +set_property IS_SOFT FALSE [get_pblocks pb_ro_8] + +create_pblock pb_ro_9 +add_cells_to_pblock [get_pblocks pb_ro_9] [get_cells -quiet [list {UART_FF_INS/RO[9]} {UART_FF_INS/chain[9]}]] +resize_pblock [get_pblocks pb_ro_9] -add {CLOCKREGION_X1Y2:CLOCKREGION_X1Y2} +set_property IS_SOFT FALSE [get_pblocks pb_ro_9] + +create_pblock pb_ro_10 +add_cells_to_pblock [get_pblocks pb_ro_10] [get_cells -quiet [list {UART_FF_INS/RO[10]} {UART_FF_INS/chain[10]}]] +resize_pblock [get_pblocks pb_ro_10] -add {CLOCKREGION_X2Y2:CLOCKREGION_X2Y2} +set_property IS_SOFT FALSE [get_pblocks pb_ro_10] + + +create_pblock pb_ro_11 +add_cells_to_pblock [get_pblocks pb_ro_11] [get_cells -quiet [list {UART_FF_INS/RO[11]} {UART_FF_INS/chain[11]}]] +resize_pblock [get_pblocks pb_ro_11] -add {CLOCKREGION_X3Y2:CLOCKREGION_X3Y2} +set_property IS_SOFT FALSE [get_pblocks pb_ro_11] + + + +create_pblock pb_ro_12 +add_cells_to_pblock [get_pblocks pb_ro_12] [get_cells -quiet [list {UART_FF_INS/RO[12]} {UART_FF_INS/chain[12]}]] +resize_pblock [get_pblocks pb_ro_12] -add {CLOCKREGION_X4Y2:CLOCKREGION_X4Y2} +set_property IS_SOFT FALSE [get_pblocks pb_ro_12] + + +create_pblock pb_ro_13 +add_cells_to_pblock [get_pblocks pb_ro_13] [get_cells -quiet [list {UART_FF_INS/RO[13]} {UART_FF_INS/chain[13]}]] +resize_pblock [get_pblocks pb_ro_13] -add {CLOCKREGION_X5Y2:CLOCKREGION_X5Y2} +set_property IS_SOFT FALSE [get_pblocks pb_ro_13] + +create_pblock pb_ro_14 +add_cells_to_pblock [get_pblocks pb_ro_14] [get_cells -quiet [list {UART_FF_INS/RO[14]} {UART_FF_INS/chain[14]}]] +resize_pblock [get_pblocks pb_ro_14] -add {CLOCKREGION_X6Y2:CLOCKREGION_X6Y2} +set_property IS_SOFT FALSE [get_pblocks pb_ro_14] + +create_pblock pb_ro_15 +add_cells_to_pblock [get_pblocks pb_ro_15] [get_cells -quiet [list {UART_FF_INS/RO[15]} {UART_FF_INS/chain[15]}]] +resize_pblock [get_pblocks pb_ro_15] -add {CLOCKREGION_X7Y2:CLOCKREGION_X7Y2} +set_property IS_SOFT FALSE [get_pblocks pb_ro_15] + +create_pblock pb_ro_16 +add_cells_to_pblock [get_pblocks pb_ro_16] [get_cells -quiet [list {UART_FF_INS/RO[16]} {UART_FF_INS/chain[16]}]] +resize_pblock [get_pblocks pb_ro_16] -add {CLOCKREGION_X0Y1:CLOCKREGION_X0Y1} +set_property IS_SOFT FALSE [get_pblocks pb_ro_16] + +create_pblock pb_ro_17 +add_cells_to_pblock [get_pblocks pb_ro_17] [get_cells -quiet [list {UART_FF_INS/RO[17]} {UART_FF_INS/chain[17]}]] +resize_pblock [get_pblocks pb_ro_17] -add {CLOCKREGION_X1Y1:CLOCKREGION_X1Y1} +set_property IS_SOFT FALSE [get_pblocks pb_ro_17] + +create_pblock pb_ro_18 +add_cells_to_pblock [get_pblocks pb_ro_18] [get_cells -quiet [list {UART_FF_INS/RO[18]} {UART_FF_INS/chain[18]}]] +resize_pblock [get_pblocks pb_ro_18] -add {CLOCKREGION_X2Y1:CLOCKREGION_X2Y1} +set_property IS_SOFT FALSE [get_pblocks pb_ro_18] + +create_pblock pb_ro_19 +add_cells_to_pblock [get_pblocks pb_ro_19] [get_cells -quiet [list {UART_FF_INS/RO[19]} {UART_FF_INS/chain[19]}]] +resize_pblock [get_pblocks pb_ro_19] -add {CLOCKREGION_X3Y1:CLOCKREGION_X3Y1} +set_property IS_SOFT FALSE [get_pblocks pb_ro_19] + +create_pblock pb_ro_20 +add_cells_to_pblock [get_pblocks pb_ro_20] [get_cells -quiet [list {UART_FF_INS/RO[20]} {UART_FF_INS/chain[20]}]] +resize_pblock [get_pblocks pb_ro_20] -add {CLOCKREGION_X4Y1:CLOCKREGION_X4Y1} +set_property IS_SOFT FALSE [get_pblocks pb_ro_20] + +create_pblock pb_ro_21 +add_cells_to_pblock [get_pblocks pb_ro_21] [get_cells -quiet [list {UART_FF_INS/RO[21]} {UART_FF_INS/chain[21]}]] +resize_pblock [get_pblocks pb_ro_21] -add {CLOCKREGION_X5Y1:CLOCKREGION_X5Y1} +set_property IS_SOFT FALSE [get_pblocks pb_ro_21] + +create_pblock pb_ro_22 +add_cells_to_pblock [get_pblocks pb_ro_22] [get_cells -quiet [list {UART_FF_INS/RO[22]} {UART_FF_INS/chain[22]}]] +resize_pblock [get_pblocks pb_ro_22] -add {CLOCKREGION_X6Y1:CLOCKREGION_X6Y1} +set_property IS_SOFT FALSE [get_pblocks pb_ro_22] + +create_pblock pb_ro_23 +add_cells_to_pblock [get_pblocks pb_ro_23] [get_cells -quiet [list {UART_FF_INS/RO[23]} {UART_FF_INS/chain[23]}]] +resize_pblock [get_pblocks pb_ro_23] -add {CLOCKREGION_X7Y1:CLOCKREGION_X7Y1} +set_property IS_SOFT FALSE [get_pblocks pb_ro_23] + + +create_pblock pb_ro_24 +add_cells_to_pblock [get_pblocks pb_ro_24] [get_cells -quiet [list {UART_FF_INS/RO[24]} {UART_FF_INS/chain[24]}]] +resize_pblock [get_pblocks pb_ro_24] -add {CLOCKREGION_X0Y0:CLOCKREGION_X0Y0} +set_property IS_SOFT FALSE [get_pblocks pb_ro_24] + +create_pblock pb_ro_25 +add_cells_to_pblock [get_pblocks pb_ro_25] [get_cells -quiet [list {UART_FF_INS/RO[25]} {UART_FF_INS/chain[25]}]] +resize_pblock [get_pblocks pb_ro_25] -add {CLOCKREGION_X1Y0:CLOCKREGION_X1Y0} +set_property IS_SOFT FALSE [get_pblocks pb_ro_25] + +create_pblock pb_ro_26 +add_cells_to_pblock [get_pblocks pb_ro_26] [get_cells -quiet [list {UART_FF_INS/RO[26]} {UART_FF_INS/chain[26]}]] +resize_pblock [get_pblocks pb_ro_26] -add {CLOCKREGION_X2Y0:CLOCKREGION_X2Y0} +set_property IS_SOFT FALSE [get_pblocks pb_ro_26] + +create_pblock pb_ro_27 +add_cells_to_pblock [get_pblocks pb_ro_27] [get_cells -quiet [list {UART_FF_INS/RO[27]} {UART_FF_INS/chain[27]}]] +resize_pblock [get_pblocks pb_ro_27] -add {CLOCKREGION_X3Y0:CLOCKREGION_X3Y0} +set_property IS_SOFT FALSE [get_pblocks pb_ro_27] + +create_pblock pb_ro_28 +add_cells_to_pblock [get_pblocks pb_ro_28] [get_cells -quiet [list {UART_FF_INS/RO[28]} {UART_FF_INS/chain[28]}]] +resize_pblock [get_pblocks pb_ro_28] -add {CLOCKREGION_X4Y0:CLOCKREGION_X4Y0} +set_property IS_SOFT FALSE [get_pblocks pb_ro_28] + +create_pblock pb_ro_29 +add_cells_to_pblock [get_pblocks pb_ro_29] [get_cells -quiet [list {UART_FF_INS/RO[29]} {UART_FF_INS/chain[29]}]] +resize_pblock [get_pblocks pb_ro_29] -add {CLOCKREGION_X5Y0:CLOCKREGION_X5Y0} +set_property IS_SOFT FALSE [get_pblocks pb_ro_29] + + +create_pblock pb_ro_30 +add_cells_to_pblock [get_pblocks pb_ro_30] [get_cells -quiet [list {UART_FF_INS/RO[30]} {UART_FF_INS/chain[30]}]] +resize_pblock [get_pblocks pb_ro_30] -add {CLOCKREGION_X6Y0:CLOCKREGION_X6Y0} +set_property IS_SOFT FALSE [get_pblocks pb_ro_30] + +create_pblock pb_ro_31 +add_cells_to_pblock [get_pblocks pb_ro_31] [get_cells -quiet [list {UART_FF_INS/RO[31]} {UART_FF_INS/chain[31]}]] +resize_pblock [get_pblocks pb_ro_31] -add {CLOCKREGION_X7Y0:CLOCKREGION_X7Y0} +set_property IS_SOFT FALSE [get_pblocks pb_ro_31] + + + + + + + +#resize_pblock {pb_ro_0} -add {SLICE_X0Y180:SLICE_X19Y239} + + +#set_property LOC {SLICE_X0Y180:SLICE_X19Y239} [get_cells -hier -filter {NAME =~ */RO[0]}] +#add_cells_to_pblock {pb_ro_0} [get_cells -hier -filter {NAME =~ */RO[0]/*}] +#add_cells_to_pblock {pb_ro_0} -verbose -clear_locs [get_cells -hier -filter {NAME =~ */RO[0]}] + +#set_property CLOCK_REGION X0Y3 [get_cells -hier -filter {NAME =~ */RO[0]}] + +#set_property BEL G5LUT [get_cells {UART_FF_INS/RO[0]/ro_fanout_ins[0]/ro_inst[0]/a_inferred_i_1__2}] +#set_property LOC SLICE_X188Y100 [get_cells {UART_FF_INS/RO[0]/ro_fanout_ins[0]/ro_inst[0]/a_inferred_i_1__2}] +#set_property BEL H6LUT [get_cells {UART_FF_INS/RO[0]/ro_fanout_ins[0]/ro_inst[0]/b_inferred_i_1__2}] +#set_property LOC SLICE_X187Y95 [get_cells {UART_FF_INS/RO[0]/ro_fanout_ins[0]/ro_inst[0]/b_inferred_i_1__2}] + + +#set_property USER_SLR_ASSIGNMENT SLR0 [get_cells -hier -filter {NAME =~ */RO_SENS}] + +#set_property USER_SLR_ASSIGNMENT SLR0 [get_cells -hier -filter {NAME =~ */chain[0]}] + + +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells -hier -filter {NAME =~ */instance_name}] + +set_property USER_SLR_ASSIGNMENT SLR0 [get_cells -hier -filter {NAME =~ */freq_gen_inst}] + + +set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets -hier -filter {NAME =~ *RO*}] + +#set_property USER_SLR_ASSIGNMENT SLR2 [get_cells -hierarchical -filter {NAME =~ *ff*}] + + + +create_pblock pb_ff +set_property IS_SOFT FALSE [get_pblocks pb_ff] +resize_pblock [get_pblocks pb_ff] -add {SLICE_X155Y480:SLICE_X163Y509} +add_cells_to_pblock {pb_ff} [get_cells -hier -filter {NAME =~ *ff*}] + + + +create_pblock pblock_SLL_1 +set_property IS_SOFT FALSE [get_pblocks pblock_SLL_1] +resize_pblock [get_pblocks pblock_SLL_1] -add {CLOCKREGION_X7Y3:CLOCKREGION_X7Y3} +add_cells_to_pblock {pblock_SLL_1} [get_nets {UART_FF_INS/v_int_sensor/inst/do_out}] +add_cells_to_pblock {pblock_SLL_1} [get_cells -hier -filter {NAME =~ *v_int*}] +set_property CONTAIN_ROUTING true [get_pblocks pblock_SLL_1] diff --git a/hwdbg/src/main/systemverilog/sensors/src/PL_CORE.v b/hwdbg/src/main/systemverilog/sensors/src/PL_CORE.v new file mode 100644 index 00000000..824e16b4 --- /dev/null +++ b/hwdbg/src/main/systemverilog/sensors/src/PL_CORE.v @@ -0,0 +1,64 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 03/08/2024 04:39:27 PM +// Design Name: +// Module Name: PL_CORE +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +module PL_CORE( + +(* clock_buffer_type="none" *) input wire QDR4_CLK_100MHZ_P, +(* clock_buffer_type="none" *) input wire QDR4_CLK_100MHZ_N, + +// input wire reg_clk, + input wire uart_rx_line, +// input wire reg_eop, +// input logic SPI_nCS, +// output wire clk_reg_out, + output wire uart_tx_line, +// output logic laser_module_trigger, + + output wire [3:0] led_out_ff +); + +wire clk_main; + clk_wiz_11 clock_main + ( + // Clock out ports + .clk_main(clk_main), // output clk_main + // Status and control signals + .reset(reset), // input reset + .locked(locked), // output locked + // Clock in ports + .clk_in1_p(QDR4_CLK_100MHZ_P), // input clk_in1_p + .clk_in1_n(QDR4_CLK_100MHZ_N) // input clk_in1_n +); + + +UART_FF UART_FF_INS ( + .clk (clk_main), + .rst ('b0), + .reg_clk (clk_main), + .reg_eop (clk_main), + .uart_rx_line (uart_rx_line), + .uart_tx_line (uart_tx_line), + .gpio (gpio), + .led_out_ff (led_out_ff) + ); + +endmodule diff --git a/hwdbg/src/main/systemverilog/sensors/src/ff_fanout.sv b/hwdbg/src/main/systemverilog/sensors/src/ff_fanout.sv new file mode 100644 index 00000000..d27277e8 --- /dev/null +++ b/hwdbg/src/main/systemverilog/sensors/src/ff_fanout.sv @@ -0,0 +1,89 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 11/16/2023 02:48:20 PM +// Design Name: +// Module Name: ff_fanout +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +module ff_fanout( +input wire clk, +input wire CE, +input wire rst, +input wire inp, +output reg res + ); + + + +//reg rst_em; // input clock on FPGA +//reg[27:0] counter=28'd0; +//parameter DIVISOR = 28'd1; +//// The frequency of the output clk_out +//// = The frequency of the input clk_in divided by DIVISOR +//// For example: Fclk_in = 50Mhz, if you want to get 1Hz signal to blink LEDs +//// You will modify the DIVISOR parameter value to 28'd50.000.000 +//// Then the frequency of the output clk_out = 50Mhz/50.000.000 = 1Hz +//always @(posedge rst) +//begin +// counter <= counter + 28'd1; +// if(counter>=(DIVISOR-1)) +// counter <= 28'd0; + + +// rst_em <= (counter= (div_int - 1)) begin + int_counter <= 32'd0; + clk_out_internal <= ~clk_out_internal; + end else begin + int_counter <= int_counter + 1; + end + end + end + + // Fractional Clock Division Logic + always_ff @(posedge clk_in or posedge reset) begin + if (reset) begin + frac_counter <= 32'd0; + frac_tick <= 1'b0; + end else begin + frac_counter <= frac_counter + div_frac; + if (frac_counter >= 32'd100000000) begin // When the counter exceeds 1.0 in fixed-point format + frac_counter <= frac_counter - 32'd100000000; + frac_tick <= 1'b1; + end else begin + frac_tick <= 1'b0; + end + end + end + + // Combine Integer and Fractional Divisions + always_ff @(posedge clk_in or posedge reset) begin + if (reset) begin + clk_out <= 1'b0; + end else if (int_counter == 0 && frac_tick) begin + clk_out <= ~clk_out_internal; + end else begin + clk_out <= clk_out_internal; + end + end + +endmodule diff --git a/hwdbg/src/main/systemverilog/sensors/src/inverter.v b/hwdbg/src/main/systemverilog/sensors/src/inverter.v new file mode 100644 index 00000000..937fff73 --- /dev/null +++ b/hwdbg/src/main/systemverilog/sensors/src/inverter.v @@ -0,0 +1,29 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 08/29/2023 01:50:41 PM +// Design Name: +// Module Name: inverter +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +module inverter( + in_data,out_data + ); + input in_data; + output out_data; + (* dont_touch = "yes" *) assign out_data = !in_data; +endmodule diff --git a/hwdbg/src/main/systemverilog/sensors/src/inverter_chain.v b/hwdbg/src/main/systemverilog/sensors/src/inverter_chain.v new file mode 100644 index 00000000..6a29a06d --- /dev/null +++ b/hwdbg/src/main/systemverilog/sensors/src/inverter_chain.v @@ -0,0 +1,43 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 09/11/2023 11:01:41 AM +// Design Name: +// Module Name: inverter_chain +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +module Chain( + chain_en, + in_data, + out_data + ); + parameter N = 2000; //This is the number of inverters in chain + input wire chain_en; + + input wire in_data; // This has to be connected to the input pin of the design according to the XDC file + + output wire out_data; // make sure to connect it to one of the output pin of the circuit according to the XDC file + (* dont_touch = "yes" *) wire [N-1:0] intermadiate_value; //For D-flip-flop implementation, make it reg instead of wire! + (* dont_touch = "yes" *) inverter inverter_in (.in_data(in_data&chain_en),.out_data(intermadiate_value[0])); // this is just for initiation, for loop chain, you can remove it. + generate + genvar i; + for (i=0; i= 'd1) begin + ff_id_reg <= uart_rx_data[0]; + current_state <= STATE_TRANSITION_INPUT; + end + end + end + + + STATE_GET_FF_ID: begin + if (uart_tx_ready) begin +// uart_tx_data[3] <= trigger_offset[7:0]; +// uart_tx_data[2] <= trigger_offset[15:8]; +// uart_tx_data[1] <= trigger_offset[23:16]; + uart_tx_data[0] <= ff_id_reg; + uart_tx_data_length <= 'd1; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + //STATE SENSORS + + + STATE_GET_TEMP_REG: begin + if (uart_tx_ready) begin + uart_tx_data[1] <= temp_reg[7:0]; + uart_tx_data[0] <= temp_reg[15:8]; + uart_tx_data_length <= 'd2; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + + STATE_GET_VINT_REG: begin + if (uart_tx_ready) begin + uart_tx_data[1] <= vint_reg[7:0]; + uart_tx_data[0] <= vint_reg[15:8]; + uart_tx_data_length <= 'd2; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + STATE_GET_VAUX_REG: begin + if (uart_tx_ready) begin + uart_tx_data[1] <= vaux_reg[7:0]; + uart_tx_data[0] <= vaux_reg[15:8]; + uart_tx_data_length <= 'd2; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + STATE_SET_FF_VAL: begin + if (uart_rx_updated_buffer) begin + if (uart_rx_data_length >= 'd1) begin + ff_in[ff_id_reg] <= uart_rx_data[0]&1; + ff_write_en[ff_id_reg]<=1; + current_state <= STATE_LOCK_VAL; + end + end + end + + + + STATE_SET_RO_MEAS_TIME: begin + if (uart_rx_updated_buffer) begin + if (uart_rx_data_length >= 'd8) begin + ro_meas_time[7:0] <= uart_rx_data[7];// data comes in big endian + ro_meas_time[15:8] <= uart_rx_data[6]; + ro_meas_time[23:16] <= uart_rx_data[5]; + ro_meas_time[31:24] <= uart_rx_data[4]; + ro_meas_time[39:32] <= uart_rx_data[3]; + ro_meas_time[47:40] <= uart_rx_data[2]; + ro_meas_time[55:48] <= uart_rx_data[1]; + ro_meas_time[63:56] <= uart_rx_data[0]; + current_state <= STATE_TRANSITION_INPUT; + end + end + end + + STATE_GET_RO_MEAS_TIME: begin + if (uart_tx_ready) begin + uart_tx_data[7]<= ro_meas_time[7:0]; // data comes in big endian + uart_tx_data[6]<=ro_meas_time[15:8] ; + uart_tx_data[5]<=ro_meas_time[23:16]; + uart_tx_data[4]<=ro_meas_time[31:24]; + uart_tx_data[3]<=ro_meas_time[39:32]; + uart_tx_data[2]<=ro_meas_time[47:40]; + uart_tx_data[1]<=ro_meas_time[55:48]; + uart_tx_data[0]<=ro_meas_time[63:56]; + uart_tx_data_length <= 'd8; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + + //AES STATES + STATE_SET_AES_PTX: begin + if (uart_rx_updated_buffer) begin + if (uart_rx_data_length >= 'd16) begin + aes_ptx[7:0] <= uart_rx_data[15];// data comes in big endian + aes_ptx[15:8] <= uart_rx_data[14]; + aes_ptx[23:16] <= uart_rx_data[13]; + aes_ptx[31:24] <= uart_rx_data[12]; + aes_ptx[39:32] <= uart_rx_data[11]; + aes_ptx[47:40] <= uart_rx_data[10]; + aes_ptx[55:48] <= uart_rx_data[9]; + aes_ptx[63:56] <= uart_rx_data[8]; + aes_ptx[71:64] <= uart_rx_data[7];// data comes in big endian + aes_ptx[79:72] <= uart_rx_data[6]; + aes_ptx[87:80] <= uart_rx_data[5]; + aes_ptx[95:88] <= uart_rx_data[4]; + aes_ptx[103:96] <= uart_rx_data[3]; + aes_ptx[111:104] <= uart_rx_data[2]; + aes_ptx[119:112] <= uart_rx_data[1]; + aes_ptx[127:120] <= uart_rx_data[0]; + current_state <= STATE_TRANSITION_INPUT; + end + end + end + + + STATE_GET_AES_PTX: begin + if (uart_tx_ready) begin + uart_tx_data[15]<= aes_ptx[7:0]; // data comes in big endian + uart_tx_data[14]<=aes_ptx[15:8] ; + uart_tx_data[13]<=aes_ptx[23:16]; + uart_tx_data[12]<=aes_ptx[31:24]; + uart_tx_data[11]<=aes_ptx[39:32]; + uart_tx_data[10]<=aes_ptx[47:40]; + uart_tx_data[9]<=aes_ptx[55:48]; + uart_tx_data[8]<=aes_ptx[63:56]; + uart_tx_data[7]<= aes_ptx[71:64]; // data comes in big endian + uart_tx_data[6]<=aes_ptx[79:72] ; + uart_tx_data[5]<=aes_ptx[87:80]; + uart_tx_data[4]<=aes_ptx[95:88]; + uart_tx_data[3]<=aes_ptx[103:96]; + uart_tx_data[2]<=aes_ptx[111:104]; + uart_tx_data[1]<=aes_ptx[119:112]; + uart_tx_data[0]<=aes_ptx[127:120]; + uart_tx_data_length <= 'd16; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + STATE_SET_AES_KEY: begin + if (uart_rx_updated_buffer) begin + if (uart_rx_data_length >= 'd16) begin + aes_key[7:0] <= uart_rx_data[15];// data comes in big endian + aes_key[15:8] <= uart_rx_data[14]; + aes_key[23:16] <= uart_rx_data[13]; + aes_key[31:24] <= uart_rx_data[12]; + aes_key[39:32] <= uart_rx_data[11]; + aes_key[47:40] <= uart_rx_data[10]; + aes_key[55:48] <= uart_rx_data[9]; + aes_key[63:56] <= uart_rx_data[8]; + aes_key[71:64] <= uart_rx_data[7];// data comes in big endian + aes_key[79:72] <= uart_rx_data[6]; + aes_key[87:80] <= uart_rx_data[5]; + aes_key[95:88] <= uart_rx_data[4]; + aes_key[103:96] <= uart_rx_data[3]; + aes_key[111:104] <= uart_rx_data[2]; + aes_key[119:112] <= uart_rx_data[1]; + aes_key[127:120] <= uart_rx_data[0]; + current_state <= STATE_TRANSITION_INPUT; + end + end + end + + + STATE_GET_AES_KEY: begin + if (uart_tx_ready) begin + uart_tx_data[15]<= aes_key[7:0]; // data comes in big endian + uart_tx_data[14]<=aes_key[15:8] ; + uart_tx_data[13]<=aes_key[23:16]; + uart_tx_data[12]<=aes_key[31:24]; + uart_tx_data[11]<=aes_key[39:32]; + uart_tx_data[10]<=aes_key[47:40]; + uart_tx_data[9]<=aes_key[55:48]; + uart_tx_data[8]<=aes_key[63:56]; + uart_tx_data[7]<= aes_key[71:64]; // data comes in big endian + uart_tx_data[6]<=aes_key[79:72] ; + uart_tx_data[5]<=aes_key[87:80]; + uart_tx_data[4]<=aes_key[95:88]; + uart_tx_data[3]<=aes_key[103:96]; + uart_tx_data[2]<=aes_key[111:104]; + uart_tx_data[1]<=aes_key[119:112]; + uart_tx_data[0]<=aes_key[127:120]; + uart_tx_data_length <= 'd16; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + + STATE_GET_AES_CTX: begin + if (uart_tx_ready) begin + uart_tx_data[15]<= aes_ctx[7:0]; // data comes in big endian + uart_tx_data[14]<=aes_ctx[15:8] ; + uart_tx_data[13]<=aes_ctx[23:16]; + uart_tx_data[12]<=aes_ctx[31:24]; + uart_tx_data[11]<=aes_ctx[39:32]; + uart_tx_data[10]<=aes_ctx[47:40]; + uart_tx_data[9]<=aes_ctx[55:48]; + uart_tx_data[8]<=aes_ctx[63:56]; + uart_tx_data[7]<= aes_ctx[71:64]; // data comes in big endian + uart_tx_data[6]<=aes_ctx[79:72] ; + uart_tx_data[5]<=aes_ctx[87:80]; + uart_tx_data[4]<=aes_ctx[95:88]; + uart_tx_data[3]<=aes_ctx[103:96]; + uart_tx_data[2]<=aes_ctx[111:104]; + uart_tx_data[1]<=aes_ctx[119:112]; + uart_tx_data[0]<=aes_ctx[127:120]; + uart_tx_data_length <= 'd16; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + + + + + STATE_EXEC_MEAS_RO: begin + ro_counter_en <= 1'b1; + current_state <= STATE_EXEC_MEAS_RO_POST; + + end + STATE_EXEC_MEAS_RO_POST: begin + ro_counter_en <= 1'b0; + current_state <= STATE_TRANSITION_INPUT; + + end + + + STATE_GET_MEAS_RO: begin + if (uart_tx_ready) begin + uart_tx_data[7]<= ro_meas_count[ro_id_reg][7:0]; // data comes in big endian + uart_tx_data[6]<=ro_meas_count[ro_id_reg][15:8] ; + uart_tx_data[5]<=ro_meas_count[ro_id_reg][23:16]; + uart_tx_data[4]<=ro_meas_count[ro_id_reg][31:24]; + uart_tx_data[3]<=ro_meas_count[ro_id_reg][39:32]; + uart_tx_data[2]<=ro_meas_count[ro_id_reg][47:40]; + uart_tx_data[1]<=ro_meas_count[ro_id_reg][55:48]; + uart_tx_data[0]<=ro_meas_count[ro_id_reg][63:56]; + uart_tx_data_length <= 'd8; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + +// STATE_GET_MEAS_RO: begin +// if (uart_tx_ready) begin +// uart_tx_data[7]<= ro_meas_count[7:0]; // data comes in big endian +// uart_tx_data[6]<=ro_meas_count[15:8] ; +// uart_tx_data[5]<=ro_meas_count[23:16]; +// uart_tx_data[4]<=ro_meas_count[31:24]; +// uart_tx_data[3]<=ro_meas_count[39:32]; +// uart_tx_data[2]<=ro_meas_count[47:40]; +// uart_tx_data[1]<=ro_meas_count[55:48]; +// uart_tx_data[0]<=ro_meas_count[63:56]; +// uart_tx_data_length <= 'd8; +// uart_tx_en <= 'b1; +// current_state <= STATE_TRANSITION_INPUT; +// end +// end + + STATE_ACTIVATE_CHAIN :begin + +// chain_en<='b1; + current_state <= STATE_TRANSITION_INPUT; + + end + + + STATE_DEACTIVATE_CHAIN :begin + +// chain_en<='b0; + current_state <= STATE_TRANSITION_INPUT; + + end + + + STATE_SET_CHAIN_FREQ_INT: begin + if (uart_rx_updated_buffer) begin + if (uart_rx_data_length >= 'd4) begin + div_int[7:0] <= uart_rx_data[3];// data comes in big endian + div_int[15:8] <= uart_rx_data[2]; + div_int[23:16] <= uart_rx_data[1]; + div_int[31:24] <= uart_rx_data[0]; + + current_state <= STATE_TRANSITION_INPUT; + end + end + end + + STATE_GET_CHAIN_FREQ_INT: begin + if (uart_tx_ready) begin + uart_tx_data[3]<= div_int[7:0]; // data comes in big endian + uart_tx_data[2]<=div_int[15:8] ; + uart_tx_data[1]<=div_int[23:16]; + uart_tx_data[0]<=div_int[31:24]; + + uart_tx_data_length <= 'd4; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + + + STATE_SET_CHAIN_FREQ_FRAC: begin + if (uart_rx_updated_buffer) begin + if (uart_rx_data_length >= 'd4) begin + div_frac[7:0] <= uart_rx_data[3];// data comes in big endian + div_frac[15:8] <= uart_rx_data[2]; + div_frac[23:16] <= uart_rx_data[1]; + div_frac[31:24] <= uart_rx_data[0]; + + current_state <= STATE_TRANSITION_INPUT; + end + end + end + + STATE_GET_CHAIN_FREQ_FRAC: begin + if (uart_tx_ready) begin + uart_tx_data[3]<= div_frac[7:0]; // data comes in big endian + uart_tx_data[2]<=div_frac[15:8] ; + uart_tx_data[1]<=div_frac[23:16]; + uart_tx_data[0]<=div_frac[31:24]; + + uart_tx_data_length <= 'd4; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + + + + STATE_LOCK_VAL: begin + + ff_write_en[ff_id_reg]<=0; + current_state <= STATE_TRANSITION_INPUT; + + end + + + + + STATE_GET_FF_VAL: begin + + if (uart_tx_ready) begin + uart_tx_data[0] <= {8{ff_in[ff_id_reg]}}; + uart_tx_data_length <= 'd1; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + +// STATE_GET_NUMBER_OF_NCS: begin +// if (uart_tx_ready) begin +// uart_tx_data[3] <= number_of_ncs[7:0]; +// uart_tx_data[2] <= number_of_ncs[15:8]; +// uart_tx_data[1] <= number_of_ncs[23:16]; +// uart_tx_data[0] <= number_of_ncs[31:24]; +// uart_tx_data_length <= 'd4; +// uart_tx_en <= 'b1; +// current_state <= STATE_TRANSITION_INPUT; +// end +// end + + STATE_SET_GPIO: begin + // gpio <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + + + + STATE_SET_RO_ID: begin + if (uart_rx_updated_buffer) begin + if (uart_rx_data_length >= 'd1) begin + ro_id_reg <= uart_rx_data[0]; + current_state <= STATE_TRANSITION_INPUT; + end + end + end + + + STATE_GET_RO_ID: begin + if (uart_tx_ready) begin +// uart_tx_data[3] <= trigger_offset[7:0]; +// uart_tx_data[2] <= trigger_offset[15:8]; +// uart_tx_data[1] <= trigger_offset[23:16]; + uart_tx_data[0] <= ro_id_reg; + uart_tx_data_length <= 'd1; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + STATE_SET_RO_VAL: begin + if (uart_rx_updated_buffer) begin + if (uart_rx_data_length >= 'd1) begin + ro_en[ro_id_reg] <= uart_rx_data[0]&1; + current_state <= STATE_TRANSITION_INPUT; + end + end + end + + + + + STATE_GET_RO_VAL: begin + if (uart_tx_ready) begin + uart_tx_data[0] <= {8{ro_en[ro_id_reg]}}; + uart_tx_data_length <= 'd1; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + // CHAIN ID/VAL States + + STATE_SET_CHAIN_ID: begin + if (uart_rx_updated_buffer) begin + if (uart_rx_data_length >= 'd1) begin + chain_id_reg <= uart_rx_data[0]; + current_state <= STATE_TRANSITION_INPUT; + end + end + end + + + STATE_GET_CHAIN_ID: begin + if (uart_tx_ready) begin +// uart_tx_data[3] <= trigger_offset[7:0]; +// uart_tx_data[2] <= trigger_offset[15:8]; +// uart_tx_data[1] <= trigger_offset[23:16]; + uart_tx_data[0] <= chain_id_reg; + uart_tx_data_length <= 'd1; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + STATE_SET_CHAIN_VAL: begin + if (uart_rx_updated_buffer) begin + if (uart_rx_data_length >= 'd1) begin + chain_en[chain_id_reg] <= uart_rx_data[0]&1; + current_state <= STATE_TRANSITION_INPUT; + end + end + end + + + + + STATE_GET_CHAIN_VAL: begin + if (uart_tx_ready) begin + uart_tx_data[0] <= {8{chain_en[chain_id_reg]}}; + uart_tx_data_length <= 'd1; + uart_tx_en <= 'b1; + current_state <= STATE_TRANSITION_INPUT; + end + end + + + + + + STATE_UNSET_GPIO: begin + // gpio <= 'b0; + current_state <= STATE_TRANSITION_INPUT; + end + + STATE_TRANSITION_INPUT: begin + uart_rx_empty_buffer <= 'b1; + current_state <= STATE_INPUT; + end + endcase + end + end +endmodule \ No newline at end of file diff --git a/hwdbg/src/main/systemverilog/sensors/src/uart_rx.sv b/hwdbg/src/main/systemverilog/sensors/src/uart_rx.sv new file mode 100644 index 00000000..a54364b4 --- /dev/null +++ b/hwdbg/src/main/systemverilog/sensors/src/uart_rx.sv @@ -0,0 +1,99 @@ +module uart_rx +#( + parameter SYSTEMCLOCK = 100_000_000, + parameter BAUDRATE = 115_200, + parameter ELEMENT_WIDTH = 8, + localparam ELEMENT_BIT_COUNTER_WIDTH = $clog2(ELEMENT_WIDTH), + localparam CLOCK_COUNTER_WIDTH = 32, + localparam CLOCKS_PER_BAUD = SYSTEMCLOCK / BAUDRATE +)( + input logic clk, + input logic rst, + input logic rx_line, + output logic [ELEMENT_WIDTH-1:0] rx_data, + output logic rx_data_valid +); + + typedef enum { + STATE_IDLE, + STATE_START_BIT, + STATE_RECEIVE_ELEMENT, + STATE_CHECK_ELEMENT_RECEIVED, + STATE_STOP_BIT, + STATE_DONE + } state_t; + state_t current_state; + + logic [ELEMENT_BIT_COUNTER_WIDTH:0] current_bit; + logic [CLOCK_COUNTER_WIDTH-1:0] clock_counter; + logic clocks_per_baud_reached; + logic half_clocks_per_baud_reached; + + assign clocks_per_baud_reached = (clock_counter >= CLOCKS_PER_BAUD); + assign half_clocks_per_baud_reached = (clock_counter >= (CLOCKS_PER_BAUD / 2)); + assign rx_data = rx_data; + assign rx_data_valid = current_state == STATE_DONE; + + always_ff @(posedge clk) begin + if (rst) begin + current_state <= STATE_IDLE; + current_bit <= 'b0; + rx_data <= 'b0; + clock_counter <= 'd0; + + end else begin + current_state <= current_state; + current_bit <= current_bit; + rx_data <= rx_data; + clock_counter <= clock_counter + 1; + + case (current_state) + + STATE_IDLE: begin + if (rx_line == 'b0) begin + current_state <= STATE_START_BIT; + clock_counter <= 'b0; + end + end + + STATE_START_BIT: begin + if (half_clocks_per_baud_reached) begin + current_state <= STATE_RECEIVE_ELEMENT; + clock_counter <= 'b0; + current_bit <= 'b0; + end + end + + STATE_RECEIVE_ELEMENT: begin + if (clocks_per_baud_reached) begin + rx_data[current_bit] <= rx_line; + current_bit <= current_bit + 1; + clock_counter <= 'd0; + current_state <= STATE_CHECK_ELEMENT_RECEIVED; + end + end + + STATE_CHECK_ELEMENT_RECEIVED: begin + if (current_bit >= ELEMENT_WIDTH) begin + current_state <= STATE_STOP_BIT; + end else begin + current_state <= STATE_RECEIVE_ELEMENT; + end + end + + STATE_STOP_BIT: begin + if (clocks_per_baud_reached) begin + current_state <= STATE_DONE; + clock_counter <= 'd0; + end + end + + STATE_DONE: begin + current_state <= STATE_IDLE; + end + + endcase + end + end + +endmodule \ No newline at end of file diff --git a/hwdbg/src/main/systemverilog/sensors/src/uart_tx.sv b/hwdbg/src/main/systemverilog/sensors/src/uart_tx.sv new file mode 100644 index 00000000..a5f4a7e3 --- /dev/null +++ b/hwdbg/src/main/systemverilog/sensors/src/uart_tx.sv @@ -0,0 +1,104 @@ +module uart_tx +#( + parameter SYSTEMCLOCK = 100_000_000, + parameter BAUDRATE = 115_200, + parameter ELEMENT_WIDTH = 8, + localparam ELEMENT_BIT_COUNTER_WIDTH = $clog2(ELEMENT_WIDTH), + localparam CLOCK_COUNTER_WIDTH = 32, + localparam CLOCKS_PER_BAUD = SYSTEMCLOCK / BAUDRATE +)( + input logic clk, + input logic rst, + input logic tx_en, + input logic [ELEMENT_WIDTH-1:0] tx_data, + output logic tx_line, + output logic tx_ready +); + + typedef enum { + STATE_IDLE, + STATE_START_BIT, + STATE_TRANSFER_ELEMENT, + STATE_CHECK_ELEMENT_TRANSFERRED, + STATE_STOP_BIT, + STATE_DONE + } state_t; + state_t current_state; + + logic [ELEMENT_BIT_COUNTER_WIDTH:0] bit_counter = 'b0; + logic [CLOCK_COUNTER_WIDTH:0] clock_counter = 'b0; + + logic clocks_per_baud_reached; + assign clocks_per_baud_reached = (clock_counter >= CLOCKS_PER_BAUD); + + always @(posedge clk) begin + + if (rst) begin + current_state <= STATE_IDLE; + bit_counter <= 'd0; + clock_counter <= 'd0; + tx_line <= 'b1; + tx_ready <= 'b0; + + end else begin + + clock_counter <= clock_counter + 1; + current_state <= current_state; + bit_counter <= bit_counter; + tx_line <= tx_line; + tx_ready <= tx_ready; + + case (current_state) + + STATE_IDLE: begin + if (tx_en) begin + current_state <= STATE_START_BIT; + tx_line <= 'b0; + tx_ready <= 'b0; + end else begin + tx_line <= 'b1; + tx_ready <= 'b1; + end + end + + STATE_START_BIT: begin + current_state <= STATE_TRANSFER_ELEMENT; + bit_counter <= 'd0; + clock_counter <= 'd0; + end + + STATE_TRANSFER_ELEMENT: begin + if(clocks_per_baud_reached) begin + clock_counter <= 'b0; + tx_line <= tx_data[bit_counter]; + bit_counter <= bit_counter + 1; + current_state <= STATE_CHECK_ELEMENT_TRANSFERRED; + end + end + + STATE_CHECK_ELEMENT_TRANSFERRED: begin + if (bit_counter >= ELEMENT_WIDTH) begin + current_state <= STATE_STOP_BIT; + end else begin + current_state <= STATE_TRANSFER_ELEMENT; + end + end + + STATE_STOP_BIT: begin + if(clocks_per_baud_reached) begin + tx_line <= 'b1; + clock_counter <= 'd0; + current_state <= STATE_DONE; + end + end + + STATE_DONE: begin + if (clocks_per_baud_reached) begin + tx_ready <= 'b1; + current_state <= STATE_IDLE; + end + end + endcase + end + end +endmodule \ No newline at end of file diff --git a/hwdbg/src/test/bram/instance_info.hex.txt b/hwdbg/src/test/bram/instance_info.hex.txt new file mode 100644 index 00000000..7c72056c --- /dev/null +++ b/hwdbg/src/test/bram/instance_info.hex.txt @@ -0,0 +1,256 @@ +0000005a ; +0x0 | Checksum +00000000 ; +0x4 | Checksum +52444247 ; +0x8 | Indicator +48595045 ; +0xc | Indicator +00000004 ; +0x10 | TypeOfThePacket - DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL (0x4) +00000001 ; +0x14 | RequestedActionOfThePacket - Value (0x1) +00000000 ; +0x18 +00000000 ; +0x1c +00000000 ; +0x20 +00000000 ; +0x24 +00000000 ; +0x28 +00000000 ; +0x2c +00000000 ; +0x30 +00000000 ; +0x34 +00000000 ; +0x38 +00000000 ; +0x3c +00000000 ; +0x40 +00000000 ; +0x44 +00000000 ; +0x48 +00000000 ; +0x4c +00000000 ; +0x50 +00000000 ; +0x54 +00000000 ; +0x58 +00000000 ; +0x5c +00000000 ; +0x60 +00000000 ; +0x64 +00000000 ; +0x68 +00000000 ; +0x6c +00000000 ; +0x70 +00000000 ; +0x74 +00000000 ; +0x78 +00000000 ; +0x7c +00000000 ; +0x80 +00000000 ; +0x84 +00000000 ; +0x88 +00000000 ; +0x8c +00000000 ; +0x90 +00000000 ; +0x94 +00000000 ; +0x98 +00000000 ; +0x9c +00000000 ; +0xa0 +00000000 ; +0xa4 +00000000 ; +0xa8 +00000000 ; +0xac +00000000 ; +0xb0 +00000000 ; +0xb4 +00000000 ; +0xb8 +00000000 ; +0xbc +00000000 ; +0xc0 +00000000 ; +0xc4 +00000000 ; +0xc8 +00000000 ; +0xcc +00000000 ; +0xd0 +00000000 ; +0xd4 +00000000 ; +0xd8 +00000000 ; +0xdc +00000000 ; +0xe0 +00000000 ; +0xe4 +00000000 ; +0xe8 +00000000 ; +0xec +00000000 ; +0xf0 +00000000 ; +0xf4 +00000000 ; +0xf8 +00000000 ; +0xfc +00000000 ; +0x100 +00000000 ; +0x104 +00000000 ; +0x108 +00000000 ; +0x10c +00000000 ; +0x110 +00000000 ; +0x114 +00000000 ; +0x118 +00000000 ; +0x11c +00000000 ; +0x120 +00000000 ; +0x124 +00000000 ; +0x128 +00000000 ; +0x12c +00000000 ; +0x130 +00000000 ; +0x134 +00000000 ; +0x138 +00000000 ; +0x13c +00000000 ; +0x140 +00000000 ; +0x144 +00000000 ; +0x148 +00000000 ; +0x14c +00000000 ; +0x150 +00000000 ; +0x154 +00000000 ; +0x158 +00000000 ; +0x15c +00000000 ; +0x160 +00000000 ; +0x164 +00000000 ; +0x168 +00000000 ; +0x16c +00000000 ; +0x170 +00000000 ; +0x174 +00000000 ; +0x178 +00000000 ; +0x17c +00000000 ; +0x180 +00000000 ; +0x184 +00000000 ; +0x188 +00000000 ; +0x18c +00000000 ; +0x190 +00000000 ; +0x194 +00000000 ; +0x198 +00000000 ; +0x19c +00000000 ; +0x1a0 +00000000 ; +0x1a4 +00000000 ; +0x1a8 +00000000 ; +0x1ac +00000000 ; +0x1b0 +00000000 ; +0x1b4 +00000000 ; +0x1b8 +00000000 ; +0x1bc +00000000 ; +0x1c0 +00000000 ; +0x1c4 +00000000 ; +0x1c8 +00000000 ; +0x1cc +00000000 ; +0x1d0 +00000000 ; +0x1d4 +00000000 ; +0x1d8 +00000000 ; +0x1dc +00000000 ; +0x1e0 +00000000 ; +0x1e4 +00000000 ; +0x1e8 +00000000 ; +0x1ec +00000000 ; +0x1f0 +00000000 ; +0x1f4 +00000000 ; +0x1f8 +00000000 ; +0x1fc +00000000 ; +0x200 +00000000 ; +0x204 +00000000 ; +0x208 +00000000 ; +0x20c +00000000 ; +0x210 +00000000 ; +0x214 +00000000 ; +0x218 +00000000 ; +0x21c +00000000 ; +0x220 +00000000 ; +0x224 +00000000 ; +0x228 +00000000 ; +0x22c +00000000 ; +0x230 +00000000 ; +0x234 +00000000 ; +0x238 +00000000 ; +0x23c +00000000 ; +0x240 +00000000 ; +0x244 +00000000 ; +0x248 +00000000 ; +0x24c +00000000 ; +0x250 +00000000 ; +0x254 +00000000 ; +0x258 +00000000 ; +0x25c +00000000 ; +0x260 +00000000 ; +0x264 +00000000 ; +0x268 +00000000 ; +0x26c +00000000 ; +0x270 +00000000 ; +0x274 +00000000 ; +0x278 +00000000 ; +0x27c +00000000 ; +0x280 +00000000 ; +0x284 +00000000 ; +0x288 +00000000 ; +0x28c +00000000 ; +0x290 +00000000 ; +0x294 +00000000 ; +0x298 +00000000 ; +0x29c +00000000 ; +0x2a0 +00000000 ; +0x2a4 +00000000 ; +0x2a8 +00000000 ; +0x2ac +00000000 ; +0x2b0 +00000000 ; +0x2b4 +00000000 ; +0x2b8 +00000000 ; +0x2bc +00000000 ; +0x2c0 +00000000 ; +0x2c4 +00000000 ; +0x2c8 +00000000 ; +0x2cc +00000000 ; +0x2d0 +00000000 ; +0x2d4 +00000000 ; +0x2d8 +00000000 ; +0x2dc +00000000 ; +0x2e0 +00000000 ; +0x2e4 +00000000 ; +0x2e8 +00000000 ; +0x2ec +00000000 ; +0x2f0 +00000000 ; +0x2f4 +00000000 ; +0x2f8 +00000000 ; +0x2fc +00000000 ; +0x300 +00000000 ; +0x304 +00000000 ; +0x308 +00000000 ; +0x30c +00000000 ; +0x310 +00000000 ; +0x314 +00000000 ; +0x318 +00000000 ; +0x31c +00000000 ; +0x320 +00000000 ; +0x324 +00000000 ; +0x328 +00000000 ; +0x32c +00000000 ; +0x330 +00000000 ; +0x334 +00000000 ; +0x338 +00000000 ; +0x33c +00000000 ; +0x340 +00000000 ; +0x344 +00000000 ; +0x348 +00000000 ; +0x34c +00000000 ; +0x350 +00000000 ; +0x354 +00000000 ; +0x358 +00000000 ; +0x35c +00000000 ; +0x360 +00000000 ; +0x364 +00000000 ; +0x368 +00000000 ; +0x36c +00000000 ; +0x370 +00000000 ; +0x374 +00000000 ; +0x378 +00000000 ; +0x37c +00000000 ; +0x380 +00000000 ; +0x384 +00000000 ; +0x388 +00000000 ; +0x38c +00000000 ; +0x390 +00000000 ; +0x394 +00000000 ; +0x398 +00000000 ; +0x39c +00000000 ; +0x3a0 +00000000 ; +0x3a4 +00000000 ; +0x3a8 +00000000 ; +0x3ac +00000000 ; +0x3b0 +00000000 ; +0x3b4 +00000000 ; +0x3b8 +00000000 ; +0x3bc +00000000 ; +0x3c0 +00000000 ; +0x3c4 +00000000 ; +0x3c8 +00000000 ; +0x3cc +00000000 ; +0x3d0 +00000000 ; +0x3d4 +00000000 ; +0x3d8 +00000000 ; +0x3dc +00000000 ; +0x3e0 +00000000 ; +0x3e4 +00000000 ; +0x3e8 +00000000 ; +0x3ec +00000000 ; +0x3f0 +00000000 ; +0x3f4 +00000000 ; +0x3f8 +00000000 ; +0x3fc \ No newline at end of file diff --git a/hwdbg/src/test/bram/script_buffer.hex.txt b/hwdbg/src/test/bram/script_buffer.hex.txt new file mode 100644 index 00000000..73e93432 --- /dev/null +++ b/hwdbg/src/test/bram/script_buffer.hex.txt @@ -0,0 +1,256 @@ +000000b9 ; +0x0 | Checksum +00000000 ; +0x4 | Checksum +52444247 ; +0x8 | Indicator +48595045 ; +0xc | Indicator +00000004 ; +0x10 | TypeOfThePacket - DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL (0x4) +00000002 ; +0x14 | RequestedActionOfThePacket - Value (0x2) +00000007 ; +0x18 | Start of Optional Data +00000006 ; +0x1c +0000000a ; +0x20 +00000003 ; +0x24 +00000000 ; +0x28 +0000000f ; +0x2c +00000000 ; +0x30 +0000000f ; +0x34 +00000000 ; +0x38 +00000006 ; +0x3c +00000018 ; +0x40 +00000003 ; +0x44 +00000001 ; +0x48 +00000000 ; +0x4c +00000000 ; +0x50 +00000004 ; +0x54 +00000000 ; +0x58 +00000000 ; +0x5c +00000000 ; +0x60 +00000000 ; +0x64 +00000000 ; +0x68 +00000000 ; +0x6c +00000000 ; +0x70 +00000000 ; +0x74 +00000000 ; +0x78 +00000000 ; +0x7c +00000000 ; +0x80 +00000000 ; +0x84 +00000000 ; +0x88 +00000000 ; +0x8c +00000000 ; +0x90 +00000000 ; +0x94 +00000000 ; +0x98 +00000000 ; +0x9c +00000000 ; +0xa0 +00000000 ; +0xa4 +00000000 ; +0xa8 +00000000 ; +0xac +00000000 ; +0xb0 +00000000 ; +0xb4 +00000000 ; +0xb8 +00000000 ; +0xbc +00000000 ; +0xc0 +00000000 ; +0xc4 +00000000 ; +0xc8 +00000000 ; +0xcc +00000000 ; +0xd0 +00000000 ; +0xd4 +00000000 ; +0xd8 +00000000 ; +0xdc +00000000 ; +0xe0 +00000000 ; +0xe4 +00000000 ; +0xe8 +00000000 ; +0xec +00000000 ; +0xf0 +00000000 ; +0xf4 +00000000 ; +0xf8 +00000000 ; +0xfc +00000000 ; +0x100 +00000000 ; +0x104 +00000000 ; +0x108 +00000000 ; +0x10c +00000000 ; +0x110 +00000000 ; +0x114 +00000000 ; +0x118 +00000000 ; +0x11c +00000000 ; +0x120 +00000000 ; +0x124 +00000000 ; +0x128 +00000000 ; +0x12c +00000000 ; +0x130 +00000000 ; +0x134 +00000000 ; +0x138 +00000000 ; +0x13c +00000000 ; +0x140 +00000000 ; +0x144 +00000000 ; +0x148 +00000000 ; +0x14c +00000000 ; +0x150 +00000000 ; +0x154 +00000000 ; +0x158 +00000000 ; +0x15c +00000000 ; +0x160 +00000000 ; +0x164 +00000000 ; +0x168 +00000000 ; +0x16c +00000000 ; +0x170 +00000000 ; +0x174 +00000000 ; +0x178 +00000000 ; +0x17c +00000000 ; +0x180 +00000000 ; +0x184 +00000000 ; +0x188 +00000000 ; +0x18c +00000000 ; +0x190 +00000000 ; +0x194 +00000000 ; +0x198 +00000000 ; +0x19c +00000000 ; +0x1a0 +00000000 ; +0x1a4 +00000000 ; +0x1a8 +00000000 ; +0x1ac +00000000 ; +0x1b0 +00000000 ; +0x1b4 +00000000 ; +0x1b8 +00000000 ; +0x1bc +00000000 ; +0x1c0 +00000000 ; +0x1c4 +00000000 ; +0x1c8 +00000000 ; +0x1cc +00000000 ; +0x1d0 +00000000 ; +0x1d4 +00000000 ; +0x1d8 +00000000 ; +0x1dc +00000000 ; +0x1e0 +00000000 ; +0x1e4 +00000000 ; +0x1e8 +00000000 ; +0x1ec +00000000 ; +0x1f0 +00000000 ; +0x1f4 +00000000 ; +0x1f8 +00000000 ; +0x1fc +00000000 ; +0x200 +00000000 ; +0x204 +00000000 ; +0x208 +00000000 ; +0x20c +00000000 ; +0x210 +00000000 ; +0x214 +00000000 ; +0x218 +00000000 ; +0x21c +00000000 ; +0x220 +00000000 ; +0x224 +00000000 ; +0x228 +00000000 ; +0x22c +00000000 ; +0x230 +00000000 ; +0x234 +00000000 ; +0x238 +00000000 ; +0x23c +00000000 ; +0x240 +00000000 ; +0x244 +00000000 ; +0x248 +00000000 ; +0x24c +00000000 ; +0x250 +00000000 ; +0x254 +00000000 ; +0x258 +00000000 ; +0x25c +00000000 ; +0x260 +00000000 ; +0x264 +00000000 ; +0x268 +00000000 ; +0x26c +00000000 ; +0x270 +00000000 ; +0x274 +00000000 ; +0x278 +00000000 ; +0x27c +00000000 ; +0x280 +00000000 ; +0x284 +00000000 ; +0x288 +00000000 ; +0x28c +00000000 ; +0x290 +00000000 ; +0x294 +00000000 ; +0x298 +00000000 ; +0x29c +00000000 ; +0x2a0 +00000000 ; +0x2a4 +00000000 ; +0x2a8 +00000000 ; +0x2ac +00000000 ; +0x2b0 +00000000 ; +0x2b4 +00000000 ; +0x2b8 +00000000 ; +0x2bc +00000000 ; +0x2c0 +00000000 ; +0x2c4 +00000000 ; +0x2c8 +00000000 ; +0x2cc +00000000 ; +0x2d0 +00000000 ; +0x2d4 +00000000 ; +0x2d8 +00000000 ; +0x2dc +00000000 ; +0x2e0 +00000000 ; +0x2e4 +00000000 ; +0x2e8 +00000000 ; +0x2ec +00000000 ; +0x2f0 +00000000 ; +0x2f4 +00000000 ; +0x2f8 +00000000 ; +0x2fc +00000000 ; +0x300 +00000000 ; +0x304 +00000000 ; +0x308 +00000000 ; +0x30c +00000000 ; +0x310 +00000000 ; +0x314 +00000000 ; +0x318 +00000000 ; +0x31c +00000000 ; +0x320 +00000000 ; +0x324 +00000000 ; +0x328 +00000000 ; +0x32c +00000000 ; +0x330 +00000000 ; +0x334 +00000000 ; +0x338 +00000000 ; +0x33c +00000000 ; +0x340 +00000000 ; +0x344 +00000000 ; +0x348 +00000000 ; +0x34c +00000000 ; +0x350 +00000000 ; +0x354 +00000000 ; +0x358 +00000000 ; +0x35c +00000000 ; +0x360 +00000000 ; +0x364 +00000000 ; +0x368 +00000000 ; +0x36c +00000000 ; +0x370 +00000000 ; +0x374 +00000000 ; +0x378 +00000000 ; +0x37c +00000000 ; +0x380 +00000000 ; +0x384 +00000000 ; +0x388 +00000000 ; +0x38c +00000000 ; +0x390 +00000000 ; +0x394 +00000000 ; +0x398 +00000000 ; +0x39c +00000000 ; +0x3a0 +00000000 ; +0x3a4 +00000000 ; +0x3a8 +00000000 ; +0x3ac +00000000 ; +0x3b0 +00000000 ; +0x3b4 +00000000 ; +0x3b8 +00000000 ; +0x3bc +00000000 ; +0x3c0 +00000000 ; +0x3c4 +00000000 ; +0x3c8 +00000000 ; +0x3cc +00000000 ; +0x3d0 +00000000 ; +0x3d4 +00000000 ; +0x3d8 +00000000 ; +0x3dc +00000000 ; +0x3e0 +00000000 ; +0x3e4 +00000000 ; +0x3e8 +00000000 ; +0x3ec +00000000 ; +0x3f0 +00000000 ; +0x3f4 +00000000 ; +0x3f8 +00000000 ; +0x3fc \ No newline at end of file diff --git a/hyperdbg/CMakeLists.txt b/hyperdbg/CMakeLists.txt new file mode 100644 index 00000000..ba5b3855 --- /dev/null +++ b/hyperdbg/CMakeLists.txt @@ -0,0 +1,94 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +cmake_minimum_required(VERSION 3.28) +project(hyperdbg C CXX) +set(CMAKE_CXX_STANDARD 23) +enable_language(ASM_MASM) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +if(LINUX) + + message(STATUS "Building on Linux") +elseif(WIN32) + message(STATUS "Building on Windows") +find_package(WDK REQUIRED) + + include_directories( + "dependencies/zydis/include" + "dependencies/zydis/src" + "dependencies/zydis/dependencies/zycore/include" + ) + + file(GLOB ZydisSourceFiles "dependencies/zydis/src/*.c") + file(GLOB ZycoreSourceFiles "dependencies/zydis/dependencies/zycore/*.c") + + set(SourceFiles + ${ZydisSourceFiles} + ${ZycoreSourceFiles} + # examples/ZydisWinKernel.c + ) + + add_definitions( + -DZYAN_NO_LIBC + -DZYDIS_NO_LIBC + -DZYCORE_STATIC_BUILD + -DZYDIS_STATIC_BUILD + ) + + wdk_add_library(zydisKernel + KMDF 1.15 + ${SourceFiles} + ) +link_directories(libraries/kdserial/x64) +add_subdirectory(kdserial) +target_link_libraries(kdserial kdserialtransport kdhv kdtelemetry) + + +add_subdirectory(hyperlog) +link_directories(libraries/zydis/kernel) +add_subdirectory(hyperhv) +target_link_libraries(hyperhv Zycore Zydis) + + +add_subdirectory(hyperkd) +target_link_libraries(hyperkd hyperlog hyperhv kdserial) + +endif() + +#add_subdirectory(dependencies/pdbex/Source) + +#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) +link_directories(libraries/zydis/user libraries/keystone/release-lib) +add_subdirectory(libhyperdbg) +find_package(Threads REQUIRED) +target_link_libraries(libhyperdbg Zycore Zydis script-engine keystone Threads::Threads) + +add_subdirectory(hyperdbg-cli) +target_link_libraries(hyperdbg-cli libhyperdbg) + + + +#set(save_src_dir ${CMAKE_CURRENT_SOURCE_DIR}/examples) +#execute_process( COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/../examples ${save_src_dir}) +# +#add_subdirectory(examples/kernel/hyperdbg_driver) +#target_link_libraries(hyperdbg_driver hyperlog hyperhv) +# +# +#add_subdirectory(examples/user/hyperdbg_app) +#target_link_libraries(hyperdbg_app libhyperdbg) + diff --git a/hyperdbg/FindWdk.cmake b/hyperdbg/FindWdk.cmake new file mode 100644 index 00000000..12765781 --- /dev/null +++ b/hyperdbg/FindWdk.cmake @@ -0,0 +1,209 @@ +# Redistribution and use is allowed under the OSI-approved 3-clause BSD license. +# Copyright (c) 2018 Sergey Podobry (sergey.podobry at gmail.com). All rights reserved. + +#.rst: +# FindWDK +# ---------- +# +# This module searches for the installed Windows Development Kit (WDK) and +# exposes commands for creating kernel drivers and kernel libraries. +# +# Output variables: +# - `WDK_FOUND` -- if false, do not try to use WDK +# - `WDK_ROOT` -- where WDK is installed +# - `WDK_VERSION` -- the version of the selected WDK +# - `WDK_WINVER` -- the WINVER used for kernel drivers and libraries +# (default value is `0x0601` and can be changed per target or globally) +# - `WDK_NTDDI_VERSION` -- the NTDDI_VERSION used for kernel drivers and libraries, +# if not set, the value will be automatically calculated by WINVER +# (default value is left blank and can be changed per target or globally) +# +# Example usage: +# +# find_package(WDK REQUIRED) +# +# wdk_add_library(KmdfCppLib STATIC KMDF 1.15 +# KmdfCppLib.h +# KmdfCppLib.cpp +# ) +# target_include_directories(KmdfCppLib INTERFACE .) +# +# wdk_add_driver(KmdfCppDriver KMDF 1.15 +# Main.cpp +# ) +# target_link_libraries(KmdfCppDriver KmdfCppLib) +# + +if(DEFINED ENV{WDKContentRoot}) + file(GLOB WDK_NTDDK_FILES + "$ENV{WDKContentRoot}/Include/*/km/ntddk.h" # WDK 10 + "$ENV{WDKContentRoot}/Include/km/ntddk.h" # WDK 8.0, 8.1 + ) +else() + file(GLOB WDK_NTDDK_FILES + "C:/Program Files*/Windows Kits/*/Include/*/km/ntddk.h" # WDK 10 + "C:/Program Files*/Windows Kits/*/Include/km/ntddk.h" # WDK 8.0, 8.1 + ) +endif() + +if(WDK_NTDDK_FILES) + if (NOT CMAKE_VERSION VERSION_LESS 3.18.0) + list(SORT WDK_NTDDK_FILES COMPARE NATURAL) # sort to use the latest available WDK + endif() + list(GET WDK_NTDDK_FILES -1 WDK_LATEST_NTDDK_FILE) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(WDK REQUIRED_VARS WDK_LATEST_NTDDK_FILE) + +if (NOT WDK_LATEST_NTDDK_FILE) + return() +endif() + +get_filename_component(WDK_ROOT ${WDK_LATEST_NTDDK_FILE} DIRECTORY) +get_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY) +get_filename_component(WDK_VERSION ${WDK_ROOT} NAME) +get_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY) +if (NOT WDK_ROOT MATCHES ".*/[0-9][0-9.]*$") # WDK 10 has a deeper nesting level + get_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY) # go up once more + set(WDK_LIB_VERSION "${WDK_VERSION}") + set(WDK_INC_VERSION "${WDK_VERSION}") +else() # WDK 8.0, 8.1 + set(WDK_INC_VERSION "") + foreach(VERSION winv6.3 win8 win7) + if (EXISTS "${WDK_ROOT}/Lib/${VERSION}/") + set(WDK_LIB_VERSION "${VERSION}") + break() + endif() + endforeach() + set(WDK_VERSION "${WDK_LIB_VERSION}") +endif() + +message(STATUS "WDK_ROOT: " ${WDK_ROOT}) +message(STATUS "WDK_VERSION: " ${WDK_VERSION}) + +set(WDK_WINVER "0x0a01" CACHE STRING "Default WINVER for WDK targets") +set(WDK_NTDDI_VERSION "" CACHE STRING "Specified NTDDI_VERSION for WDK targets if needed") + +set(WDK_ADDITIONAL_FLAGS_FILE "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/wdkflags.h") +file(WRITE ${WDK_ADDITIONAL_FLAGS_FILE} "#pragma runtime_checks(\"suc\", off)") + +set(WDK_COMPILE_FLAGS + "/Zp8" # set struct alignment + "/GF" # enable string pooling + "/GR-" # disable RTTI + "/Gz" # __stdcall by default + "/kernel" # create kernel mode binary + "/FIwarning.h" # disable warnings in WDK headers + "/FI${WDK_ADDITIONAL_FLAGS_FILE}" # include file to disable RTC + ) + +set(WDK_COMPILE_DEFINITIONS "WINNT=1") +set(WDK_COMPILE_DEFINITIONS_DEBUG "MSC_NOOPT;DEPRECATE_DDK_FUNCTIONS=1;DBG=1") + +if(CMAKE_SIZEOF_VOID_P EQUAL 4) + list(APPEND WDK_COMPILE_DEFINITIONS "_X86_=1;i386=1;STD_CALL") + set(WDK_PLATFORM "x86") +elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND WDK_COMPILE_DEFINITIONS "_WIN64;_AMD64_;AMD64") + set(WDK_PLATFORM "x64") +else() + message(FATAL_ERROR "Unsupported architecture") +endif() + +string(CONCAT WDK_LINK_FLAGS + "/MANIFEST:NO " # + "/DRIVER " # + "/OPT:REF " # + "/INCREMENTAL:NO " # + "/OPT:ICF " # + "/SUBSYSTEM:NATIVE " # + "/MERGE:_TEXT=.text;_PAGE=PAGE " # + "/NODEFAULTLIB " # do not link default CRT + "/SECTION:INIT,d " # + "/VERSION:10.0 " # + ) + +# Generate imported targets for WDK lib files +file(GLOB WDK_LIBRARIES "${WDK_ROOT}/Lib/${WDK_LIB_VERSION}/km/${WDK_PLATFORM}/*.lib") +foreach(LIBRARY IN LISTS WDK_LIBRARIES) + get_filename_component(LIBRARY_NAME ${LIBRARY} NAME_WE) + string(TOUPPER ${LIBRARY_NAME} LIBRARY_NAME) + add_library(WDK::${LIBRARY_NAME} INTERFACE IMPORTED) + set_property(TARGET WDK::${LIBRARY_NAME} PROPERTY INTERFACE_LINK_LIBRARIES ${LIBRARY}) +endforeach(LIBRARY) +unset(WDK_LIBRARIES) + +function(wdk_add_driver _target) + cmake_parse_arguments(WDK "" "KMDF;WINVER;NTDDI_VERSION" "" ${ARGN}) + + add_executable(${_target} ${WDK_UNPARSED_ARGUMENTS}) + + set_target_properties(${_target} PROPERTIES SUFFIX ".sys") + set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "${WDK_COMPILE_FLAGS}") + set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS + "${WDK_COMPILE_DEFINITIONS};$<$:${WDK_COMPILE_DEFINITIONS_DEBUG}>;_WIN32_WINNT=${WDK_WINVER}" + ) + set_target_properties(${_target} PROPERTIES LINK_FLAGS "${WDK_LINK_FLAGS}") + if(WDK_NTDDI_VERSION) + target_compile_definitions(${_target} PRIVATE NTDDI_VERSION=${WDK_NTDDI_VERSION}) + endif() + + target_include_directories(${_target} SYSTEM PRIVATE + "${WDK_ROOT}/Include/${WDK_INC_VERSION}/shared" + "${WDK_ROOT}/Include/${WDK_INC_VERSION}/km" + "${WDK_ROOT}/Include/${WDK_INC_VERSION}/km/crt" + ) + + target_link_libraries(${_target} WDK::NTOSKRNL WDK::HAL WDK::BUFFEROVERFLOWK WDK::WMILIB) + + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + target_link_libraries(${_target} WDK::MEMCMP) + endif() + + if(DEFINED WDK_KMDF) + target_include_directories(${_target} SYSTEM PRIVATE "${WDK_ROOT}/Include/wdf/kmdf/${WDK_KMDF}") + target_link_libraries(${_target} + "${WDK_ROOT}/Lib/wdf/kmdf/${WDK_PLATFORM}/${WDK_KMDF}/WdfDriverEntry.lib" + "${WDK_ROOT}/Lib/wdf/kmdf/${WDK_PLATFORM}/${WDK_KMDF}/WdfLdr.lib" + ) + + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:FxDriverEntry@8") + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:FxDriverEntry") + endif() + else() + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:GsDriverEntry@8") + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:GsDriverEntry") + endif() + endif() +endfunction() + +function(wdk_add_library _target) + cmake_parse_arguments(WDK "" "KMDF;WINVER;NTDDI_VERSION" "" ${ARGN}) + + add_library(${_target} ${WDK_UNPARSED_ARGUMENTS}) + + set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "${WDK_COMPILE_FLAGS}") + set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS + "${WDK_COMPILE_DEFINITIONS};$<$:${WDK_COMPILE_DEFINITIONS_DEBUG};>_WIN32_WINNT=${WDK_WINVER}" + ) + if(WDK_NTDDI_VERSION) + target_compile_definitions(${_target} PRIVATE NTDDI_VERSION=${WDK_NTDDI_VERSION}) + endif() + + target_include_directories(${_target} SYSTEM PRIVATE + "${WDK_ROOT}/Include/${WDK_INC_VERSION}/shared" + "${WDK_ROOT}/Include/${WDK_INC_VERSION}/km" + "${WDK_ROOT}/Include/${WDK_INC_VERSION}/km/crt" + ) + + target_link_libraries(${_target} WDK::NTOSKRNL WDK::HAL WDK::WMILIB) + + if(DEFINED WDK_KMDF) + target_include_directories(${_target} SYSTEM PRIVATE "${WDK_ROOT}/Include/wdf/kmdf/${WDK_KMDF}") + endif() +endfunction() diff --git a/hyperdbg/dependencies/ia32-doc b/hyperdbg/dependencies/ia32-doc index 6ef251e3..2bc5284e 160000 --- a/hyperdbg/dependencies/ia32-doc +++ b/hyperdbg/dependencies/ia32-doc @@ -1 +1 @@ -Subproject commit 6ef251e3e58c759fda025c186ef0f44c556c14c1 +Subproject commit 2bc5284e04ff862220def160517bc72baf3d1a03 diff --git a/hyperdbg/dependencies/keystone/include/keystone/arm.h b/hyperdbg/dependencies/keystone/include/keystone/arm.h new file mode 100644 index 00000000..f4d2489a --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/arm.h @@ -0,0 +1,23 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_ARM_H +#define KEYSTONE_ARM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_arm { + KS_ERR_ASM_ARM_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_ARM_MISSINGFEATURE, + KS_ERR_ASM_ARM_MNEMONICFAIL, +} ks_err_asm_arm; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/keystone/include/keystone/arm64.h b/hyperdbg/dependencies/keystone/include/keystone/arm64.h new file mode 100644 index 00000000..7a7af411 --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/arm64.h @@ -0,0 +1,23 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_ARM64_H +#define KEYSTONE_ARM64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_arm64 { + KS_ERR_ASM_ARM64_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_ARM64_MISSINGFEATURE, + KS_ERR_ASM_ARM64_MNEMONICFAIL, +} ks_err_asm_arm64; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/keystone/include/keystone/evm.h b/hyperdbg/dependencies/keystone/include/keystone/evm.h new file mode 100644 index 00000000..60ac408c --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/evm.h @@ -0,0 +1,23 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016-2018 */ + +#ifndef KEYSTONE_EVM_H +#define KEYSTONE_EVM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_evm { + KS_ERR_ASM_EVM_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_EVM_MISSINGFEATURE, + KS_ERR_ASM_EVM_MNEMONICFAIL, +} ks_err_asm_evm; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/keystone/include/keystone/hexagon.h b/hyperdbg/dependencies/keystone/include/keystone/hexagon.h new file mode 100644 index 00000000..e6158123 --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/hexagon.h @@ -0,0 +1,24 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_HEXAGON_H +#define KEYSTONE_HEXAGON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_hexagon { + KS_ERR_ASM_HEXAGON_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_HEXAGON_MISSINGFEATURE, + KS_ERR_ASM_HEXAGON_MNEMONICFAIL, +} ks_err_asm_hexagon; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/keystone/include/keystone/keystone.h b/hyperdbg/dependencies/keystone/include/keystone/keystone.h new file mode 100644 index 00000000..03fd54a3 --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/keystone.h @@ -0,0 +1,346 @@ +/* Keystone Assembler Engine (www.keystone-engine.org) */ +/* By Nguyen Anh Quynh , 2016 */ + +#ifndef KEYSTONE_ENGINE_H +#define KEYSTONE_ENGINE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#ifdef _MSC_VER // MSVC compiler +#pragma warning(disable:4201) +#pragma warning(disable:4100) +#ifndef KEYSTONE_STATIC +#define KEYSTONE_EXPORT __declspec(dllexport) +#else +#define KEYSTONE_EXPORT +#endif +#else +#ifdef __GNUC__ +#include +#ifndef KEYSTONE_STATIC +#define KEYSTONE_EXPORT __attribute__((visibility("default"))) +#else +#define KEYSTONE_EXPORT +#endif +#else +#define KEYSTONE_EXPORT +#endif +#endif + + +struct ks_struct; +typedef struct ks_struct ks_engine; + +// Keystone API version +#define KS_API_MAJOR 0 +#define KS_API_MINOR 9 + +// Package version +#define KS_VERSION_MAJOR KS_API_MAJOR +#define KS_VERSION_MINOR KS_API_MINOR +#define KS_VERSION_EXTRA 2 + +/* + Macro to create combined version which can be compared to + result of ks_version() API. +*/ +#define KS_MAKE_VERSION(major, minor) ((major << 8) + minor) + +// Architecture type +typedef enum ks_arch { + KS_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2) + KS_ARCH_ARM64, // ARM-64, also called AArch64 + KS_ARCH_MIPS, // Mips architecture + KS_ARCH_X86, // X86 architecture (including x86 & x86-64) + KS_ARCH_PPC, // PowerPC architecture (currently unsupported) + KS_ARCH_SPARC, // Sparc architecture + KS_ARCH_SYSTEMZ, // SystemZ architecture (S390X) + KS_ARCH_HEXAGON, // Hexagon architecture + KS_ARCH_EVM, // Ethereum Virtual Machine architecture + KS_ARCH_RISCV, // RISC-V architecture + KS_ARCH_MAX, +} ks_arch; + +// Mode type +typedef enum ks_mode { + KS_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) + KS_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode + // arm / arm64 + KS_MODE_ARM = 1 << 0, // ARM mode + KS_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2) + KS_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM + // mips + KS_MODE_MICRO = 1 << 4, // MicroMips mode + KS_MODE_MIPS3 = 1 << 5, // Mips III ISA + KS_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA + KS_MODE_MIPS32 = 1 << 2, // Mips32 ISA + KS_MODE_MIPS64 = 1 << 3, // Mips64 ISA + // x86 / x64 + KS_MODE_16 = 1 << 1, // 16-bit mode + KS_MODE_32 = 1 << 2, // 32-bit mode + KS_MODE_64 = 1 << 3, // 64-bit mode + // ppc + KS_MODE_PPC32 = 1 << 2, // 32-bit mode + KS_MODE_PPC64 = 1 << 3, // 64-bit mode + KS_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode + //riscv + KS_MODE_RISCV32 = 1 << 2, // 32-bit mode + KS_MODE_RISCV64 = 1 << 3, // 64-bit mode + // sparc + KS_MODE_SPARC32 = 1 << 2, // 32-bit mode + KS_MODE_SPARC64 = 1 << 3, // 64-bit mode + KS_MODE_V9 = 1 << 4, // SparcV9 mode +} ks_mode; + +// All generic errors related to input assembly >= KS_ERR_ASM +#define KS_ERR_ASM 128 + +// All architecture-specific errors related to input assembly >= KS_ERR_ASM_ARCH +#define KS_ERR_ASM_ARCH 512 + +// All type of errors encountered by Keystone API. +typedef enum ks_err { + KS_ERR_OK = 0, // No error: everything was fine + KS_ERR_NOMEM, // Out-Of-Memory error: ks_open(), ks_emulate() + KS_ERR_ARCH, // Unsupported architecture: ks_open() + KS_ERR_HANDLE, // Invalid handle + KS_ERR_MODE, // Invalid/unsupported mode: ks_open() + KS_ERR_VERSION, // Unsupported version (bindings) + KS_ERR_OPT_INVALID, // Unsupported option + + // generic input assembly errors - parser specific + KS_ERR_ASM_EXPR_TOKEN = KS_ERR_ASM, // unknown token in expression + KS_ERR_ASM_DIRECTIVE_VALUE_RANGE, // literal value out of range for directive + KS_ERR_ASM_DIRECTIVE_ID, // expected identifier in directive + KS_ERR_ASM_DIRECTIVE_TOKEN, // unexpected token in directive + KS_ERR_ASM_DIRECTIVE_STR, // expected string in directive + KS_ERR_ASM_DIRECTIVE_COMMA, // expected comma in directive + KS_ERR_ASM_DIRECTIVE_RELOC_NAME, // expected relocation name in directive + KS_ERR_ASM_DIRECTIVE_RELOC_TOKEN, // unexpected token in .reloc directive + KS_ERR_ASM_DIRECTIVE_FPOINT, // invalid floating point in directive + KS_ERR_ASM_DIRECTIVE_UNKNOWN, // unknown directive + KS_ERR_ASM_DIRECTIVE_EQU, // invalid equal directive + KS_ERR_ASM_DIRECTIVE_INVALID, // (generic) invalid directive + KS_ERR_ASM_VARIANT_INVALID, // invalid variant + KS_ERR_ASM_EXPR_BRACKET, // brackets expression not supported on this target + KS_ERR_ASM_SYMBOL_MODIFIER, // unexpected symbol modifier following '@' + KS_ERR_ASM_SYMBOL_REDEFINED, // invalid symbol redefinition + KS_ERR_ASM_SYMBOL_MISSING, // cannot find a symbol + KS_ERR_ASM_RPAREN, // expected ')' in parentheses expression + KS_ERR_ASM_STAT_TOKEN, // unexpected token at start of statement + KS_ERR_ASM_UNSUPPORTED, // unsupported token yet + KS_ERR_ASM_MACRO_TOKEN, // unexpected token in macro instantiation + KS_ERR_ASM_MACRO_PAREN, // unbalanced parentheses in macro argument + KS_ERR_ASM_MACRO_EQU, // expected '=' after formal parameter identifier + KS_ERR_ASM_MACRO_ARGS, // too many positional arguments + KS_ERR_ASM_MACRO_LEVELS_EXCEED, // macros cannot be nested more than 20 levels deep + KS_ERR_ASM_MACRO_STR, // invalid macro string + KS_ERR_ASM_MACRO_INVALID, // invalid macro (generic error) + KS_ERR_ASM_ESC_BACKSLASH, // unexpected backslash at end of escaped string + KS_ERR_ASM_ESC_OCTAL, // invalid octal escape sequence (out of range) + KS_ERR_ASM_ESC_SEQUENCE, // invalid escape sequence (unrecognized character) + KS_ERR_ASM_ESC_STR, // broken escape string + KS_ERR_ASM_TOKEN_INVALID, // invalid token + KS_ERR_ASM_INSN_UNSUPPORTED, // this instruction is unsupported in this mode + KS_ERR_ASM_FIXUP_INVALID, // invalid fixup + KS_ERR_ASM_LABEL_INVALID, // invalid label + KS_ERR_ASM_FRAGMENT_INVALID, // invalid fragment + + // generic input assembly errors - architecture specific + KS_ERR_ASM_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_MISSINGFEATURE, + KS_ERR_ASM_MNEMONICFAIL, +} ks_err; + +// Resolver callback to provide value for a missing symbol in @symbol. +// To handle a symbol, the resolver must put value of the symbol in @value, +// then returns True. +// If we do not resolve a missing symbol, this function must return False. +// In that case, ks_asm() would eventually return with error KS_ERR_ASM_SYMBOL_MISSING. + +// To register the resolver, pass its function address to ks_option(), using +// option KS_OPT_SYM_RESOLVER. For example, see samples/sample.c. +typedef bool (*ks_sym_resolver)(const char *symbol, uint64_t *value); + +// Runtime option for the Keystone engine +typedef enum ks_opt_type { + KS_OPT_SYNTAX = 1, // Choose syntax for input assembly + KS_OPT_SYM_RESOLVER, // Set symbol resolver callback +} ks_opt_type; + + +// Runtime option value (associated with ks_opt_type above) +typedef enum ks_opt_value { + KS_OPT_SYNTAX_INTEL = 1 << 0, // X86 Intel syntax - default on X86 (KS_OPT_SYNTAX). + KS_OPT_SYNTAX_ATT = 1 << 1, // X86 ATT asm syntax (KS_OPT_SYNTAX). + KS_OPT_SYNTAX_NASM = 1 << 2, // X86 Nasm syntax (KS_OPT_SYNTAX). + KS_OPT_SYNTAX_MASM = 1 << 3, // X86 Masm syntax (KS_OPT_SYNTAX) - unsupported yet. + KS_OPT_SYNTAX_GAS = 1 << 4, // X86 GNU GAS syntax (KS_OPT_SYNTAX). + KS_OPT_SYNTAX_RADIX16 = 1 << 5, // All immediates are in hex format (i.e 12 is 0x12) +} ks_opt_value; + + +#include "arm64.h" +#include "arm.h" +#include "evm.h" +#include "hexagon.h" +#include "mips.h" +#include "ppc.h" +#include "riscv.h" +#include "sparc.h" +#include "systemz.h" +#include "x86.h" + +/* + Return combined API version & major and minor version numbers. + + @major: major number of API version + @minor: minor number of API version + + @return hexical number as (major << 8 | minor), which encodes both + major & minor versions. + NOTE: This returned value can be compared with version number made + with macro KS_MAKE_VERSION + + For example, second API version would return 1 in @major, and 1 in @minor + The return value would be 0x0101 + + NOTE: if you only care about returned value, but not major and minor values, + set both @major & @minor arguments to NULL. +*/ +KEYSTONE_EXPORT +unsigned int ks_version(unsigned int *major, unsigned int *minor); + + +/* + Determine if the given architecture is supported by this library. + + @arch: architecture type (KS_ARCH_*) + + @return True if this library supports the given arch. +*/ +KEYSTONE_EXPORT +bool ks_arch_supported(ks_arch arch); + + +/* + Create new instance of Keystone engine. + + @arch: architecture type (KS_ARCH_*) + @mode: hardware mode. This is combined of KS_MODE_* + @ks: pointer to ks_engine, which will be updated at return time + + @return KS_ERR_OK on success, or other value on failure (refer to ks_err enum + for detailed error). +*/ +KEYSTONE_EXPORT +ks_err ks_open(ks_arch arch, int mode, ks_engine **ks); + + +/* + Close KS instance: MUST do to release the handle when it is not used anymore. + NOTE: this must be called only when there is no longer usage of Keystone. + The reason is the this API releases some cached memory, thus access to any + Keystone API after ks_close() might crash your application. + After this, @ks is invalid, and nolonger usable. + + @ks: pointer to a handle returned by ks_open() + + @return KS_ERR_OK on success, or other value on failure (refer to ks_err enum + for detailed error). +*/ +KEYSTONE_EXPORT +ks_err ks_close(ks_engine *ks); + + +/* + Report the last error number when some API function fail. + Like glibc's errno, ks_errno might not retain its old error once accessed. + + @ks: handle returned by ks_open() + + @return: error code of ks_err enum type (KS_ERR_*, see above) +*/ +KEYSTONE_EXPORT +ks_err ks_errno(ks_engine *ks); + + +/* + Return a string describing given error code. + + @code: error code (see KS_ERR_* above) + + @return: returns a pointer to a string that describes the error code + passed in the argument @code + */ +KEYSTONE_EXPORT +const char *ks_strerror(ks_err code); + + +/* + Set option for Keystone engine at runtime + + @ks: handle returned by ks_open() + @type: type of option to be set. See ks_opt_type + @value: option value corresponding with @type + + @return: KS_ERR_OK on success, or other value on failure. + Refer to ks_err enum for detailed error. +*/ +KEYSTONE_EXPORT +ks_err ks_option(ks_engine *ks, ks_opt_type type, size_t value); + + +/* + Assemble a string given its the buffer, size, start address and number + of instructions to be decoded. + This API dynamically allocate memory to contain assembled instruction. + Resulted array of bytes containing the machine code is put into @*encoding + + NOTE 1: this API will automatically determine memory needed to contain + output bytes in *encoding. + + NOTE 2: caller must free the allocated memory itself to avoid memory leaking. + + @ks: handle returned by ks_open() + @str: NULL-terminated assembly string. Use ; or \n to separate statements. + @address: address of the first assembly instruction, or 0 to ignore. + @encoding: array of bytes containing encoding of input assembly string. + NOTE: *encoding will be allocated by this function, and should be freed + with ks_free() function. + @encoding_size: size of *encoding + @stat_count: number of statements successfully processed + + @return: 0 on success, or -1 on failure. + + On failure, call ks_errno() for error code. +*/ +KEYSTONE_EXPORT +int ks_asm(ks_engine *ks, + const char *string, + uint64_t address, + unsigned char **encoding, size_t *encoding_size, + size_t *stat_count); + + +/* + Free memory allocated by ks_asm() + + @p: memory allocated in @encoding argument of ks_asm() +*/ +KEYSTONE_EXPORT +void ks_free(unsigned char *p); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/keystone/include/keystone/mips.h b/hyperdbg/dependencies/keystone/include/keystone/mips.h new file mode 100644 index 00000000..e71c553c --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/mips.h @@ -0,0 +1,23 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_MIPS_H +#define KEYSTONE_MIPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_mips { + KS_ERR_ASM_MIPS_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_MIPS_MISSINGFEATURE, + KS_ERR_ASM_MIPS_MNEMONICFAIL, +} ks_err_asm_mips; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/keystone/include/keystone/ppc.h b/hyperdbg/dependencies/keystone/include/keystone/ppc.h new file mode 100644 index 00000000..39a602c2 --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/ppc.h @@ -0,0 +1,24 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_PPC_H +#define KEYSTONE_PPC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_ppc { + KS_ERR_ASM_PPC_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_PPC_MISSINGFEATURE, + KS_ERR_ASM_PPC_MNEMONICFAIL, +} ks_err_asm_ppc; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/keystone/include/keystone/riscv.h b/hyperdbg/dependencies/keystone/include/keystone/riscv.h new file mode 100644 index 00000000..0910f986 --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/riscv.h @@ -0,0 +1,24 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ +/* Added by Mark Juvan, 2023*/ +#ifndef KEYSTONE_RISCV_H +#define KEYSTONE_RISCV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_riscv { + KS_ERR_ASM_RISCV_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_RISCV_MISSINGFEATURE, + KS_ERR_ASM_RISCV_MNEMONICFAIL, +} ks_err_asm_riscv; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/keystone/include/keystone/sparc.h b/hyperdbg/dependencies/keystone/include/keystone/sparc.h new file mode 100644 index 00000000..e49c4264 --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/sparc.h @@ -0,0 +1,24 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_SPARC_H +#define KEYSTONE_SPARC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_sparc { + KS_ERR_ASM_SPARC_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_SPARC_MISSINGFEATURE, + KS_ERR_ASM_SPARC_MNEMONICFAIL, +} ks_err_asm_sparc; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/keystone/include/keystone/systemz.h b/hyperdbg/dependencies/keystone/include/keystone/systemz.h new file mode 100644 index 00000000..ec2b07a4 --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/systemz.h @@ -0,0 +1,24 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_SYSTEMZ_H +#define KEYSTONE_SYSTEMZ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_systemz { + KS_ERR_ASM_SYSTEMZ_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_SYSTEMZ_MISSINGFEATURE, + KS_ERR_ASM_SYSTEMZ_MNEMONICFAIL, +} ks_err_asm_systemz; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/keystone/include/keystone/x86.h b/hyperdbg/dependencies/keystone/include/keystone/x86.h new file mode 100644 index 00000000..1fac684e --- /dev/null +++ b/hyperdbg/dependencies/keystone/include/keystone/x86.h @@ -0,0 +1,23 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_X86_H +#define KEYSTONE_X86_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_x86 { + KS_ERR_ASM_X86_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_X86_MISSINGFEATURE, + KS_ERR_ASM_X86_MNEMONICFAIL, +} ks_err_asm_x86; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/dependencies/libipt/intel-pt.h b/hyperdbg/dependencies/libipt/intel-pt.h new file mode 100644 index 00000000..4b90482c --- /dev/null +++ b/hyperdbg/dependencies/libipt/intel-pt.h @@ -0,0 +1,3177 @@ +/* + * Copyright (C) 2013-2026 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef INTEL_PT_H +#define INTEL_PT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Intel(R) Processor Trace (Intel PT) decoder library. + * + * This file is logically structured into the following sections: + * + * - Version + * - Errors + * - Configuration + * - Packet encoder / decoder + * - Event decoder + * - Query decoder + * - Traced image + * - Instruction flow decoder + * - Block decoder + */ + + + +struct pt_encoder; +struct pt_packet_decoder; +struct pt_event_decoder; +struct pt_query_decoder; +struct pt_insn_decoder; +struct pt_block_decoder; + + + +/* A macro to mark functions as exported. */ +#ifndef pt_export +# if defined(__GNUC__) +# define pt_export __attribute__((visibility("default"))) +# elif defined(_MSC_VER) +# define pt_export __declspec(dllimport) +# else +# error "unknown compiler" +# endif +#endif + + + +/* Version. */ + + +/** The header version. */ +#define LIBIPT_VERSION_MAJOR 2 +#define LIBIPT_VERSION_MINOR 3 +#define LIBIPT_VERSION_PATCH 0 + +#define LIBIPT_VERSION ((LIBIPT_VERSION_MAJOR << 8) + LIBIPT_VERSION_MINOR) + + +/** The library version. */ +struct pt_version { + /** Major version number. */ + uint8_t major; + + /** Minor version number. */ + uint8_t minor; + + /** Patch level. */ + uint16_t patch; + + /** Build number. */ + uint32_t build; + + /** Version extension. */ + const char *ext; +}; + + +/** Return the library version. */ +extern pt_export struct pt_version pt_library_version(void); + + + +/* Errors. */ + + + +/** Error codes. */ +enum pt_error_code { + /* No error. Everything is OK. */ + pte_ok, + + /* Internal decoder error. */ + pte_internal, + + /* Invalid argument. */ + pte_invalid, + + /* Decoder out of sync. */ + pte_nosync, + + /* Unknown opcode. */ + pte_bad_opc, + + /* Unknown payload. */ + pte_bad_packet, + + /* Unexpected packet context. */ + pte_bad_context, + + /* Decoder reached end of trace stream. */ + pte_eos, + + /* No packet matching the query to be found. */ + pte_bad_query, + + /* Decoder out of memory. */ + pte_nomem, + + /* Bad configuration. */ + pte_bad_config, + + /* There is no IP. */ + pte_noip, + + /* The IP has been suppressed. */ + pte_ip_suppressed, + + /* There is no memory mapped at the requested address. */ + pte_nomap, + + /* An instruction could not be decoded. */ + pte_bad_insn, + + /* No wall-clock time is available. */ + pte_no_time, + + /* No core:bus ratio available. */ + pte_no_cbr, + + /* Bad traced image. */ + pte_bad_image, + + /* A locking error. */ + pte_bad_lock, + + /* The requested feature is not supported. */ + pte_not_supported, + + /* The return address stack is empty. */ + pte_retstack_empty, + + /* A compressed return is not indicated correctly by a taken branch. */ + pte_bad_retcomp, + + /* The current decoder state does not match the state in the trace. */ + pte_bad_status_update, + + /* The trace did not contain an expected enabled event. */ + pte_no_enable, + + /* An event was ignored. */ + pte_event_ignored, + + /* Something overflowed. */ + pte_overflow, + + /* A file handling error. */ + pte_bad_file, + + /* Unknown cpu. */ + pte_bad_cpu +}; + + +/** Decode a function return value into an pt_error_code. */ +static inline enum pt_error_code pt_errcode(int status) +{ + return (status >= 0) ? pte_ok : (enum pt_error_code) -status; +} + +/** Return a human readable error string. */ +extern pt_export const char *pt_errstr(enum pt_error_code); + + + +/* Configuration. */ + + + +/** A cpu vendor. */ +enum pt_cpu_vendor { + pcv_unknown, + pcv_intel +}; + +/** A cpu identifier. */ +struct pt_cpu { + /** The cpu vendor. */ + enum pt_cpu_vendor vendor; + + /** The cpu family. */ + uint16_t family; + + /** The cpu model. */ + uint8_t model; + + /** The stepping. */ + uint8_t stepping; +}; + +/** A collection of Intel PT errata. */ +struct pt_errata { + /** BDM70: Intel(R) Processor Trace PSB+ Packets May Contain + * Unexpected Packets. + * + * Same as: SKD024, SKL021, KBL021. + * + * Some Intel Processor Trace packets should be issued only between + * TIP.PGE and TIP.PGD packets. Due to this erratum, when a TIP.PGE + * packet is generated it may be preceded by a PSB+ that incorrectly + * includes FUP and MODE.Exec packets. + */ + uint32_t bdm70:1; + + /** BDM64: An Incorrect LBR or Intel(R) Processor Trace Packet May Be + * Recorded Following a Transactional Abort. + * + * Use of Intel(R) Transactional Synchronization Extensions (Intel(R) + * TSX) may result in a transactional abort. If an abort occurs + * immediately following a branch instruction, an incorrect branch + * target may be logged in an LBR (Last Branch Record) or in an Intel(R) + * Processor Trace (Intel(R) PT) packet before the LBR or Intel PT + * packet produced by the abort. + */ + uint32_t bdm64:1; + + /** SKD007: Intel(R) PT Buffer Overflow May Result in Incorrect Packets. + * + * Same as: SKL049, KBL041. + * + * Under complex micro-architectural conditions, an Intel PT (Processor + * Trace) OVF (Overflow) packet may be issued after the first byte of a + * multi-byte CYC (Cycle Count) packet, instead of any remaining bytes + * of the CYC. + */ + uint32_t skd007:1; + + /** SKD022: VM Entry That Clears TraceEn May Generate a FUP. + * + * Same as: SKL024, KBL023. + * + * If VM entry clears Intel(R) PT (Intel Processor Trace) + * IA32_RTIT_CTL.TraceEn (MSR 570H, bit 0) while PacketEn is 1 then a + * FUP (Flow Update Packet) will precede the TIP.PGD (Target IP Packet, + * Packet Generation Disable). VM entry can clear TraceEn if the + * VM-entry MSR-load area includes an entry for the IA32_RTIT_CTL MSR. + */ + uint32_t skd022:1; + + /** SKD010: Intel(R) PT FUP May be Dropped After OVF. + * + * Same as: SKD014, SKL033, KBL030. + * + * Some Intel PT (Intel Processor Trace) OVF (Overflow) packets may not + * be followed by a FUP (Flow Update Packet) or TIP.PGE (Target IP + * Packet, Packet Generation Enable). + */ + uint32_t skd010:1; + + /** SKL014: Intel(R) PT TIP.PGD May Not Have Target IP Payload. + * + * Same as: KBL014. + * + * When Intel PT (Intel Processor Trace) is enabled and a direct + * unconditional branch clears IA32_RTIT_STATUS.FilterEn (MSR 571H, bit + * 0), due to this erratum, the resulting TIP.PGD (Target IP Packet, + * Packet Generation Disable) may not have an IP payload with the target + * IP. + */ + uint32_t skl014:1; + + /** APL12: Intel(R) PT OVF May Be Followed By An Unexpected FUP Packet. + * + * Certain Intel PT (Processor Trace) packets including FUPs (Flow + * Update Packets), should be issued only between TIP.PGE (Target IP + * Packet - Packet Generation Enable) and TIP.PGD (Target IP Packet - + * Packet Generation Disable) packets. When outside a TIP.PGE/TIP.PGD + * pair, as a result of IA32_RTIT_STATUS.FilterEn[0] (MSR 571H) being + * cleared, an OVF (Overflow) packet may be unexpectedly followed by a + * FUP. + */ + uint32_t apl12:1; + + /** APL11: Intel(R) PT OVF Packet May Be Followed by TIP.PGD Packet + * + * If Intel PT (Processor Trace) encounters an internal buffer overflow + * and generates an OVF (Overflow) packet just as IA32_RTIT_CTL (MSR + * 570H) bit 0 (TraceEn) is cleared, or during a far transfer that + * causes IA32_RTIT_STATUS.ContextEn[1] (MSR 571H) to be cleared, the + * OVF may be followed by a TIP.PGD (Target Instruction Pointer - Packet + * Generation Disable) packet. + */ + uint32_t apl11:1; + + /** SKL168: Intel(R) PT CYC Packets Can be Dropped When Immediately + * Preceding PSB + * + * Due to a rare microarchitectural condition, generation of an Intel + * PT (Processor Trace) PSB (Packet Stream Boundary) packet can cause a + * single CYC (Cycle Count) packet, possibly along with an associated + * MTC (Mini Time Counter) packet, to be dropped. + */ + uint32_t skl168:1; + + /** SKZ84: Use of VMX TSC Scaling or TSC Offsetting Will Result in + * Corrupted Intel PT Packets + * + * When Intel(R) PT (Processor Trace) is enabled within a VMX (Virtual + * Machine Extensions) guest, and TSC (Time Stamp Counter) offsetting + * or TSC scaling is enabled for that guest, by setting primary + * processor-based execution control bit 3 or secondary processor-based + * execution control bit 25, respectively, in the VMCS (Virtual Machine + * Control Structure) for that guest, any TMA (TSC(MTC Alignment) + * packet generated will have corrupted values in the CTC (Core Timer + * Copy) and FastCounter fields. Additionally, the corrupted TMA + * packet will be followed by a bogus data byte. + */ + uint32_t skz84:1; + + /* Reserve a few bytes for the future. */ + uint32_t reserved[15]; +}; + +/** A collection of decoder-specific configuration flags. */ +struct pt_conf_flags { + /** The decoder variant. */ + union { + /** Flags for the block decoder. */ + struct { + /** End a block after a call instruction. */ + uint32_t end_on_call:1; + + /** Enable tick events for timing updates. */ + uint32_t enable_tick_events:1; + + /** End a block after a jump instruction. */ + uint32_t end_on_jump:1; + +#if (LIBIPT_VERSION >= 0x201) + /** Preserve timing calibration on overflow. */ + uint32_t keep_tcal_on_ovf:1; + + /** Enable iflags events. + * + * Use this only when Event Tracing was enabled via + * IA32_RTIT_CTL[31]. + */ + uint32_t enable_iflags_events:1; +#endif + } block; + + /** Flags for the instruction flow decoder. */ + struct { + /** Enable tick events for timing updates. */ + uint32_t enable_tick_events:1; + +#if (LIBIPT_VERSION >= 0x201) + /** Preserve timing calibration on overflow. */ + uint32_t keep_tcal_on_ovf:1; + + /** Enable iflags events. + * + * Use this only when Event Tracing was enabled via + * IA32_RTIT_CTL[31]. + */ + uint32_t enable_iflags_events:1; +#endif + } insn; + +#if (LIBIPT_VERSION >= 0x201) + /** Flags for the query decoder. */ + struct { + /** Preserve timing calibration on overflow. */ + uint32_t keep_tcal_on_ovf:1; + + /** Enable iflags events. + * + * Use this only when Event Tracing was enabled via + * IA32_RTIT_CTL[31]. + */ + uint32_t enable_iflags_events:1; + } query; + + /** Flags for the event decoder. */ + struct { + /** Preserve timing calibration on overflow. */ + uint32_t keep_tcal_on_ovf:1; + + /** Enable iflags events. + * + * Use this only when Event Tracing was enabled via + * IA32_RTIT_CTL[31]. + */ + uint32_t enable_iflags_events:1; + } event; +#endif /* (LIBIPT_VERSION >= 0x201) */ + + /* Reserve a few bytes for future extensions. */ + uint32_t reserved[4]; + } variant; +}; + +/** The address filter configuration. */ +struct pt_conf_addr_filter { + /** The address filter configuration. + * + * This corresponds to the respective fields in IA32_RTIT_CTL MSR. + */ + union { + uint64_t addr_cfg; + + struct { + uint32_t addr0_cfg:4; + uint32_t addr1_cfg:4; + uint32_t addr2_cfg:4; + uint32_t addr3_cfg:4; + } ctl; + } config; + + /** The address ranges configuration. + * + * This corresponds to the IA32_RTIT_ADDRn_A/B MSRs. + */ + uint64_t addr0_a; + uint64_t addr0_b; + uint64_t addr1_a; + uint64_t addr1_b; + uint64_t addr2_a; + uint64_t addr2_b; + uint64_t addr3_a; + uint64_t addr3_b; + + /* Reserve some space. */ + uint64_t reserved[8]; +}; + +/** An unknown packet. */ +struct pt_packet_unknown; + +/** An Intel PT decoder configuration. + */ +struct pt_config { + /** The size of the config structure in bytes. */ + size_t size; + + /** The trace buffer begin address. */ + uint8_t *begin; + + /** The trace buffer end address. */ + uint8_t *end; + + /** An optional callback for handling unknown packets. + * + * If \@callback is not NULL, it is called for any unknown opcode. + */ + struct { + /** The callback function. + * + * It shall decode the packet at \@pos into \@unknown. + * It shall return the number of bytes read upon success. + * It shall return a negative pt_error_code otherwise. + * The below context is passed as \@context. + */ + int (*callback)(struct pt_packet_unknown *unknown, + const struct pt_config *config, + const uint8_t *pos, void *context); + + /** The user-defined context for this configuration. */ + void *context; + } decode; + + /** The cpu on which Intel PT has been recorded. */ + struct pt_cpu cpu; + + /** The errata to apply when encoding or decoding Intel PT. */ + struct pt_errata errata; + + /* The CTC frequency. + * + * This is only required if MTC packets have been enabled in + * IA32_RTIT_CTRL.MTCEn. + */ + uint32_t cpuid_0x15_eax, cpuid_0x15_ebx; + + /* The MTC frequency as defined in IA32_RTIT_CTL.MTCFreq. + * + * This is only required if MTC packets have been enabled in + * IA32_RTIT_CTRL.MTCEn. + */ + uint8_t mtc_freq; + + /* The nominal frequency as defined in MSR_PLATFORM_INFO[15:8]. + * + * This is only required if CYC packets have been enabled in + * IA32_RTIT_CTRL.CYCEn. + * + * If zero, timing calibration will only be able to use MTC and CYC + * packets. + * + * If not zero, timing calibration will also be able to use CBR + * packets. + */ + uint8_t nom_freq; + + /** A collection of decoder-specific flags. */ + struct pt_conf_flags flags; + + /** The address filter configuration. */ + struct pt_conf_addr_filter addr_filter; +}; + + +/** Zero-initialize an Intel PT configuration. */ +static inline void pt_config_init(struct pt_config *config) +{ + memset(config, 0, sizeof(*config)); + + config->size = sizeof(*config); +} + +/** Determine errata for a given cpu. + * + * Updates \@errata based on \@cpu. + * + * Returns 0 on success, a negative error code otherwise. + * Returns -pte_invalid if \@errata or \@cpu is NULL. + * Returns -pte_bad_cpu if \@cpu is not known. + */ +extern pt_export int pt_cpu_errata(struct pt_errata *errata, + const struct pt_cpu *cpu); + + + +/* Packet encoder / decoder. */ + + + +/** Intel PT packet types. */ +enum pt_packet_type { + /* An invalid packet. */ + ppt_invalid, + + /* A packet decodable by the optional decoder callback. */ + ppt_unknown, + + /* Actual packets supported by this library. */ + ppt_pad, + ppt_psb, + ppt_psbend, + ppt_fup, + ppt_tip, + ppt_tip_pge, + ppt_tip_pgd, + ppt_tnt_8, + ppt_tnt_64, + ppt_mode, + ppt_pip, + ppt_vmcs, + ppt_cbr, + ppt_tsc, + ppt_tma, + ppt_mtc, + ppt_cyc, + ppt_stop, + ppt_ovf, + ppt_mnt, + ppt_exstop, + ppt_mwait, + ppt_pwre, + ppt_pwrx, + ppt_ptw, +#if (LIBIPT_VERSION >= 0x201) + ppt_cfe, + ppt_evd, +#endif +#if (LIBIPT_VERSION >= 0x202) + ppt_trig, +#endif +}; + +/** The IP compression. */ +enum pt_ip_compression { + /* The bits encode the payload size and the encoding scheme. + * + * No payload. The IP has been suppressed. + */ + pt_ipc_suppressed = 0x0, + + /* Payload: 16 bits. Update last IP. */ + pt_ipc_update_16 = 0x01, + + /* Payload: 32 bits. Update last IP. */ + pt_ipc_update_32 = 0x02, + + /* Payload: 48 bits. Sign extend to full address. */ + pt_ipc_sext_48 = 0x03, + + /* Payload: 48 bits. Update last IP. */ + pt_ipc_update_48 = 0x04, + + /* Payload: 64 bits. Full address. */ + pt_ipc_full = 0x06 +}; + +/** An execution mode. */ +enum pt_exec_mode { + ptem_unknown, + ptem_16bit, + ptem_32bit, + ptem_64bit +}; + +/** Mode packet leaves. */ +enum pt_mode_leaf { + pt_mol_exec = 0x00, + pt_mol_tsx = 0x20 +}; + +/** A TNT-8 or TNT-64 packet. */ +struct pt_packet_tnt { + /** TNT payload bit size. */ + uint8_t bit_size; + + /** TNT payload excluding stop bit. */ + uint64_t payload; +}; + +/** A packet with IP payload. */ +struct pt_packet_ip { + /** IP compression. */ + enum pt_ip_compression ipc; + + /** Zero-extended payload ip. */ + uint64_t ip; +}; + +/** A mode.exec packet. */ +struct pt_packet_mode_exec { + /** The mode.exec csl bit. */ + uint32_t csl:1; + + /** The mode.exec csd bit. */ + uint32_t csd:1; + +#if (LIBIPT_VERSION >= 0x201) + /** The mode.exec if bit. + * + * Enable Event Tracing to get updates when IF changes. + */ + uint32_t iflag:1; +#endif +}; + +static inline enum pt_exec_mode +pt_get_exec_mode(const struct pt_packet_mode_exec *packet) +{ + if (packet->csl) + return packet->csd ? ptem_unknown : ptem_64bit; + else + return packet->csd ? ptem_32bit : ptem_16bit; +} + +static inline struct pt_packet_mode_exec +pt_set_exec_mode(enum pt_exec_mode mode) +{ + struct pt_packet_mode_exec packet; + + memset(&packet, 0, sizeof(packet)); + switch (mode) { + default: + packet.csl = 1; + packet.csd = 1; + break; + + case ptem_64bit: + packet.csl = 1; + break; + + case ptem_32bit: + packet.csd = 1; + break; + + case ptem_16bit: + break; + } + + return packet; +} + +/** A mode.tsx packet. */ +struct pt_packet_mode_tsx { + /** The mode.tsx intx bit. */ + uint32_t intx:1; + + /** The mode.tsx abrt bit. */ + uint32_t abrt:1; +}; + +/** A mode packet. */ +struct pt_packet_mode { + /** Mode leaf. */ + enum pt_mode_leaf leaf; + + /** Mode bits. */ + union { + /** Packet: mode.exec. */ + struct pt_packet_mode_exec exec; + + /** Packet: mode.tsx. */ + struct pt_packet_mode_tsx tsx; + } bits; +}; + +/** A PIP packet. */ +struct pt_packet_pip { + /** The CR3 value. */ + uint64_t cr3; + + /** The non-root bit. */ + uint32_t nr:1; +}; + +/** A TSC packet. */ +struct pt_packet_tsc { + /** The TSC value. */ + uint64_t tsc; +}; + +/** A CBR packet. */ +struct pt_packet_cbr { + /** The core/bus cycle ratio. */ + uint8_t ratio; +}; + +/** A TMA packet. */ +struct pt_packet_tma { + /** The crystal clock tick counter value. */ + uint16_t ctc; + + /** The fast counter value. */ + uint16_t fc; +}; + +/** A MTC packet. */ +struct pt_packet_mtc { + /** The crystal clock tick counter value. */ + uint8_t ctc; +}; + +/** A CYC packet. */ +struct pt_packet_cyc { + /** The cycle counter value. */ + uint64_t value; +}; + +/** A VMCS packet. */ +struct pt_packet_vmcs { + /* The VMCS Base Address (i.e. the shifted payload). */ + uint64_t base; +}; + +/** A MNT packet. */ +struct pt_packet_mnt { + /** The raw payload. */ + uint64_t payload; +}; + +/** A EXSTOP packet. */ +struct pt_packet_exstop { + /** A flag specifying the binding of the packet: + * + * set: binds to the next FUP. + * clear: standalone. + */ + uint32_t ip:1; +}; + +/** A MWAIT packet. */ +struct pt_packet_mwait { + /** The MWAIT hints (EAX). */ + uint32_t hints; + + /** The MWAIT extensions (ECX). */ + uint32_t ext; +}; + +/** A PWRE packet. */ +struct pt_packet_pwre { + /** The resolved thread C-state. */ + uint8_t state; + + /** The resolved thread sub C-state. */ + uint8_t sub_state; + + /** A flag indicating whether the C-state entry was initiated by h/w. */ + uint32_t hw:1; +}; + +/** A PWRX packet. */ +struct pt_packet_pwrx { + /** The core C-state at the time of the wake. */ + uint8_t last; + + /** The deepest core C-state achieved during sleep. */ + uint8_t deepest; + + /** The wake reason: + * + * - due to external interrupt received. + */ + uint32_t interrupt:1; + + /** - due to store to monitored address. */ + uint32_t store:1; + + /** - due to h/w autonomous condition such as HDC. */ + uint32_t autonomous:1; +}; + +/** A PTW packet. */ +struct pt_packet_ptw { + /** The raw payload. */ + uint64_t payload; + + /** The payload size as encoded in the packet. */ + uint8_t plc; + + /** A flag saying whether a FUP is following PTW that provides + * the IP of the corresponding PTWRITE instruction. + */ + uint32_t ip:1; +}; + +static inline int pt_ptw_size(uint8_t plc) +{ + switch (plc) { + case 0: + return 4; + + case 1: + return 8; + + case 2: + case 3: + return -pte_bad_packet; + } + + return -pte_internal; +} + +#if (LIBIPT_VERSION >= 0x201) +/* Control-flow event types. */ +enum pt_cfe_type { + pt_cfe_intr = 0x01, + pt_cfe_iret = 0x02, + pt_cfe_smi = 0x03, + pt_cfe_rsm = 0x04, + pt_cfe_sipi = 0x05, + pt_cfe_init = 0x06, + pt_cfe_vmentry = 0x07, + pt_cfe_vmexit = 0x08, + pt_cfe_vmexit_intr = 0x09, + pt_cfe_shutdown = 0x0a, + pt_cfe_uintr = 0x0c, + pt_cfe_uiret = 0x0d, +#if (LIBIPT_VERSION >= 0x202) + pt_cfe_swintr = 0x0e, + pt_cfe_syscall = 0x0f, +#endif +}; + +/* Interrupt vectors defined in Table 6-1 in §6.5 of Vol.1 of the SDM. */ +enum pt_cfe_intr { + pt_cfe_intr_de = 0, /* Divide Error. */ + pt_cfe_intr_db = 1, /* Debug. */ + pt_cfe_intr_nmi = 2, /* Non Maskable Interrupt. */ + pt_cfe_intr_bp = 3, /* Breakpoint. */ + pt_cfe_intr_of = 4, /* Overflow. */ + pt_cfe_intr_br = 5, /* Bound Range Exceeded. */ + pt_cfe_intr_ud = 6, /* Undefined Opcode. */ + pt_cfe_intr_nm = 7, /* Device Not Available. */ + pt_cfe_intr_df = 8, /* Double Fault. */ + pt_cfe_intr_ts = 10, /* Invalid TSS. */ + pt_cfe_intr_np = 11, /* Segment Not Present. */ + pt_cfe_intr_ss = 12, /* Stack Segment Fault. */ + pt_cfe_intr_gp = 13, /* General Protection Fault. */ + pt_cfe_intr_pf = 14, /* Page Fault. */ + pt_cfe_intr_mf = 16, /* Math Fault. */ + pt_cfe_intr_ac = 17, /* Alignment Check. */ + pt_cfe_intr_mc = 18, /* Machine Check. */ + pt_cfe_intr_xm = 19, /* SIMD Floating Point Exception. */ + pt_cfe_intr_ve = 20, /* Virtualization Exception. */ + pt_cfe_intr_cp = 21, /* Control Protection Exception. */ +}; + +/** A CFE packet. */ +struct pt_packet_cfe { + /** The type of control-flow event. */ + enum pt_cfe_type type; + + /** The vector depending on the type: + * + * pt_cfe_intr: the event vector. + * pt_cfe_vmexit_intr: the event vector. + * pt_cfe_sipi: the SIPI vector. + * pt_cfe_uintr: the user interrupt vector. + * pt_cfe_swintr: the event vector. + */ + uint8_t vector; + + /** A flag specifying the binding of the packet: + * + * set: binds to the next FUP. + * clear: binds to the next FUP + TIP, if tracing enabled. + * clear: standalone, if tracing disabled. + */ + uint32_t ip:1; +}; + +/* Event data types. */ +enum pt_evd_type { + pt_evd_cr2 = 0x00, /* Page fault linear address (cr2). */ + pt_evd_vmxq = 0x01, /* VMX exit qualification. */ + pt_evd_vmxr = 0x02, /* VMX exit reason. */ +}; + +/** A EVD packet. */ +struct pt_packet_evd { + /** The type of control-flow event. */ + enum pt_evd_type type; + + /** The payload depending on the type: + * + * 0x00: page fault linear address (cr2). + * 0x01: vmx exit qualification. + * 0x02: vmx exit reason. + */ + uint64_t payload; +}; +#endif /* (LIBIPT_VERSION >= 0x201) */ + +#if (LIBIPT_VERSION >= 0x202) +/** A TRIG packet. */ +struct pt_packet_trig { + /** A bit vector of triggers that are represented by this packet. */ + uint8_t trbv; + + /** An instruction count from the last IP packet (FUP, TIP*, or TNT) + * indicating the instruction to which this packet is attributed. + * + * This field is only valid if \@icntv is set. + */ + uint16_t icnt; + + /** A flag saying whether a FUP is following TRIG that provides a + * reference IP from which to start counting. + */ + uint32_t ip:1; + + /** A flag saying whether the \@icnt field is valid.*/ + uint32_t icntv:1; + + /** A flag saying whether there were other triggers firing that are not + * reported. + */ + uint32_t mult:1; +}; +#endif /* (LIBIPT_VERSION >= 0x202) */ + +/** An unknown packet decodable by the optional decoder callback. */ +struct pt_packet_unknown { + /** Pointer to the raw packet bytes. */ + const uint8_t *packet; + + /** Optional pointer to a user-defined structure. */ + void *priv; +}; + +/** An Intel PT packet. */ +struct pt_packet { + /** The type of the packet. + * + * This also determines the \@payload field. + */ + enum pt_packet_type type; + + /** The size of the packet including opcode and payload. */ + uint8_t size; + + /** Packet specific data. */ + union { + /** Packets: pad, ovf, psb, psbend, stop - no payload. */ + + /** Packet: tnt-8, tnt-64. */ + struct pt_packet_tnt tnt; + + /** Packet: tip, fup, tip.pge, tip.pgd. */ + struct pt_packet_ip ip; + + /** Packet: mode. */ + struct pt_packet_mode mode; + + /** Packet: pip. */ + struct pt_packet_pip pip; + + /** Packet: tsc. */ + struct pt_packet_tsc tsc; + + /** Packet: cbr. */ + struct pt_packet_cbr cbr; + + /** Packet: tma. */ + struct pt_packet_tma tma; + + /** Packet: mtc. */ + struct pt_packet_mtc mtc; + + /** Packet: cyc. */ + struct pt_packet_cyc cyc; + + /** Packet: vmcs. */ + struct pt_packet_vmcs vmcs; + + /** Packet: mnt. */ + struct pt_packet_mnt mnt; + + /** Packet: exstop. */ + struct pt_packet_exstop exstop; + + /** Packet: mwait. */ + struct pt_packet_mwait mwait; + + /** Packet: pwre. */ + struct pt_packet_pwre pwre; + + /** Packet: pwrx. */ + struct pt_packet_pwrx pwrx; + + /** Packet: ptw. */ + struct pt_packet_ptw ptw; + +#if (LIBIPT_VERSION >= 0x201) + /** Packet: cfe. */ + struct pt_packet_cfe cfe; + + /** Packet: evd. */ + struct pt_packet_evd evd; +#endif +#if (LIBIPT_VERSION >= 0x202) + /** Packet: trig. */ + struct pt_packet_trig trig; +#endif + /** Packet: unknown. */ + struct pt_packet_unknown unknown; + } payload; +}; + + + +/* Packet encoder. */ + + + +/** Allocate an Intel PT packet encoder. + * + * The encoder will work on the buffer defined in \@config, it shall contain + * raw trace data and remain valid for the lifetime of the encoder. + * + * The encoder starts at the beginning of the trace buffer. + */ +extern pt_export struct pt_encoder * +pt_alloc_encoder(const struct pt_config *config); + +/** Free an Intel PT packet encoder. + * + * The \@encoder must not be used after a successful return. + */ +extern pt_export void pt_free_encoder(struct pt_encoder *encoder); + +/** Hard set synchronization point of an Intel PT packet encoder. + * + * Synchronize \@encoder to \@offset within the trace buffer. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_eos if the given offset is behind the end of the trace buffer. + * Returns -pte_invalid if \@encoder is NULL. + */ +extern pt_export int pt_enc_sync_set(struct pt_encoder *encoder, + uint64_t offset); + +/** Get the current packet encoder position. + * + * Fills the current \@encoder position into \@offset. + * + * This is useful for reporting errors. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@encoder or \@offset is NULL. + */ +extern pt_export int pt_enc_get_offset(const struct pt_encoder *encoder, + uint64_t *offset); + +/* Return a pointer to \@encoder's configuration. + * + * Returns a non-null pointer on success, NULL if \@encoder is NULL. + */ +extern pt_export const struct pt_config * +pt_enc_get_config(const struct pt_encoder *encoder); + +/** Encode an Intel PT packet. + * + * Writes \@packet at \@encoder's current position in the Intel PT buffer and + * advances the \@encoder beyond the written packet. + * + * The \@packet.size field is ignored. + * + * In case of errors, the \@encoder is not advanced and nothing is written + * into the Intel PT buffer. + * + * Returns the number of bytes written on success, a negative error code + * otherwise. + * + * Returns -pte_bad_opc if \@packet.type is not known. + * Returns -pte_bad_packet if \@packet's payload is invalid. + * Returns -pte_eos if \@encoder reached the end of the Intel PT buffer. + * Returns -pte_invalid if \@encoder or \@packet is NULL. + */ +extern pt_export int pt_enc_next(struct pt_encoder *encoder, + const struct pt_packet *packet); + + + +/* Packet decoder. */ + + + +/** Allocate an Intel PT packet decoder. + * + * The decoder will work on the buffer defined in \@config, it shall contain + * raw trace data and remain valid for the lifetime of the decoder. + * + * The decoder needs to be synchronized before it can be used. + */ +extern pt_export struct pt_packet_decoder * +pt_pkt_alloc_decoder(const struct pt_config *config); + +/** Free an Intel PT packet decoder. + * + * The \@decoder must not be used after a successful return. + */ +extern pt_export void pt_pkt_free_decoder(struct pt_packet_decoder *decoder); + +/** Synchronize an Intel PT packet decoder. + * + * Search for the next synchronization point in forward or backward direction. + * + * If \@decoder has not been synchronized, yet, the search is started at the + * beginning of the trace buffer in case of forward synchronization and at the + * end of the trace buffer in case of backward synchronization. + * + * Returns zero or a positive value on success, a negative error code otherwise. + * + * Returns -pte_eos if no further synchronization point is found. + * Returns -pte_invalid if \@decoder is NULL. + */ +extern pt_export int pt_pkt_sync_forward(struct pt_packet_decoder *decoder); +extern pt_export int pt_pkt_sync_backward(struct pt_packet_decoder *decoder); + +/** Hard set synchronization point of an Intel PT decoder. + * + * Synchronize \@decoder to \@offset within the trace buffer. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_eos if the given offset is behind the end of the trace buffer. + * Returns -pte_invalid if \@decoder is NULL. + */ +extern pt_export int pt_pkt_sync_set(struct pt_packet_decoder *decoder, + uint64_t offset); + +/** Get the current decoder position. + * + * Fills the current \@decoder position into \@offset. + * + * This is useful for reporting errors. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@offset is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_pkt_get_offset(const struct pt_packet_decoder *decoder, + uint64_t *offset); + +/** Get the position of the last synchronization point. + * + * Fills the last synchronization position into \@offset. + * + * This is useful when splitting a trace stream for parallel decoding. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@offset is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int +pt_pkt_get_sync_offset(const struct pt_packet_decoder *decoder, + uint64_t *offset); + +/* Return a pointer to \@decoder's configuration. + * + * Returns a non-null pointer on success, NULL if \@decoder is NULL. + */ +extern pt_export const struct pt_config * +pt_pkt_get_config(const struct pt_packet_decoder *decoder); + +/** Decode the next packet and advance the decoder. + * + * Decodes the packet at \@decoder's current position into \@packet and + * adjusts the \@decoder's position by the number of bytes the packet had + * consumed. + * + * The \@size argument must be set to sizeof(struct pt_packet). + * + * Returns the number of bytes consumed on success, a negative error code + * otherwise. + * + * Returns -pte_bad_opc if the packet is unknown. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if \@decoder reached the end of the Intel PT buffer. + * Returns -pte_invalid if \@decoder or \@packet is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_pkt_next(struct pt_packet_decoder *decoder, + struct pt_packet *packet, size_t size); + + + +/* Event decoder. */ + + + +/** Event types. */ +enum pt_event_type { + /* Tracing has been enabled/disabled. */ + ptev_enabled, + ptev_disabled, + + /* Tracing has been disabled asynchronously. */ + ptev_async_disabled, + + /* An asynchronous branch, e.g. interrupt. */ + ptev_async_branch, + + /* A synchronous paging event. */ + ptev_paging, + + /* An asynchronous paging event. */ + ptev_async_paging, + + /* Trace overflow. */ + ptev_overflow, + + /* An execution mode change. */ + ptev_exec_mode, + + /* A transactional execution state change. */ + ptev_tsx, + + /* Trace Stop. */ + ptev_stop, + + /* A synchronous vmcs event. */ + ptev_vmcs, + + /* An asynchronous vmcs event. */ + ptev_async_vmcs, + + /* Execution has stopped. */ + ptev_exstop, + + /* An MWAIT operation completed. */ + ptev_mwait, + + /* A power state was entered. */ + ptev_pwre, + + /* A power state was exited. */ + ptev_pwrx, + + /* A PTWRITE event. */ + ptev_ptwrite, + + /* A timing event. */ + ptev_tick, + + /* A core:bus ratio event. */ + ptev_cbr, + + /* A maintenance event. */ + ptev_mnt, + +#if (LIBIPT_VERSION >= 0x201) + /* An indirect branch event. */ + ptev_tip, + + /* A conditional branch indicator event. */ + ptev_tnt, + + /* An interrupt status event. */ + ptev_iflags, + + /* An interrupt or exception event. + * + * This event extends the async_branch event generated for the + * control-flow change; it does not replace that event. + */ + ptev_interrupt, + + /* A return from interrupt event. */ + ptev_iret, + + /* A system management interrupt. */ + ptev_smi, + + /* A return from system management mode. */ + ptev_rsm, + + /* A SIPI message. */ + ptev_sipi, + + /* An INIT reset. */ + ptev_init, + + /* A Virtual Machine entry. */ + ptev_vmentry, + + /* A Virtual Machine exit. */ + ptev_vmexit, + + /* A shutdown event. */ + ptev_shutdown, + + /* A user interrupt. */ + ptev_uintr, + + /* A return from user interrupt. */ + ptev_uiret, +#endif +#if (LIBIPT_VERSION >= 0x202) + /* A trigger event. */ + ptev_trig, + + /* A software interrupt. */ + ptev_swintr, + + /* A system call. */ + ptev_syscall, +#endif +}; + +/** An event. */ +struct pt_event { + /** The type of the event. */ + enum pt_event_type type; + + /** A flag indicating that the event IP has been suppressed. */ + uint32_t ip_suppressed:1; + + /** A flag indicating that the event is for status update. */ + uint32_t status_update:1; + + /** A flag indicating that the event has timing information. */ + uint32_t has_tsc:1; + + /** The time stamp count of the event. + * + * This field is only valid if \@has_tsc is set. + */ + uint64_t tsc; + + /** The number of lost mtc and cyc packets. + * + * This gives an idea about the quality of the \@tsc. The more packets + * were dropped, the less precise timing is. + */ + uint32_t lost_mtc; + uint32_t lost_cyc; + + /* Reserved space for future extensions. */ + uint64_t reserved[2]; + + /** Event specific data. */ + union { + /** Event: enabled. */ + struct { + /** The address at which tracing resumes. */ + uint64_t ip; + + /** A flag indicating that tracing resumes from the IP + * at which tracing had been disabled before. + */ + uint32_t resumed:1; + } enabled; + + /** Event: disabled. */ + struct { + /** The destination of the first branch inside a + * filtered area. + * + * This field is not valid if \@ip_suppressed is set. + */ + uint64_t ip; + + /* The exact source ip needs to be determined using + * disassembly and the filter configuration. + */ + } disabled; + + /** Event: async disabled. */ + struct { + /** The source address of the asynchronous branch that + * disabled tracing. + */ + uint64_t at; + + /** The destination of the first branch inside a + * filtered area. + * + * This field is not valid if \@ip_suppressed is set. + */ + uint64_t ip; + } async_disabled; + + /** Event: async branch. */ + struct { + /** The branch source address. */ + uint64_t from; + + /** The branch destination address. + * + * This field is not valid if \@ip_suppressed is set. + */ + uint64_t to; + } async_branch; + + /** Event: paging. */ + struct { + /** The updated CR3 value. + * + * The lower 5 bit have been zeroed out. + * The upper bits have been zeroed out depending on the + * maximum possible address. + */ + uint64_t cr3; + + /** A flag indicating whether the cpu is operating in + * vmx non-root (guest) mode. + */ + uint32_t non_root:1; + + /* The address at which the event is effective is + * obvious from the disassembly. + */ + } paging; + + /** Event: async paging. */ + struct { + /** The updated CR3 value. + * + * The lower 5 bit have been zeroed out. + * The upper bits have been zeroed out depending on the + * maximum possible address. + */ + uint64_t cr3; + + /** A flag indicating whether the cpu is operating in + * vmx non-root (guest) mode. + */ + uint32_t non_root:1; + + /** The address at which the event is effective. */ + uint64_t ip; + } async_paging; + + /** Event: overflow. */ + struct { + /** The address at which tracing resumes after overflow. + * + * This field is not valid, if ip_suppressed is set. + * In this case, the overflow resolved while tracing + * was disabled. + */ + uint64_t ip; + } overflow; + + /** Event: exec mode. */ + struct { + /** The execution mode. */ + enum pt_exec_mode mode; + + /** The address at which the event is effective. */ + uint64_t ip; + } exec_mode; + + /** Event: tsx. */ + struct { + /** The address at which the event is effective. + * + * This field is not valid if \@ip_suppressed is set. + */ + uint64_t ip; + + /** A flag indicating speculative execution mode. */ + uint32_t speculative:1; + + /** A flag indicating speculative execution aborts. */ + uint32_t aborted:1; + } tsx; + + /** Event: vmcs. */ + struct { + /** The VMCS base address. + * + * The address is zero-extended with the lower 12 bits + * all zero. + */ + uint64_t base; + + /* The new VMCS base address should be stored and + * applied on subsequent VM entries. + */ + } vmcs; + + /** Event: async vmcs. */ + struct { + /** The VMCS base address. + * + * The address is zero-extended with the lower 12 bits + * all zero. + */ + uint64_t base; + + /** The address at which the event is effective. */ + uint64_t ip; + + /* An async paging event that binds to the same IP + * will always succeed this async vmcs event. + */ + } async_vmcs; + + /** Event: execution stopped. */ + struct { + /** The address at which execution has stopped. This is + * the last instruction that did not complete. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } exstop; + + /** Event: mwait. */ + struct { + /** The address of the instruction causing the mwait. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + + /** The mwait hints (eax). + * + * Reserved bits are undefined. + */ + uint32_t hints; + + /** The mwait extensions (ecx). + * + * Reserved bits are undefined. + */ + uint32_t ext; + } mwait; + + /** Event: power state entry. */ + struct { + /** The resolved thread C-state. */ + uint8_t state; + + /** The resolved thread sub C-state. */ + uint8_t sub_state; + + /** A flag indicating whether the C-state entry was + * initiated by h/w. + */ + uint32_t hw:1; + } pwre; + + /** Event: power state exit. */ + struct { + /** The core C-state at the time of the wake. */ + uint8_t last; + + /** The deepest core C-state achieved during sleep. */ + uint8_t deepest; + + /** The wake reason: + * + * - due to external interrupt received. + */ + uint32_t interrupt:1; + + /** - due to store to monitored address. */ + uint32_t store:1; + + /** - due to h/w autonomous condition such as HDC. */ + uint32_t autonomous:1; + } pwrx; + + /** Event: ptwrite. */ + struct { + /** The address of the ptwrite instruction. + * + * This field is not valid, if \@ip_suppressed is set. + * + * In this case, the address is obvious from the + * disassembly. + */ + uint64_t ip; + + /** The size of the below \@payload in bytes. */ + uint8_t size; + + /** The ptwrite payload. */ + uint64_t payload; + } ptwrite; + + /** Event: tick. */ + struct { + /** The instruction address near which the tick + * occurred. + * + * A timestamp can sometimes be attributed directly to + * an instruction (e.g. to an indirect branch that + * receives CYC + TIP) and sometimes not (e.g. MTC). + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } tick; + + /** Event: cbr. */ + struct { + /** The core:bus ratio. */ + uint16_t ratio; + } cbr; + + /** Event: mnt. */ + struct { + /** The raw payload. */ + uint64_t payload; + } mnt; + +#if (LIBIPT_VERSION >= 0x201) + /** Event: tip. */ + struct { + /** The target instruction address. */ + uint64_t ip; + } tip; + + /** Event: tnt. */ + struct { + /** A sequence of conditional branch indicator bits. + * + * Indicators are ordered from oldest (bits[size-1]) to + * youngest (bits[0]) branch: + * + * 0...branch not taken + * 1...branch taken + */ + uint64_t bits; + + /** The number of valid bits in @bits. */ + uint8_t size; + } tnt; + + /** Event: iflags. */ + struct { + /** The EFLAGS.IF status. */ + uint32_t iflag:1; + + /** The address of the instruction at which the new + * status applies. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } iflags; + + /** Event: interrupt/exception. */ + struct { + /** A flag saying whether the \@cr2 field is valid. */ + uint32_t has_cr2:1; + + /** The interrupt/exception vector. */ + uint8_t vector; + + /** The page fault linear address in cr2. + * + * This field is only valid if \@has_cr2 is set. + */ + uint64_t cr2; + + /** The address of the instruction at which the + * interrupt or exception occurred. + * + * For faults, this will be the faulting instruction. + * For traps, this will be the next instruction. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } interrupt; + + /** Event: iret. */ + struct { + /** The address of the instruction. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } iret; + + /** Event: smi. */ + struct { + /** The address of the instruction at/before which the + * system management interrupt occurred. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } smi; + + /** Event: rsm. */ + struct { + /** The address of the instruction. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } rsm; + + /** Event: sipi. */ + struct { + /** The SIPI vector. */ + uint8_t vector; + } sipi; + + /** Event: init. */ + struct { + /** The address of the instruction. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } init; + + /** Event: vmentry. */ + struct { + /** The address of the instruction. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } vmentry; + + /** Event: vmexit. */ + struct { + /** A flag saying whether the \@vector field is valid. + * + * When set, the vmexit occurred due to an interrupt or + * exception. + */ + uint32_t has_vector:1; + + /** A flag saying whether the \@vmxr field is valid. */ + uint32_t has_vmxr:1; + + /** A flag saying whether the \@vmxq field is valid. */ + uint32_t has_vmxq:1; + + /** The interrupt/exception vector. + * + * This field is only valid if \@has_vector is set. + */ + uint8_t vector; + + /** The vmexit reason. + * + * This field is only valid if \@has_vmxr is set. + */ + uint64_t vmxr; + + /** The vmexit qualification. + * + * This field is only valid if \@has_vmxq is set. + */ + uint64_t vmxq; + + /** The address of the instruction at which the + * interrupt or exception occurred. + * + * For faults, this will be the faulting instruction. + * For traps, this will be the next instruction. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } vmexit; + + /** Event: shutdown. */ + struct { + /** The address of the first instruction that did not + * complete due to the shutdown. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } shutdown; + + /** Event: user interrupt. */ + struct { + /** The user interrupt vector. */ + uint8_t vector; + + /** The address of the instruction before which the + * user interrupt was delivered. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } uintr; + + /** Event: uiret. */ + struct { + /** The address of the instruction. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } uiret; +#endif /* (LIBIPT_VERSION >= 0x201) */ + +#if (LIBIPT_VERSION >= 0x202) + /** Event: trigger. */ + struct { + /** A bit vector of triggers represented by this event. + * + * Triggers are configured via IA32_RTIT_TRIGGERx_CFG. + */ + uint8_t trbv; + + /** The number of instructions after the anchor. + * + * The insn and block decoders will attempty to reduce + * \@icount to zero and update \@ip. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint16_t icnt; + + /** The address of the anchor instruction. + * + * If this field is zero, use the address of the last + * trig, tip, tip.pge, or async event, or the address + * after applying the final bit in the last tnt event. + * + * The insn and block decoders will supply a non-zero + * address or set \@ip_suppressed. + * + * The event is reported when reaching the instruction + * address before the instruction itself to correctly + * handle cases where the instruction faults. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + + /** A flag saying whether there were other triggers + * firing that are not reported. + */ + uint32_t mult:1; + } trig; + + /** Event: software interrupt. */ + struct { + /** The interrupt vector. */ + uint8_t vector; + + /** The address of the instruction that generated the + * software interrupt. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } swintr; + + /** Event: system call. */ + struct { + /** The address of the instruction. + * + * This field is not valid, if \@ip_suppressed is set. + */ + uint64_t ip; + } syscall; +#endif /* (LIBIPT_VERSION >= 0x202) */ + } variant; +}; + + +#if (LIBIPT_VERSION >= 0x201) +/** Allocate an Intel PT event decoder. + * + * The decoder will work on the buffer defined in \@config, it shall contain + * raw trace data and remain valid for the lifetime of the decoder. + * + * The decoder needs to be synchronized before it can be used. + */ +extern pt_export struct pt_event_decoder * +pt_evt_alloc_decoder(const struct pt_config *config); + +/** Free an Intel PT event decoder. + * + * The \@decoder must not be used after a successful return. + */ +extern pt_export void pt_evt_free_decoder(struct pt_event_decoder *decoder); + +/** Synchronize an Intel PT event decoder. + * + * Search for the next synchronization point in forward or backward direction. + * + * If \@decoder has not been synchronized, yet, the search is started at the + * beginning of the trace buffer in case of forward synchronization and at the + * end of the trace buffer in case of backward synchronization. + * + * Returns zero or a positive value on success, a negative error code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if no further synchronization point is found. + * Returns -pte_invalid if \@decoder is NULL. + */ +extern pt_export int pt_evt_sync_forward(struct pt_event_decoder *decoder); +extern pt_export int pt_evt_sync_backward(struct pt_event_decoder *decoder); + +/** Manually synchronize an Intel PT event decoder. + * + * Synchronize \@decoder on the syncpoint at \@offset. There must be a PSB + * packet at \@offset. + * + * Returns zero or a positive value on success, a negative error code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if \@offset lies outside of \@decoder's trace buffer. + * Returns -pte_eos if \@decoder reaches the end of its trace buffer. + * Returns -pte_invalid if \@decoder is NULL. + * Returns -pte_nosync if there is no syncpoint at \@offset. + */ +extern pt_export int pt_evt_sync_set(struct pt_event_decoder *decoder, + uint64_t offset); + +/** Get the current decoder position. + * + * Fills the current \@decoder position into \@offset. + * + * This is useful for reporting errors. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@offset is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_evt_get_offset(const struct pt_event_decoder *decoder, + uint64_t *offset); + +/** Get the position of the last synchronization point. + * + * Fills the last synchronization position into \@offset. + * + * This is useful for splitting a trace stream for parallel decoding. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@offset is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int +pt_evt_get_sync_offset(const struct pt_event_decoder *decoder, + uint64_t *offset); + +/* Return a pointer to \@decoder's configuration. + * + * Returns a non-null pointer on success, NULL if \@decoder is NULL. + */ +extern pt_export const struct pt_config * +pt_evt_get_config(const struct pt_event_decoder *decoder); + +/** Determine the next event. + * + * On success, provides the next event in \@event. + * + * The \@size argument must be set to sizeof(struct pt_event). + * + * Returns zero or a positive value on success, a negative error code + * otherwise. + * + * Returns -pte_bad_opc if the packet is unknown. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if \@decoder reached the end of the Intel PT buffer. + * Returns -pte_invalid if \@decoder or \@event is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_evt_next(struct pt_event_decoder *decoder, + struct pt_event *event, size_t size); +#endif /* (LIBIPT_VERSION >= 0x201) */ + + + +/* Query decoder. */ + + + +/** Decoder status flags. */ +enum pt_status_flag { + /** There is an event pending. */ + pts_event_pending = 1 << 0, + + /** The address has been suppressed. */ + pts_ip_suppressed = 1 << 1, + + /** There is no more trace data available. */ + pts_eos = 1 << 2 +}; + +/** Allocate an Intel PT query decoder. + * + * The decoder will work on the buffer defined in \@config, it shall contain + * raw trace data and remain valid for the lifetime of the decoder. + * + * The decoder needs to be synchronized before it can be used. + */ +extern pt_export struct pt_query_decoder * +pt_qry_alloc_decoder(const struct pt_config *config); + +/** Free an Intel PT query decoder. + * + * The \@decoder must not be used after a successful return. + */ +extern pt_export void pt_qry_free_decoder(struct pt_query_decoder *decoder); + +/** Synchronize an Intel PT query decoder. + * + * Search for the next synchronization point in forward or backward direction. + * + * If \@decoder has not been synchronized, yet, the search is started at the + * beginning of the trace buffer in case of forward synchronization and at the + * end of the trace buffer in case of backward synchronization. + * + * If \@ip is not NULL, set it to last ip. + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative error + * code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if no further synchronization point is found. + * Returns -pte_invalid if \@decoder is NULL. + */ +extern pt_export int pt_qry_sync_forward(struct pt_query_decoder *decoder, + uint64_t *ip); +extern pt_export int pt_qry_sync_backward(struct pt_query_decoder *decoder, + uint64_t *ip); + +/** Manually synchronize an Intel PT query decoder. + * + * Synchronize \@decoder on the syncpoint at \@offset. There must be a PSB + * packet at \@offset. + * + * If \@ip is not NULL, set it to last ip. + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative error + * code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if \@offset lies outside of \@decoder's trace buffer. + * Returns -pte_eos if \@decoder reaches the end of its trace buffer. + * Returns -pte_invalid if \@decoder is NULL. + * Returns -pte_nosync if there is no syncpoint at \@offset. + */ +extern pt_export int pt_qry_sync_set(struct pt_query_decoder *decoder, + uint64_t *ip, uint64_t offset); + +/** Get the current decoder position. + * + * Fills the current \@decoder position into \@offset. + * + * This is useful for reporting errors. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@offset is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_qry_get_offset(const struct pt_query_decoder *decoder, + uint64_t *offset); + +/** Get the position of the last synchronization point. + * + * Fills the last synchronization position into \@offset. + * + * This is useful for splitting a trace stream for parallel decoding. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@offset is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int +pt_qry_get_sync_offset(const struct pt_query_decoder *decoder, + uint64_t *offset); + +/* Return a pointer to \@decoder's configuration. + * + * Returns a non-null pointer on success, NULL if \@decoder is NULL. + */ +extern pt_export const struct pt_config * +pt_qry_get_config(const struct pt_query_decoder *decoder); + +/** Query whether the next unconditional branch has been taken. + * + * On success, provides 1 (taken) or 0 (not taken) in \@taken for the next + * conditional branch and updates \@decoder. + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative error + * code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_bad_query if no conditional branch is found. + * Returns -pte_eos if decoding reached the end of the Intel PT buffer. + * Returns -pte_invalid if \@decoder or \@taken is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_qry_cond_branch(struct pt_query_decoder *decoder, + int *taken); + +/** Get the next indirect branch destination. + * + * On success, provides the linear destination address of the next indirect + * branch in \@ip and updates \@decoder. + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative error + * code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_bad_query if no indirect branch is found. + * Returns -pte_eos if decoding reached the end of the Intel PT buffer. + * Returns -pte_invalid if \@decoder or \@ip is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_qry_indirect_branch(struct pt_query_decoder *decoder, + uint64_t *ip); + +/** Query the next pending event. + * + * On success, provides the next event \@event and updates \@decoder. + * + * The \@size argument must be set to sizeof(struct pt_event). + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative error + * code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_bad_query if no event is found. + * Returns -pte_eos if decoding reached the end of the Intel PT buffer. + * Returns -pte_invalid if \@decoder or \@event is NULL. + * Returns -pte_invalid if \@size is too small. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_qry_event(struct pt_query_decoder *decoder, + struct pt_event *event, size_t size); + +/** Query the current time. + * + * On success, provides the time at the last query in \@time. + * + * The time is similar to what a rdtsc instruction would return. Depending + * on the configuration, the time may not be fully accurate. If TSC is not + * enabled, the time is relative to the last synchronization and can't be used + * to correlate with other TSC-based time sources. In this case, -pte_no_time + * is returned and the relative time is provided in \@time. + * + * Some timing-related packets may need to be dropped (mostly due to missing + * calibration or incomplete configuration). To get an idea about the quality + * of the estimated time, we record the number of dropped MTC and CYC packets. + * + * If \@lost_mtc is not NULL, set it to the number of lost MTC packets. + * If \@lost_cyc is not NULL, set it to the number of lost CYC packets. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@time is NULL. + * Returns -pte_no_time if there has not been a TSC packet. + */ +extern pt_export int pt_qry_time(struct pt_query_decoder *decoder, + uint64_t *time, uint32_t *lost_mtc, + uint32_t *lost_cyc); + +/** Return the current core bus ratio. + * + * On success, provides the current core:bus ratio in \@cbr. The ratio is + * defined as core cycles per bus clock cycle. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@cbr is NULL. + * Returns -pte_no_cbr if there has not been a CBR packet. + */ +extern pt_export int pt_qry_core_bus_ratio(struct pt_query_decoder *decoder, + uint32_t *cbr); + + + +/* Traced image. */ + + + +/** An Intel PT address space identifier. + * + * This identifies a particular address space when adding file sections or + * when reading memory. + */ +struct pt_asid { + /** The size of this object - set to sizeof(struct pt_asid). */ + size_t size; + + /** The CR3 value. */ + uint64_t cr3; + + /** The VMCS Base address. */ + uint64_t vmcs; +}; + +/** An unknown CR3 value to be used for pt_asid objects. */ +static const uint64_t pt_asid_no_cr3 = 0xffffffffffffffffull; + +/** An unknown VMCS Base value to be used for pt_asid objects. */ +static const uint64_t pt_asid_no_vmcs = 0xffffffffffffffffull; + +/** Initialize an address space identifier. */ +static inline void pt_asid_init(struct pt_asid *asid) +{ + asid->size = sizeof(*asid); + asid->cr3 = pt_asid_no_cr3; + asid->vmcs = pt_asid_no_vmcs; +} + + +/** A cache of traced image sections. */ +struct pt_image_section_cache; + +/** Allocate a traced memory image section cache. + * + * An optional \@name may be given to the cache. The name string is copied. + * + * Returns a new traced memory image section cache on success, NULL otherwise. + */ +extern pt_export struct pt_image_section_cache * +pt_iscache_alloc(const char *name); + +/** Free a traced memory image section cache. + * + * The \@iscache must have been allocated with pt_iscache_alloc(). + * The \@iscache must not be used after a successful return. + */ +extern pt_export void pt_iscache_free(struct pt_image_section_cache *iscache); + +/** Set the image section cache limit. + * + * Set the limit for a section cache in bytes. A non-zero limit will keep the + * least recently used sections mapped until the limit is reached. A limit of + * zero disables caching. + * + * Returns zero on success, a negative pt_error_code otherwise. + * Returns -pte_invalid if \@iscache is NULL. + */ +extern pt_export int +pt_iscache_set_limit(struct pt_image_section_cache *iscache, uint64_t limit); + +/** Get the image section cache name. + * + * Returns a pointer to \@iscache's name or NULL if there is no name. + */ +extern pt_export const char * +pt_iscache_name(const struct pt_image_section_cache *iscache); + +/** Add a new file section to the traced memory image section cache. + * + * Adds a new section consisting of \@size bytes starting at \@offset in + * \@filename loaded at the virtual address \@vaddr if \@iscache does not + * already contain such a section. + * + * Returns an image section identifier (isid) uniquely identifying that section + * in \@iscache. + * + * The section is silently truncated to match the size of \@filename. + * + * Returns a positive isid on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@iscache or \@filename is NULL. + * Returns -pte_invalid if \@offset is too big. + */ +extern pt_export int pt_iscache_add_file(struct pt_image_section_cache *iscache, + const char *filename, uint64_t offset, + uint64_t size, uint64_t vaddr); + +/** Read memory from a cached file section + * + * Reads \@size bytes of memory starting at virtual address \@vaddr in the + * section identified by \@isid in \@iscache into \@buffer. + * + * The caller is responsible for allocating a \@buffer of at least \@size bytes. + * + * The read request may be truncated if it crosses section boundaries or if + * \@size is getting too big. We support reading at least 4Kbyte in one chunk + * unless the read would cross a section boundary. + * + * Returns the number of bytes read on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@iscache or \@buffer is NULL. + * Returns -pte_invalid if \@size is zero. + * Returns -pte_nomap if \@vaddr is not contained in section \@isid. + * Returns -pte_bad_image if \@iscache does not contain \@isid. + */ +extern pt_export int pt_iscache_read(struct pt_image_section_cache *iscache, + uint8_t *buffer, uint64_t size, int isid, + uint64_t vaddr); + +/** The traced memory image. */ +struct pt_image; + + +/** Allocate a traced memory image. + * + * An optional \@name may be given to the image. The name string is copied. + * + * Returns a new traced memory image on success, NULL otherwise. + */ +extern pt_export struct pt_image *pt_image_alloc(const char *name); + +/** Free a traced memory image. + * + * The \@image must have been allocated with pt_image_alloc(). + * The \@image must not be used after a successful return. + */ +extern pt_export void pt_image_free(struct pt_image *image); + +/** Get the image name. + * + * Returns a pointer to \@image's name or NULL if there is no name. + */ +extern pt_export const char *pt_image_name(const struct pt_image *image); + +/** Add a new file section to the traced memory image. + * + * Adds \@size bytes starting at \@offset in \@filename. The section is + * loaded at the virtual address \@vaddr in the address space \@asid. + * + * The \@asid may be NULL or (partially) invalid. In that case only the valid + * fields are considered when comparing with other address-spaces. Use this + * when tracing a single process or when adding sections to all processes. + * + * The section is silently truncated to match the size of \@filename. + * + * Existing sections that would overlap with the new section will be shrunk + * or split. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@image or \@filename is NULL. + * Returns -pte_invalid if \@offset is too big. + */ +extern pt_export int pt_image_add_file(struct pt_image *image, + const char *filename, uint64_t offset, + uint64_t size, + const struct pt_asid *asid, + uint64_t vaddr); + +/** Add a section from an image section cache. + * + * Add the section from \@iscache identified by \@isid in address space \@asid. + * + * Existing sections that would overlap with the new section will be shrunk + * or split. + * + * Returns zero on success, a negative error code otherwise. + * Returns -pte_invalid if \@image or \@iscache is NULL. + * Returns -pte_bad_image if \@iscache does not contain \@isid. + */ +extern pt_export int pt_image_add_cached(struct pt_image *image, + struct pt_image_section_cache *iscache, + int isid, const struct pt_asid *asid); + +/** Copy an image. + * + * Adds all sections from \@src to \@image. Sections that could not be added + * will be ignored. + * + * Returns the number of ignored sections on success, a negative error code + * otherwise. + * + * Returns -pte_invalid if \@image or \@src is NULL. + */ +extern pt_export int pt_image_copy(struct pt_image *image, + const struct pt_image *src); + +/** Remove all sections loaded from a file. + * + * Removes all sections loaded from \@filename from the address space \@asid. + * Specify the same \@asid that was used for adding sections from \@filename. + * + * Returns the number of removed sections on success, a negative error code + * otherwise. + * + * Returns -pte_invalid if \@image or \@filename is NULL. + */ +extern pt_export int pt_image_remove_by_filename(struct pt_image *image, + const char *filename, + const struct pt_asid *asid); + +/** Remove all sections loaded into an address space. + * + * Removes all sections loaded into \@asid. Specify the same \@asid that was + * used for adding sections. + * + * Returns the number of removed sections on success, a negative error code + * otherwise. + * + * Returns -pte_invalid if \@image is NULL. + */ +extern pt_export int pt_image_remove_by_asid(struct pt_image *image, + const struct pt_asid *asid); + +/** A read memory callback function. + * + * It shall read \@size bytes of memory from address space \@asid starting + * at \@ip into \@buffer. + * + * It shall return the number of bytes read on success. + * It shall return a negative pt_error_code otherwise. + */ +typedef int (read_memory_callback_t)(uint8_t *buffer, size_t size, + const struct pt_asid *asid, + uint64_t ip, void *context); + +/** Set the memory callback for the traced memory image. + * + * Sets \@callback for reading memory. The callback is used for addresses + * that are not found in file sections. The \@context argument is passed + * to \@callback on each use. + * + * There can only be one callback at any time. A subsequent call will replace + * the previous callback. If \@callback is NULL, the callback is removed. + * + * Returns -pte_invalid if \@image is NULL. + */ +extern pt_export int pt_image_set_callback(struct pt_image *image, + read_memory_callback_t *callback, + void *context); + + + +/* Instruction flow decoder. */ + + + +/** The instruction class. + * + * We provide only a very coarse classification suitable for reconstructing + * the execution flow. + */ +enum pt_insn_class { +#if (LIBIPT_VERSION >= 0x201) + /* The instruction has not been classified. */ + ptic_unknown, + + /* For backwards compatibility. */ + ptic_error = ptic_unknown, +#else + /* The instruction has not been classified. */ + ptic_error, +#endif + + /* The instruction is something not listed below. */ + ptic_other, + + /* The instruction is a near (function) call. */ + ptic_call, + + /* The instruction is a near (function) return. */ + ptic_return, + + /* The instruction is a near unconditional jump. */ + ptic_jump, + + /* The instruction is a near conditional jump. */ + ptic_cond_jump, + + /* The instruction is a call-like far transfer. + * E.g. SYSCALL, SYSENTER, or FAR CALL. + */ + ptic_far_call, + + /* The instruction is a return-like far transfer. + * E.g. SYSRET, SYSEXIT, IRET, or FAR RET. + */ + ptic_far_return, + + /* The instruction is a jump-like far transfer. + * E.g. FAR JMP. + */ + ptic_far_jump, + + /* The instruction is a PTWRITE. */ + ptic_ptwrite, + +#if (LIBIPT_VERSION >= 0x201) + /* The instruction is an indirect jump or a far transfer. */ + ptic_indirect, +#endif +}; + +/** The maximal size of an instruction. */ +enum { + pt_max_insn_size = 15 +}; + +/** A single traced instruction. */ +struct pt_insn { + /** The virtual address in its process. */ + uint64_t ip; + + /** The image section identifier for the section containing this + * instruction. + * + * A value of zero means that the section did not have an identifier. + * The section was not added via an image section cache or the memory + * was read via the read memory callback. + */ + int isid; + + /** The execution mode. */ + enum pt_exec_mode mode; + + /** A coarse classification. */ + enum pt_insn_class iclass; + + /** The raw bytes. */ + uint8_t raw[pt_max_insn_size]; + + /** The size in bytes. */ + uint8_t size; + + /** A collection of flags giving additional information: + * + * - the instruction was executed speculatively. + */ + uint32_t speculative:1; + + /** - this instruction is truncated in its image section. + * + * It starts in the image section identified by \@isid and continues + * in one or more other sections. + */ + uint32_t truncated:1; +}; + + +/** Allocate an Intel PT instruction flow decoder. + * + * The decoder will work on the buffer defined in \@config, it shall contain + * raw trace data and remain valid for the lifetime of the decoder. + * + * The decoder needs to be synchronized before it can be used. + */ +extern pt_export struct pt_insn_decoder * +pt_insn_alloc_decoder(const struct pt_config *config); + +/** Free an Intel PT instruction flow decoder. + * + * This will destroy the decoder's default image. + * + * The \@decoder must not be used after a successful return. + */ +extern pt_export void pt_insn_free_decoder(struct pt_insn_decoder *decoder); + +/** Synchronize an Intel PT instruction flow decoder. + * + * Search for the next synchronization point in forward or backward direction. + * + * If \@decoder has not been synchronized, yet, the search is started at the + * beginning of the trace buffer in case of forward synchronization and at the + * end of the trace buffer in case of backward synchronization. + * + * Returns zero or a positive value on success, a negative error code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if no further synchronization point is found. + * Returns -pte_invalid if \@decoder is NULL. + */ +extern pt_export int pt_insn_sync_forward(struct pt_insn_decoder *decoder); +extern pt_export int pt_insn_sync_backward(struct pt_insn_decoder *decoder); + +/** Manually synchronize an Intel PT instruction flow decoder. + * + * Synchronize \@decoder on the syncpoint at \@offset. There must be a PSB + * packet at \@offset. + * + * Returns zero or a positive value on success, a negative error code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if \@offset lies outside of \@decoder's trace buffer. + * Returns -pte_eos if \@decoder reaches the end of its trace buffer. + * Returns -pte_invalid if \@decoder is NULL. + * Returns -pte_nosync if there is no syncpoint at \@offset. + */ +extern pt_export int pt_insn_sync_set(struct pt_insn_decoder *decoder, + uint64_t offset); + +#if (LIBIPT_VERSION >= 0x202) +/** Re-synchronize an Intel PT instruction flow decoder. + * + * Scan ahead for the next IP providing packet. Apply state changing packets + * along the way, including timing packets, but ignore everything else. + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative + * error code otherwise. + * + * Returns pts_ip_suppressed if re-synchronization succeeded with tracing + * disabled. + * + * Returns -pte_event_ignored if an event cannot safely be skipped + * (e.g. ptwrite). Use pt_insn_event() to read the event, then continue with + * pt_insn_resync() until re-synchronization completes or fails with an error. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if no further synchronization point is found. + * Returns -pte_invalid if \@decoder is NULL. + */ +extern pt_export int pt_insn_resync(struct pt_insn_decoder *decoder); +#endif + +/** Get the current decoder position. + * + * Fills the current \@decoder position into \@offset. + * + * This is useful for reporting errors. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@offset is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_insn_get_offset(const struct pt_insn_decoder *decoder, + uint64_t *offset); + +/** Get the position of the last synchronization point. + * + * Fills the last synchronization position into \@offset. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@offset is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int +pt_insn_get_sync_offset(const struct pt_insn_decoder *decoder, + uint64_t *offset); + +/** Get the traced image. + * + * The returned image may be modified as long as no decoder that uses this + * image is running. + * + * Returns a pointer to the traced image the decoder uses for reading memory. + * Returns NULL if \@decoder is NULL. + */ +extern pt_export struct pt_image * +pt_insn_get_image(struct pt_insn_decoder *decoder); + +/** Set the traced image. + * + * Sets the image that \@decoder uses for reading memory to \@image. If \@image + * is NULL, sets the image to \@decoder's default image. + * + * Only one image can be active at any time. + * + * Returns zero on success, a negative error code otherwise. + * Return -pte_invalid if \@decoder is NULL. + */ +extern pt_export int pt_insn_set_image(struct pt_insn_decoder *decoder, + struct pt_image *image); + +/* Return a pointer to \@decoder's configuration. + * + * Returns a non-null pointer on success, NULL if \@decoder is NULL. + */ +extern pt_export const struct pt_config * +pt_insn_get_config(const struct pt_insn_decoder *decoder); + +/** Return the current time. + * + * On success, provides the time at the last preceding timing packet in \@time. + * + * The time is similar to what a rdtsc instruction would return. Depending + * on the configuration, the time may not be fully accurate. If TSC is not + * enabled, the time is relative to the last synchronization and can't be used + * to correlate with other TSC-based time sources. In this case, -pte_no_time + * is returned and the relative time is provided in \@time. + * + * Some timing-related packets may need to be dropped (mostly due to missing + * calibration or incomplete configuration). To get an idea about the quality + * of the estimated time, we record the number of dropped MTC and CYC packets. + * + * If \@lost_mtc is not NULL, set it to the number of lost MTC packets. + * If \@lost_cyc is not NULL, set it to the number of lost CYC packets. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@time is NULL. + * Returns -pte_no_time if there has not been a TSC packet. + */ +extern pt_export int pt_insn_time(struct pt_insn_decoder *decoder, + uint64_t *time, uint32_t *lost_mtc, + uint32_t *lost_cyc); + +/** Return the current core bus ratio. + * + * On success, provides the current core:bus ratio in \@cbr. The ratio is + * defined as core cycles per bus clock cycle. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@cbr is NULL. + * Returns -pte_no_cbr if there has not been a CBR packet. + */ +extern pt_export int pt_insn_core_bus_ratio(struct pt_insn_decoder *decoder, + uint32_t *cbr); + +/** Return the current address space identifier. + * + * On success, provides the current address space identifier in \@asid. + * + * The \@size argument must be set to sizeof(struct pt_asid). At most \@size + * bytes will be copied and \@asid->size will be set to the actual size of the + * provided address space identifier. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@asid is NULL. + */ +extern pt_export int pt_insn_asid(const struct pt_insn_decoder *decoder, + struct pt_asid *asid, size_t size); + +/** Determine the next instruction. + * + * On success, provides the next instruction in execution order in \@insn. + * + * The \@size argument must be set to sizeof(struct pt_insn). + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative error + * code otherwise. + * + * Returns pts_eos to indicate the end of the trace stream. Subsequent calls + * to pt_insn_next() will continue to return pts_eos until trace is required + * to determine the next instruction. + * + * Returns -pte_event_ignored to indicate that the user needs to drain events + * using pt_insn_event() before continuing. + * + * Returns -pte_bad_context if the decoder encountered an unexpected packet. + * Returns -pte_bad_opc if the decoder encountered unknown packets. + * Returns -pte_bad_packet if the decoder encountered unknown packet payloads. + * Returns -pte_bad_query if the decoder got out of sync. + * Returns -pte_eos if decoding reached the end of the Intel PT buffer. + * Returns -pte_invalid if \@decoder or \@insn is NULL. + * Returns -pte_nomap if the memory at the instruction address can't be read. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_insn_next(struct pt_insn_decoder *decoder, + struct pt_insn *insn, size_t size); + +/** Get the next pending event. + * + * On success, provides the next event in \@event and updates \@decoder. + * + * The \@size argument must be set to sizeof(struct pt_event). + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative error + * code otherwise. + * + * Returns -pte_bad_query if there is no event. + * Returns -pte_invalid if \@decoder or \@event is NULL. + * Returns -pte_invalid if \@size is too small. + */ +extern pt_export int pt_insn_event(struct pt_insn_decoder *decoder, + struct pt_event *event, size_t size); + + + +/* Block decoder. */ + + + +/** A block of instructions. + * + * Instructions in this block are executed sequentially but are not necessarily + * contiguous in memory. Users are expected to follow direct branches. + */ +struct pt_block { + /** The IP of the first instruction in this block. */ + uint64_t ip; + + /** The IP of the last instruction in this block. + * + * This can be used for error-detection. + */ + uint64_t end_ip; + + /** The image section that contains the instructions in this block. + * + * A value of zero means that the section did not have an identifier. + * The section was not added via an image section cache or the memory + * was read via the read memory callback. + */ + int isid; + + /** The execution mode for all instructions in this block. */ + enum pt_exec_mode mode; + + /** The instruction class for the last instruction in this block. + * + * This field may be set to ptic_unknown (ptic_error prior to v2.1) to + * indicate that the instruction class is not available. The block + * decoder may choose to not provide the instruction class in some + * cases for performance reasons. + */ + enum pt_insn_class iclass; + + /** The number of instructions in this block. */ + uint16_t ninsn; + + /** The raw bytes of the last instruction in this block in case the + * instruction does not fit entirely into this block's section. + * + * This field is only valid if \@truncated is set. + */ + uint8_t raw[pt_max_insn_size]; + + /** The size of the last instruction in this block in bytes. + * + * This field is only valid if \@truncated is set. + */ + uint8_t size; + + /** A collection of flags giving additional information about the + * instructions in this block. + * + * - all instructions in this block were executed speculatively. + */ + uint32_t speculative:1; + + /** - the last instruction in this block is truncated. + * + * It starts in this block's section but continues in one or more + * other sections depending on how fragmented the memory image is. + * + * The raw bytes for the last instruction are provided in \@raw and + * its size in \@size in this case. + */ + uint32_t truncated:1; +}; + +/** Allocate an Intel PT block decoder. + * + * The decoder will work on the buffer defined in \@config, it shall contain + * raw trace data and remain valid for the lifetime of the decoder. + * + * The decoder needs to be synchronized before it can be used. + */ +extern pt_export struct pt_block_decoder * +pt_blk_alloc_decoder(const struct pt_config *config); + +/** Free an Intel PT block decoder. + * + * This will destroy the decoder's default image. + * + * The \@decoder must not be used after a successful return. + */ +extern pt_export void pt_blk_free_decoder(struct pt_block_decoder *decoder); + +/** Synchronize an Intel PT block decoder. + * + * Search for the next synchronization point in forward or backward direction. + * + * If \@decoder has not been synchronized, yet, the search is started at the + * beginning of the trace buffer in case of forward synchronization and at the + * end of the trace buffer in case of backward synchronization. + * + * Returns zero or a positive value on success, a negative error code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if no further synchronization point is found. + * Returns -pte_invalid if \@decoder is NULL. + */ +extern pt_export int pt_blk_sync_forward(struct pt_block_decoder *decoder); +extern pt_export int pt_blk_sync_backward(struct pt_block_decoder *decoder); + +/** Manually synchronize an Intel PT block decoder. + * + * Synchronize \@decoder on the syncpoint at \@offset. There must be a PSB + * packet at \@offset. + * + * Returns zero or a positive value on success, a negative error code otherwise. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if \@offset lies outside of \@decoder's trace buffer. + * Returns -pte_eos if \@decoder reaches the end of its trace buffer. + * Returns -pte_invalid if \@decoder is NULL. + * Returns -pte_nosync if there is no syncpoint at \@offset. + */ +extern pt_export int pt_blk_sync_set(struct pt_block_decoder *decoder, + uint64_t offset); + +#if (LIBIPT_VERSION >= 0x202) +/** Re-synchronize an Intel PT block decoder. + * + * Scan ahead for the next IP providing packet. Apply state changing packets + * along the way, including timing packets, but ignore everything else. + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative + * error code otherwise. + * + * Returns pts_ip_suppressed if re-synchronization succeeded with tracing + * disabled. + * + * Returns -pte_event_ignored if an event cannot safely be skipped + * (e.g. ptwrite). Use pt_blk_event() to read the event, then continue with + * pt_blk_resync() until re-synchronization completes or fails with an error. + * + * Returns -pte_bad_opc if an unknown packet is encountered. + * Returns -pte_bad_packet if an unknown packet payload is encountered. + * Returns -pte_eos if no further synchronization point is found. + * Returns -pte_invalid if \@decoder is NULL. + */ +extern pt_export int pt_blk_resync(struct pt_block_decoder *decoder); +#endif + +/** Get the current decoder position. + * + * Fills the current \@decoder position into \@offset. + * + * This is useful for reporting errors. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@offset is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_blk_get_offset(const struct pt_block_decoder *decoder, + uint64_t *offset); + +/** Get the position of the last synchronization point. + * + * Fills the last synchronization position into \@offset. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@offset is NULL. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int +pt_blk_get_sync_offset(const struct pt_block_decoder *decoder, + uint64_t *offset); + +/** Get the traced image. + * + * The returned image may be modified as long as \@decoder is not running. + * + * Returns a pointer to the traced image \@decoder uses for reading memory. + * Returns NULL if \@decoder is NULL. + */ +extern pt_export struct pt_image * +pt_blk_get_image(struct pt_block_decoder *decoder); + +/** Set the traced image. + * + * Sets the image that \@decoder uses for reading memory to \@image. If \@image + * is NULL, sets the image to \@decoder's default image. + * + * Only one image can be active at any time. + * + * Returns zero on success, a negative error code otherwise. + * Return -pte_invalid if \@decoder is NULL. + */ +extern pt_export int pt_blk_set_image(struct pt_block_decoder *decoder, + struct pt_image *image); + +/* Return a pointer to \@decoder's configuration. + * + * Returns a non-null pointer on success, NULL if \@decoder is NULL. + */ +extern pt_export const struct pt_config * +pt_blk_get_config(const struct pt_block_decoder *decoder); + +/** Return the current time. + * + * On success, provides the time at the last preceding timing packet in \@time. + * + * The time is similar to what a rdtsc instruction would return. Depending + * on the configuration, the time may not be fully accurate. If TSC is not + * enabled, the time is relative to the last synchronization and can't be used + * to correlate with other TSC-based time sources. In this case, -pte_no_time + * is returned and the relative time is provided in \@time. + * + * Some timing-related packets may need to be dropped (mostly due to missing + * calibration or incomplete configuration). To get an idea about the quality + * of the estimated time, we record the number of dropped MTC and CYC packets. + * + * If \@lost_mtc is not NULL, set it to the number of lost MTC packets. + * If \@lost_cyc is not NULL, set it to the number of lost CYC packets. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@time is NULL. + * Returns -pte_no_time if there has not been a TSC packet. + */ +extern pt_export int pt_blk_time(struct pt_block_decoder *decoder, + uint64_t *time, uint32_t *lost_mtc, + uint32_t *lost_cyc); + +/** Return the current core bus ratio. + * + * On success, provides the current core:bus ratio in \@cbr. The ratio is + * defined as core cycles per bus clock cycle. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@cbr is NULL. + * Returns -pte_no_cbr if there has not been a CBR packet. + */ +extern pt_export int pt_blk_core_bus_ratio(struct pt_block_decoder *decoder, + uint32_t *cbr); + +/** Return the current address space identifier. + * + * On success, provides the current address space identifier in \@asid. + * + * The \@size argument must be set to sizeof(struct pt_asid). At most \@size + * bytes will be copied and \@asid->size will be set to the actual size of the + * provided address space identifier. + * + * Returns zero on success, a negative error code otherwise. + * + * Returns -pte_invalid if \@decoder or \@asid is NULL. + */ +extern pt_export int pt_blk_asid(const struct pt_block_decoder *decoder, + struct pt_asid *asid, size_t size); + +/** Determine the next block of instructions. + * + * On success, provides the next block of instructions in execution order in + * \@block. + * + * The \@size argument must be set to sizeof(struct pt_block). + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative error + * code otherwise. + * + * Returns pts_eos to indicate the end of the trace stream. Subsequent calls + * to pt_block_next() will continue to return pts_eos until trace is required + * to determine the next instruction. + * + * Returns -pte_bad_context if the decoder encountered an unexpected packet. + * Returns -pte_bad_opc if the decoder encountered unknown packets. + * Returns -pte_bad_packet if the decoder encountered unknown packet payloads. + * Returns -pte_bad_query if the decoder got out of sync. + * Returns -pte_eos if decoding reached the end of the Intel PT buffer. + * Returns -pte_invalid if \@decoder or \@block is NULL. + * Returns -pte_nomap if the memory at the instruction address can't be read. + * Returns -pte_nosync if \@decoder is out of sync. + */ +extern pt_export int pt_blk_next(struct pt_block_decoder *decoder, + struct pt_block *block, size_t size); + +/** Get the next pending event. + * + * On success, provides the next event in \@event and updates \@decoder. + * + * The \@size argument must be set to sizeof(struct pt_event). + * + * Returns a non-negative pt_status_flag bit-vector on success, a negative error + * code otherwise. + * + * Returns -pte_bad_query if there is no event. + * Returns -pte_invalid if \@decoder or \@event is NULL. + * Returns -pte_invalid if \@size is too small. + */ +extern pt_export int pt_blk_event(struct pt_block_decoder *decoder, + struct pt_event *event, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* INTEL_PT_H */ diff --git a/hyperdbg/dependencies/pdbex b/hyperdbg/dependencies/pdbex index c827cf47..0e114472 160000 --- a/hyperdbg/dependencies/pdbex +++ b/hyperdbg/dependencies/pdbex @@ -1 +1 @@ -Subproject commit c827cf477cc7de8fb08b989fa7bbcde439a17712 +Subproject commit 0e1144729a5b2d737cce11d1c0e083033630fff8 diff --git a/hyperdbg/dependencies/phnt b/hyperdbg/dependencies/phnt deleted file mode 160000 index 619cbb46..00000000 --- a/hyperdbg/dependencies/phnt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 619cbb4672c6739bcd0302a1d542f34f51effe93 diff --git a/hyperdbg/dependencies/zydis b/hyperdbg/dependencies/zydis index d45e7416..e910df2f 160000 --- a/hyperdbg/dependencies/zydis +++ b/hyperdbg/dependencies/zydis @@ -1 +1 @@ -Subproject commit d45e7416b2123706c3695fa802e6b29543f1a549 +Subproject commit e910df2fa54273b1a489b39771d331036e8de2db diff --git a/hyperdbg/hprdbgctrl/code/app/hprdbgctrl.cpp b/hyperdbg/hprdbgctrl/code/app/hprdbgctrl.cpp deleted file mode 100644 index 533406d9..00000000 --- a/hyperdbg/hprdbgctrl/code/app/hprdbgctrl.cpp +++ /dev/null @@ -1,749 +0,0 @@ -/** - * @file hprdbgctrl.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Main interface to connect applications to driver - * @details - * @version 0.1 - * @date 2020-04-11 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -using namespace std; - -// -// Global Variables -// -extern HANDLE g_DeviceHandle; -extern HANDLE g_IsDriverLoadedSuccessfully; -extern BOOLEAN g_IsVmxOffProcessStart; -extern Callback g_MessageHandler; -extern TCHAR g_DriverLocation[MAX_PATH]; -extern LIST_ENTRY g_EventTrace; -extern BOOLEAN g_LogOpened; -extern BOOLEAN g_BreakPrintingOutput; -extern BOOLEAN g_IsConnectedToRemoteDebugger; -extern BOOLEAN g_OutputSourcesInitialized; -extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; -extern BOOLEAN g_IsDebuggerModulesLoaded; -extern BOOLEAN g_IsReversingMachineModulesLoaded; -extern LIST_ENTRY g_OutputSources; - -/** - * @brief Set the function callback that will be called if any message - * needs to be shown - * - * @param handler Function that handles the messages - */ -VOID -HyperDbgSetTextMessageCallback(Callback handler) -{ - g_MessageHandler = handler; -} - -/** - * @brief Show messages - * - * @param Fmt format string message - */ -VOID -ShowMessages(const char * Fmt, ...) -{ - va_list ArgList; - va_list Args; - char TempMessage[COMMUNICATION_BUFFER_SIZE + TCP_END_OF_BUFFER_CHARS_COUNT] = {0}; - - if (g_MessageHandler == NULL && !g_IsConnectedToRemoteDebugger && !g_IsSerialConnectedToRemoteDebugger) - { - va_start(Args, Fmt); - vprintf(Fmt, Args); - va_end(Args); - if (!g_LogOpened) - { - return; - } - } - - va_start(ArgList, Fmt); - int sprintfresult = vsprintf_s(TempMessage, Fmt, ArgList); - va_end(ArgList); - - if (sprintfresult != -1) - { - if (g_IsConnectedToRemoteDebugger) - { - // - // vsprintf_s and vswprintf_s return the number of characters written, - // not including the terminating null character, or a negative value - // if an output error occurs. - // - RemoteConnectionSendResultsToHost(TempMessage, sprintfresult); - } - else if (g_IsSerialConnectedToRemoteDebugger) - { - KdSendUsermodePrints(TempMessage, sprintfresult); - } - - if (g_LogOpened) - { - // - // .logopen command executed - // - LogopenSaveToFile(TempMessage); - } - if (g_MessageHandler != NULL) - { - // - // There is another handler - // - g_MessageHandler(TempMessage); - } - } -} - -/** - * @brief Read kernel buffers using IRP Pending - * - * @param Device Driver handle - */ -void -ReadIrpBasedBuffer() -{ - BOOL Status; - ULONG ReturnedLength; - REGISTER_NOTIFY_BUFFER RegisterEvent; - UINT32 OperationCode; - DWORD ErrorNum; - HANDLE Handle; - - RegisterEvent.hEvent = NULL; - RegisterEvent.Type = IRP_BASED; - - // - // Create another handle to be used in for reading kernel messages, - // it is because I noticed that if I use a same handle for IRP Pending - // and other IOCTLs then if I complete that IOCTL then both of the current - // IOCTL and the Pending IRP are completed and return to user mode, - // even if it's odd but that what happens, so this way we can solve it - // if you know why this problem happens, then contact me ! - // - Handle = CreateFileA( - "\\\\.\\HyperDbgDebuggerDevice", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, /// lpSecurityAttirbutes - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - NULL); /// lpTemplateFile - - if (Handle == INVALID_HANDLE_VALUE) - { - ErrorNum = GetLastError(); - - if (ErrorNum == ERROR_ACCESS_DENIED) - { - ShowMessages("err, access denied\nare you sure you have administrator " - "rights?\n"); - } - else if (ErrorNum == ERROR_GEN_FAILURE) - { - ShowMessages("err, a device attached to the system is not functioning\n" - "vmx feature might be disabled from BIOS or VBS/HVCI is active\n"); - } - else - { - ShowMessages("err, CreateFile failed with (%x)\n", ErrorNum); - } - - g_DeviceHandle = NULL; - Handle = NULL; - - return; - } - - // - // allocate buffer for transferring messages - // - char * OutputBuffer = (char *)malloc(UsermodeBufferSize); - - try - { - while (TRUE) - { - if (!g_IsVmxOffProcessStart) - { - // - // Clear the buffer - // - ZeroMemory(OutputBuffer, UsermodeBufferSize); - - Sleep(DefaultSpeedOfReadingKernelMessages); // we're not trying to eat all of the CPU ;) - - Status = DeviceIoControl( - Handle, // Handle to device - IOCTL_REGISTER_EVENT, // IO Control Code (IOCTL) - &RegisterEvent, // Input Buffer to driver. - SIZEOF_REGISTER_EVENT * 2, // Length of input buffer in bytes. (x 2 is bcuz as the - // driver is x64 and has 64 bit values) - OutputBuffer, // Output Buffer from driver. - UsermodeBufferSize, // Length of output buffer in bytes. - &ReturnedLength, // Bytes placed in buffer. - NULL // synchronous call - ); - - if (!Status) - { - // - // Error occurred for second time, and we show the error message - // - // ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); - - // - // if we reach here, the packet is probably failed, it might - // be because of using flush command - // - continue; - } - - // - // Compute the received buffer's operation code - // - OperationCode = 0; - memcpy(&OperationCode, OutputBuffer, sizeof(UINT32)); - - /* - ShowMessages("Returned Length : 0x%x \n", ReturnedLength); - ShowMessages("Operation Code : 0x%x \n", OperationCode); - */ - - switch (OperationCode) - { - case OPERATION_LOG_NON_IMMEDIATE_MESSAGE: - - if (g_BreakPrintingOutput) - { - // - // means that the user asserts a CTRL+C or CTRL+BREAK Signal - // we shouldn't show or save anything in this case - // - continue; - } - - ShowMessages("%s", OutputBuffer + sizeof(UINT32)); - - break; - case OPERATION_LOG_INFO_MESSAGE: - - if (g_BreakPrintingOutput) - { - // - // means that the user asserts a CTRL+C or CTRL+BREAK Signal - // we shouldn't show or save anything in this case - // - continue; - } - - ShowMessages("%s", OutputBuffer + sizeof(UINT32)); - - break; - case OPERATION_LOG_ERROR_MESSAGE: - if (g_BreakPrintingOutput) - { - // - // means that the user asserts a CTRL+C or CTRL+BREAK Signal - // we shouldn't show or save anything in this case - // - continue; - } - - ShowMessages("%s", OutputBuffer + sizeof(UINT32)); - - break; - case OPERATION_LOG_WARNING_MESSAGE: - - if (g_BreakPrintingOutput) - { - // - // means that the user asserts a CTRL+C or CTRL+BREAK Signal - // we shouldn't show or save anything in this case - // - continue; - } - - ShowMessages("%s", OutputBuffer + sizeof(UINT32)); - - break; - - case OPERATION_COMMAND_FROM_DEBUGGER_CLOSE_AND_UNLOAD_VMM: - - KdCloseConnection(); - - break; - - case OPERATION_DEBUGGEE_USER_INPUT: - - KdHandleUserInputInDebuggee((DEBUGGEE_USER_INPUT_PACKET *)(OutputBuffer + sizeof(UINT32))); - - break; - - case OPERATION_DEBUGGEE_REGISTER_EVENT: - - KdRegisterEventInDebuggee( - (PDEBUGGER_GENERAL_EVENT_DETAIL)(OutputBuffer + sizeof(UINT32)), - ReturnedLength); - - break; - - case OPERATION_DEBUGGEE_ADD_ACTION_TO_EVENT: - - KdAddActionToEventInDebuggee( - (PDEBUGGER_GENERAL_ACTION)(OutputBuffer + sizeof(UINT32)), - ReturnedLength); - - break; - - case OPERATION_DEBUGGEE_CLEAR_EVENTS: - - KdSendModifyEventInDebuggee( - (PDEBUGGER_MODIFY_EVENTS)(OutputBuffer + sizeof(UINT32)), - TRUE); - - break; - - case OPERATION_DEBUGGEE_CLEAR_EVENTS_WITHOUT_NOTIFYING_DEBUGGER: - - KdSendModifyEventInDebuggee( - (PDEBUGGER_MODIFY_EVENTS)(OutputBuffer + sizeof(UINT32)), - FALSE); - - break; - - case OPERATION_HYPERVISOR_DRIVER_IS_SUCCESSFULLY_LOADED: - - // - // Indicate that driver (Hypervisor) is loaded successfully - // - SetEvent(g_IsDriverLoadedSuccessfully); - - break; - - case OPERATION_HYPERVISOR_DRIVER_END_OF_IRPS: - - // - // End of receiving messages (IRPs), nothing to do - // - break; - - case OPERATION_COMMAND_FROM_DEBUGGER_RELOAD_SYMBOL: - - // - // Pause debugger after getting the results - // - KdReloadSymbolsInDebuggee(TRUE, - ((PDEBUGGEE_SYMBOL_REQUEST_PACKET)(OutputBuffer + sizeof(UINT32)))->ProcessId); - - break; - - case OPERATION_NOTIFICATION_FROM_USER_DEBUGGER_PAUSE: - - // - // handle pausing packet from user debugger - // - UdHandleUserDebuggerPausing( - (PDEBUGGEE_UD_PAUSED_PACKET)(OutputBuffer + sizeof(UINT32))); - - break; - - default: - - // - // Check if there are available output sources - // - if (!g_OutputSourcesInitialized || !ForwardingCheckAndPerformEventForwarding(OperationCode, - OutputBuffer + sizeof(UINT32), - ReturnedLength - sizeof(UINT32) - 1)) - { - if (g_BreakPrintingOutput) - { - // - // means that the user asserts a CTRL+C or CTRL+BREAK Signal - // we shouldn't show or save anything in this case - // - continue; - } - - ShowMessages("%s", OutputBuffer + sizeof(UINT32)); - } - - break; - } - } - else - { - // - // the thread should not work anymore - // - free(OutputBuffer); - - // - // closeHandle - // - if (!CloseHandle(Handle)) - { - ShowMessages("err, closing handle 0x%x\n", GetLastError()); - } - - return; - } - } - } - catch (const std::exception &) - { - ShowMessages("err, exception occurred in creating handle or parsing buffer\n"); - } - - free(OutputBuffer); - - // - // closeHandle - // - if (!CloseHandle(Handle)) - { - ShowMessages("err, closing handle 0x%x\n", GetLastError()); - }; -} - -/** - * @brief Create a thread for pending buffers - * - * @param Data - * @return DWORD Device Handle - */ -DWORD WINAPI -IrpBasedBufferThread(void * data) -{ - // - // Do stuff. This will be the first function called on the new - // thread. When this function returns, the thread goes away. See - // MSDN for more details. Test Irp Based Notifications - // - ReadIrpBasedBuffer(); - - return 0; -} - -/** - * @brief Install VMM driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -HPRDBGCTRL_API int -HyperDbgInstallVmmDriver() -{ - // - // The driver is not started yet so let us the install driver - // First setup full path to driver name - // - - if (!SetupDriverName(KERNEL_DEBUGGER_DRIVER_NAME, g_DriverLocation, sizeof(g_DriverLocation))) - { - return 1; - } - - if (!ManageDriver(KERNEL_DEBUGGER_DRIVER_NAME, g_DriverLocation, DRIVER_FUNC_INSTALL)) - { - ShowMessages("unable to install VMM driver\n"); - - // - // Error - remove driver - // - ManageDriver(KERNEL_DEBUGGER_DRIVER_NAME, g_DriverLocation, DRIVER_FUNC_REMOVE); - - return 1; - } - - return 0; -} - -/** - * @brief Stop the driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -int -HyperDbgStopDriver(LPCTSTR DriverName) -{ - // - // Unload the driver if loaded - // - if (g_DriverLocation[0] != (TCHAR)0 && ManageDriver(DriverName, g_DriverLocation, DRIVER_FUNC_STOP)) - { - return 0; - } - else - { - return 1; - } -} - -/** - * @brief Stop VMM driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -HPRDBGCTRL_API int -HyperDbgStopVmmDriver() -{ - return HyperDbgStopDriver(KERNEL_DEBUGGER_DRIVER_NAME); -} - -/** - * @brief Remove the driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -int -HyperDbgUninstallDriver(LPCTSTR DriverName) -{ - // - // Unload the driver if loaded. Ignore any errors - // - if (g_DriverLocation[0] != (TCHAR)0 && ManageDriver(DriverName, g_DriverLocation, DRIVER_FUNC_REMOVE)) - { - return 0; - } - else - { - return 1; - } -} - -/** - * @brief Remove the VMM driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -HPRDBGCTRL_API int -HyperDbgUninstallVmmDriver() -{ - return HyperDbgUninstallDriver(KERNEL_DEBUGGER_DRIVER_NAME); -} - -/** - * @brief Load the VMM driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -HPRDBGCTRL_API int -HyperDbgLoadVmm() -{ - char CpuId[13] = {0}; - DWORD ErrorNum; - DWORD ThreadId; - - if (g_DeviceHandle) - { - ShowMessages("handle of the driver found, if you use 'load' before, please " - "unload it using 'unload'\n"); - return 1; - } - - // - // Read the vendor string - // - HyperDbgReadVendorString(CpuId); - - ShowMessages("current processor vendor is : %s\n", CpuId); - - if (strcmp(CpuId, "GenuineIntel") == 0) - { - ShowMessages("virtualization technology is vt-x\n"); - } - else - { - ShowMessages("this program is not designed to run in a non-VT-x " - "environment !\n"); - return 1; - } - - if (HyperDbgVmxSupportDetection()) - { - ShowMessages("vmx operation is supported by your processor\n"); - } - else - { - ShowMessages("vmx operation is not supported by your processor\n"); - return 1; - } - - // - // Make sure that this variable is false, because it might be set to - // true as the result of a previous load - // - g_IsVmxOffProcessStart = FALSE; - - // - // Init entering vmx - // - g_DeviceHandle = CreateFileA( - "\\\\.\\HyperDbgDebuggerDevice", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, /// lpSecurityAttirbutes - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - NULL); /// lpTemplateFile - - if (g_DeviceHandle == INVALID_HANDLE_VALUE) - { - ErrorNum = GetLastError(); - if (ErrorNum == ERROR_ACCESS_DENIED) - { - ShowMessages("err, access denied\nare you sure you have administrator " - "rights?\n"); - } - else if (ErrorNum == ERROR_GEN_FAILURE) - { - ShowMessages("err, a device attached to the system is not functioning\n" - "vmx feature might be disabled from BIOS or VBS/HVCI is active\n"); - } - else - { - ShowMessages("err, CreateFile failed (%x)\n", ErrorNum); - } - - g_DeviceHandle = NULL; - return 1; - } - - // - // Initialize the list of events - // - InitializeListHead(&g_EventTrace); - -#if !UseDbgPrintInsteadOfUsermodeMessageTracking - HANDLE Thread = CreateThread(NULL, 0, IrpBasedBufferThread, NULL, 0, &ThreadId); - - // if (Thread) - // { - // ShowMessages("thread Created successfully\n"); - // } - -#endif - - return 0; -} - -/** - * @brief Unload VMM driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -HPRDBGCTRL_API int -HyperDbgUnloadVmm() -{ - BOOL Status; - - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnOne); - - ShowMessages("start terminating...\n"); - - // - // Uninitialize the user debugger if it's initialized - // - UdUninitializeUserDebugger(); - - // - // Send IOCTL to mark complete all IRP Pending - // - Status = DeviceIoControl(g_DeviceHandle, // Handle to device - IOCTL_TERMINATE_VMX, // IO Control Code (IOCTL) - NULL, // Input Buffer to driver. - 0, // Length of input buffer in bytes. (x 2 is bcuz - // as the driver is x64 and has 64 bit values) - NULL, // Output Buffer from driver. - 0, // Length of output buffer in bytes. - NULL, // Bytes placed in buffer. - NULL // synchronous call - ); - - // - // wait to make sure we don't use an invalid handle in another Ioctl - // - if (!Status) - { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); - return 1; - } - - // - // Send IOCTL to mark complete all IRP Pending - // - Status = DeviceIoControl( - g_DeviceHandle, // Handle to device - IOCTL_RETURN_IRP_PENDING_PACKETS_AND_DISALLOW_IOCTL, // IO - // Control - // code - NULL, // Input Buffer to driver. - 0, // Length of input buffer in bytes. (x 2 is bcuz as the - // driver is x64 and has 64 bit values) - NULL, // Output Buffer from driver. - 0, // Length of output buffer in bytes. - NULL, // Bytes placed in buffer. - NULL // synchronous call - ); - - // - // wait to make sure we don't use an invalid handle in another Ioctl - // - if (!Status) - { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); - return 1; - } - - // - // Indicate that the finish process start or not - // - g_IsVmxOffProcessStart = TRUE; - - Sleep(1000); // Wait so next thread can return from IRP Pending - - // - // Send IRP_MJ_CLOSE to driver to terminate Vmxs - // - if (!CloseHandle(g_DeviceHandle)) - { - ShowMessages("err, closing handle 0x%x\n", GetLastError()); - return 1; - }; - - // - // Null the handle to indicate that the driver's device is not ready - // to use - // - g_DeviceHandle = NULL; - - // - // Debugger module is not loaded anymore - // - g_IsDebuggerModulesLoaded = FALSE; - - // - // Check if we found an already built symbol table - // - SymbolDeleteSymTable(); - - ShowMessages("you're not on HyperDbg's hypervisor anymore!\n"); - - return 0; -} diff --git a/hyperdbg/hprdbgctrl/code/common/list.cpp b/hyperdbg/hprdbgctrl/code/common/list.cpp deleted file mode 100644 index 58c2fc44..00000000 --- a/hyperdbg/hprdbgctrl/code/common/list.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file list.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief The list working functions headers - * @details - * @version 0.1 - * @date 2020-04-11 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" -// -///** -// * @brief List initializer -// * -// * @param ListHead -// */ -// void -// InitializeListHead(PLIST_ENTRY ListHead) -//{ -// ListHead->Flink = ListHead->Blink = ListHead; -//} -// -///** -// * @brief insert entry to the top of the list -// * -// * @param ListHead -// * @param Entry -// */ -// void -// InsertHeadList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry) -//{ -// PLIST_ENTRY Flink; -// -// Flink = ListHead->Flink; -// Entry->Flink = Flink; -// Entry->Blink = ListHead; -// Flink->Blink = Entry; -// ListHead->Flink = Entry; -//} -// -///** -// * @brief remove the entry from the list -// * -// * @param Entry -// * @return BOOLEAN -// */ -// BOOLEAN -// RemoveEntryList(PLIST_ENTRY Entry) -//{ -// PLIST_ENTRY PrevEntry; -// PLIST_ENTRY NextEntry; -// -// NextEntry = Entry->Flink; -// PrevEntry = Entry->Blink; -// if ((NextEntry->Blink != Entry) || (PrevEntry->Flink != Entry)) -// { -// // -// // Error -// // -// _CrtDbgBreak(); -// } -// -// PrevEntry->Flink = NextEntry; -// NextEntry->Blink = PrevEntry; -// return (BOOLEAN)(PrevEntry == NextEntry); -//} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bp.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bp.cpp deleted file mode 100644 index 26c4e9a1..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bp.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/** - * @file bp.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief bp command - * @details - * @version 0.1 - * @date 2021-10-03 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -// -// Global Variables -// -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; - -/** - * @brief help of the bp command - * - * @return VOID - */ -VOID -CommandBpHelp() -{ - ShowMessages("bp : puts a breakpoint (0xcc).\n"); - - ShowMessages( - "Note : 'bp' is not an event, if you want to use an event version " - "of breakpoints use !epthook or !epthook2 instead. See " - "documentation for more information.\n\n"); - - ShowMessages("syntax : \tbp [Address (hex)] [pid ProcessId (hex)] [tid ThreadId (hex)] [core CoreId (hex)]\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : bp nt!ExAllocatePoolWithTag\n"); - ShowMessages("\t\te.g : bp nt!ExAllocatePoolWithTag+5\n"); - ShowMessages("\t\te.g : bp nt!ExAllocatePoolWithTag+@rcx+rbx\n"); - ShowMessages("\t\te.g : bp fffff8077356f010\n"); - ShowMessages("\t\te.g : bp fffff8077356f010 pid 0x4\n"); - ShowMessages("\t\te.g : bp fffff8077356f010 tid 0x1000\n"); - ShowMessages("\t\te.g : bp fffff8077356f010 pid 0x4 core 2\n"); -} - -/** - * @brief bp command handler - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandBp(vector SplitCommand, string Command) -{ - BOOL IsNextCoreId = FALSE; - BOOL IsNextPid = FALSE; - BOOL IsNextTid = FALSE; - - BOOLEAN SetCoreId = FALSE; - BOOLEAN SetPid = FALSE; - BOOLEAN SetTid = FALSE; - BOOLEAN SetAddress = FALSE; - - UINT32 Tid = DEBUGGEE_BP_APPLY_TO_ALL_THREADS; - UINT32 Pid = DEBUGGEE_BP_APPLY_TO_ALL_PROCESSES; - UINT32 CoreNumer = DEBUGGEE_BP_APPLY_TO_ALL_CORES; - UINT64 Address = NULL; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - UINT32 IndexInCommandCaseSensitive = 0; - BOOLEAN IsFirstCommand = TRUE; - - DEBUGGEE_BP_PACKET BpPacket = {0}; - - if (SplitCommand.size() >= 9) - { - ShowMessages("incorrect use of the 'bp'\n\n"); - CommandBpHelp(); - return; - } - - for (auto Section : SplitCommand) - { - IndexInCommandCaseSensitive++; - - // - // Ignore the first argument as it's the command string itself (bp) - // - if (IsFirstCommand == TRUE) - { - IsFirstCommand = FALSE; - continue; - } - - if (IsNextCoreId) - { - if (!ConvertStringToUInt32(Section, &CoreNumer)) - { - ShowMessages("please specify a correct hex value for core id\n\n"); - CommandBpHelp(); - return; - } - IsNextCoreId = FALSE; - continue; - } - if (IsNextPid) - { - if (!ConvertStringToUInt32(Section, &Pid)) - { - ShowMessages("please specify a correct hex value for process id\n\n"); - CommandBpHelp(); - return; - } - IsNextPid = FALSE; - continue; - } - - if (IsNextTid) - { - if (!ConvertStringToUInt32(Section, &Tid)) - { - ShowMessages("please specify a correct hex value for thread id\n\n"); - CommandBpHelp(); - return; - } - IsNextTid = FALSE; - continue; - } - - if (!Section.compare("pid")) - { - IsNextPid = TRUE; - continue; - } - if (!Section.compare("tid")) - { - IsNextTid = TRUE; - continue; - } - if (!Section.compare("core")) - { - IsNextCoreId = TRUE; - continue; - } - - if (!SetAddress) - { - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1), &Address)) - { - // - // Couldn't resolve or unknown parameter - // - ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1).c_str()); - CommandBpHelp(); - return; - } - else - { - // - // Means that address is received - // - SetAddress = TRUE; - continue; - } - } - } - - // - // Check if address is set or not - // - if (!SetAddress) - { - ShowMessages( - "please specify a correct hex value as the breakpoint address\n\n"); - CommandBpHelp(); - return; - } - if (IsNextPid) - { - ShowMessages("please specify a correct hex value for process id\n\n"); - CommandBpHelp(); - return; - } - if (IsNextCoreId) - { - ShowMessages("please specify a correct hex value for core\n\n"); - CommandBpHelp(); - return; - } - if (IsNextTid) - { - ShowMessages("please specify a correct hex value for thread id\n\n"); - CommandBpHelp(); - return; - } - - if (!g_IsSerialConnectedToRemoteDebuggee) - { - ShowMessages("err, setting breakpoints is not possible when you're not " - "connected to a debuggee\n"); - return; - } - - // - // Set the details for the remote packet - // - BpPacket.Address = Address; - BpPacket.Core = CoreNumer; - BpPacket.Pid = Pid; - BpPacket.Tid = Tid; - - // - // Send the bp packet - // - KdSendBpPacketToDebuggee(&BpPacket); -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/e.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/e.cpp deleted file mode 100644 index c9906e93..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/e.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/** - * @file e.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief e* command - * @details - * @version 0.1 - * @date 2020-07-27 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -// -// Global Variables -// -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; -extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; - -/** - * @brief help of !e* and e* commands - * - * @return VOID - */ -VOID -CommandEditMemoryHelp() -{ - ShowMessages("eb !eb ed !ed eq !eq : edits the memory at specific address \n"); - ShowMessages("eb Byte and ASCII characters\n"); - ShowMessages("ed Double-word values (4 bytes)\n"); - ShowMessages("eq Quad-word values (8 bytes). \n"); - - ShowMessages("\n If you want to edit physical (address) memory then add '!' " - "at the start of the command\n"); - - ShowMessages("syntax : \teb [Address (hex)] [Contents (hex)] [pid ProcessId (hex)]\n"); - ShowMessages("syntax : \ted [Address (hex)] [Contents (hex)] [pid ProcessId (hex)]\n"); - ShowMessages("syntax : \teq [Address (hex)] [Contents (hex)] [pid ProcessId (hex)]\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : eb fffff8077356f010 90 \n"); - ShowMessages("\t\te.g : eb nt!Kd_DEFAULT_Mask ff ff ff ff \n"); - ShowMessages("\t\te.g : eb nt!Kd_DEFAULT_Mask+10+@rcx ff ff ff ff \n"); - ShowMessages("\t\te.g : eb fffff8077356f010 90 90 90 90 \n"); - ShowMessages("\t\te.g : !eq 100000 9090909090909090\n"); - ShowMessages("\t\te.g : !eq nt!ExAllocatePoolWithTag+55 9090909090909090\n"); - ShowMessages("\t\te.g : !eq 100000 9090909090909090 9090909090909090 " - "9090909090909090 9090909090909090 9090909090909090\n"); -} - -/** - * @brief !e* and e* commands handler - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandEditMemory(vector SplitCommand, string Command) -{ - BOOL Status; - UINT64 Address; - UINT64 * FinalBuffer; - vector ValuesToEdit; - BOOL SetAddress = FALSE; - BOOL SetValue = FALSE; - BOOL SetProcId = FALSE; - BOOL NextIsProcId = FALSE; - DEBUGGER_EDIT_MEMORY EditMemoryRequest = {0}; - UINT64 Value = 0; - UINT32 ProcId = 0; - UINT32 CountOfValues = 0; - UINT32 FinalSize = 0; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - UINT32 IndexInCommandCaseSensitive = 0; - BOOLEAN IsFirstCommand = TRUE; - - // - // By default if the user-debugger is active, we use these commands - // on the memory layout of the debuggee process - // - if (g_ActiveProcessDebuggingState.IsActive) - { - ProcId = g_ActiveProcessDebuggingState.ProcessId; - } - - if (SplitCommand.size() <= 2) - { - ShowMessages("incorrect use of the 'e*'\n\n"); - CommandEditMemoryHelp(); - return; - } - - for (auto Section : SplitCommand) - { - IndexInCommandCaseSensitive++; - - if (IsFirstCommand) - { - if (!Section.compare("!eb")) - { - EditMemoryRequest.MemoryType = EDIT_PHYSICAL_MEMORY; - EditMemoryRequest.ByteSize = EDIT_BYTE; - } - else if (!Section.compare("!ed")) - { - EditMemoryRequest.MemoryType = EDIT_PHYSICAL_MEMORY; - EditMemoryRequest.ByteSize = EDIT_DWORD; - } - else if (!Section.compare("!eq")) - { - EditMemoryRequest.MemoryType = EDIT_PHYSICAL_MEMORY; - EditMemoryRequest.ByteSize = EDIT_QWORD; - } - else if (!Section.compare("eb")) - { - EditMemoryRequest.MemoryType = EDIT_VIRTUAL_MEMORY; - EditMemoryRequest.ByteSize = EDIT_BYTE; - } - else if (!Section.compare("ed")) - { - EditMemoryRequest.MemoryType = EDIT_VIRTUAL_MEMORY; - EditMemoryRequest.ByteSize = EDIT_DWORD; - } - else if (!Section.compare("eq")) - { - EditMemoryRequest.MemoryType = EDIT_VIRTUAL_MEMORY; - EditMemoryRequest.ByteSize = EDIT_QWORD; - } - else - { - // - // What's this? :( - // - ShowMessages("unknown error happened !\n\n"); - CommandEditMemoryHelp(); - return; - } - - IsFirstCommand = FALSE; - - continue; - } - - if (NextIsProcId) - { - // - // It's a process id - // - NextIsProcId = FALSE; - - if (!ConvertStringToUInt32(Section, &ProcId)) - { - ShowMessages("please specify a correct hex process id\n\n"); - CommandEditMemoryHelp(); - return; - } - else - { - // - // Means that the proc id is set, next we should read value - // - continue; - } - } - - // - // Check if it's a process id or not - // - if (!SetProcId && !Section.compare("pid")) - { - NextIsProcId = TRUE; - continue; - } - - if (!SetAddress) - { - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1), - &Address)) - { - ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1).c_str()); - CommandEditMemoryHelp(); - return; - } - else - { - // - // Means that the address is set, next we should read value - // - SetAddress = TRUE; - continue; - } - } - - if (SetAddress) - { - // - // Remove the hex notations - // - if (Section.rfind("0x", 0) == 0 || Section.rfind("0X", 0) == 0 || - Section.rfind("\\x", 0) == 0 || Section.rfind("\\X", 0) == 0) - { - Section = Section.erase(0, 2); - } - else if (Section.rfind('x', 0) == 0 || Section.rfind('X', 0) == 0) - { - Section = Section.erase(0, 1); - } - Section.erase(remove(Section.begin(), Section.end(), '`'), Section.end()); - - // - // Check if the value is valid based on byte counts - // - if (EditMemoryRequest.ByteSize == EDIT_BYTE && Section.size() >= 3) - { - ShowMessages("please specify a byte (hex) value for 'eb' or '!eb'\n\n"); - return; - } - if (EditMemoryRequest.ByteSize == EDIT_DWORD && Section.size() >= 9) - { - ShowMessages( - "please specify a dword (hex) value for 'ed' or '!ed'\n\n"); - return; - } - if (EditMemoryRequest.ByteSize == EDIT_QWORD && Section.size() >= 17) - { - ShowMessages( - "please specify a qword (hex) value for 'eq' or '!eq'\n\n"); - return; - } - - // - // Qword is checked by the following function, no need to double - // check it above. - // - - if (!ConvertStringToUInt64(Section, &Value)) - { - ShowMessages("please specify a correct hex value to change the memory " - "content\n\n"); - CommandEditMemoryHelp(); - return; - } - else - { - // - // Add it to the list - // - - ValuesToEdit.push_back(Value); - - // - // Keep track of values to modify - // - CountOfValues++; - - if (!SetValue) - { - // - // At least on value is there - // - SetValue = TRUE; - } - continue; - } - } - } - - // - // Check to prevent using process id in e* commands - // - if (g_IsSerialConnectedToRemoteDebuggee && ProcId != 0) - { - ShowMessages(ASSERT_MESSAGE_CANNOT_SPECIFY_PID); - return; - } - - if (ProcId == 0) - { - ProcId = GetCurrentProcessId(); - } - - // - // Fill the structure - // - EditMemoryRequest.ProcessId = ProcId; - EditMemoryRequest.Address = Address; - EditMemoryRequest.CountOf64Chunks = CountOfValues; - - // - // Check if address and value are set or not - // - if (!SetAddress) - { - ShowMessages("please specify a correct hex address\n\n"); - CommandEditMemoryHelp(); - return; - } - if (!SetValue) - { - ShowMessages( - "please specify a correct hex value as the content to edit\n\n"); - CommandEditMemoryHelp(); - return; - } - if (NextIsProcId) - { - ShowMessages("please specify a correct hex value as the process id\n\n"); - CommandEditMemoryHelp(); - return; - } - - // - // Now it's time to put everything together in one structure - // - FinalSize = (CountOfValues * sizeof(UINT64)) + SIZEOF_DEBUGGER_EDIT_MEMORY; - - // - // Set the size - // - EditMemoryRequest.FinalStructureSize = FinalSize; - - // - // Allocate structure + buffer - // - FinalBuffer = (UINT64 *)malloc(FinalSize); - - if (!FinalBuffer) - { - ShowMessages("unable to allocate memory\n\n"); - return; - } - - // - // Zero the buffer - // - ZeroMemory(FinalBuffer, FinalSize); - - // - // Copy the structure on top of the allocated buffer - // - memcpy(FinalBuffer, &EditMemoryRequest, SIZEOF_DEBUGGER_EDIT_MEMORY); - - // - // Put the values in 64 bit structures - // - std::copy(ValuesToEdit.begin(), ValuesToEdit.end(), (UINT64 *)((UINT64)FinalBuffer + SIZEOF_DEBUGGER_EDIT_MEMORY)); - - // - // send the request - // - if (g_IsSerialConnectedToRemoteDebuggee) - { - KdSendEditMemoryPacketToDebuggee((DEBUGGER_EDIT_MEMORY *)FinalBuffer, FinalSize); - return; - } - - // - // It's on VMI mode - // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); - - Status = DeviceIoControl( - g_DeviceHandle, // Handle to device - IOCTL_DEBUGGER_EDIT_MEMORY, // IO Control Code (IOCTL) - FinalBuffer, // Input Buffer to driver. - FinalSize, // Input buffer length - &EditMemoryRequest, // Output Buffer from driver. - SIZEOF_DEBUGGER_EDIT_MEMORY, // Length of output buffer in bytes. - NULL, // Bytes placed in buffer. - NULL // synchronous call - ); - - if (!Status) - { - free(FinalBuffer); - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); - return; - } - - if (EditMemoryRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL) - { - // - // Was successful, nothing to do - // - } - else if ( - EditMemoryRequest.Result == - DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS) - { - ShowMessages("err, the address is invalid in system process layout\n"); - } - else if ( - EditMemoryRequest.Result == - DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_OTHER_PROCESS) - { - ShowMessages("err, the address is invalid based on your specific process id\n"); - } - else if (EditMemoryRequest.Result == - DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_PARAMETER) - { - ShowMessages("invalid parameter\n"); - } - else - { - ShowErrorMessage(EditMemoryRequest.Result); - } - - // - // Free the malloc buffer - // - free(FinalBuffer); -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/load.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/load.cpp deleted file mode 100644 index 7dc5a1fe..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/load.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/** - * @file load.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief load command - * @details - * @version 0.1 - * @date 2020-05-27 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -// -// Global Variables -// -extern HANDLE g_IsDriverLoadedSuccessfully; -extern HANDLE g_DeviceHandle; -extern BOOLEAN g_IsConnectedToHyperDbgLocally; -extern BOOLEAN g_IsDebuggerModulesLoaded; - -/** - * @brief help of the load command - * - * @return VOID - */ -VOID -CommandLoadHelp() -{ - ShowMessages("load : installs the drivers and load the modules.\n\n"); - - ShowMessages("syntax : \tload [ModuleName (string)]\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : load vmm\n"); -} - -/** - * @brief load vmm module - * - * @return BOOLEAN - */ -BOOLEAN -CommandLoadVmmModule() -{ - BOOL Status; - HANDLE hToken; - - // - // Enable Debug privilege - // - Status = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken); - if (!Status) - { - ShowMessages("err, OpenProcessToken failed (%x)\n", GetLastError()); - return FALSE; - } - - Status = SetPrivilege(hToken, SE_DEBUG_NAME, TRUE); - if (!Status) - { - CloseHandle(hToken); - return FALSE; - } - - // - // Install vmm driver - // - if (HyperDbgInstallVmmDriver() == 1) - { - return FALSE; - } - - // - // Create event to show if the hypervisor is loaded or not - // - g_IsDriverLoadedSuccessfully = CreateEvent(NULL, FALSE, FALSE, NULL); - - if (HyperDbgLoadVmm() == 1) - { - // - // No need to handle anymore - // - CloseHandle(g_IsDriverLoadedSuccessfully); - return FALSE; - } - - // - // Vmm module (Hypervisor) is loaded - // - - // - // We wait for the first message from the kernel debugger to continue - // - WaitForSingleObject( - g_IsDriverLoadedSuccessfully, - INFINITE); - - // - // No need to handle anymore - // - CloseHandle(g_IsDriverLoadedSuccessfully); - - // - // If we reach here so the module are loaded - // - g_IsDebuggerModulesLoaded = TRUE; - - ShowMessages("vmm module is running...\n"); - - return TRUE; -} - -/** - * @brief load command handler - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandLoad(vector SplitCommand, string Command) -{ - if (SplitCommand.size() != 2) - { - ShowMessages("incorrect use of the 'load'\n\n"); - CommandLoadHelp(); - return; - } - - if (!g_IsConnectedToHyperDbgLocally) - { - ShowMessages("you're not connected to any instance of HyperDbg, did you " - "use '.connect'? \n"); - return; - } - - // - // Check for the module - // - if (!SplitCommand.at(1).compare("vmm")) - { - // - // Check to make sure that the driver is not already loaded - // - if (g_DeviceHandle) - { - ShowMessages("handle of the driver found, if you use 'load' before, please " - "first unload it then call 'unload'\n"); - return; - } - - // - // Load VMM Module - // - ShowMessages("loading the vmm driver\n"); - - if (!CommandLoadVmmModule()) - { - ShowMessages("failed to install or load the driver\n"); - return; - } - - // - // If in vmi-mode then initialize and load symbols (pdb) - // for previously downloaded symbols - // When the VMM module is loaded, we use the current - // process (HyperDbg's process) as the base for user-mode - // symbols - // - SymbolLocalReload(GetCurrentProcessId()); - } - else - { - // - // Module not found - // - ShowMessages("err, module not found\n"); - } -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/print.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/print.cpp deleted file mode 100644 index a2fde89a..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/print.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/** - * @file print.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @author M.H. Gholamrezaei (mh@hyperdbg.org) - * @brief print command - * @details - * @version 0.1 - * @date 2020-10-08 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -using namespace std; - -// -// Global Variables -// -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; - -/** - * @brief help of the print command - * - * @return VOID - */ -VOID -CommandPrintHelp() -{ - ShowMessages("print : evaluates expressions.\n\n"); - - ShowMessages("syntax : \tprint [Expression (string)]\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : print dq(poi(@rcx))\n"); -} - -/** - * @brief handler of print command - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandPrint(vector SplitCommand, string Command) -{ - PVOID CodeBuffer; - UINT64 BufferAddress; - UINT32 BufferLength; - UINT32 Pointer; - - if (SplitCommand.size() == 1) - { - ShowMessages("incorrect use of the 'print'\n\n"); - CommandPrintHelp(); - return; - } - - // - // Trim the command - // - Trim(Command); - - // - // Remove print from it - // - Command.erase(0, SplitCommand.at(0).size()); - - // - // Trim it again - // - Trim(Command); - - // - // Prepend and append 'print(' and ')' - // - Command.insert(0, "print("); - Command.append(");"); - - if (g_IsSerialConnectedToRemoteDebuggee) - { - // - // Send over serial - // - - // - // Run script engine handler - // - CodeBuffer = ScriptEngineParseWrapper((char *)Command.c_str(), TRUE); - - if (CodeBuffer == NULL) - { - // - // return to show that this item contains an script - // - return; - } - - // - // Print symbols (test) - // - // PrintSymbolBufferWrapper(CodeBuffer); - - // - // Set the buffer and length - // - BufferAddress = ScriptEngineWrapperGetHead(CodeBuffer); - BufferLength = ScriptEngineWrapperGetSize(CodeBuffer); - Pointer = ScriptEngineWrapperGetPointer(CodeBuffer); - - // - // Send it to the remote debuggee - // - KdSendScriptPacketToDebuggee(BufferAddress, BufferLength, Pointer, FALSE); - - // - // Remove the buffer of script engine interpreted code - // - ScriptEngineWrapperRemoveSymbolBuffer(CodeBuffer); - - ShowMessages("\n"); - } - else - { - // - // error - // - ShowMessages("err, you're not connected to any debuggee\n"); - } -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/r.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/r.cpp deleted file mode 100644 index 02159c12..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/r.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/** - * @file r.cpp - * @author Alee Amini (alee@hyperdbg.org) - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief r command - * @details - * @version 0.1 - * @date 2021-02-27 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -// using namespace std; - -// -// Global Variables -// -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; - -std::map RegistersMap = { - {"rax", REGISTER_RAX}, - {"eax", REGISTER_EAX}, - {"ax", REGISTER_AX}, - {"ah", REGISTER_AH}, - {"al", REGISTER_AL}, - {"rbx", REGISTER_RBX}, - {"ebx", REGISTER_EBX}, - {"bx", REGISTER_BX}, - {"bh", REGISTER_BH}, - {"bl", REGISTER_BL}, - {"rcx", REGISTER_RCX}, - {"ecx", REGISTER_ECX}, - {"cx", REGISTER_CX}, - {"ch", REGISTER_CH}, - {"cl", REGISTER_CL}, - {"rdx", REGISTER_RDX}, - {"edx", REGISTER_EDX}, - {"dx", REGISTER_DX}, - {"dh", REGISTER_DH}, - {"dl", REGISTER_DL}, - {"rsi", REGISTER_RSI}, - {"esi", REGISTER_ESI}, - {"si", REGISTER_SI}, - {"sil", REGISTER_SIL}, - {"rdi", REGISTER_RDI}, - {"edi", REGISTER_EDI}, - {"di", REGISTER_DI}, - {"dil", REGISTER_DIL}, - {"rbp", REGISTER_RBP}, - {"ebp", REGISTER_EBP}, - {"bp", REGISTER_BP}, - {"bpl", REGISTER_BPL}, - {"rsp", REGISTER_RSP}, - {"esp", REGISTER_ESP}, - {"sp", REGISTER_SP}, - {"spl", REGISTER_SPL}, - {"r8", REGISTER_R8}, - {"r8d", REGISTER_R8D}, - {"r8w", REGISTER_R8W}, - {"r8h", REGISTER_R8H}, - {"r8l", REGISTER_R8L}, - {"r9", REGISTER_R9}, - {"r9d", REGISTER_R9D}, - {"r9w", REGISTER_R9W}, - {"r9h", REGISTER_R9H}, - {"r9l", REGISTER_R9L}, - {"r10", REGISTER_R10}, - {"r10d", REGISTER_R10D}, - {"r10w", REGISTER_R10W}, - {"r10h", REGISTER_R10H}, - {"r10l", REGISTER_R10L}, - {"r11", REGISTER_R11}, - {"r11d", REGISTER_R11D}, - {"r11w", REGISTER_R11W}, - {"r11h", REGISTER_R11H}, - {"r11l", REGISTER_R11L}, - {"r12", REGISTER_R12}, - {"r12d", REGISTER_R12D}, - {"r12w", REGISTER_R12W}, - {"r12h", REGISTER_R12H}, - {"r12l", REGISTER_R12L}, - {"r13", REGISTER_R13}, - {"r13d", REGISTER_R13D}, - {"r13w", REGISTER_R13W}, - {"r13h", REGISTER_R13H}, - {"r13l", REGISTER_R13L}, - {"r14", REGISTER_R14}, - {"r14d", REGISTER_R14D}, - {"r14w", REGISTER_R14W}, - {"r14h", REGISTER_R14H}, - {"r14l", REGISTER_R14L}, - {"r15", REGISTER_R15}, - {"r15d", REGISTER_R15D}, - {"r15w", REGISTER_R15W}, - {"r15h", REGISTER_R15H}, - {"r15l", REGISTER_R15L}, - {"ds", REGISTER_DS}, - {"es", REGISTER_ES}, - {"fs", REGISTER_FS}, - {"gs", REGISTER_GS}, - {"cs", REGISTER_CS}, - {"ss", REGISTER_SS}, - {"rflags", REGISTER_RFLAGS}, - {"eflags", REGISTER_EFLAGS}, - {"flags", REGISTER_FLAGS}, - {"cf", REGISTER_CF}, - {"pf", REGISTER_PF}, - {"af", REGISTER_AF}, - {"zf", REGISTER_ZF}, - {"sf", REGISTER_SF}, - {"tf", REGISTER_TF}, - {"if", REGISTER_IF}, - {"df", REGISTER_DF}, - {"of", REGISTER_OF}, - {"iopl", REGISTER_IOPL}, - {"nt", REGISTER_NT}, - {"rf", REGISTER_RF}, - {"vm", REGISTER_VM}, - {"ac", REGISTER_AC}, - {"vif", REGISTER_VIF}, - {"vip", REGISTER_VIP}, - {"id", REGISTER_ID}, - {"idtr", REGISTER_IDTR}, - {"gdtr", REGISTER_GDTR}, - {"ldtr", REGISTER_LDTR}, - {"tr", REGISTER_TR}, - {"cr0", REGISTER_CR0}, - {"cr2", REGISTER_CR2}, - {"cr3", REGISTER_CR3}, - {"cr4", REGISTER_CR4}, - {"cr8", REGISTER_CR8}, - {"dr0", REGISTER_DR0}, - {"dr1", REGISTER_DR1}, - {"dr2", REGISTER_DR2}, - {"dr3", REGISTER_DR3}, - {"dr6", REGISTER_DR6}, - {"dr7", REGISTER_DR7}, - {"rip", REGISTER_RIP}, - {"eip", REGISTER_EIP}, - {"ip", REGISTER_IP}, -}; - -/** - * @brief help of the r command - * - * @return VOID - */ -VOID -CommandRHelp() -{ - ShowMessages("r : reads or modifies registers.\n\n"); - - ShowMessages("syntax : \tr\n"); - ShowMessages("syntax : \tr [Register (string)] [= Expr (string)]\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : r\n"); - ShowMessages("\t\te.g : r @rax\n"); - ShowMessages("\t\te.g : r rax\n"); - ShowMessages("\t\te.g : r rax = 0x55\n"); - ShowMessages("\t\te.g : r rax = @rbx + @rcx + 0n10\n"); -} - -/** - * @brief handler of r show all registers command - * - * @return BOOLEAN - */ - -VOID -ShowAllRegisters() -{ - DEBUGGEE_REGISTER_READ_DESCRIPTION RegState = {0}; - RegState.RegisterID = DEBUGGEE_SHOW_ALL_REGISTERS; - KdSendReadRegisterPacketToDebuggee(&RegState); -} -/** - * @brief handler of r command - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandR(std::vector SplitCommand, std::string Command) -{ - // - // Interpret here - // - PVOID CodeBuffer; - UINT64 BufferAddress; - UINT32 BufferLength; - UINT32 Pointer; - REGS_ENUM RegKind; - std::vector Tmp; - - std::string SetRegValue = "SetRegValue"; - - if (SplitCommand[0] != "r") - { - return; - } - - if (SplitCommand.size() == 1) - { - // - // show all registers - // - if (g_IsSerialConnectedToRemoteDebuggee) - { - ShowAllRegisters(); - } - else - { - ShowMessages("err, reading registers (r) is not valid in the current " - "context, you should connect to a debuggee\n"); - } - - return; - } - // - // clear additional space of the command string - // - - // - // if command does not contain a '=' means user wants to read it - // - if (Command.find('=', 0) == string::npos) - { - // - // erase '=' from the string now we have just the name of register - // - Command.erase(0, 1); - ReplaceAll(Command, "@", ""); - ReplaceAll(Command, " ", ""); - if (RegistersMap.find(Command) != RegistersMap.end()) - { - RegKind = RegistersMap[Command]; - } - else - { - // - // set the Reg to -1(invalid register) - // - RegKind = (REGS_ENUM)-1; - } - if (RegKind != -1) - { - DEBUGGEE_REGISTER_READ_DESCRIPTION RegState = {0}; - RegState.RegisterID = RegKind; - - // - // send the request - // - if (g_IsSerialConnectedToRemoteDebuggee) - { - KdSendReadRegisterPacketToDebuggee(&RegState); - } - else - { - ShowMessages("err, reading registers (r) is not valid in the current " - "context, you should connect to a debuggee\n"); - } - } - else - { - ShowMessages("err, invalid register\n"); - } - } - - // - // if command contains a '=' means user wants modify the register - // - - else if (Command.find('=', 0) != string::npos) - { - Command.erase(0, 1); - Tmp = Split(Command, '='); - if (Tmp.size() == 2) - { - ReplaceAll(Tmp[0], " ", ""); - string tmp = Tmp[0]; - if (RegistersMap.find(Tmp[0]) != RegistersMap.end()) - { - RegKind = RegistersMap[Tmp[0]]; - } - else - { - ReplaceAll(tmp, "@", ""); - if (RegistersMap.find(tmp) != RegistersMap.end()) - { - RegKind = RegistersMap[tmp]; - } - else - { - RegKind = (REGS_ENUM)-1; - } - } - if (RegKind != -1) - { - // - // send the request - // - - SetRegValue = "@" + tmp + '=' + Tmp[1] + "; "; - if (g_IsSerialConnectedToRemoteDebuggee) - { - // - // Send over serial - // - - // - // Run script engine handler - // - CodeBuffer = ScriptEngineParseWrapper((char *)SetRegValue.c_str(), TRUE); - if (CodeBuffer == NULL) - { - // - // return to show that this item contains an script - // - return; - } - - // - // Print symbols (test) - // - // PrintSymbolBufferWrapper(CodeBuffer); - - // - // Set the buffer and length - // - BufferAddress = ScriptEngineWrapperGetHead(CodeBuffer); - BufferLength = ScriptEngineWrapperGetSize(CodeBuffer); - Pointer = ScriptEngineWrapperGetPointer(CodeBuffer); - - // - // Send it to the remote debuggee - // - KdSendScriptPacketToDebuggee(BufferAddress, BufferLength, Pointer, FALSE); - - // - // Remove the buffer of script engine interpreted code - // - ScriptEngineWrapperRemoveSymbolBuffer(CodeBuffer); - } - else - { - // - // error - // - ShowMessages("err, you're not connected to any debuggee\n"); - } - } - else - { - // - // error - // - ShowMessages("err, invalid register\n"); - } - } - } -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/unload.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/unload.cpp deleted file mode 100644 index 804e183c..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/unload.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @file unload.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief unload command - * @details - * @version 0.1 - * @date 2020-05-27 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -// -// Global Variables -// -extern BOOLEAN g_IsConnectedToHyperDbgLocally; -extern BOOLEAN g_IsDebuggerModulesLoaded; -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; -extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; - -/** - * @brief help of the unload command - * - * @return VOID - */ -VOID -CommandUnloadHelp() -{ - ShowMessages( - "unload : unloads the kernel modules and uninstalls the drivers.\n\n"); - - ShowMessages("syntax : \tunload [remove] [ModuleName (string)]\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : unload vmm\n"); - ShowMessages("\t\te.g : unload remove vmm\n"); -} - -/** - * @brief unload command handler - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandUnload(vector SplitCommand, string Command) -{ - if (SplitCommand.size() != 2 && SplitCommand.size() != 3) - { - ShowMessages("incorrect use of the 'unload'\n\n"); - CommandUnloadHelp(); - return; - } - - // - // Check for the module - // - if ((SplitCommand.size() == 2 && !SplitCommand.at(1).compare("vmm")) || (SplitCommand.size() == 3 && !SplitCommand.at(2).compare("vmm") && !SplitCommand.at(1).compare("remove"))) - { - if (!g_IsConnectedToHyperDbgLocally) - { - ShowMessages("you're not connected to any instance of HyperDbg, did you " - "use '.connect'? \n"); - return; - } - - // - // Check to avoid using this command in debugger-mode - // - if (g_IsSerialConnectedToRemoteDebuggee || g_IsSerialConnectedToRemoteDebugger) - { - ShowMessages("you're connected to a an instance of HyperDbg, please use " - "'.debug close' command\n"); - return; - } - - if (g_IsDebuggerModulesLoaded) - { - HyperDbgUnloadVmm(); - } - else - { - ShowMessages("there is nothing to unload\n"); - } - - // - // Check to remove the driver - // - if (!SplitCommand.at(1).compare("remove")) - { - // - // Stop the driver - // - if (HyperDbgStopVmmDriver()) - { - ShowMessages("err, failed to stop driver\n"); - return; - } - - // - // Uninstall the driver - // - if (HyperDbgUninstallVmmDriver()) - { - ShowMessages("err, failed to uninstall the driver\n"); - return; - } - - ShowMessages("the driver is removed\n"); - } - } - else - { - // - // Module not found - // - ShowMessages("err, module not found\n"); - } -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/hide.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/hide.cpp deleted file mode 100644 index b4b373f5..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/hide.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/** - * @file hide.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief !hide command - * @details - * @version 0.1 - * @date 2020-07-07 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -// -// Global Variables -// -extern UINT64 g_CpuidAverage; -extern UINT64 g_CpuidStandardDeviation; -extern UINT64 g_CpuidMedian; - -extern UINT64 g_RdtscAverage; -extern UINT64 g_RdtscStandardDeviation; -extern UINT64 g_RdtscMedian; - -extern BOOLEAN g_TransparentResultsMeasured; -extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; - -/** - * @brief help of the !hide command - * - * @return VOID - */ -VOID -CommandHideHelp() -{ - ShowMessages("!hide : tries to make HyperDbg transparent from anti-debugging " - "and anti-hypervisor methods.\n\n"); - - ShowMessages("syntax : \t!hide\n"); - ShowMessages("syntax : \t!hide [pid ProcessId (hex)]\n"); - ShowMessages("syntax : \t!hide [name ProcessName (string)]\n"); - - ShowMessages("note : \tprocess names are case sensitive and you can use " - "this command multiple times.\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : !hide\n"); - ShowMessages("\t\te.g : !hide pid b60 \n"); - ShowMessages("\t\te.g : !hide name procexp.exe\n"); -} - -/** - * @brief !hide command handler - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandHide(vector SplitCommand, string Command) -{ - BOOLEAN Status; - ULONG ReturnedLength; - UINT64 TargetPid; - BOOLEAN TrueIfProcessIdAndFalseIfProcessName; - DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE HideRequest = {0}; - PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE FinalRequestBuffer = 0; - size_t RequestBufferSize = 0; - - if (SplitCommand.size() <= 2 && SplitCommand.size() != 1) - { - ShowMessages("incorrect use of the '!hide'\n\n"); - CommandHideHelp(); - return; - } - - // - // Find out whether the user enters pid or name - // - if (SplitCommand.size() == 1) - { - if (g_ActiveProcessDebuggingState.IsActive) - { - TrueIfProcessIdAndFalseIfProcessName = TRUE; - TargetPid = g_ActiveProcessDebuggingState.ProcessId; - } - else - { - // - // There is no user-debugging process - // - ShowMessages("you're not attached to any user-mode process, " - "please explicitly specify the process id or process name\n"); - return; - } - } - else if (!SplitCommand.at(1).compare("pid")) - { - TrueIfProcessIdAndFalseIfProcessName = TRUE; - - // - // Check for the user to not add extra arguments - // - if (SplitCommand.size() != 3) - { - ShowMessages("incorrect use of the '!hide'\n\n"); - CommandHideHelp(); - return; - } - - // - // It's just a pid for the process - // - if (!ConvertStringToUInt64(SplitCommand.at(2), &TargetPid)) - { - ShowMessages("incorrect process id\n\n"); - return; - } - } - else if (!SplitCommand.at(1).compare("name")) - { - TrueIfProcessIdAndFalseIfProcessName = FALSE; - - // - // Trim the command - // - Trim(Command); - - // - // Remove !hide from it - // - Command.erase(0, SplitCommand.at(0).size()); - - // - // remove name + space - // - Command.erase(0, 4 + 1); - - // - // Trim it again - // - Trim(Command); - } - else - { - // - // Invalid argument for the second parameter to the command - // - ShowMessages("incorrect use of the '!hide'\n\n"); - CommandHideHelp(); - return; - } - - // - // Check if the user used !measure or not - // - if (!g_TransparentResultsMeasured || !g_CpuidAverage || - !g_CpuidStandardDeviation || !g_CpuidMedian) - { - ShowMessages("the average, median and standard deviation is not measured. " - "Did you use '!measure' command?\n"); - return; - } - - // - // Check if debugger is loaded or not - // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); - - // - // We wanna hide the debugger and make transparent vm-exits - // - HideRequest.IsHide = TRUE; - - // - // Set the measured times cpuid - // - HideRequest.CpuidAverage = g_CpuidAverage; - HideRequest.CpuidMedian = g_CpuidMedian; - HideRequest.CpuidStandardDeviation = g_CpuidStandardDeviation; - - // - // Set the measured times rdtsc/p - // - HideRequest.RdtscAverage = g_RdtscAverage; - HideRequest.RdtscMedian = g_RdtscMedian; - HideRequest.RdtscStandardDeviation = g_RdtscStandardDeviation; - - HideRequest.TrueIfProcessIdAndFalseIfProcessName = - TrueIfProcessIdAndFalseIfProcessName; - - if (TrueIfProcessIdAndFalseIfProcessName) - { - // - // It's a process id - // - HideRequest.ProcId = (UINT32)TargetPid; - - RequestBufferSize = sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE); - } - else - { - // - // It's a process name - // - HideRequest.LengthOfProcessName = (UINT32)Command.size() + 1; - RequestBufferSize = sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE) + Command.size() + 1; - } - - // - // Allocate the requested buffer - // - FinalRequestBuffer = - (PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE)malloc(RequestBufferSize); - - if (FinalRequestBuffer == NULL) - { - ShowMessages("insufficient space\n"); - return; - } - - // - // Zero the memory - // - RtlZeroMemory(FinalRequestBuffer, RequestBufferSize); - - // - // Copy the buffer on the top of the final buffer - // to send the kernel - // - memcpy(FinalRequestBuffer, &HideRequest, sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE)); - - // - // If it's a name then we should add it to the end of the buffer - // - memcpy(((UINT64 *)((UINT64)FinalRequestBuffer + - sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE))), - Command.c_str(), - Command.size()); - - // - // Send the request to the kernel - // - - Status = DeviceIoControl( - g_DeviceHandle, // Handle to device - IOCTL_DEBUGGER_HIDE_AND_UNHIDE_TO_TRANSPARENT_THE_DEBUGGER, // IO Control - // code - FinalRequestBuffer, // Input Buffer to driver. - (DWORD)RequestBufferSize, // Input buffer length - FinalRequestBuffer, // Output Buffer from driver. - SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE, // Length of output - // buffer in bytes. - &ReturnedLength, // Bytes placed in buffer. - NULL // synchronous call - ); - - if (!Status) - { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); - free(FinalRequestBuffer); - return; - } - - if (FinalRequestBuffer->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) - { - ShowMessages("transparent debugging successfully enabled :)\n"); - } - else if (FinalRequestBuffer->KernelStatus == - DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER) - { - ShowMessages("unable to hide the debugger (transparent-debugging) :(\n"); - free(FinalRequestBuffer); - return; - } - else - { - ShowMessages("unknown error occurred :(\n"); - free(FinalRequestBuffer); - return; - } - - // - // free the buffer - // - free(FinalRequestBuffer); -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/rev.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/rev.cpp deleted file mode 100644 index 9463196a..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/rev.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/** - * @file rev.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief !rev command - * @details - * @version 0.2 - * @date 2023-03-22 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -// -// Global Variables -// -extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; -extern std::wstring g_StartCommandPath; -extern std::wstring g_StartCommandPathAndArguments; -extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; - -/** - * @brief help of the !rev command - * - * @return VOID - */ -VOID -CommandRevHelp() -{ - ShowMessages("!rev : uses the reversing machine module in order to reconstruct the programmer/memory assumptions.\n\n"); - - ShowMessages("syntax : \t!rev [config] [pid ProcessId (hex)]\n"); - ShowMessages("syntax : \t!rev [path Path (string)] [Parameters (string)]\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : !rev path c:\\reverse eng\\my_file.exe\n"); - ShowMessages("\t\te.g : !rev pattern\n"); - ShowMessages("\t\te.g : !rev reconstruct\n"); - ShowMessages("\t\te.g : !rev pattern pid 1c0\n"); - ShowMessages("\t\te.g : !rev reconstruct pid 1c0\n"); -} - -/** - * @brief !rev command handler - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandRev(vector SplitCommand, string Command) -{ - /* - vector PathAndArgs; - string Arguments = ""; - - // - // Disable user-mode debugger in this version - // -#if ActivateUserModeDebugger == FALSE - - if (!g_IsSerialConnectedToRemoteDebugger) - { - ShowMessages("the user-mode debugger in VMI Mode is still in the beta version and not stable. " - "we decided to exclude it from this release and release it in future versions. " - "if you want to test the user-mode debugger in VMI Mode, you should build " - "HyperDbg with special instructions. But starting processes is fully supported " - "in the Debugger Mode.\n" - "(it's not recommended to use it in VMI Mode yet!)\n"); - return; - } - -#endif // !ActivateUserModeDebugger - - if (SplitCommand.size() <= 2) - { - ShowMessages("incorrect use of the '.start'\n\n"); - CommandStartHelp(); - return; - } - - - if (!SplitCommand.at(1).compare("path")) - { - // - // *** It's a run of target PE file *** - // - - // - // Trim the command - // - Trim(Command); - - // - // Remove !rev from it - // - Command.erase(0, SplitCommand.at(0).size()); - - // - // Remove path + space - // - Command.erase(0, 4 + 1); - - // - // Trim it again - // - Trim(Command); - - // - // Split Path and args - // - SplitPathAndArgs(PathAndArgs, Command); - - // - // Convert path to wstring - // - StringToWString(g_StartCommandPath, PathAndArgs.at(0)); - - if (PathAndArgs.size() != 1) - { - // - // There are arguments to this command - // - - for (auto item : PathAndArgs) - { - // - // Append the arguments - // - // ShowMessages("Arg : %s\n", item.c_str()); - Arguments += item + " "; - } - - // - // Remove the latest space - // - Arguments.pop_back(); - - // - // Convert arguments to wstring - // - StringToWString(g_StartCommandPathAndArguments, Arguments); - } - } - else - { - ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommand.at(1).c_str()); - CommandStartHelp(); - return; - } - - // - // Perform run of the target file - // - if (Arguments.empty()) - { - UdAttachToProcess(NULL, - g_StartCommandPath.c_str(), - NULL, - TRUE); - } - else - { - UdAttachToProcess(NULL, - g_StartCommandPath.c_str(), - (WCHAR *)g_StartCommandPathAndArguments.c_str(), - TRUE); - } - - /////////////////////////////////////////////////////////////////////////////// - return; - - */ - - REVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST RevRequest = {0}; - BOOLEAN SetPid = FALSE; - UINT32 TargetPid = NULL; - BOOLEAN IgnoreFirstCommand = TRUE; - REVERSING_MACHINE_RECONSTRUCT_MEMORY_MODE Mode = REVERSING_MACHINE_RECONSTRUCT_MEMORY_MODE_UNKNOWN; - REVERSING_MACHINE_RECONSTRUCT_MEMORY_TYPE Type = REVERSING_MACHINE_RECONSTRUCT_MEMORY_TYPE_UNKNOWN; - - // - // Interpret command specific details - // - for (auto Section : SplitCommand) - { - if (!Section.compare("!rev") && IgnoreFirstCommand) - { - IgnoreFirstCommand = FALSE; - continue; - } - else if (!Section.compare("pid") && !SetPid) - { - SetPid = TRUE; - } - else if (SetPid) - { - if (!ConvertStringToUInt32(Section, &TargetPid)) - { - // - // couldn't resolve or unknown parameter - // - ShowMessages("err, couldn't resolve error at '%s'\n\n", - Section.c_str()); - CommandRevHelp(); - return; - } - SetPid = FALSE; - } - else if (!Section.compare("pattern")) - { - Type = REVERSING_MACHINE_RECONSTRUCT_MEMORY_TYPE_PATTERN; - } - else if (!Section.compare("reconstruct")) - { - Type = REVERSING_MACHINE_RECONSTRUCT_MEMORY_TYPE_RECONSTRUCT; - } - else - { - // - // Unknown parameter - // - ShowMessages("err, couldn't resolve error at '%s'\n\n", - Section.c_str()); - CommandRevHelp(); - return; - } - } - - if (SetPid) - { - ShowMessages("err, please enter a valid process id in hex format, " - "or if you want to use it in decimal format, add '0n' " - "prefix to the number\n"); - return; - } - - RevRequest.ProcessId = TargetPid; - - // ================================================================================ - - // - // Send the request to the hypervisor (kernel) - // - RevRequestService(&RevRequest); -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/track.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/track.cpp deleted file mode 100644 index 7efefe7f..00000000 Binary files a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/track.cpp and /dev/null differ diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/debug.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/debug.cpp deleted file mode 100644 index 9f004f00..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/debug.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/** - * @file debug.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief .debug command - * @details - * @version 0.1 - * @date 2020-12-19 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -// -// Global Variables -// -extern HANDLE g_SerialListeningThreadHandle; -extern HANDLE g_SerialRemoteComPortHandle; -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; -extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; -extern BOOLEAN g_IsDebuggeeRunning; - -/** - * @brief help of the .debug command - * - * @return VOID - */ -VOID -CommandDebugHelp() -{ - ShowMessages( - ".debug : debugs a target machine or makes this machine a debuggee.\n\n"); - - ShowMessages( - "syntax : \t.debug [remote] [serial|namedpipe] [Baudrate (decimal)] [Address (string)]\n"); - ShowMessages( - "syntax : \t.debug [prepare] [serial] [Baudrate (decimal)] [Address (string)]\n"); - ShowMessages("syntax : \t.debug [close]\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : .debug remote serial 115200 com2\n"); - ShowMessages("\t\te.g : .debug remote namedpipe \\\\.\\pipe\\HyperDbgPipe\n"); - ShowMessages("\t\te.g : .debug prepare serial 115200 com1\n"); - ShowMessages("\t\te.g : .debug prepare serial 115200 com2\n"); - ShowMessages("\t\te.g : .debug close\n"); - - ShowMessages( - "\nvalid baud rates (decimal) : 110, 300, 600, 1200, 2400, 4800, 9600, " - "14400, 19200, 38400, 56000, 57600, 115200, 128000, 256000\n"); - ShowMessages("valid COM ports : COM1, COM2, COM3, COM4 \n"); -} - -/** - * @brief Check if baud rate is valid or not - * - * @param Baudrate - * @return BOOLEAN - */ -BOOLEAN -CommandDebugCheckBaudrate(DWORD Baudrate) -{ - if (Baudrate == CBR_110 || Baudrate == CBR_300 || Baudrate == CBR_600 || - Baudrate == CBR_1200 || Baudrate == CBR_2400 || Baudrate == CBR_4800 || - Baudrate == CBR_9600 || Baudrate == CBR_14400 || Baudrate == CBR_19200 || - Baudrate == CBR_38400 || Baudrate == CBR_56000 || Baudrate == CBR_57600 || - Baudrate == CBR_115200 || Baudrate == CBR_128000 || - Baudrate == CBR_256000) - { - return TRUE; - } - return FALSE; -} - -/** - * @brief Check if COM port is valid or not - * - * @param ComPort - * @return BOOLEAN - */ -BOOLEAN -CommandDebugCheckComPort(const string & ComPort, UINT32 * Port) -{ - if (!ComPort.compare("com1")) - { - *Port = COM1_PORT; - return TRUE; - } - else if (!ComPort.compare("com2")) - { - *Port = COM2_PORT; - return TRUE; - } - else if (!ComPort.compare("com3")) - { - *Port = COM3_PORT; - return TRUE; - } - else if (!ComPort.compare("com4")) - { - *Port = COM4_PORT; - return TRUE; - } - - return FALSE; -} - -/** - * @brief .debug command handler - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandDebug(vector SplitCommand, string Command) -{ - UINT32 Baudrate; - UINT32 Port; - - if (SplitCommand.size() == 2 && !SplitCommand.at(1).compare("close")) - { - // - // Check if the debugger is attached to a debuggee - // - if (g_IsSerialConnectedToRemoteDebuggee) - { - KdCloseConnection(); - } - else - { - ShowMessages( - "err, debugger is not attached to any instance of debuggee\n"); - } - return; - } - else if (SplitCommand.size() <= 3) - { - ShowMessages("incorrect use of the '.debug'\n\n"); - CommandDebugHelp(); - return; - } - - // - // Check the main command - // - if (!SplitCommand.at(1).compare("remote")) - { - // - // in the case of the 'remote' - // - - if (!SplitCommand.at(2).compare("serial")) - { - // - // Connect to a remote serial device - // - if (SplitCommand.size() != 5) - { - ShowMessages("incorrect use of the '.debug'\n\n"); - CommandDebugHelp(); - return; - } - - // - // Set baudrate - // - if (!IsNumber(SplitCommand.at(3))) - { - // - // Unknown parameter - // - ShowMessages("unknown parameter '%s'\n\n", - SplitCommand.at(3).c_str()); - CommandDebugHelp(); - return; - } - - Baudrate = stoi(SplitCommand.at(3)); - - // - // Check if baudrate is valid or not - // - if (!CommandDebugCheckBaudrate(Baudrate)) - { - // - // Baud-rate is invalid - // - ShowMessages("err, baud rate is invalid\n\n"); - CommandDebugHelp(); - return; - } - - // - // check if com port address is valid or not - // - if (!CommandDebugCheckComPort(SplitCommand.at(4), &Port)) - { - // - // com port is invalid - // - ShowMessages("err, COM port is invalid\n\n"); - CommandDebugHelp(); - return; - } - - // - // Everything is okay, connect to the remote machine to send (debugger) - // - KdPrepareAndConnectDebugPort(SplitCommand.at(4).c_str(), Baudrate, Port, FALSE, FALSE); - } - else if (!SplitCommand.at(2).compare("namedpipe")) - { - // - // Connect to a remote namedpipe - // - string Delimiter = "namedpipe"; - string Token = Command.substr( - Command.find(Delimiter) + Delimiter.size() + 1, - Command.size()); - - // - // Connect to a namedpipe (it's probably a Virtual Machine debugging) - // - KdPrepareAndConnectDebugPort(Token.c_str(), NULL, NULL, FALSE, TRUE); - } - else - { - // - // Unknown parameter - // - ShowMessages("unknown parameter '%s'\n\n", SplitCommand.at(2).c_str()); - CommandDebugHelp(); - return; - } - } - else if (!SplitCommand.at(1).compare("prepare")) - { - if (SplitCommand.size() != 5) - { - ShowMessages("incorrect use of the '.debug'\n\n"); - CommandDebugHelp(); - return; - } - - // - // in the case of the 'prepare' - // currently we only support serial - // - if (!SplitCommand.at(2).compare("serial")) - { - // - // Set baudrate - // - if (!IsNumber(SplitCommand.at(3))) - { - // - // Unknown parameter - // - ShowMessages("unknown parameter '%s'\n\n", - SplitCommand.at(3).c_str()); - CommandDebugHelp(); - return; - } - - Baudrate = stoi(SplitCommand.at(3)); - - // - // Check if baudrate is valid or not - // - if (!CommandDebugCheckBaudrate(Baudrate)) - { - // - // Baud-rate is invalid - // - ShowMessages("err, baud rate is invalid\n\n"); - CommandDebugHelp(); - return; - } - - // - // check if com port address is valid or not - // - if (!CommandDebugCheckComPort(SplitCommand.at(4), &Port)) - { - // - // com port is invalid - // - ShowMessages("err, COM port is invalid\n\n"); - CommandDebugHelp(); - return; - } - - // - // Everything is okay, prepare to send (debuggee) - // - KdPrepareAndConnectDebugPort(SplitCommand.at(4).c_str(), Baudrate, Port, TRUE, FALSE); - } - else - { - ShowMessages("invalid parameter '%s'\n\n", SplitCommand.at(2)); - CommandDebugHelp(); - return; - } - } - else - { - ShowMessages("invalid parameter '%s'\n\n", SplitCommand.at(1)); - CommandDebugHelp(); - return; - } -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/pe.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/pe.cpp deleted file mode 100644 index 3130b674..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/pe.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/** - * @file pe.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief .pe command - * @details - * @version 0.1 - * @date 2021-12-27 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -using namespace std; - -/** - * @brief help of the .pe command - * - * @return VOID - */ -VOID -CommandPeHelp() -{ - ShowMessages(".pe : parses portable executable (PE) files and dump sections.\n\n"); - - ShowMessages("syntax : \t.pe [header] [FilePath (string)]\n"); - ShowMessages("syntax : \t.pe [section] [SectionName (string)] [FilePath (string)]\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : .pe header c:\\reverse files\\myfile.exe\n"); - ShowMessages("\t\te.g : .pe section .text c:\\reverse files\\myfile.exe\n"); - ShowMessages("\t\te.g : .pe section .rdata c:\\reverse files\\myfile.exe\n"); -} - -/** - * @brief .pe command handler - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandPe(vector SplitCommand, string Command) -{ - BOOLEAN Is32Bit = FALSE; - wstring Filepath; - BOOLEAN ShowDumpOfSection = FALSE; - - if (SplitCommand.size() <= 2) - { - ShowMessages("err, incorrect use of the '.pe' command\n\n"); - CommandPeHelp(); - return; - } - - // - // Check for first option - // - if (!SplitCommand.at(1).compare("section")) - { - if (SplitCommand.size() == 3) - { - ShowMessages("please specify a valid PE file\n\n"); - CommandPeHelp(); - return; - } - ShowDumpOfSection = TRUE; - } - else if (!SplitCommand.at(1).compare("header")) - { - ShowDumpOfSection = FALSE; - } - else - { - // - // Couldn't resolve or unknown parameter - // - ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommand.at(1).c_str()); - CommandPeHelp(); - return; - } - - // - // Trim the command - // - Trim(Command); - - // - // Remove .pe from it - // - Command.erase(0, SplitCommand.at(0).size()); - - if (!ShowDumpOfSection) - { - // - // Remove header + space - // - Command.erase(0, 6 + 1); - } - else - { - // - // Remove section + space - // - Command.erase(0, 7 + 1); - - // - // Remove the string param for section + space - // - Command.erase(0, SplitCommand.at(2).size() + 1); - } - - // - // Trim it again - // - Trim(Command); - - // - // Convert path to wstring - // - StringToWString(Filepath, Command); - - // - // Detect whether PE is 32-bit or 64-bit - // - if (!PeIsPE32BitOr64Bit(Filepath.c_str(), &Is32Bit)) - { - // - // File was invalid, the error message is shown in the above function - // - return; - } - - // - // Parse PE file - // - if (!ShowDumpOfSection) - { - PeShowSectionInformationAndDump(Filepath.c_str(), NULL, Is32Bit); - } - else - { - PeShowSectionInformationAndDump(Filepath.c_str(), SplitCommand.at(2).c_str(), Is32Bit); - } -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/start.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/start.cpp deleted file mode 100644 index 072964ca..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/start.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @file start.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief .start command - * @details - * @version 0.1 - * @date 2022-01-06 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -// -// Global Variables -// -extern std::wstring g_StartCommandPath; -extern std::wstring g_StartCommandPathAndArguments; -extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; - -/** - * @brief help of the .start command - * - * @return VOID - */ -VOID -CommandStartHelp() -{ - ShowMessages(".start : runs a user-mode process.\n\n"); - - ShowMessages("syntax : \t.start [path Path (string)] [Parameters (string)]\n"); - - ShowMessages("\n"); - ShowMessages("\t\te.g : .start path c:\\reverse eng\\my_file.exe\n"); -} - -/** - * @brief .start command handler - * - * @param SplitCommand - * @param Command - * @return VOID - */ -VOID -CommandStart(vector SplitCommand, string Command) -{ - vector PathAndArgs; - string Arguments = ""; - - // - // Disable user-mode debugger in this version - // -#if ActivateUserModeDebugger == FALSE - - if (!g_IsSerialConnectedToRemoteDebugger) - { - ShowMessages("the user-mode debugger in VMI Mode is still in the beta version and not stable. " - "we decided to exclude it from this release and release it in future versions. " - "if you want to test the user-mode debugger in VMI Mode, you should build " - "HyperDbg with special instructions. But starting processes is fully supported " - "in the Debugger Mode.\n" - "(it's not recommended to use it in VMI Mode yet!)\n"); - return; - } - -#endif // !ActivateUserModeDebugger - - if (SplitCommand.size() <= 2) - { - ShowMessages("incorrect use of the '.start'\n\n"); - CommandStartHelp(); - return; - } - - if (!SplitCommand.at(1).compare("path")) - { - // - // *** It's a run of target PE file *** - // - - // - // Trim the command - // - Trim(Command); - - // - // Remove '.start' or 'start' from it - // - Command.erase(0, SplitCommand.at(0).size()); - - // - // Remove path + space - // - Command.erase(0, 4 + 1); - - // - // Trim it again - // - Trim(Command); - - // - // Split Path and args - // - SplitPathAndArgs(PathAndArgs, Command); - - // - // Convert path to wstring - // - StringToWString(g_StartCommandPath, PathAndArgs.at(0)); - - if (PathAndArgs.size() != 1) - { - // - // There are arguments to this command - // - - for (auto item : PathAndArgs) - { - // - // Append the arguments - // - // ShowMessages("Arg : %s\n", item.c_str()); - Arguments += item + " "; - } - - // - // Remove the latest space - // - Arguments.pop_back(); - - // - // Convert arguments to wstring - // - StringToWString(g_StartCommandPathAndArguments, Arguments); - } - } - else - { - ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommand.at(1).c_str()); - CommandStartHelp(); - return; - } - - // - // Perform run of the target file - // - if (Arguments.empty()) - { - UdAttachToProcess(NULL, - g_StartCommandPath.c_str(), - NULL, - FALSE); - } - else - { - UdAttachToProcess(NULL, - g_StartCommandPath.c_str(), - (WCHAR *)g_StartCommandPathAndArguments.c_str(), - FALSE); - } -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/core/interpreter.cpp b/hyperdbg/hprdbgctrl/code/debugger/core/interpreter.cpp deleted file mode 100644 index e64bff7b..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/core/interpreter.cpp +++ /dev/null @@ -1,871 +0,0 @@ -/** - * @file interpreter.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief The hyperdbg command interpreter and driver connector - * @details - * @version 0.1 - * @date 2020-04-11 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -using namespace std; - -// -// Global Variables -// -extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; -extern CommandType g_CommandsList; - -extern BOOLEAN g_ShouldPreviousCommandBeContinued; -extern BOOLEAN g_IsCommandListInitialized; -extern BOOLEAN g_LogOpened; -extern BOOLEAN g_ExecutingScript; -extern BOOLEAN g_IsConnectedToHyperDbgLocally; -extern BOOLEAN g_IsConnectedToRemoteDebuggee; -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; -extern BOOLEAN g_IsDebuggeeRunning; -extern BOOLEAN g_BreakPrintingOutput; -extern BOOLEAN g_IsInterpreterOnString; -extern BOOLEAN g_IsInterpreterPreviousCharacterABackSlash; -extern BOOLEAN g_RtmSupport; - -extern UINT32 g_VirtualAddressWidth; -extern UINT32 g_InterpreterCountOfOpenCurlyBrackets; -extern ULONG g_CurrentRemoteCore; - -extern string g_ServerPort; -extern string g_ServerIp; - -/** - * @brief Interpret commands - * - * @param Command The text of command - * @return int returns return zero if it was successful or non-zero if there was - * error - */ -int -HyperDbgInterpreter(char * Command) -{ - BOOLEAN HelpCommand = FALSE; - UINT64 CommandAttributes = NULL; - CommandType::iterator Iterator; - - // - // Check if it's the first command and whether the mapping of command is - // initialized or not - // - if (!g_IsCommandListInitialized) - { - // - // Initialize the debugger - // - InitializeDebugger(); - - g_IsCommandListInitialized = TRUE; - } - - // - // Save the command into log open file - // - if (g_LogOpened && !g_ExecutingScript) - { - LogopenSaveToFile(Command); - LogopenSaveToFile("\n"); - } - - // - // Remove the comments - // - InterpreterRemoveComments(Command); - - // - // Convert to string - // - string CommandString(Command); - - // - // Convert to lower case - // - transform(CommandString.begin(), CommandString.end(), CommandString.begin(), [](unsigned char c) { return std::tolower(c); }); - - vector SplitCommand {Split(CommandString, ' ')}; - - // - // Check if user entered an empty input - // - if (SplitCommand.empty()) - { - ShowMessages("\n"); - return 0; - } - - string FirstCommand = SplitCommand.front(); - - // - // Read the command's attributes - // - CommandAttributes = GetCommandAttributes(FirstCommand); - - // - // Check if the command needs to be continued by pressing enter - // - if (CommandAttributes & DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER) - { - g_ShouldPreviousCommandBeContinued = TRUE; - } - else - { - g_ShouldPreviousCommandBeContinued = FALSE; - } - - // - // Check and send remote command and also we check whether this - // is a command that should be handled in this command or we can - // send it to the remote computer, it is because in a remote connection - // still some of the commands should be handled in the local HyperDbg - // - if (g_IsConnectedToRemoteDebuggee && - !(CommandAttributes & DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_REMOTE_CONNECTION)) - { - // - // Check it here because generally, we use this variable in host - // for showing the correct signature but we won't try to block - // other commands, the only thing is events which is blocked - // by the remote computer itself - // - if (g_BreakPrintingOutput) - { - g_BreakPrintingOutput = FALSE; - } - - // - // It's a connection over network (VMI-Mode) - // - RemoteConnectionSendCommand(Command, (UINT32)strlen(Command) + 1); - - ShowMessages("\n"); - - // - // Indicate that we sent the command to the target system - // - return 2; - } - else if (g_IsSerialConnectedToRemoteDebuggee && - !(CommandAttributes & - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE)) - { - // - // It's a connection over serial (Debugger-Mode) - // - - if (CommandAttributes & DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN) - { - KdSendUserInputPacketToDebuggee(Command, (UINT32)strlen(Command) + 1, TRUE); - - // - // Set the debuggee to show that it's running - // - KdSetStatusAndWaitForPause(); - } - else - { - // - // Disable the breakpoints and events while executing the command in the remote computer - // - KdSendTestQueryPacketToDebuggee(TEST_BREAKPOINT_TURN_OFF_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER); - KdSendUserInputPacketToDebuggee(Command, (UINT32)strlen(Command) + 1, FALSE); - KdSendTestQueryPacketToDebuggee(TEST_BREAKPOINT_TURN_ON_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER); - } - - // - // Indicate that we sent the command to the target system - // - return 2; - } - - // - // Detect whether it's a .help command or not - // - if (!FirstCommand.compare(".help") || !FirstCommand.compare("help") || - !FirstCommand.compare(".hh")) - { - if (SplitCommand.size() == 2) - { - // - // Show that it's a help command - // - HelpCommand = TRUE; - FirstCommand = SplitCommand.at(1); - } - else - { - ShowMessages("incorrect use of the '%s'\n", FirstCommand.c_str()); - CommandHelpHelp(); - return 0; - } - } - - // - // Start parsing commands - // - Iterator = g_CommandsList.find(FirstCommand); - - if (Iterator == g_CommandsList.end()) - { - // - // Command doesn't exist - // - string CaseSensitiveCommandString(Command); - vector CaseSensitiveSplitCommand {Split(CaseSensitiveCommandString, ' ')}; - - if (!HelpCommand) - { - ShowMessages("err, couldn't resolve command at '%s'\n", CaseSensitiveSplitCommand.front().c_str()); - } - else - { - ShowMessages("err, couldn't find the help for the command at '%s'\n", - CaseSensitiveSplitCommand.at(1).c_str()); - } - } - else - { - if (HelpCommand) - { - Iterator->second.CommandHelpFunction(); - } - else - { - // - // Check if command is case-sensitive or not - // - if ((Iterator->second.CommandAttrib & - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE)) - { - string CaseSensitiveCommandString(Command); - Iterator->second.CommandFunction(SplitCommand, CaseSensitiveCommandString); - } - else - { - Iterator->second.CommandFunction(SplitCommand, CommandString); - } - } - } - - // - // Save the command into log open file - // - if (g_LogOpened && !g_ExecutingScript) - { - LogopenSaveToFile("\n"); - } - - return 0; -} - -/** - * @brief Remove batch comments - * - * @return VOID - */ -VOID -InterpreterRemoveComments(char * CommandText) -{ - BOOLEAN IsComment = FALSE; - BOOLEAN IsOnString = FALSE; - UINT32 LengthOfCommand = (UINT32)strlen(CommandText); - - for (size_t i = 0; i < LengthOfCommand; i++) - { - if (IsComment) - { - if (CommandText[i] == '\n') - { - IsComment = FALSE; - } - else - { - if (CommandText[i] != '\0') - { - memmove((void *)&CommandText[i], (const void *)&CommandText[i + 1], strlen(CommandText) - i); - i--; - } - } - } - else if (CommandText[i] == '#' && !IsOnString) - { - // - // Comment detected - // - IsComment = TRUE; - i--; - } - else if (CommandText[i] == '"') - { - if (i != 0 && CommandText[i - 1] == '\\') - { - // - // It's an escape character for : \" - // - } - else if (IsOnString) - { - IsOnString = FALSE; - } - else - { - IsOnString = TRUE; - } - } - } -} - -/** - * @brief Show signature of HyperDbg - * - * @return VOID - */ -VOID -HyperDbgShowSignature() -{ - if (g_IsConnectedToRemoteDebuggee) - { - // - // Remote debugging over tcp (vmi-mode) - // - ShowMessages("[%s:%s] HyperDbg> ", g_ServerIp.c_str(), g_ServerPort.c_str()); - } - else if (g_ActiveProcessDebuggingState.IsActive) - { - // - // Debugging a special process - // - ShowMessages("%x:%x u%sHyperDbg> ", - g_ActiveProcessDebuggingState.ProcessId, - g_ActiveProcessDebuggingState.ThreadId, - g_ActiveProcessDebuggingState.Is32Bit ? "86" : "64"); - } - else if (g_IsSerialConnectedToRemoteDebuggee) - { - // - // Remote debugging over serial (debugger-mode) - // - ShowMessages("%x: kHyperDbg> ", g_CurrentRemoteCore); - } - else - { - // - // Anything other than above scenarios including local debugging - // in vmi-mode - // - ShowMessages("HyperDbg> "); - } -} - -/** - * @brief check for multi-line commands - * - * @param CurrentCommand - * @param Reset - * @return bool return true if the command needs extra input, otherwise - * return false - */ -bool -HyperDbgCheckMultilineCommand(char * CurrentCommand, bool Reset) -{ - UINT32 CurrentCommandLen = 0; - std::string CurrentCommandStr(CurrentCommand); - - if (Reset) - { - g_IsInterpreterOnString = FALSE; - g_IsInterpreterPreviousCharacterABackSlash = FALSE; - g_InterpreterCountOfOpenCurlyBrackets = 0; - } - - CurrentCommandLen = (UINT32)CurrentCommandStr.length(); - - for (size_t i = 0; i < CurrentCommandLen; i++) - { - switch (CurrentCommandStr.at(i)) - { - case '"': - - if (g_IsInterpreterPreviousCharacterABackSlash) - { - g_IsInterpreterPreviousCharacterABackSlash = FALSE; - break; // it's an escaped \" double-quote - } - - if (g_IsInterpreterOnString) - g_IsInterpreterOnString = FALSE; - else - g_IsInterpreterOnString = TRUE; - - break; - - case '{': - - if (g_IsInterpreterPreviousCharacterABackSlash) - g_IsInterpreterPreviousCharacterABackSlash = FALSE; - - if (!g_IsInterpreterOnString) - g_InterpreterCountOfOpenCurlyBrackets++; - - break; - - case '}': - - if (g_IsInterpreterPreviousCharacterABackSlash) - g_IsInterpreterPreviousCharacterABackSlash = FALSE; - - if (!g_IsInterpreterOnString && g_InterpreterCountOfOpenCurlyBrackets > 0) - g_InterpreterCountOfOpenCurlyBrackets--; - - break; - - case '\\': - - if (g_IsInterpreterPreviousCharacterABackSlash) - g_IsInterpreterPreviousCharacterABackSlash = FALSE; // it's not a escape character (two backslashes \\ ) - else - g_IsInterpreterPreviousCharacterABackSlash = TRUE; - - break; - - default: - - if (g_IsInterpreterPreviousCharacterABackSlash) - g_IsInterpreterPreviousCharacterABackSlash = FALSE; - - break; - } - } - - if (g_IsInterpreterOnString == FALSE && g_InterpreterCountOfOpenCurlyBrackets == 0) - { - // - // either the command is finished or it's a single - // line command - // - return false; - } - else - { - // - // There still other lines, this command is incomplete - // - return true; - } -} - -/** - * @brief Some of commands like stepping commands (i, p, t) and etc. - * need to be repeated when the user press enter, this function shows - * whether we should continue the previous command or not - * - * @return true means the command should be continued, false means command - * should be ignored - */ -bool -HyperDbgContinuePreviousCommand() -{ - BOOLEAN Result = g_ShouldPreviousCommandBeContinued; - - // - // We should keep it false for the next command - // - g_ShouldPreviousCommandBeContinued = FALSE; - - if (Result) - { - return true; - } - else - { - return false; - } -} - -/** - * @brief Get Command Attributes - * - * @param FirstCommand just the first word of command (without other parameters) - * @return BOOLEAN Mask of the command's attributes - */ -UINT64 -GetCommandAttributes(const string & FirstCommand) -{ - CommandType::iterator Iterator; - - // - // Some commands should not be passed to the remote system - // and instead should be handled in the current debugger - // - - Iterator = g_CommandsList.find(FirstCommand); - - if (Iterator == g_CommandsList.end()) - { - // - // Command doesn't exist, if it's not exists then it's better to handle - // it locally, instead of sending it to the remote computer - // - return DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL; - } - else - { - return Iterator->second.CommandAttrib; - } - - return NULL; -} - -/** - * @brief Initialize the debugger and adjust commands for the first run - * - * @return VOID - */ -VOID -InitializeDebugger() -{ - // - // Initialize the mapping of functions - // - InitializeCommandsDictionary(); - - // - // Set the callback for symbol message handler - // - ScriptEngineSetTextMessageCallbackWrapper(ShowMessages); - - // - // Register the CTRL+C and CTRL+BREAK Signals handler - // - if (!SetConsoleCtrlHandler(BreakController, TRUE)) - { - ShowMessages("err, when registering CTRL+C and CTRL+BREAK Signals " - "handler\n"); - // - // prefer to continue - // - } - - // - // *** Check for feature indicators *** - // - - // - // Get x86 processor width for virtual address - // - g_VirtualAddressWidth = Getx86VirtualAddressWidth(); - - // - // Check if processor supports TSX (RTM) - // - g_RtmSupport = CheckCpuSupportRtm(); - - // - // Load default settings - // - CommandSettingsLoadDefaultValuesFromConfigFile(); -} - -/** - * @brief Initialize commands and attributes - * - * @return VOID - */ -VOID -InitializeCommandsDictionary() -{ - g_CommandsList[".help"] = {NULL, &CommandHelpHelp, DEBUGGER_COMMAND_HELP_ATTRIBUTES}; - g_CommandsList[".hh"] = {NULL, &CommandHelpHelp, DEBUGGER_COMMAND_HELP_ATTRIBUTES}; - g_CommandsList["help"] = {NULL, &CommandHelpHelp, DEBUGGER_COMMAND_HELP_ATTRIBUTES}; - - g_CommandsList["clear"] = {&CommandClearScreen, &CommandClearScreenHelp, DEBUGGER_COMMAND_CLEAR_ATTRIBUTES}; - g_CommandsList[".cls"] = {&CommandClearScreen, &CommandClearScreenHelp, DEBUGGER_COMMAND_CLEAR_ATTRIBUTES}; - g_CommandsList["cls"] = {&CommandClearScreen, &CommandClearScreenHelp, DEBUGGER_COMMAND_CLEAR_ATTRIBUTES}; - - g_CommandsList[".connect"] = {&CommandConnect, &CommandConnectHelp, DEBUGGER_COMMAND_CONNECT_ATTRIBUTES}; - g_CommandsList["connect"] = {&CommandConnect, &CommandConnectHelp, DEBUGGER_COMMAND_CONNECT_ATTRIBUTES}; - - g_CommandsList[".listen"] = {&CommandListen, &CommandListenHelp, DEBUGGER_COMMAND_LISTEN_ATTRIBUTES}; - g_CommandsList["listen"] = {&CommandListen, &CommandListenHelp, DEBUGGER_COMMAND_LISTEN_ATTRIBUTES}; - - g_CommandsList["g"] = {&CommandG, &CommandGHelp, DEBUGGER_COMMAND_G_ATTRIBUTES}; - g_CommandsList["go"] = {&CommandG, &CommandGHelp, DEBUGGER_COMMAND_G_ATTRIBUTES}; - - g_CommandsList[".attach"] = {&CommandAttach, &CommandAttachHelp, DEBUGGER_COMMAND_ATTACH_ATTRIBUTES}; - g_CommandsList["attach"] = {&CommandAttach, &CommandAttachHelp, DEBUGGER_COMMAND_ATTACH_ATTRIBUTES}; - - g_CommandsList[".detach"] = {&CommandDetach, &CommandDetachHelp, DEBUGGER_COMMAND_DETACH_ATTRIBUTES}; - g_CommandsList["detach"] = {&CommandDetach, &CommandDetachHelp, DEBUGGER_COMMAND_DETACH_ATTRIBUTES}; - - g_CommandsList[".start"] = {&CommandStart, &CommandStartHelp, DEBUGGER_COMMAND_START_ATTRIBUTES}; - g_CommandsList["start"] = {&CommandStart, &CommandStartHelp, DEBUGGER_COMMAND_START_ATTRIBUTES}; - - g_CommandsList[".restart"] = {&CommandRestart, &CommandRestartHelp, DEBUGGER_COMMAND_RESTART_ATTRIBUTES}; - g_CommandsList["restart"] = {&CommandRestart, &CommandRestartHelp, DEBUGGER_COMMAND_RESTART_ATTRIBUTES}; - - g_CommandsList[".switch"] = {&CommandSwitch, &CommandSwitchHelp, DEBUGGER_COMMAND_SWITCH_ATTRIBUTES}; - g_CommandsList["switch"] = {&CommandSwitch, &CommandSwitchHelp, DEBUGGER_COMMAND_SWITCH_ATTRIBUTES}; - - g_CommandsList[".kill"] = {&CommandKill, &CommandKillHelp, DEBUGGER_COMMAND_KILL_ATTRIBUTES}; - g_CommandsList["kill"] = {&CommandKill, &CommandKillHelp, DEBUGGER_COMMAND_KILL_ATTRIBUTES}; - - g_CommandsList[".process"] = {&CommandProcess, &CommandProcessHelp, DEBUGGER_COMMAND_PROCESS_ATTRIBUTES}; - g_CommandsList[".process2"] = {&CommandProcess, &CommandProcessHelp, DEBUGGER_COMMAND_PROCESS_ATTRIBUTES}; - g_CommandsList["process"] = {&CommandProcess, &CommandProcessHelp, DEBUGGER_COMMAND_PROCESS_ATTRIBUTES}; - g_CommandsList["process2"] = {&CommandProcess, &CommandProcessHelp, DEBUGGER_COMMAND_PROCESS_ATTRIBUTES}; - - g_CommandsList[".thread"] = {&CommandThread, &CommandThreadHelp, DEBUGGER_COMMAND_THREAD_ATTRIBUTES}; - g_CommandsList[".thread2"] = {&CommandThread, &CommandThreadHelp, DEBUGGER_COMMAND_THREAD_ATTRIBUTES}; - g_CommandsList["thread"] = {&CommandThread, &CommandThreadHelp, DEBUGGER_COMMAND_THREAD_ATTRIBUTES}; - g_CommandsList["thread2"] = {&CommandThread, &CommandThreadHelp, DEBUGGER_COMMAND_THREAD_ATTRIBUTES}; - - g_CommandsList["sleep"] = {&CommandSleep, &CommandSleepHelp, DEBUGGER_COMMAND_SLEEP_ATTRIBUTES}; - - g_CommandsList["event"] = {&CommandEvents, &CommandEventsHelp, DEBUGGER_COMMAND_EVENTS_ATTRIBUTES}; - g_CommandsList["events"] = {&CommandEvents, &CommandEventsHelp, DEBUGGER_COMMAND_EVENTS_ATTRIBUTES}; - - g_CommandsList["setting"] = {&CommandSettings, &CommandSettingsHelp, DEBUGGER_COMMAND_SETTINGS_ATTRIBUTES}; - g_CommandsList["settings"] = {&CommandSettings, &CommandSettingsHelp, DEBUGGER_COMMAND_SETTINGS_ATTRIBUTES}; - g_CommandsList[".setting"] = {&CommandSettings, &CommandSettingsHelp, DEBUGGER_COMMAND_SETTINGS_ATTRIBUTES}; - g_CommandsList[".settings"] = {&CommandSettings, &CommandSettingsHelp, DEBUGGER_COMMAND_SETTINGS_ATTRIBUTES}; - - g_CommandsList[".disconnect"] = {&CommandDisconnect, &CommandDisconnectHelp, DEBUGGER_COMMAND_DISCONNECT_ATTRIBUTES}; - g_CommandsList["disconnect"] = {&CommandDisconnect, &CommandDisconnectHelp, DEBUGGER_COMMAND_DISCONNECT_ATTRIBUTES}; - - g_CommandsList[".debug"] = {&CommandDebug, &CommandDebugHelp, DEBUGGER_COMMAND_DEBUG_ATTRIBUTES}; - g_CommandsList["debug"] = {&CommandDebug, &CommandDebugHelp, DEBUGGER_COMMAND_DEBUG_ATTRIBUTES}; - - g_CommandsList[".status"] = {&CommandStatus, &CommandStatusHelp, DEBUGGER_COMMAND_DOT_STATUS_ATTRIBUTES}; - g_CommandsList["status"] = {&CommandStatus, &CommandStatusHelp, DEBUGGER_COMMAND_STATUS_ATTRIBUTES}; - - g_CommandsList["load"] = {&CommandLoad, &CommandLoadHelp, DEBUGGER_COMMAND_LOAD_ATTRIBUTES}; - - g_CommandsList["exit"] = {&CommandExit, &CommandExitHelp, DEBUGGER_COMMAND_EXIT_ATTRIBUTES}; - g_CommandsList[".exit"] = {&CommandExit, &CommandExitHelp, DEBUGGER_COMMAND_EXIT_ATTRIBUTES}; - - g_CommandsList["flush"] = {&CommandFlush, &CommandFlushHelp, DEBUGGER_COMMAND_FLUSH_ATTRIBUTES}; - - g_CommandsList["pause"] = {&CommandPause, &CommandPauseHelp, DEBUGGER_COMMAND_PAUSE_ATTRIBUTES}; - - g_CommandsList["unload"] = {&CommandUnload, &CommandUnloadHelp, DEBUGGER_COMMAND_UNLOAD_ATTRIBUTES}; - - g_CommandsList[".script"] = {&CommandScript, &CommandScriptHelp, DEBUGGER_COMMAND_SCRIPT_ATTRIBUTES}; - g_CommandsList["script"] = {&CommandScript, &CommandScriptHelp, DEBUGGER_COMMAND_SCRIPT_ATTRIBUTES}; - - g_CommandsList["output"] = {&CommandOutput, &CommandOutputHelp, DEBUGGER_COMMAND_OUTPUT_ATTRIBUTES}; - - g_CommandsList["print"] = {&CommandPrint, &CommandPrintHelp, DEBUGGER_COMMAND_PRINT_ATTRIBUTES}; - - g_CommandsList["?"] = {&CommandEval, &CommandEvalHelp, DEBUGGER_COMMAND_EVAL_ATTRIBUTES}; - g_CommandsList["eval"] = {&CommandEval, &CommandEvalHelp, DEBUGGER_COMMAND_EVAL_ATTRIBUTES}; - g_CommandsList["evaluate"] = {&CommandEval, &CommandEvalHelp, DEBUGGER_COMMAND_EVAL_ATTRIBUTES}; - - g_CommandsList[".logopen"] = {&CommandLogopen, &CommandLogopenHelp, DEBUGGER_COMMAND_LOGOPEN_ATTRIBUTES}; - - g_CommandsList[".logclose"] = {&CommandLogclose, &CommandLogcloseHelp, DEBUGGER_COMMAND_LOGCLOSE_ATTRIBUTES}; - - g_CommandsList[".pagein"] = {&CommandPagein, &CommandPageinHelp, DEBUGGER_COMMAND_PAGEIN_ATTRIBUTES}; - g_CommandsList["pagein"] = {&CommandPagein, &CommandPageinHelp, DEBUGGER_COMMAND_PAGEIN_ATTRIBUTES}; - - g_CommandsList["test"] = {&CommandTest, &CommandTestHelp, DEBUGGER_COMMAND_TEST_ATTRIBUTES}; - - g_CommandsList["cpu"] = {&CommandCpu, &CommandCpuHelp, DEBUGGER_COMMAND_CPU_ATTRIBUTES}; - - g_CommandsList["wrmsr"] = {&CommandWrmsr, &CommandWrmsrHelp, DEBUGGER_COMMAND_WRMSR_ATTRIBUTES}; - - g_CommandsList["rdmsr"] = {&CommandRdmsr, &CommandRdmsrHelp, DEBUGGER_COMMAND_RDMSR_ATTRIBUTES}; - - g_CommandsList["!va2pa"] = {&CommandVa2pa, &CommandVa2paHelp, DEBUGGER_COMMAND_VA2PA_ATTRIBUTES}; - - g_CommandsList["!pa2va"] = {&CommandPa2va, &CommandPa2vaHelp, DEBUGGER_COMMAND_PA2VA_ATTRIBUTES}; - - g_CommandsList[".formats"] = {&CommandFormats, &CommandFormatsHelp, DEBUGGER_COMMAND_FORMATS_ATTRIBUTES}; - g_CommandsList[".format"] = {&CommandFormats, &CommandFormatsHelp, DEBUGGER_COMMAND_FORMATS_ATTRIBUTES}; - - g_CommandsList["!pte"] = {&CommandPte, &CommandPteHelp, DEBUGGER_COMMAND_PTE_ATTRIBUTES}; - - g_CommandsList["~"] = {&CommandCore, &CommandCoreHelp, DEBUGGER_COMMAND_CORE_ATTRIBUTES}; - g_CommandsList["core"] = {&CommandCore, &CommandCoreHelp, DEBUGGER_COMMAND_CORE_ATTRIBUTES}; - - g_CommandsList["!monitor"] = {&CommandMonitor, &CommandMonitorHelp, DEBUGGER_COMMAND_MONITOR_ATTRIBUTES}; - - g_CommandsList["!vmcall"] = {&CommandVmcall, &CommandVmcallHelp, DEBUGGER_COMMAND_VMCALL_ATTRIBUTES}; - - g_CommandsList["!epthook"] = {&CommandEptHook, &CommandEptHookHelp, DEBUGGER_COMMAND_EPTHOOK_ATTRIBUTES}; - g_CommandsList["bh"] = {&CommandEptHook, &CommandEptHookHelp, DEBUGGER_COMMAND_EPTHOOK_ATTRIBUTES}; - - g_CommandsList["bp"] = {&CommandBp, &CommandBpHelp, DEBUGGER_COMMAND_BP_ATTRIBUTES}; - - g_CommandsList["bl"] = {&CommandBl, &CommandBlHelp, DEBUGGER_COMMAND_BD_ATTRIBUTES}; - - g_CommandsList["be"] = {&CommandBe, &CommandBeHelp, DEBUGGER_COMMAND_BD_ATTRIBUTES}; - - g_CommandsList["bd"] = {&CommandBd, &CommandBdHelp, DEBUGGER_COMMAND_BD_ATTRIBUTES}; - - g_CommandsList["bc"] = {&CommandBc, &CommandBcHelp, DEBUGGER_COMMAND_BD_ATTRIBUTES}; - - g_CommandsList["!epthook2"] = {&CommandEptHook2, &CommandEptHook2Help, DEBUGGER_COMMAND_EPTHOOK2_ATTRIBUTES}; - - g_CommandsList["!cpuid"] = {&CommandCpuid, &CommandCpuidHelp, DEBUGGER_COMMAND_CPUID_ATTRIBUTES}; - - g_CommandsList["!msrread"] = {&CommandMsrread, &CommandMsrreadHelp, DEBUGGER_COMMAND_MSRREAD_ATTRIBUTES}; - g_CommandsList["!msread"] = {&CommandMsrread, &CommandMsrreadHelp, DEBUGGER_COMMAND_MSRREAD_ATTRIBUTES}; - - g_CommandsList["!msrwrite"] = {&CommandMsrwrite, &CommandMsrwriteHelp, DEBUGGER_COMMAND_MSRWRITE_ATTRIBUTES}; - - g_CommandsList["!tsc"] = {&CommandTsc, &CommandTscHelp, DEBUGGER_COMMAND_TSC_ATTRIBUTES}; - - g_CommandsList["!pmc"] = {&CommandPmc, &CommandPmcHelp, DEBUGGER_COMMAND_PMC_ATTRIBUTES}; - - g_CommandsList["!crwrite"] = {&CommandCrwrite, &CommandCrwriteHelp, DEBUGGER_COMMAND_CRWRITE_ATTRIBUTES}; - - g_CommandsList["!dr"] = {&CommandDr, &CommandDrHelp, DEBUGGER_COMMAND_DR_ATTRIBUTES}; - - g_CommandsList["!ioin"] = {&CommandIoin, &CommandIoinHelp, DEBUGGER_COMMAND_IOIN_ATTRIBUTES}; - - g_CommandsList["!ioout"] = {&CommandIoout, &CommandIooutHelp, DEBUGGER_COMMAND_IOOUT_ATTRIBUTES}; - - g_CommandsList["!exception"] = {&CommandException, &CommandExceptionHelp, DEBUGGER_COMMAND_EXCEPTION_ATTRIBUTES}; - - g_CommandsList["!interrupt"] = {&CommandInterrupt, &CommandInterruptHelp, DEBUGGER_COMMAND_INTERRUPT_ATTRIBUTES}; - - g_CommandsList["!syscall"] = {&CommandSyscallAndSysret, &CommandSyscallHelp, DEBUGGER_COMMAND_SYSCALL_ATTRIBUTES}; - g_CommandsList["!syscall2"] = {&CommandSyscallAndSysret, &CommandSyscallHelp, DEBUGGER_COMMAND_SYSCALL_ATTRIBUTES}; - - g_CommandsList["!sysret"] = {&CommandSyscallAndSysret, &CommandSysretHelp, DEBUGGER_COMMAND_SYSRET_ATTRIBUTES}; - g_CommandsList["!sysret2"] = {&CommandSyscallAndSysret, &CommandSysretHelp, DEBUGGER_COMMAND_SYSRET_ATTRIBUTES}; - - g_CommandsList["!mode"] = {&CommandMode, &CommandModeHelp, DEBUGGER_COMMAND_MODE_ATTRIBUTES}; - - g_CommandsList["!trace"] = {&CommandTrace, &CommandTraceHelp, DEBUGGER_COMMAND_TRACE_ATTRIBUTES}; - - g_CommandsList["!hide"] = {&CommandHide, &CommandHideHelp, DEBUGGER_COMMAND_HIDE_ATTRIBUTES}; - - g_CommandsList["!unhide"] = {&CommandUnhide, &CommandUnhideHelp, DEBUGGER_COMMAND_UNHIDE_ATTRIBUTES}; - - g_CommandsList["!measure"] = {&CommandMeasure, &CommandMeasureHelp, DEBUGGER_COMMAND_MEASURE_ATTRIBUTES}; - - g_CommandsList["lm"] = {&CommandLm, &CommandLmHelp, DEBUGGER_COMMAND_LM_ATTRIBUTES}; - - g_CommandsList["p"] = {&CommandP, &CommandPHelp, DEBUGGER_COMMAND_P_ATTRIBUTES}; - g_CommandsList["pr"] = {&CommandP, &CommandPHelp, DEBUGGER_COMMAND_P_ATTRIBUTES}; - - g_CommandsList["t"] = {&CommandT, &CommandTHelp, DEBUGGER_COMMAND_T_ATTRIBUTES}; - g_CommandsList["tr"] = {&CommandT, &CommandTHelp, DEBUGGER_COMMAND_T_ATTRIBUTES}; - - g_CommandsList["i"] = {&CommandI, &CommandIHelp, DEBUGGER_COMMAND_I_ATTRIBUTES}; - g_CommandsList["ir"] = {&CommandI, &CommandIHelp, DEBUGGER_COMMAND_I_ATTRIBUTES}; - - g_CommandsList["gu"] = {&CommandGu, &CommandGuHelp, DEBUGGER_COMMAND_GU_ATTRIBUTES}; - - g_CommandsList["db"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["dc"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["dd"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["dq"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["!db"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["!dc"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["!dd"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["!dq"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["!u"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["u"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["!u64"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["u64"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["!u2"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["u2"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["!u32"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - g_CommandsList["u32"] = {&CommandReadMemoryAndDisassembler, - &CommandReadMemoryAndDisassemblerHelp, - DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; - - g_CommandsList["eb"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; - g_CommandsList["ed"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; - g_CommandsList["eq"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; - g_CommandsList["!eb"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; - g_CommandsList["!ed"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; - g_CommandsList["!eq"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; - - g_CommandsList["sb"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; - g_CommandsList["sd"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; - g_CommandsList["sq"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; - g_CommandsList["!sb"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; - g_CommandsList["!sd"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; - g_CommandsList["!sq"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; - - g_CommandsList["r"] = {&CommandR, &CommandRHelp, DEBUGGER_COMMAND_R_ATTRIBUTES}; - - g_CommandsList[".sympath"] = {&CommandSympath, &CommandSympathHelp, DEBUGGER_COMMAND_SYMPATH_ATTRIBUTES}; - g_CommandsList["sympath"] = {&CommandSympath, &CommandSympathHelp, DEBUGGER_COMMAND_SYMPATH_ATTRIBUTES}; - - g_CommandsList[".sym"] = {&CommandSym, &CommandSymHelp, DEBUGGER_COMMAND_SYM_ATTRIBUTES}; - g_CommandsList["sym"] = {&CommandSym, &CommandSymHelp, DEBUGGER_COMMAND_SYM_ATTRIBUTES}; - - g_CommandsList["x"] = {&CommandX, &CommandXHelp, DEBUGGER_COMMAND_X_ATTRIBUTES}; - - g_CommandsList["prealloc"] = {&CommandPrealloc, &CommandPreallocHelp, DEBUGGER_COMMAND_PREALLOC_ATTRIBUTES}; - g_CommandsList["preallocate"] = {&CommandPrealloc, &CommandPreallocHelp, DEBUGGER_COMMAND_PREALLOC_ATTRIBUTES}; - g_CommandsList["preallocation"] = {&CommandPrealloc, &CommandPreallocHelp, DEBUGGER_COMMAND_PREALLOC_ATTRIBUTES}; - - g_CommandsList["preactivate"] = {&CommandPreactivate, &CommandPreactivateHelp, DEBUGGER_COMMAND_PREACTIVATE_ATTRIBUTES}; - g_CommandsList["preactive"] = {&CommandPreactivate, &CommandPreactivateHelp, DEBUGGER_COMMAND_PREACTIVATE_ATTRIBUTES}; - g_CommandsList["preactivation"] = {&CommandPreactivate, &CommandPreactivateHelp, DEBUGGER_COMMAND_PREACTIVATE_ATTRIBUTES}; - - g_CommandsList["k"] = {&CommandK, &CommandKHelp, DEBUGGER_COMMAND_K_ATTRIBUTES}; - g_CommandsList["kd"] = {&CommandK, &CommandKHelp, DEBUGGER_COMMAND_K_ATTRIBUTES}; - g_CommandsList["kq"] = {&CommandK, &CommandKHelp, DEBUGGER_COMMAND_K_ATTRIBUTES}; - - g_CommandsList["dt"] = {&CommandDtAndStruct, &CommandDtHelp, DEBUGGER_COMMAND_DT_ATTRIBUTES}; - g_CommandsList["!dt"] = {&CommandDtAndStruct, &CommandDtHelp, DEBUGGER_COMMAND_DT_ATTRIBUTES}; - - g_CommandsList["struct"] = {&CommandDtAndStruct, &CommandStructHelp, DEBUGGER_COMMAND_STRUCT_ATTRIBUTES}; - g_CommandsList["structure"] = {&CommandDtAndStruct, &CommandStructHelp, DEBUGGER_COMMAND_STRUCT_ATTRIBUTES}; - - g_CommandsList[".pe"] = {&CommandPe, &CommandPeHelp, DEBUGGER_COMMAND_PE_ATTRIBUTES}; - - g_CommandsList["!rev"] = {&CommandRev, &CommandRevHelp, DEBUGGER_COMMAND_REV_ATTRIBUTES}; - g_CommandsList["rev"] = {&CommandRev, &CommandRevHelp, DEBUGGER_COMMAND_REV_ATTRIBUTES}; - - g_CommandsList["!track"] = {&CommandTrack, &CommandTrackHelp, DEBUGGER_COMMAND_TRACK_ATTRIBUTES}; - g_CommandsList["track"] = {&CommandTrack, &CommandTrackHelp, DEBUGGER_COMMAND_TRACK_ATTRIBUTES}; - - g_CommandsList[".dump"] = {&CommandDump, &CommandDumpHelp, DEBUGGER_COMMAND_DUMP_ATTRIBUTES}; - g_CommandsList["dump"] = {&CommandDump, &CommandDumpHelp, DEBUGGER_COMMAND_DUMP_ATTRIBUTES}; - g_CommandsList["!dump"] = {&CommandDump, &CommandDumpHelp, DEBUGGER_COMMAND_DUMP_ATTRIBUTES}; -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/script-engine/script-engine.cpp b/hyperdbg/hprdbgctrl/code/debugger/script-engine/script-engine.cpp deleted file mode 100644 index e0abeb21..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/script-engine/script-engine.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @file script-engine.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Interpret script engine affairs - * @details - * @version 0.1 - * @date 2021-09-23 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -// -// Global Variables -// -extern UINT64 g_ResultOfEvaluatedExpression; -extern UINT32 g_ErrorStateOfResultOfEvaluatedExpression; -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; - -/** - * @brief Get the value from the evaluation of single expression - * from local debuggee and remote debuggee - * - * @param Expr - * @param HasError - * @return UINT64 - */ -UINT64 -ScriptEngineEvalSingleExpression(string Expr, PBOOLEAN HasError) -{ - PVOID CodeBuffer; - UINT64 BufferAddress; - UINT32 BufferLength; - UINT32 Pointer; - UINT64 Result = NULL; - - // - // Prepend and append 'formats(' and ')' - // - Expr.insert(0, "formats("); - Expr.append(");"); - - // - // Run script engine handler - // - CodeBuffer = ScriptEngineParseWrapper((char *)Expr.c_str(), FALSE); - - if (CodeBuffer == NULL) - { - // - // return to show that this item contains an script - // - *HasError = TRUE; - return NULL; - } - - // - // Print symbols (test) - // - // PrintSymbolBufferWrapper(CodeBuffer); - - // - // Set the buffer and length - // - BufferAddress = ScriptEngineWrapperGetHead(CodeBuffer); - BufferLength = ScriptEngineWrapperGetSize(CodeBuffer); - Pointer = ScriptEngineWrapperGetPointer(CodeBuffer); - - // - // Check if it's connected over remote debuggee (in the Debugger Mode) - // - if (g_IsSerialConnectedToRemoteDebuggee) - { - // - // Send over serial - // - - // - // Send it to the remote debuggee - // - KdSendScriptPacketToDebuggee(BufferAddress, BufferLength, Pointer, TRUE); - - // - // Check whether there was an error in evaluation or not - // - if (g_ErrorStateOfResultOfEvaluatedExpression == DEBUGGER_OPERATION_WAS_SUCCESSFUL) - { - // - // Everything was fine, return the result of the evaluated - // expression and null the global holders - // - Result = g_ResultOfEvaluatedExpression; - g_ErrorStateOfResultOfEvaluatedExpression = NULL; - g_ResultOfEvaluatedExpression = NULL; - *HasError = FALSE; - } - else - { - // - // There was an error evaluating the expression from the kernel (debuggee) - // - g_ErrorStateOfResultOfEvaluatedExpression = NULL; - g_ResultOfEvaluatedExpression = NULL; - - *HasError = TRUE; - Result = NULL; - } - } - else - { - // - // It's in vmi-mode, - // execute it locally with regs set to ZERO - // - Result = ScriptEngineEvalUInt64StyleExpressionWrapper(Expr, HasError); - } - - // - // Remove the buffer of script engine interpreted code - // - ScriptEngineWrapperRemoveSymbolBuffer(CodeBuffer); - - return Result; -} diff --git a/hyperdbg/hprdbgctrl/code/debugger/user-level/pe-parser.cpp b/hyperdbg/hprdbgctrl/code/debugger/user-level/pe-parser.cpp deleted file mode 100644 index 26725647..00000000 --- a/hyperdbg/hprdbgctrl/code/debugger/user-level/pe-parser.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/** - * @file pe-parser.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Portable Executable parser - * @details - * @version 0.1 - * @date 2021-12-26 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Show hex dump of sections of PE - * @param Ptr - * @param Size - * @param SecAddress - * - * @return VOID - */ -VOID -PeHexDump(CHAR * Ptr, int Size, int SecAddress) -{ - int i = 1, Temp = 0; - - // - // Buffer to store the character dump displayed at the - // right side - // - wchar_t Buf[18]; - ShowMessages("\n\n%x: |", SecAddress); - - Buf[Temp] = ' '; // initial space - Buf[Temp + 16] = ' '; // final space - Buf[Temp + 17] = 0; // End of Buf - Temp++; // Temp = 1; - - for (; i <= Size; i++, Ptr++, Temp++) - { - Buf[Temp] = !iswcntrl((*Ptr) & 0xff) ? (*Ptr) & 0xff : '.'; - ShowMessages("%-3.2x", (*Ptr) & 0xff); - - if (i % 16 == 0) - { - // - // print the character dump to the right - // - _putws(Buf); - if (i + 1 <= Size) - ShowMessages("%x: ", SecAddress += 16); - Temp = 0; - } - if (i % 4 == 0) - ShowMessages("| "); - } - if (i % 16 != 0) - { - Buf[Temp] = 0; - for (; i % 16 != 0; i++) - ShowMessages("%-3.2c", ' '); - _putws(Buf); - } -} - -/** - * @brief Show information about different sections of PE and the dump of sections - * @param AddressOfFile - * @param SectionToShow - * @param Is32Bit - * - * @return BOOLEAN - */ -BOOLEAN -PeShowSectionInformationAndDump(const WCHAR * AddressOfFile, const CHAR * SectionToShow, BOOLEAN Is32Bit) -{ - BOOLEAN Result = FALSE; - HANDLE MapObjectHandle, FileHandle; // File Mapping Object - UINT32 NumberOfSections; // Number of sections - LPVOID BaseAddr; // Pointer to the base memory of mapped file - PIMAGE_DOS_HEADER DosHeader; // Pointer to DOS Header - PIMAGE_NT_HEADERS32 NtHeader32 = NULL; // Pointer to NT Header 32 bit - PIMAGE_NT_HEADERS64 NtHeader64 = NULL; // Pointer to NT Header 64 bit - IMAGE_FILE_HEADER Header; // Pointer to image file header of NT Header - IMAGE_OPTIONAL_HEADER32 OpHeader32; // Optional Header of PE files present in NT Header structure - IMAGE_OPTIONAL_HEADER64 OpHeader64; // Optional Header of PE files present in NT Header structure - PIMAGE_SECTION_HEADER SecHeader; // Section Header or Section Table Header - - // - // Open the EXE File - // - FileHandle = CreateFileW(AddressOfFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (FileHandle == INVALID_HANDLE_VALUE) - { - ShowMessages("err, could not open the file specified\n"); - return FALSE; - }; - - // - // Mapping Given EXE file to Memory - // - MapObjectHandle = - CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL); - - if (MapObjectHandle == NULL) - { - CloseHandle(FileHandle); - return FALSE; - } - - BaseAddr = MapViewOfFile(MapObjectHandle, FILE_MAP_READ, 0, 0, 0); - - if (BaseAddr == NULL) - { - CloseHandle(FileHandle); - return FALSE; - } - - // - // Get the DOS Header Base - // - DosHeader = (PIMAGE_DOS_HEADER)BaseAddr; // 0x04000000 - - // - // Check for Valid DOS file - // - if (DosHeader->e_magic == IMAGE_DOS_SIGNATURE) - { - // - // Dump the Dos Header info - // - ShowMessages("\nValid Dos Exe File\n------------------\n"); - ShowMessages("\nDumping DOS Header Info....\n---------------------------"); - ShowMessages("\n%-36s%s ", - "Magic number : ", - DosHeader->e_magic == 0x5a4d ? "MZ" : "-"); - ShowMessages("\n%-36s%#x", "Bytes on last page of file :", DosHeader->e_cblp); - ShowMessages("\n%-36s%#x", "Pages in file : ", DosHeader->e_cp); - ShowMessages("\n%-36s%#x", "Relocation : ", DosHeader->e_crlc); - ShowMessages("\n%-36s%#x", - "Size of header in paragraphs : ", - DosHeader->e_cparhdr); - ShowMessages("\n%-36s%#x", - "Minimum extra paragraphs needed : ", - DosHeader->e_minalloc); - ShowMessages("\n%-36s%#x", - "Maximum extra paragraphs needed : ", - DosHeader->e_maxalloc); - ShowMessages("\n%-36s%#x", "Initial (relative) SS value : ", DosHeader->e_ss); - ShowMessages("\n%-36s%#x", "Initial SP value : ", DosHeader->e_sp); - ShowMessages("\n%-36s%#x", "Checksum : ", DosHeader->e_csum); - ShowMessages("\n%-36s%#x", "Initial IP value : ", DosHeader->e_ip); - ShowMessages("\n%-36s%#x", "Initial (relative) CS value : ", DosHeader->e_cs); - ShowMessages("\n%-36s%#x", - "File address of relocation table : ", - DosHeader->e_lfarlc); - ShowMessages("\n%-36s%#x", "Overlay number : ", DosHeader->e_ovno); - ShowMessages("\n%-36s%#x", "OEM identifier : ", DosHeader->e_oemid); - ShowMessages("\n%-36s%#x", - "OEM information(e_oemid specific) :", - DosHeader->e_oeminfo); - ShowMessages("\n%-36s%#x", "RVA address of PE header : ", DosHeader->e_lfanew); - ShowMessages("\n===============================================================" - "================\n"); - } - else - { - ShowMessages("\nGiven File is not a valid DOS file\n"); - Result = FALSE; - goto Finished; - } - - // - // Offset of NT Header is found at 0x3c location in DOS header specified by - // e_lfanew - // Get the Base of NT Header(PE Header) = DosHeader + RVA address of PE - // header - // - if (Is32Bit) - { - NtHeader32 = (PIMAGE_NT_HEADERS32)((UINT64)(DosHeader) + (DosHeader->e_lfanew)); - } - else - { - NtHeader64 = (PIMAGE_NT_HEADERS64)((UINT64)(DosHeader) + (DosHeader->e_lfanew)); - } - - // - // Identify for valid PE file - // - if (Is32Bit && NtHeader32->Signature == IMAGE_NT_SIGNATURE) - { - ShowMessages("\nValid PE32 file \n-------------\n"); - } - else if (!Is32Bit && NtHeader64->Signature == IMAGE_NT_SIGNATURE) - { - ShowMessages("\nValid PE64 file \n-------------\n"); - } - else - { - ShowMessages("err, the specified file is not a valid PE file"); - Result = FALSE; - goto Finished; - } - - // - // Dump NT Header Info.... - // - ShowMessages("\nDumping COFF/PE Header " - "Info....\n--------------------------------"); - ShowMessages("\n%-36s%s", "Signature :", "PE"); - - // - // Get the IMAGE FILE HEADER Structure - // - if (Is32Bit) - { - Header = NtHeader32->FileHeader; - } - else - { - Header = NtHeader64->FileHeader; - } - - // - // Determine Machine Architecture - // - ShowMessages("\n%-36s", "Machine Architecture :"); - - // - // Only few are determined (for remaining refer - // to the above specification) - // - switch (Header.Machine) - { - case 0x0: - ShowMessages("All "); - break; - case 0x14d: - ShowMessages("Intel i860"); - break; - case 0x14c: - ShowMessages("Intel i386, i486, i586"); - break; - case 0x200: - ShowMessages("Intel Itanium processor"); - break; - case 0x8664: - ShowMessages("AMD x64"); - break; - case 0x162: - ShowMessages("MIPS R3000"); - break; - case 0x166: - ShowMessages("MIPS R4000"); - break; - case 0x183: - ShowMessages("DEC Alpha AXP"); - break; - default: - ShowMessages("Not Found"); - break; - } - - // - // Determine the characteristics of the given file - // - ShowMessages("\n%-36s", "Characteristics : "); - if ((Header.Characteristics & 0x0002) == 0x0002) - ShowMessages("Executable Image, "); - if ((Header.Characteristics & 0x0020) == 0x0020) - ShowMessages("Application can address > 2GB, "); - if ((Header.Characteristics & 0x1000) == 0x1000) - ShowMessages("System file (Kernel Mode Driver(I think)), "); - if ((Header.Characteristics & 0x2000) == 0x2000) - ShowMessages("Dll file, "); - if ((Header.Characteristics & 0x4000) == 0x4000) - ShowMessages("Application runs only in Uniprocessor, "); - - // - // Determine Time Stamp - // - ShowMessages("\n%-36s%s", - "Time Stamp :", - ctime((const time_t *)&(Header.TimeDateStamp))); - - // - // Determine number of sections - // - ShowMessages("%-36s%d", "No.sections(size) :", Header.NumberOfSections); - ShowMessages("\n%-36s%d", "No.entries in symbol table :", Header.NumberOfSymbols); - ShowMessages("\n%-36s%d", - "Size of optional header :", - Header.SizeOfOptionalHeader); - - ShowMessages("\n\nDumping PE Optional Header " - "Info....\n-----------------------------------"); - - if (Is32Bit) - { - // - // Info about Optional Header - // - OpHeader32 = NtHeader32->OptionalHeader; - ShowMessages("\n\nInfo of optional Header\n-----------------------"); - ShowMessages("\n%-36s%#x", - "Address of Entry Point : ", - OpHeader32.AddressOfEntryPoint); - ShowMessages("\n%-36s%#llx", "Base Address of the Image : ", OpHeader32.ImageBase); - ShowMessages("\n%-36s%s", "SubSystem type : ", OpHeader32.Subsystem == 1 ? "Device Driver(Native windows Process)" : OpHeader32.Subsystem == 2 ? "Windows GUI" - : OpHeader32.Subsystem == 3 ? "Windows CLI" - : OpHeader32.Subsystem == 3 ? "Windows CLI" - : OpHeader32.Subsystem == 9 ? "Windows CE GUI" - : "Unknown"); - ShowMessages("\n%-36s%s", "Given file is a : ", OpHeader32.Magic == 0x20b ? "PE32+(64)" : "PE32"); - ShowMessages("\n%-36s%d", "Size of code segment(.text) : ", OpHeader32.SizeOfCode); - ShowMessages("\n%-36s%#x", - "Base address of code segment(RVA) :", - OpHeader32.BaseOfCode); - ShowMessages("\n%-36s%d", - "Size of Initialized data : ", - OpHeader32.SizeOfInitializedData); - - ShowMessages("\n%-36s%#x", - "Base address of data segment(RVA) :", - OpHeader32.BaseOfData); - - ShowMessages("\n%-36s%#x", "Section Alignment :", OpHeader32.SectionAlignment); - ShowMessages("\n%-36s%d", "Major Linker Version : ", OpHeader32.MajorLinkerVersion); - ShowMessages("\n%-36s%d", "Minor Linker Version : ", OpHeader32.MinorLinkerVersion); - } - else - { - // - // Info about Optional Header - // - OpHeader64 = NtHeader64->OptionalHeader; - ShowMessages("\n\nInfo of optional Header\n-----------------------"); - ShowMessages("\n%-36s%#x", - "Address of Entry Point : ", - OpHeader64.AddressOfEntryPoint); - ShowMessages("\n%-36s%#llx", "Base Address of the Image : ", OpHeader64.ImageBase); - ShowMessages("\n%-36s%s", "SubSystem type : ", OpHeader64.Subsystem == 1 ? "Device Driver(Native windows Process)" : OpHeader64.Subsystem == 2 ? "Windows GUI" - : OpHeader64.Subsystem == 3 ? "Windows CLI" - : OpHeader64.Subsystem == 3 ? "Windows CLI" - : OpHeader64.Subsystem == 9 ? "Windows CE GUI" - : "Unknown"); - ShowMessages("\n%-36s%s", "Given file is a : ", OpHeader64.Magic == 0x20b ? "PE32+(64)" : "PE32"); - ShowMessages("\n%-36s%d", "Size of code segment(.text) : ", OpHeader64.SizeOfCode); - ShowMessages("\n%-36s%#x", - "Base address of code segment(RVA) :", - OpHeader64.BaseOfCode); - ShowMessages("\n%-36s%d", - "Size of Initialized data : ", - OpHeader64.SizeOfInitializedData); - - ShowMessages("\n%-36s%#x", "Section Alignment :", OpHeader64.SectionAlignment); - ShowMessages("\n%-36s%d", "Major Linker Version : ", OpHeader64.MajorLinkerVersion); - ShowMessages("\n%-36s%d", "Minor Linker Version : ", OpHeader64.MinorLinkerVersion); - } - - ShowMessages("\n\nDumping Sections Header " - "Info....\n--------------------------------"); - - // - // Retrieve a pointer to First Section Header(or Section Table Entry) - // - if (Is32Bit) - { - SecHeader = IMAGE_FIRST_SECTION(NtHeader32); - NumberOfSections = NtHeader32->FileHeader.NumberOfSections; - } - else - { - SecHeader = IMAGE_FIRST_SECTION(NtHeader64); - NumberOfSections = NtHeader64->FileHeader.NumberOfSections; - } - - for (UINT32 i = 0; i < NumberOfSections; i++, SecHeader++) - { - if (Is32Bit) - { - ShowMessages("\n\nSection Info (%d of %d)", i + 1, NtHeader32->FileHeader.NumberOfSections); - } - else - { - ShowMessages("\n\nSection Info (%d of %d)", i + 1, NtHeader64->FileHeader.NumberOfSections); - } - - ShowMessages("\n---------------------"); - ShowMessages("\n%-36s%s", "Section Header name : ", SecHeader->Name); - ShowMessages("\n%-36s%#x", - "ActualSize of code or data : ", - SecHeader->Misc.VirtualSize); - ShowMessages("\n%-36s%#x", "Virtual Address(RVA) :", SecHeader->VirtualAddress); - ShowMessages("\n%-36s%#x", - "Size of raw data (rounded to FA) : ", - SecHeader->SizeOfRawData); - ShowMessages("\n%-36s%#x", - "Pointer to Raw Data : ", - SecHeader->PointerToRawData); - ShowMessages("\n%-36s%#x", - "Pointer to Relocations : ", - SecHeader->PointerToRelocations); - ShowMessages("\n%-36s%#x", - "Pointer to Line numbers : ", - SecHeader->PointerToLinenumbers); - ShowMessages("\n%-36s%#x", - "Number of relocations : ", - SecHeader->NumberOfRelocations); - ShowMessages("\n%-36s%#x", - "Number of line numbers : ", - SecHeader->NumberOfLinenumbers); - ShowMessages("\n%-36s%s", "Characteristics : ", "Contains "); - if ((SecHeader->Characteristics & 0x20) == 0x20) - ShowMessages("executable code, "); - if ((SecHeader->Characteristics & 0x40) == 0x40) - ShowMessages("initialized data, "); - if ((SecHeader->Characteristics & 0x80) == 0x80) - ShowMessages("uninitialized data, "); - if ((SecHeader->Characteristics & 0x200) == 0x200) - ShowMessages("comments and linker commands, "); - if ((SecHeader->Characteristics & 0x10000000) == 0x10000000) - ShowMessages("shareable data(via DLLs), "); - if ((SecHeader->Characteristics & 0x40000000) == 0x40000000) - ShowMessages("Readable, "); - if ((SecHeader->Characteristics & 0x80000000) == 0x80000000) - ShowMessages("Writable, "); - - // - // show the hex dump if the user needs it - // - if (SectionToShow != NULL) - { - if (!_strcmpi(SectionToShow, (const char *)SecHeader->Name)) - { - if (SecHeader->SizeOfRawData != 0) - { - if (Is32Bit) - { - PeHexDump((char *)((UINT64)DosHeader + SecHeader->PointerToRawData), - SecHeader->SizeOfRawData, - OpHeader32.ImageBase + SecHeader->VirtualAddress); - } - else - { - PeHexDump((char *)((UINT64)DosHeader + SecHeader->PointerToRawData), - SecHeader->SizeOfRawData, - (int)(OpHeader64.ImageBase + SecHeader->VirtualAddress)); - } - } - } - } - } - - ShowMessages("\n===============================================================" - "================\n"); - - // - // Set result to true - // - Result = TRUE; - -Finished: - // - // Unmap and close the handles - // - UnmapViewOfFile(BaseAddr); - CloseHandle(MapObjectHandle); - - return Result; -} - -/** - * @brief Detect whether PE is a 32-bit PE or 64-bit PE - * @param AddressOfFile - * @param Is32Bit - * - * @return BOOLEAN - */ -BOOLEAN -PeIsPE32BitOr64Bit(const WCHAR * AddressOfFile, PBOOLEAN Is32Bit) -{ - BOOLEAN Result = FALSE; - HANDLE MapObjectHandle, FileHandle; // File Mapping Object - LPVOID BaseAddr; // Pointer to the base memory of mapped file - PIMAGE_DOS_HEADER DosHeader; // Pointer to DOS Header - PIMAGE_NT_HEADERS32 NtHeader32 = NULL; // Pointer to NT Header 32 bit - IMAGE_OPTIONAL_HEADER32 OpHeader32; // Optional Header of PE files present in NT Header structure - IMAGE_FILE_HEADER Header; // Pointer to image file header of NT Header - - // - // Open the EXE File - // - FileHandle = CreateFileW(AddressOfFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (FileHandle == INVALID_HANDLE_VALUE) - { - ShowMessages("err, unable to read the file (%x)\n", GetLastError()); - return FALSE; - }; - - // - // Mapping Given EXE file to Memory - // - MapObjectHandle = - CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL); - - if (MapObjectHandle == NULL) - { - CloseHandle(FileHandle); - - ShowMessages("err, unable to create file mappings (%x)\n", GetLastError()); - return FALSE; - } - - BaseAddr = MapViewOfFile(MapObjectHandle, FILE_MAP_READ, 0, 0, 0); - - if (BaseAddr == NULL) - { - CloseHandle(FileHandle); - - ShowMessages("err, unable to create map view of file (%x)\n", GetLastError()); - return FALSE; - } - - // - // Get the DOS Header Base - // - DosHeader = (PIMAGE_DOS_HEADER)BaseAddr; // 0x04000000 - - // - // Check for Valid DOS file - // - if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) - { - Result = FALSE; - - ShowMessages("err, the selected file is not in a valid PE format\n"); - goto Finished; - } - - // - // Offset of NT Header is found at 0x3c location in DOS header specified by - // e_lfanew - // Get the Base of NT Header(PE Header) = DosHeader + RVA address of PE - // header - // - - NtHeader32 = (PIMAGE_NT_HEADERS32)((UINT64)(DosHeader) + (DosHeader->e_lfanew)); - - // - // Identify for valid PE file - // - if (NtHeader32->Signature != IMAGE_NT_SIGNATURE) - { - Result = FALSE; - - ShowMessages("err, invalid image NT signature\n"); - goto Finished; - } - - // - // Info about Optional Header - // - OpHeader32 = NtHeader32->OptionalHeader; - - // - // Get the IMAGE FILE HEADER Structure - // - Header = NtHeader32->FileHeader; - - // - // Only few are determined (for remaining refer - // to the above specification) - // - switch (Header.Machine) - { - case IMAGE_FILE_MACHINE_I386: - *Is32Bit = TRUE; - Result = TRUE; - goto Finished; - break; - case IMAGE_FILE_MACHINE_AMD64: - *Is32Bit = FALSE; - Result = TRUE; - goto Finished; - break; - default: - ShowMessages("err, PE file is not i386 or AMD64; thus, it's not supported " - "in HyperDbg\n"); - Result = FALSE; - goto Finished; - break; - } - -Finished: - // - // Unmap and close the handles - // - UnmapViewOfFile(BaseAddr); - CloseHandle(MapObjectHandle); - - return Result; -} diff --git a/hyperdbg/hprdbgctrl/header/commands.h b/hyperdbg/hprdbgctrl/header/commands.h deleted file mode 100644 index 6fe7d587..00000000 --- a/hyperdbg/hprdbgctrl/header/commands.h +++ /dev/null @@ -1,669 +0,0 @@ -/** - * @file commands.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @author Alee Amini (alee@hyperdbg.org) - * @brief The hyperdbg command interpreter and driver connector - * @details - * @version 0.1 - * @date 2020-04-11 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -using namespace std; - -////////////////////////////////////////////////// -// Externs // -////////////////////////////////////////////////// - -extern HANDLE g_DeviceHandle; - -////////////////////////////////////////////////// -// Settings // -////////////////////////////////////////////////// - -VOID -CommandSettingsLoadDefaultValuesFromConfigFile(); - -VOID -CommandSettingsSetValueFromConfigFile(std::string OptionName, std::string OptionValue); - -BOOLEAN -CommandSettingsGetValueFromConfigFile(std::string OptionName, std::string & OptionValue); - -////////////////////////////////////////////////// -// Functions // -////////////////////////////////////////////////// - -int -ReadCpuDetails(); - -VOID -ShowMessages(const char * Fmt, ...); - -string -SeparateTo64BitValue(UINT64 Value); - -void -ShowMemoryCommandDB(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length); - -void -ShowMemoryCommandDD(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length); - -void -ShowMemoryCommandDC(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length); - -void -ShowMemoryCommandDQ(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length); - -VOID -CommandPteShowResults(UINT64 TargetVa, PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PteRead); - -DEBUGGER_CONDITIONAL_JUMP_STATUS -HyperDbgIsConditionalJumpTaken(unsigned char * BufferToDisassemble, - UINT64 BuffLength, - RFLAGS Rflags, - BOOLEAN Isx86_64); - -int -HyperDbgDisassembler64(unsigned char * BufferToDisassemble, - UINT64 BaseAddress, - UINT64 Size, - UINT32 MaximumInstrDecoded, - BOOLEAN ShowBranchIsTakenOrNot, - PRFLAGS Rflags); - -int -HyperDbgDisassembler32(unsigned char * BufferToDisassemble, - UINT64 BaseAddress, - UINT64 Size, - UINT32 MaximumInstrDecoded, - BOOLEAN ShowBranchIsTakenOrNot, - PRFLAGS Rflags); - -UINT32 -HyperDbgLengthDisassemblerEngine( - unsigned char * BufferToDisassemble, - UINT64 BuffLength, - BOOLEAN Isx86_64); - -BOOLEAN -HyperDbgCheckWhetherTheCurrentInstructionIsCall( - unsigned char * BufferToDisassemble, - UINT64 BuffLength, - BOOLEAN Isx86_64, - PUINT32 CallLength); - -BOOLEAN -HyperDbgCheckWhetherTheCurrentInstructionIsCallOrRet( - unsigned char * BufferToDisassemble, - UINT64 CurrentRip, - UINT32 BuffLength, - BOOLEAN Isx86_64, - PBOOLEAN IsRet); - -BOOLEAN -HyperDbgCheckWhetherTheCurrentInstructionIsRet( - unsigned char * BufferToDisassemble, - UINT64 BuffLength, - BOOLEAN Isx86_64); - -VOID -HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, - UINT64 Address, - DEBUGGER_READ_MEMORY_TYPE MemoryType, - DEBUGGER_READ_READING_TYPE ReadingType, - UINT32 Pid, - UINT32 Size, - PDEBUGGER_DT_COMMAND_OPTIONS DtDetails); - -VOID -InitializeCommandsDictionary(); - -VOID -InitializeDebugger(); - -VOID -CommandDumpSaveIntoFile(PVOID Buffer, UINT32 Length); - -////////////////////////////////////////////////// -// Type of Commands // -////////////////////////////////////////////////// - -/** - * @brief Command's function type - * - */ -typedef VOID (*CommandFuncType)(vector SplitCommand, string Command); - -/** - * @brief Command's help function type - * - */ -typedef VOID (*CommandHelpFuncType)(); - -/** - * @brief Details of each command - * - */ -typedef struct _COMMAND_DETAIL -{ - CommandFuncType CommandFunction; - CommandHelpFuncType CommandHelpFunction; - UINT64 CommandAttrib; - -} COMMAND_DETAIL, *PCOMMAND_DETAIL; - -/** - * @brief Type saving commands and mapping to command string - * - */ -typedef std::map CommandType; - -/** - * @brief Different attributes of commands - * - */ -#define DEBUGGER_COMMAND_ATTRIBUTE_EVENT \ - 0x1 | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE -#define DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE 0x2 -#define DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_REMOTE_CONNECTION 0x4 -#define DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE 0x8 -#define DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER 0x10 -#define DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN 0x20 - -/** - * @brief Absolute local commands - * - */ -#define DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_REMOTE_CONNECTION - -/** - * @brief Command's attributes - * - */ -#define DEBUGGER_COMMAND_CLEAR_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL - -#define DEBUGGER_COMMAND_HELP_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL - -#define DEBUGGER_COMMAND_CONNECT_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL - -#define DEBUGGER_COMMAND_LISTEN_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL - -#define DEBUGGER_COMMAND_G_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -#define DEBUGGER_COMMAND_ATTACH_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_DETACH_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_SWITCH_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_START_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN - -#define DEBUGGER_COMMAND_RESTART_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN - -#define DEBUGGER_COMMAND_KILL_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_PROCESS_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_THREAD_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_SLEEP_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL - -#define DEBUGGER_COMMAND_EVENTS_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_SETTINGS_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_DISCONNECT_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL - -#define DEBUGGER_COMMAND_DEBUG_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_DOT_STATUS_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL - -#define DEBUGGER_COMMAND_STATUS_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_LOAD_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_EXIT_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL - -#define DEBUGGER_COMMAND_FLUSH_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_PAUSE_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL - -#define DEBUGGER_COMMAND_UNLOAD_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_SCRIPT_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_OUTPUT_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_PRINT_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -#define DEBUGGER_COMMAND_EVAL_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -#define DEBUGGER_COMMAND_LOGOPEN_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_LOGCLOSE_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL - -#define DEBUGGER_COMMAND_TEST_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_CPU_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_WRMSR_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_RDMSR_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_VA2PA_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_PA2VA_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_FORMATS_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -#define DEBUGGER_COMMAND_PTE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_CORE_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_MONITOR_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_VMCALL_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_EPTHOOK_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_EPTHOOK2_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_CPUID_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_MSRREAD_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_MSRWRITE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_TSC_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_PMC_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_CRWRITE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_DR_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_IOIN_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_IOOUT_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_EXCEPTION_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_INTERRUPT_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_SYSCALL_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_SYSRET_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_MODE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_TRACE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT - -#define DEBUGGER_COMMAND_HIDE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_UNHIDE_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_MEASURE_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_LM_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_P_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -#define DEBUGGER_COMMAND_T_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -#define DEBUGGER_COMMAND_I_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -#define DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -#define DEBUGGER_COMMAND_E_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_S_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_R_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -#define DEBUGGER_COMMAND_BP_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_BE_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_BD_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_BC_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_BL_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_SYMPATH_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_SYM_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_X_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_PREALLOC_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_PREACTIVATE_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_K_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_DT_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -#define DEBUGGER_COMMAND_STRUCT_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_PE_ATTRIBUTES NULL - -// #define DEBUGGER_COMMAND_REV_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN -#define DEBUGGER_COMMAND_REV_ATTRIBUTES NULL - -#define DEBUGGER_COMMAND_TRACK_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_PAGEIN_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE - -#define DEBUGGER_COMMAND_DUMP_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_CASE_SENSITIVE - -#define DEBUGGER_COMMAND_GU_ATTRIBUTES \ - DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER - -////////////////////////////////////////////////// -// Command Functions // -////////////////////////////////////////////////// - -VOID -CommandTest(vector SplitCommand, string Command); - -VOID -CommandClearScreen(vector SplitCommand, string Command); - -VOID -CommandReadMemoryAndDisassembler(vector SplitCommand, - string Command); - -VOID -CommandConnect(vector SplitCommand, string Command); - -VOID -CommandLoad(vector SplitCommand, string Command); - -VOID -CommandUnload(vector SplitCommand, string Command); - -VOID -CommandScript(vector SplitCommand, string Command); - -VOID -CommandCpu(vector SplitCommand, string Command); - -VOID -CommandExit(vector SplitCommand, string Command); - -VOID -CommandDisconnect(vector SplitCommand, string Command); - -VOID -CommandFormats(vector SplitCommand, string Command); - -VOID -CommandRdmsr(vector SplitCommand, string Command); - -VOID -CommandWrmsr(vector SplitCommand, string Command); - -VOID -CommandPte(vector SplitCommand, string Command); - -VOID -CommandMonitor(vector SplitCommand, string Command); - -VOID -CommandSyscallAndSysret(vector SplitCommand, string Command); - -VOID -CommandEptHook(vector SplitCommand, string Command); - -VOID -CommandEptHook2(vector SplitCommand, string Command); - -VOID -CommandCpuid(vector SplitCommand, string Command); - -VOID -CommandMsrread(vector SplitCommand, string Command); - -VOID -CommandMsrwrite(vector SplitCommand, string Command); - -VOID -CommandTsc(vector SplitCommand, string Command); - -VOID -CommandPmc(vector SplitCommand, string Command); - -VOID -CommandException(vector SplitCommand, string Command); - -VOID -CommandCrwrite(vector SplitCommand, string Command); - -VOID -CommandDr(vector SplitCommand, string Command); - -VOID -CommandInterrupt(vector SplitCommand, string Command); - -VOID -CommandIoin(vector SplitCommand, string Command); - -VOID -CommandIoout(vector SplitCommand, string Command); - -VOID -CommandVmcall(vector SplitCommand, string Command); - -VOID -CommandMode(vector SplitCommand, string Command); - -VOID -CommandTrace(vector SplitCommand, string Command); - -VOID -CommandHide(vector SplitCommand, string Command); - -VOID -CommandUnhide(vector SplitCommand, string Command); - -VOID -CommandLogopen(vector SplitCommand, string Command); - -VOID -CommandLogclose(vector SplitCommand, string Command); - -VOID -CommandVa2pa(vector SplitCommand, string Command); - -VOID -CommandPa2va(vector SplitCommand, string Command); - -VOID -CommandEvents(vector SplitCommand, string Command); - -VOID -CommandG(vector SplitCommand, string Command); - -VOID -CommandLm(vector SplitCommand, string Command); - -VOID -CommandSleep(vector SplitCommand, string Command); - -VOID -CommandEditMemory(vector SplitCommand, string Command); - -VOID -CommandSearchMemory(vector SplitCommand, string Command); - -VOID -CommandMeasure(vector SplitCommand, string Command); - -VOID -CommandSettings(vector SplitCommand, string Command); - -VOID -CommandFlush(vector SplitCommand, string Command); - -VOID -CommandPause(vector SplitCommand, string Command); - -VOID -CommandListen(vector SplitCommand, string Command); - -VOID -CommandStatus(vector SplitCommand, string Command); - -VOID -CommandAttach(vector SplitCommand, string Command); - -VOID -CommandDetach(vector SplitCommand, string Command); - -VOID -CommandStart(vector SplitCommand, string Command); - -VOID -CommandRestart(vector SplitCommand, string Command); - -VOID -CommandSwitch(vector SplitCommand, string Command); - -VOID -CommandKill(vector SplitCommand, string Command); - -VOID -CommandT(vector SplitCommand, string Command); - -VOID -CommandI(vector SplitCommand, string Command); - -VOID -CommandPrint(vector SplitCommand, string Command); - -VOID -CommandOutput(vector SplitCommand, string Command); - -VOID -CommandDebug(vector SplitCommand, string Command); - -VOID -CommandP(vector SplitCommand, string Command); - -VOID -CommandCore(vector SplitCommand, string Command); - -VOID -CommandProcess(vector SplitCommand, string Command); - -VOID -CommandThread(vector SplitCommand, string Command); - -VOID -CommandEval(vector SplitCommand, string Command); - -VOID -CommandR(vector SplitCommand, string Command); - -VOID -CommandBp(vector SplitCommand, string Command); - -VOID -CommandBl(vector SplitCommand, string Command); - -VOID -CommandBe(vector SplitCommand, string Command); - -VOID -CommandBd(vector SplitCommand, string Command); - -VOID -CommandBc(vector SplitCommand, string Command); - -VOID -CommandSympath(vector SplitCommand, string Command); - -VOID -CommandSym(vector SplitCommand, string Command); - -VOID -CommandX(vector SplitCommand, string Command); - -VOID -CommandPrealloc(vector SplitCommand, string Command); - -VOID -CommandPreactivate(vector SplitCommand, string Command); - -VOID -CommandDtAndStruct(vector SplitCommand, string Command); - -VOID -CommandK(vector SplitCommand, string Command); - -VOID -CommandPe(vector SplitCommand, string Command); - -VOID -CommandRev(vector SplitCommand, string Command); - -VOID -CommandTrack(vector SplitCommand, string Command); - -VOID -CommandPagein(vector SplitCommand, string Command); - -VOID -CommandDump(vector SplitCommand, string Command); - -VOID -CommandGu(vector SplitCommand, string Command); diff --git a/hyperdbg/hprdbgctrl/header/common.h b/hyperdbg/hprdbgctrl/header/common.h deleted file mode 100644 index f807cd59..00000000 --- a/hyperdbg/hprdbgctrl/header/common.h +++ /dev/null @@ -1,203 +0,0 @@ -/** - * @file common.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief header for HyperDbg's general functions for reading and converting and - * etc - * @details - * @version 0.1 - * @date 2020-05-27 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Definitions // -////////////////////////////////////////////////// - -#define AssertReturn return; - -#define AssertReturnFalse return FALSE; - -#define AssertReturnOne return 1; - -#define ASSERT_MESSAGE_DRIVER_NOT_LOADED "handle of the driver not found, probably the driver is not loaded. Did you use 'load' command?\n" - -#define ASSERT_MESSAGE_BUILD_SIGNATURE_DOESNT_MATCH "the handshaking process was successful; however, there is a mismatch between " \ - "the version/build of the debuggee and the debugger. please use the same " \ - "version/build for both the debuggee and debugger\n" - -#define ASSERT_MESSAGE_CANNOT_SPECIFY_PID "err, since HyperDbg won't context-switch to keep the system in a halted state, " \ - "you cannot specify 'pid' for this command in the debugger mode. You can switch to the target process " \ - "memory layout using the '.process' or the '.thread' command. After that, you can use " \ - "this command without specifying the process ID. Alternatively, you can modify the current " \ - "CR3 register to achieve the same functionality\n" - -#define AssertReturnStmt(expr, stmt, rc) \ - do \ - { \ - if (expr) \ - { \ - /* likely */ \ - } \ - else \ - { \ - stmt; \ - rc; \ - } \ - } while (0) - -#define AssertShowMessageReturnStmt(expr, message, rc) \ - do \ - { \ - if (expr) \ - { \ - /* likely */ \ - } \ - else \ - { \ - ShowMessages(message); \ - rc; \ - } \ - } while (0) - -/** - * @brief Size of each page (4096 bytes) - * - */ -#define PAGE_SIZE 0x1000 - -/** - * @brief Aligning a page - * - */ -#define PAGE_ALIGN(Va) ((PVOID)((ULONG_PTR)(Va) & ~(PAGE_SIZE - 1))) - -/** - * @brief Cpuid to get virtual address width - * - */ -#define CPUID_ADDR_WIDTH 0x80000008 - -////////////////////////////////////////////////// -// Assembly Functions // -////////////////////////////////////////////////// - -#ifdef __cplusplus -extern "C" { -#endif - -extern bool -AsmVmxSupportDetection(); - -#ifdef __cplusplus -} -#endif - -////////////////////////////////////////////////// -// Spinlocks // -////////////////////////////////////////////////// - -void -SpinlockLock(volatile LONG * Lock); - -void -SpinlockLockWithCustomWait(volatile LONG * Lock, unsigned MaximumWait); - -void -SpinlockUnlock(volatile LONG * Lock); - -////////////////////////////////////////////////// -// Functions // -////////////////////////////////////////////////// - -VOID -PrintBits(const UINT32 size, const void * ptr); - -BOOL -Replace(std::string & str, const std::string & from, const std::string & to); - -VOID -ReplaceAll(string & str, const string & from, const string & to); - -const vector -Split(const string & s, const char & c); - -BOOLEAN -IsNumber(const string & str); - -vector -SplitIp(const string & str, char delim); - -BOOLEAN -IsHexNotation(const string & s); - -vector -HexToBytes(const string & hex); - -BOOLEAN -ConvertStringToUInt64(string TextToConvert, PUINT64 Result); - -BOOLEAN -ConvertStringToUInt32(string TextToConvert, PUINT32 Result); - -BOOLEAN -HasEnding(string const & fullString, string const & ending); - -BOOLEAN -ValidateIP(const string & ip); - -BOOL -SetPrivilege(HANDLE Token, // access token handle - LPCTSTR Privilege, // name of privilege to enable/disable - BOOL EnablePrivilege // to enable or disable privilege -); - -void -Trim(std::string & s); - -std::string -RemoveSpaces(std::string str); - -BOOLEAN -IsFileExistA(const char * FileName); - -BOOLEAN -IsFileExistW(const wchar_t * FileName); - -VOID -GetConfigFilePath(PWCHAR ConfigPath); - -VOID -StringToWString(std::wstring & ws, const std::string & s); - -VOID -SplitPathAndArgs(std::vector & Qargs, const std::string & Command); - -size_t -FindCaseInsensitive(std::string Input, std::string ToSearch, size_t Pos); - -size_t -FindCaseInsensitiveW(std::wstring Input, std::wstring ToSearch, size_t Pos); - -char * -ConvertStringVectorToCharPointerArray(const std::string & s); - -std::vector -ListDirectory(const std::string & Directory, const std::string & Extension); - -BOOLEAN -IsEmptyString(char * Text); - -VOID -CommonCpuidInstruction(UINT32 Func, UINT32 SubFunc, int * CpuInfo); - -BOOLEAN -CheckCpuSupportRtm(); - -UINT32 -Getx86VirtualAddressWidth(); - -BOOLEAN -CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size); diff --git a/hyperdbg/hprdbgctrl/header/install.h b/hyperdbg/hprdbgctrl/header/install.h deleted file mode 100644 index 3713d725..00000000 --- a/hyperdbg/hprdbgctrl/header/install.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file hprdbgctrl.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Main interface to connect applications to driver headers - * @details - * @version 0.1 - * @date 2020-04-11 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -// -// The following ifdef block is the standard way of creating macros which make -// exporting from a DLL simpler. All files within this DLL are compiled with the -// HPRDBGCTRL_EXPORTS symbol defined on the command line. This symbol should not -// be defined on any project that uses this DLL. This way any other project -// whose source files include this file see HPRDBGCTRL_API functions as being -// imported from a DLL, whereas this DLL sees symbols defined with this macro as -// being exported. -// - -#ifdef HPRDBGCTRL_EXPORTS -# define HPRDBGCTRL_API __declspec(dllexport) -#else -# define HPRDBGCTRL_API __declspec(dllimport) -#endif - -////////////////////////////////////////////////// -// Installer // -////////////////////////////////////////////////// - -#define DRIVER_FUNC_INSTALL 0x01 -#define DRIVER_FUNC_STOP 0x02 -#define DRIVER_FUNC_REMOVE 0x03 - -BOOLEAN -ManageDriver(_In_ LPCTSTR DriverName, _In_ LPCTSTR ServiceName, _In_ UINT16 Function); - -BOOLEAN -SetupDriverName(const CHAR * DriverName, - _Inout_updates_bytes_all_(BufferLength) PCHAR DriverLocation, - ULONG BufferLength); diff --git a/hyperdbg/hprdbgctrl/header/pe-parser.h b/hyperdbg/hprdbgctrl/header/pe-parser.h deleted file mode 100644 index 960f034a..00000000 --- a/hyperdbg/hprdbgctrl/header/pe-parser.h +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @file pe-parser.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Header for Portable Executable parser - * @details - * @version 0.1 - * @date 2021-12-26 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Functions // -////////////////////////////////////////////////// - -BOOLEAN -PeShowSectionInformationAndDump(const WCHAR * AddressOfFile, const CHAR * SectionToShow, BOOLEAN Is32Bit); - -BOOLEAN -PeIsPE32BitOr64Bit(const WCHAR * AddressOfFile, PBOOLEAN Is32Bit); diff --git a/hyperdbg/hprdbgctrl/pch.h b/hyperdbg/hprdbgctrl/pch.h deleted file mode 100644 index 6eed2c9a..00000000 --- a/hyperdbg/hprdbgctrl/pch.h +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @file pch.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief header file corresponding to the pre-compiled header - * @details - * @version 0.1 - * @date 2020-04-11 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -// -// add headers that you want to pre-compile here -// - -// -// Windows SDK headers -// - -#define WIN32_LEAN_AND_MEAN - -// -// IA32-doc has structures for the entire intel SDM. -// - -#define USE_LIB_IA32 -#if defined(USE_LIB_IA32) -# pragma warning(push, 0) -// # pragma warning(disable : 4201) // suppress nameless struct/union warning -# include -# pragma warning(pop) -typedef RFLAGS * PRFLAGS; -#endif // USE_LIB_IA32 - -// -// Native API header files for the Process Hacker project. -// -#define USE__NATIVE_PHNT_HEADERS - -#if defined(USE__NATIVE_PHNT_HEADERS) - -// -// Dirty fix: the "PCWCHAR" in undefined in "ntrtl.h" so I deifined it here. -// -typedef const wchar_t *LPCWCHAR, *PCWCHAR; - -# define PHNT_MODE PHNT_MODE_USER -# define PHNT_VERSION PHNT_WIN11 // Windows 7 -# define PHNT_PATCH_FOR_HYPERDBG TRUE - -# include -# include - -#elif defined(USE_NATIVE_SDK_HEADERS) - -# include -# include -# include - -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -// STL headers -// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Scope definitions -// -#define SCRIPT_ENGINE_USER_MODE -#define HYPERDBG_USER_MODE -#define HYPERDBG_HPRDBGCTRL - -// -// Zydis Debug Disable Flag -// -#ifndef NDEBUG -# define NDEBUG -#endif // !NDEBUG - -// -// HyperDbg defined headers -// -#include "Configuration.h" -#include "Definition.h" -#include "SDK/HyperDbgSdk.h" -#include "SDK/Imports/HyperDbgCtrlImports.h" - -// -// Script-engine -// -#include "..\script-eval\header\ScriptEngineCommonDefinitions.h" -#include "..\script-eval\header\ScriptEngineHeader.h" - -// -// Imports/Exports -// -#include "SDK/Imports/HyperDbgScriptImports.h" -#include "SDK/Imports/HyperDbgCtrlImports.h" - -// -// General -// -#include "header/inipp.h" -#include "header/commands.h" -#include "header/common.h" -#include "header/symbol.h" -#include "header/debugger.h" -#include "header/script-engine.h" -#include "header/help.h" -#include "header/install.h" -#include "header/list.h" -#include "header/tests.h" -#include "header/transparency.h" -#include "header/communication.h" -#include "header/namedpipe.h" -#include "header/forwarding.h" -#include "header/kd.h" -#include "header/pe-parser.h" -#include "header/ud.h" -#include "header/objects.h" -#include "header/rev-ctrl.h" - -// -// Libraries -// - -#pragma comment(lib, "ntdll.lib") - -// -// For path combine -// -#pragma comment(lib, "Shlwapi.lib") - -// -// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib -// for tcpclient.cpp and tcpserver.cpp -// -#pragma comment(lib, "Ws2_32.lib") -#pragma comment(lib, "Mswsock.lib") -#pragma comment(lib, "AdvApi32.lib") - -// -// For GetModuleFileNameExA on script-engine for user-mode -// Kernel32.lib is not needed, but seems that it's the library -// for Windows 7 -// -#pragma comment(lib, "Psapi.lib") -#pragma comment(lib, "Kernel32.lib") diff --git a/hyperdbg/hprdbghv/code/assembly/AsmVmexitHandler.asm b/hyperdbg/hprdbghv/code/assembly/AsmVmexitHandler.asm deleted file mode 100644 index 0a41fbd1..00000000 --- a/hyperdbg/hprdbghv/code/assembly/AsmVmexitHandler.asm +++ /dev/null @@ -1,199 +0,0 @@ -PUBLIC AsmVmexitHandler - -EXTERN VmxVmexitHandler:PROC -EXTERN VmxVmresume:PROC -EXTERN VmxReturnStackPointerForVmxoff:PROC -EXTERN VmxReturnInstructionPointerForVmxoff:PROC - -.code _text - -;------------------------------------------------------------------------ - -AsmVmexitHandler PROC - - push 0 ; we might be in an unaligned stack state, so the memory before stack might cause - ; irql less or equal as it doesn't exist, so we just put some extra space avoid - ; these kind of errors - - pushfq - - ; ------------ Save XMM Registers ------------ - ; - ; ;;;;;;;;;;;; 16 Byte * 16 Byte = 256 + 4 = 260 (0x106 == 0x110 but let's align it to have better performance) ;;;;;;;;;;;; - ; sub rsp, 0110h - ; - ; movaps xmmword ptr [rsp+000h], xmm0 ; each xmm register 128 bit (16 Byte) - ; movaps xmmword ptr [rsp+010h], xmm1 - ; movaps xmmword ptr [rsp+020h], xmm2 - ; movaps xmmword ptr [rsp+030h], xmm3 - ; movaps xmmword ptr [rsp+040h], xmm4 - ; movaps xmmword ptr [rsp+050h], xmm5 - ; movaps xmmword ptr [rsp+060h], xmm6 - ; movaps xmmword ptr [rsp+070h], xmm7 - ; movaps xmmword ptr [rsp+080h], xmm8 - ; movaps xmmword ptr [rsp+090h], xmm9 - ; movaps xmmword ptr [rsp+0a0h], xmm10 - ; movaps xmmword ptr [rsp+0b0h], xmm11 - ; movaps xmmword ptr [rsp+0c0h], xmm12 - ; movaps xmmword ptr [rsp+0d0h], xmm13 - ; movaps xmmword ptr [rsp+0e0h], xmm14 - ; movaps xmmword ptr [rsp+0f0h], xmm15 - ; stmxcsr dword ptr [rsp+0100h] ; MxCsr is 4 Byte - ; - ;--------------------------------------------- - - push r15 - push r14 - push r13 - push r12 - push r11 - push r10 - push r9 - push r8 - push rdi - push rsi - push rbp - push rbp ; rsp - push rbx - push rdx - push rcx - push rax - - mov rcx, rsp ; Fast call argument to PGUEST_REGS - sub rsp, 020h ; Free some space for Shadow Section - call VmxVmexitHandler - add rsp, 020h ; Restore the state - - cmp al, 1 ; Check whether we have to turn off VMX or Not (the result is in RAX) - je AsmVmxoffHandler - -RestoreState: - pop rax - pop rcx - pop rdx - pop rbx - pop rbp ; rsp - pop rbp - pop rsi - pop rdi - pop r8 - pop r9 - pop r10 - pop r11 - pop r12 - pop r13 - pop r14 - pop r15 - - ; ------------ Restore XMM Registers ------------ - ; - ; movaps xmm0, xmmword ptr [rsp+000h] - ; movaps xmm1, xmmword ptr [rsp+010h] - ; movaps xmm2, xmmword ptr [rsp+020h] - ; movaps xmm3, xmmword ptr [rsp+030h] - ; movaps xmm4, xmmword ptr [rsp+040h] - ; movaps xmm5, xmmword ptr [rsp+050h] - ; movaps xmm6, xmmword ptr [rsp+060h] - ; movaps xmm7, xmmword ptr [rsp+070h] - ; movaps xmm8, xmmword ptr [rsp+080h] - ; movaps xmm9, xmmword ptr [rsp+090h] - ; movaps xmm10, xmmword ptr [rsp+0a0h] - ; movaps xmm11, xmmword ptr [rsp+0b0h] - ; movaps xmm12, xmmword ptr [rsp+0c0h] - ; movaps xmm13, xmmword ptr [rsp+0d0h] - ; movaps xmm14, xmmword ptr [rsp+0e0h] - ; movaps xmm15, xmmword ptr [rsp+0f0h] - ; - ; ldmxcsr dword ptr [rsp+0100h] - ; - ; add rsp, 0110h - ; ---------------------------------------------- - - popfq - - sub rsp, 0100h ; to avoid error in future functions - jmp VmxVmresume - -AsmVmexitHandler ENDP - -;------------------------------------------------------------------------ - -AsmVmxoffHandler PROC - - sub rsp, 020h ; shadow space - call VmxReturnStackPointerForVmxoff - add rsp, 020h ; remove for shadow space - - mov [rsp+88h], rax ; now, rax contains rsp - - sub rsp, 020h ; shadow space - call VmxReturnInstructionPointerForVmxoff - add rsp, 020h ; remove for shadow space - - mov rdx, rsp ; save current rsp - - mov rbx, [rsp+88h] ; read rsp again - - mov rsp, rbx - - push rax ; push the return address as we changed the stack, we push - ; it to the new stack - - mov rsp, rdx ; restore previous rsp - - sub rbx,08h ; we push sth, so we have to add (sub) +8 from previous stack - ; also rbx already contains the rsp - mov [rsp+88h], rbx ; move the new pointer to the current stack - -RestoreState: - pop rax - pop rcx - pop rdx - pop rbx - pop rbp ; rsp - pop rbp - pop rsi - pop rdi - pop r8 - pop r9 - pop r10 - pop r11 - pop r12 - pop r13 - pop r14 - pop r15 - - ; ------------ Restore XMM Registers ------------ - ; - ; movaps xmm0, xmmword ptr [rsp+000h] - ; movaps xmm1, xmmword ptr [rsp+010h] - ; movaps xmm2, xmmword ptr [rsp+020h] - ; movaps xmm3, xmmword ptr [rsp+030h] - ; movaps xmm4, xmmword ptr [rsp+040h] - ; movaps xmm5, xmmword ptr [rsp+050h] - ; movaps xmm6, xmmword ptr [rsp+060h] - ; movaps xmm7, xmmword ptr [rsp+070h] - ; movaps xmm8, xmmword ptr [rsp+080h] - ; movaps xmm9, xmmword ptr [rsp+090h] - ; movaps xmm10, xmmword ptr [rsp+0a0h] - ; movaps xmm11, xmmword ptr [rsp+0b0h] - ; movaps xmm12, xmmword ptr [rsp+0c0h] - ; movaps xmm13, xmmword ptr [rsp+0d0h] - ; movaps xmm14, xmmword ptr [rsp+0e0h] - ; movaps xmm15, xmmword ptr [rsp+0f0h] - ; - ; ldmxcsr dword ptr [rsp+0100h] - ; - ; add rsp, 0110h - ; ---------------------------------------------- - - popfq - pop rsp ; restore rsp - - ret ; jump back to where we called Vmcall - -AsmVmxoffHandler ENDP - -;------------------------------------------------------------------------ - -END diff --git a/hyperdbg/hprdbghv/code/devices/Apic.c b/hyperdbg/hprdbghv/code/devices/Apic.c deleted file mode 100644 index 1711213b..00000000 --- a/hyperdbg/hprdbghv/code/devices/Apic.c +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @file Apic.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Routines for Advanced Programmable Interrupt Controller (APIC) - * @details The code is derived from (https://www.cpl0.com/blog/?p=46) - * @version 0.1 - * @date 2020-12-31 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Trigger NMI on XAPIC - * @param Low - * @param High - * - * @return VOID - */ -VOID -XApicIcrWrite(UINT32 Low, UINT32 High) -{ - *(UINT32 *)((uintptr_t)g_ApicBase + ICROffset + 0x10) = High; - *(UINT32 *)((uintptr_t)g_ApicBase + ICROffset) = Low; -} - -/** - * @brief Trigger NMI on X2APIC - * @param Low - * @param High - * - * @return VOID - */ -VOID -X2ApicIcrWrite(UINT32 Low, UINT32 High) -{ - __writemsr(X2_MSR_BASE + TO_X2(ICROffset), ((UINT64)High << 32) | Low); -} - -/** - * @brief Trigger NMI on X2APIC or APIC based on Current system - * - * @return VOID - */ -VOID -ApicTriggerGenericNmi() -{ - if (g_CompatibilityCheck.IsX2Apic) - { - X2ApicIcrWrite((4 << 8) | (1 << 14) | (3 << 18), 0); - } - else - { - XApicIcrWrite((4 << 8) | (1 << 14) | (3 << 18), 0); - } -} - -/** - * @brief Initialize APIC - * - * @return BOOLEAN - */ -BOOLEAN -ApicInitialize() -{ - UINT64 ApicBaseMSR; - PHYSICAL_ADDRESS PaApicBase; - - ApicBaseMSR = __readmsr(0x1B); - if (!(ApicBaseMSR & (1 << 11))) - return FALSE; - - if (ApicBaseMSR & (1 << 10)) - { - g_CompatibilityCheck.IsX2Apic = TRUE; - return FALSE; - } - else - { - PaApicBase.QuadPart = ApicBaseMSR & 0xFFFFFF000; - g_ApicBase = MmMapIoSpace(PaApicBase, 0x1000, MmNonCached); - - if (!g_ApicBase) - return FALSE; - - g_CompatibilityCheck.IsX2Apic = FALSE; - } - return TRUE; -} - -/** - * @brief Uninitialize APIC - * - * @return VOID - */ -VOID -ApicUninitialize() -{ - // - // Unmap I/O Base - // - if (g_ApicBase) - MmUnmapIoSpace(g_ApicBase, 0x1000); -} - -/** - * @brief Self IPI the current core - * - * @param Vector - * @return VOID - */ -VOID -ApicSelfIpi(UINT32 Vector) -{ - // - // Check and apply self-IPI to x2APIC and xAPIC - // - if (g_CompatibilityCheck.IsX2Apic) - { - X2ApicIcrWrite(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | Vector, 0); - } - else - { - XApicIcrWrite(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | Vector, 0); - } -} diff --git a/hyperdbg/hprdbghv/code/hooks/syscall-hook/SsdtHook.c b/hyperdbg/hprdbghv/code/hooks/syscall-hook/SsdtHook.c deleted file mode 100644 index 3fabe02d..00000000 --- a/hyperdbg/hprdbghv/code/hooks/syscall-hook/SsdtHook.c +++ /dev/null @@ -1,303 +0,0 @@ -/** - * @file SsdtHook.c - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Implementation of functions to find SSDT entries for SSDT Hook - * @details - * @version 0.1 - * @date 2020-04-11 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Get the kernel base and Image size - * - * @param pImageSize [Out] Image size - * @return PVOID - */ -PVOID -SyscallHookGetKernelBase(PULONG ImageSize) -{ - NTSTATUS Status; - ZWQUERYSYSTEMINFORMATION ZwQSI = 0; - UNICODE_STRING RoutineName; - PVOID ModuleBase = NULL; - PSYSTEM_MODULE_INFORMATION SystemInfoBuffer = NULL; - ULONG SystemInfoBufferSize = 0; - - RtlInitUnicodeString(&RoutineName, L"ZwQuerySystemInformation"); - ZwQSI = (ZWQUERYSYSTEMINFORMATION)MmGetSystemRoutineAddress(&RoutineName); - if (!ZwQSI) - return NULL; - - Status = ZwQSI(SystemModuleInformation, - &SystemInfoBufferSize, - 0, - &SystemInfoBufferSize); - - if (!SystemInfoBufferSize) - { - LogError("Err, ZwQuerySystemInformation (1) failed"); - return NULL; - } - - SystemInfoBuffer = (PSYSTEM_MODULE_INFORMATION)CrsAllocateNonPagedPool(SystemInfoBufferSize * 2); - - if (!SystemInfoBuffer) - { - LogError("Err, insufficient memory"); - return NULL; - } - - memset(SystemInfoBuffer, 0, SystemInfoBufferSize * 2); - - Status = ZwQSI(SystemModuleInformation, - SystemInfoBuffer, - SystemInfoBufferSize * 2, - &SystemInfoBufferSize); - - if (NT_SUCCESS(Status)) - { - ModuleBase = SystemInfoBuffer->Module.ImageBase; - if (ImageSize) - *ImageSize = SystemInfoBuffer->Module.ImageSize; - } - else - { - LogError("Err, ZwQuerySystemInformation (2) failed"); - return NULL; - } - - ExFreePool(SystemInfoBuffer); - return ModuleBase; -} - -/** - * @brief Find SSDT address of Nt functions and W32Table - * - * @param NtTable [Out] Address of Nt Syscall Table - * @param Win32kTable [Out] Address of Win32k Syscall Table - * @return BOOLEAN Returns true if it can find the nt tables and win32k successfully otherwise - * returns false - */ -BOOLEAN -SyscallHookFindSsdt(PUINT64 NtTable, PUINT64 Win32kTable) -{ - ULONG KernelSize = 0; - ULONG_PTR KernelBase; - const unsigned char KiSystemServiceStartPattern[] = {0x8B, 0xF8, 0xC1, 0xEF, 0x07, 0x83, 0xE7, 0x20, 0x25, 0xFF, 0x0F, 0x00, 0x00}; - const ULONG SignatureSize = sizeof(KiSystemServiceStartPattern); - BOOLEAN Found = FALSE; - LONG RelativeOffset = 0; - ULONG_PTR AddressAfterPattern; - ULONG_PTR Address; - SSDTStruct * Shadow; - PVOID TableNT; - PVOID TableWin32k; - - // - // x64 code - // - KernelBase = (ULONG_PTR)SyscallHookGetKernelBase(&KernelSize); - - if (KernelBase == 0 || KernelSize == 0) - return FALSE; - - // - // Find KiSystemServiceStart - // - ULONG KiSSSOffset; - for (KiSSSOffset = 0; KiSSSOffset < KernelSize - SignatureSize; KiSSSOffset++) - { - if (RtlCompareMemory(((unsigned char *)KernelBase + KiSSSOffset), KiSystemServiceStartPattern, SignatureSize) == SignatureSize) - { - Found = TRUE; - break; - } - } - - if (!Found) - return FALSE; - - AddressAfterPattern = KernelBase + KiSSSOffset + SignatureSize; - Address = AddressAfterPattern + 7; // Skip lea r10,[nt!KeServiceDescriptorTable] - - // - // lea r11, KeServiceDescriptorTableShadow - // - if ((*(unsigned char *)Address == 0x4c) && - (*(unsigned char *)(Address + 1) == 0x8d) && - (*(unsigned char *)(Address + 2) == 0x1d)) - { - RelativeOffset = *(LONG *)(Address + 3); - } - - if (RelativeOffset == 0) - return FALSE; - - Shadow = (SSDTStruct *)(Address + RelativeOffset + 7); - - TableNT = (PVOID)Shadow; - TableWin32k = (PVOID)((ULONG_PTR)Shadow + 0x20); // Offset showed in Windbg - - *NtTable = (UINT64)TableNT; - *Win32kTable = (UINT64)TableWin32k; - - return TRUE; -} - -/** - * @brief Find entry from SSDT table of Nt functions and W32Table syscalls - * - * @param ApiNumber The Syscall Number - * @param GetFromWin32k Is this syscall from Win32K - * @return PVOID Returns the address of the function from SSDT, otherwise returns NULL - */ -PVOID -SyscallHookGetFunctionAddress(INT32 ApiNumber, BOOLEAN GetFromWin32k) -{ - SSDTStruct * SSDT; - BOOLEAN Result; - ULONG_PTR SSDTbase; - UINT64 NtTable, Win32kTable; - - // - // Read the address og SSDT - // - Result = SyscallHookFindSsdt(&NtTable, &Win32kTable); - - if (!Result) - { - LogError("Err, SSDT not found"); - return 0; - } - - if (!GetFromWin32k) - { - SSDT = (SSDTStruct *)NtTable; - } - else - { - // - // Win32k APIs start from 0x1000 - // - ApiNumber = ApiNumber - 0x1000; - SSDT = (SSDTStruct *)Win32kTable; - } - - SSDTbase = (ULONG_PTR)SSDT->pServiceTable; - - if (!SSDTbase) - { - LogError("Err, ServiceTable not found"); - return 0; - } - return (PVOID)((SSDT->pServiceTable[ApiNumber] >> 4) + SSDTbase); -} - -/** - * @brief Hook function that hooks NtCreateFile - * - * @param FileHandle - * @param DesiredAccess - * @param ObjectAttributes - * @param IoStatusBlock - * @param AllocationSize - * @param FileAttributes - * @param ShareAccess - * @param CreateDisposition - * @param CreateOptions - * @param EaBuffer - * @param EaLength - * @return NTSTATUS - */ -NTSTATUS -NtCreateFileHook( - PHANDLE FileHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - PIO_STATUS_BLOCK IoStatusBlock, - PLARGE_INTEGER AllocationSize, - ULONG FileAttributes, - ULONG ShareAccess, - ULONG CreateDisposition, - ULONG CreateOptions, - PVOID EaBuffer, - ULONG EaLength) -{ - NTSTATUS ConvertStatus; - UNICODE_STRING ObjectName; - ANSI_STRING FileNameA; - - ObjectName.Buffer = NULL; - - __try - { - ProbeForRead(FileHandle, sizeof(HANDLE), 1); - ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), 1); - ProbeForRead(ObjectAttributes->ObjectName, sizeof(UNICODE_STRING), 1); - ProbeForRead(ObjectAttributes->ObjectName->Buffer, ObjectAttributes->ObjectName->Length, 1); - - FileHandle = *FileHandle; - ObjectName.Length = ObjectAttributes->ObjectName->Length; - ObjectName.MaximumLength = ObjectAttributes->ObjectName->MaximumLength; - ObjectName.Buffer = CrsAllocateZeroedNonPagedPool(ObjectName.MaximumLength); - RtlCopyUnicodeString(&ObjectName, ObjectAttributes->ObjectName); - - ConvertStatus = RtlUnicodeStringToAnsiString(&FileNameA, ObjectAttributes->ObjectName, TRUE); - LogInfo("NtCreateFile called for : %s", FileNameA.Buffer); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } - - if (ObjectName.Buffer) - { - CrsFreePool(ObjectName.Buffer); - } - - return NtCreateFileOrig(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength); -} - -/** - * @brief Make examples for testing hidden hooks - * @details THIS EXAMPLE IS NOT VALID ANYMORE, PLEASE USE !syscall OR !epthook2 COMMANDS - * - * @return VOID - */ -VOID -SyscallHookTest() -{ - // - // THIS EXAMPLE IS NOT VALID ANYMORE, PLEASE USE !syscall OR !epthook2 COMMANDS - // - - // - // Note that this syscall number is only valid for Windows 10 1909, - // you have to find the syscall number of NtCreateFile based on - // Your Windows version, please visit https://j00ru.vexillium.org/syscalls/nt/64/ - // for finding NtCreateFile's Syscall number for your Windows - // - - INT32 ApiNumberOfNtCreateFile = 0x0055; - PVOID ApiLocationFromSSDTOfNtCreateFile = SyscallHookGetFunctionAddress(ApiNumberOfNtCreateFile, FALSE); - - if (!ApiLocationFromSSDTOfNtCreateFile) - { - LogError("Err, address finding for syscall base address"); - return; - } - - // - // THIS EXAMPLE IS NOT VALID ANYMORE, PLEASE USE !syscall OR !epthook2 COMMANDS - // - if (EptHookInlineHook(&g_GuestState[KeGetCurrentProcessorNumberEx(NULL)], - ApiLocationFromSSDTOfNtCreateFile, - (PVOID)NtCreateFileHook, - HANDLE_TO_UINT32(PsGetCurrentProcessId()))) - { - LogInfo("Hook appkied to address of API Number : 0x%x at %llx\n", ApiNumberOfNtCreateFile, ApiLocationFromSSDTOfNtCreateFile); - } -} diff --git a/hyperdbg/hprdbghv/code/platform/CrossApi.c b/hyperdbg/hprdbghv/code/platform/CrossApi.c deleted file mode 100644 index a4944502..00000000 --- a/hyperdbg/hprdbghv/code/platform/CrossApi.c +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @file CrossApi.c - * @author Behrooz Abbassi (BehroozAbbassi@hyperdbg.org) - * @brief Implementation of cross APIs for different platforms - * @details - * @version 0.1 - * @date 2022-01-17 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Allocate a contiguous zeroed memory - * - * @param NumberOfBytes - * @return PVOID - */ -PVOID -CrsAllocateContiguousZeroedMemory(SIZE_T NumberOfBytes) -{ - PVOID Result = NULL; - PHYSICAL_ADDRESS MaxPhysicalAddr = {.QuadPart = MAXULONG64}; - - Result = MmAllocateContiguousMemory(NumberOfBytes, MaxPhysicalAddr); - if (Result != NULL) - RtlSecureZeroMemory(Result, NumberOfBytes); - - return Result; -} - -/** - * @brief Allocate a non-paged buffer - * - * @param NumberOfBytes - * @return PVOID - */ -PVOID -CrsAllocateNonPagedPool(SIZE_T NumberOfBytes) -{ - PVOID Result = ExAllocatePoolWithTag(NonPagedPool, NumberOfBytes, POOLTAG); - - return Result; -} - -/** - * @brief Allocate a non-paged buffer (zeroed) - * - * @param NumberOfBytes - * @return PVOID - */ -PVOID -CrsAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes) -{ - PVOID Result = ExAllocatePoolWithTag(NonPagedPool, NumberOfBytes, POOLTAG); - - if (Result != NULL) - RtlSecureZeroMemory(Result, NumberOfBytes); - - return Result; -} - -/** - * @brief Free (dellocate) a non-paged buffer - * - * @param BufferAddress - * @return VOID - */ -VOID -CrsFreePool(PVOID BufferAddress) -{ - ExFreePoolWithTag(BufferAddress, POOLTAG); -} diff --git a/hyperdbg/hprdbghv/code/transparency/Transparency.c b/hyperdbg/hprdbghv/code/transparency/Transparency.c deleted file mode 100644 index 4ce647e6..00000000 --- a/hyperdbg/hprdbghv/code/transparency/Transparency.c +++ /dev/null @@ -1,659 +0,0 @@ -/** - * @file Transparency.c - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief try to hide the debugger from anti-debugging and anti-hypervisor methods - * @details - * @version 0.1 - * @date 2020-07-07 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief maximum random value - */ -#define MY_RAND_MAX 32768 - -/** - * @brief pre-defined log result - * @details we used this because we want to avoid using floating-points in - * kernel - */ -int TransparentTableLog[] = - { - 0, - 69, - 110, - 139, - 161, - 179, - 195, - 208, - 220, - 230, - 240, - 248, - 256, - 264, - 271, - 277, - 283, - 289, - 294, - 300, - 304, - 309, - 314, - 318, - 322, - 326, - 330, - 333, - 337, - 340, - 343, - 347, - 350, - 353, - 356, - 358, - 361, - 364, - 366, - 369, - 371, - 374, - 376, - 378, - 381, - 383, - 385, - 387, - 389, - 391, - 393, - 395, - 397, - 399, - 401, - 403, - 404, - 406, - 408, - 409, - 411, - 413, - 414, - 416, - 417, - 419, - 420, - 422, - 423, - 425, - 426, - 428, - 429, - 430, - 432, - 433, - 434, - 436, - 437, - 438, - 439, - 441, - 442, - 443, - 444, - 445, - 447, - 448, - 449, - 450, - 451, - 452, - 453, - 454, - 455, - 456, - 457, - 458, - 460, - 461}; - -/** - * @brief Generate a random number by utilizing RDTSC instruction. - * - * Masking 16 LSB of the measured clock time. - * @return UINT32 - */ -UINT32 -TransparentGetRand() -{ - UINT64 Tsc; - UINT32 Rand; - - Tsc = __rdtsc(); - Rand = Tsc & 0xffff; - - return Rand; -} - -/** - * @brief Integer power function definition. - * - * @params x Base Value - * @params p Power Value - * @return int - */ -int -TransparentPow(int x, int p) -{ - int Res = 1; - for (int i = 0; i < p; i++) - { - Res = Res * x; - } - return Res; -} - -/** - * @brief Integer Natural Logarithm function estimation. - * - * @params x input value - * @return int - */ -int -TransparentLog(int x) -{ - int n = x; - int Digit = 0; - - while (n >= 100) - { - n = n / 10; - Digit++; - } - - // - // Use pre-defined values of logarithms and estimate the total value - // - return TransparentTableLog[n] / 100 + (Digit * 23) / 10; -} -/** - * @brief Integer root function estimation. - * - * @params x input value - * @return int - */ -int -TransparentSqrt(int x) -{ - int Res = 0; - int Bit; - - // - // The second-to-top bit is set. - // - Bit = 1 << 30; - - // - // "Bit" starts at the highest power of four <= the argument. - // - while (Bit > x) - Bit >>= 2; - - while (Bit != 0) - { - if (x >= Res + Bit) - { - x -= Res + Bit; - Res = (Res >> 1) + Bit; - } - else - Res >>= 1; - Bit >>= 2; - } - return Res; -} - -/** - * @brief Integer Gaussian Random Number Generator(GRNG) based on Box-Muller method. A Float to Integer - * mapping is used in the function. - * - * @params Average Mean - * @parans Sigma Standard Deviation of the targeted Gaussian Distribution - * @return int - */ -int -TransparentRandn(int Average, int Sigma) -{ - int U1, r1, U2, r2, W, Mult; - int X1, X2 = 0, XS1; - int LogTemp = 0; - - do - { - r1 = TransparentGetRand(); - r2 = TransparentGetRand(); - - U1 = (r1 % MY_RAND_MAX) - (MY_RAND_MAX / 2); - - U2 = (r2 % MY_RAND_MAX) - (MY_RAND_MAX / 2); - - W = U1 * U1 + U2 * U2; - } while (W >= MY_RAND_MAX * MY_RAND_MAX / 2 || W == 0); - - LogTemp = (TransparentLog(W) - TransparentLog(MY_RAND_MAX * MY_RAND_MAX)); - - Mult = TransparentSqrt((-2 * LogTemp) * (MY_RAND_MAX * MY_RAND_MAX / W)); - - X1 = U1 * Mult / MY_RAND_MAX; - XS1 = U1 * Mult; - - X2 = U2 * Mult / MY_RAND_MAX; - - return (Average + (Sigma * XS1) / MY_RAND_MAX); -} - -/** - * @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 - * @return BOOLEAN - */ -BOOLEAN -TransparentAddNameOrProcessIdToTheList(PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE Measurements) -{ - SIZE_T SizeOfBuffer; - PTRANSPARENCY_PROCESS PidAndNameBuffer; - - // - // Check whether it's a process id or it's a process name - // - if (Measurements->TrueIfProcessIdAndFalseIfProcessName) - { - // - // It's a process Id - // - SizeOfBuffer = sizeof(TRANSPARENCY_PROCESS); - } - else - { - // - // It's a process name - // - SizeOfBuffer = sizeof(TRANSPARENCY_PROCESS) + Measurements->LengthOfProcessName; - } - - // - // Allocate the Buffer - // - PidAndNameBuffer = CrsAllocateZeroedNonPagedPool(SizeOfBuffer); - - if (PidAndNameBuffer == NULL) - { - return FALSE; - } - - // - // Save the address of the buffer for future de-allocation - // - PidAndNameBuffer->BufferAddress = PidAndNameBuffer; - - // - // Check again whether it's a process id or it's a process name - // then fill the structure - // - if (Measurements->TrueIfProcessIdAndFalseIfProcessName) - { - // - // It's a process Id - // - PidAndNameBuffer->ProcessId = Measurements->ProcId; - PidAndNameBuffer->TrueIfProcessIdAndFalseIfProcessName = TRUE; - } - else - { - // - // It's a process name - // - PidAndNameBuffer->TrueIfProcessIdAndFalseIfProcessName = FALSE; - - // - // 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)), - Measurements->LengthOfProcessName); - - // - // Set the process name location - // - PidAndNameBuffer->ProcessName = (PVOID)((UINT64)PidAndNameBuffer + sizeof(TRANSPARENCY_PROCESS)); - } - - // - // Link it to the list of process that we need to transparent - // vm-exits for them - // - InsertHeadList(&g_TransparentModeMeasurements->ProcessList, &(PidAndNameBuffer->OtherProcesses)); - - return TRUE; -} - -/** - * @brief Hide debugger on transparent-mode (activate transparent-mode) - * - * @param Measurements - * @return NTSTATUS - */ -NTSTATUS -TransparentHideDebugger(PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE Measurements) -{ - // - // Check whether the transparent-mode was already initialized or not - // - if (!g_TransparentMode) - { - // - // Allocate the measurements buffer - // - g_TransparentModeMeasurements = (PTRANSPARENCY_MEASUREMENTS)CrsAllocateZeroedNonPagedPool(sizeof(TRANSPARENCY_MEASUREMENTS)); - - if (!g_TransparentModeMeasurements) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Initialize the lists - // - InitializeListHead(&g_TransparentModeMeasurements->ProcessList); - - // - // Fill the transparency details CPUID - // - g_TransparentModeMeasurements->CpuidAverage = Measurements->CpuidAverage; - g_TransparentModeMeasurements->CpuidMedian = Measurements->CpuidMedian; - g_TransparentModeMeasurements->CpuidStandardDeviation = Measurements->CpuidStandardDeviation; - - // - // Fill the transparency details RDTSC - // - g_TransparentModeMeasurements->RdtscAverage = Measurements->RdtscAverage; - g_TransparentModeMeasurements->RdtscMedian = Measurements->RdtscMedian; - g_TransparentModeMeasurements->RdtscStandardDeviation = Measurements->RdtscStandardDeviation; - - // - // add the new process name or Id to the list - // - TransparentAddNameOrProcessIdToTheList(Measurements); - - // - // Enable RDTSC and RDTSCP exiting on all cores - // - BroadcastEnableRdtscExitingAllCores(); - - // - // Finally, enable the transparent-mode - // - g_TransparentMode = TRUE; - } - else - { - // - // It's already initialized, we just need to - // add the new process name or Id to the list - // - TransparentAddNameOrProcessIdToTheList(Measurements); - } - - return STATUS_SUCCESS; -} - -/** - * @brief Deactivate transparent-mode - * - * @return NTSTATUS - */ -NTSTATUS -TransparentUnhideDebugger() -{ - PLIST_ENTRY TempList = 0; - PVOID BufferToDeAllocate = 0; - - if (g_TransparentMode) - { - // - // Disable the transparent-mode - // - g_TransparentMode = FALSE; - - // - // Disable RDTSC and RDTSCP emulation - // - BroadcastDisableRdtscExitingAllCores(); - - // - // Free list of allocated buffers - // - // Check for process id and process name, if not match then we don't emulate it - // - TempList = &g_TransparentModeMeasurements->ProcessList; - while (&g_TransparentModeMeasurements->ProcessList != TempList->Flink) - { - TempList = TempList->Flink; - PTRANSPARENCY_PROCESS ProcessDetails = (PTRANSPARENCY_PROCESS)CONTAINING_RECORD(TempList, TRANSPARENCY_PROCESS, OtherProcesses); - - // - // Save the buffer so we can de-allocate it - // - BufferToDeAllocate = ProcessDetails->BufferAddress; - - // - // We have to remove the event from the list - // - RemoveEntryList(&ProcessDetails->OtherProcesses); - - // - // Free the buffer - // - CrsFreePool(BufferToDeAllocate); - } - - // - // Deallocate the measurements buffer - // - CrsFreePool(g_TransparentModeMeasurements); - g_TransparentModeMeasurements = NULL; - - return STATUS_SUCCESS; - } - else - { - return STATUS_UNSUCCESSFUL; - } -} - -/** - * @brief VM-Exit handler for different exit reasons - * @details Should be called from vmx-root - * - * @param VCpu The virtual processor's state - * @param ExitReason Exit Reason - * @return BOOLEAN Return True we should emulate RDTSCP - * or return false if we should not emulate RDTSCP - */ -BOOLEAN -TransparentModeStart(VIRTUAL_MACHINE_STATE * VCpu, UINT32 ExitReason) -{ - UINT32 Aux = 0; - PLIST_ENTRY TempList = 0; - PCHAR CurrentProcessName = 0; - UINT32 CurrentProcessId; - UINT64 CurrrentTime; - HANDLE CurrentThreadId; - BOOLEAN Result = TRUE; - BOOLEAN IsProcessOnTransparencyList = FALSE; - - // - // Save the current time - // - CurrrentTime = __rdtscp(&Aux); - - // - // Save time of vm-exit on each logical processor separately - // - VCpu->TransparencyState.PreviousTimeStampCounter = CurrrentTime; - - // - // Find the current process id and name - // - CurrentProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId()); - CurrentProcessName = CommonGetProcessNameFromProcessControlBlock(PsGetCurrentProcess()); - - // - // Check for process id and process name, if not match then we don't emulate it - // - TempList = &g_TransparentModeMeasurements->ProcessList; - while (&g_TransparentModeMeasurements->ProcessList != TempList->Flink) - { - TempList = TempList->Flink; - PTRANSPARENCY_PROCESS ProcessDetails = (PTRANSPARENCY_PROCESS)CONTAINING_RECORD(TempList, TRANSPARENCY_PROCESS, OtherProcesses); - if (ProcessDetails->TrueIfProcessIdAndFalseIfProcessName) - { - // - // This entry is process id - // - if (ProcessDetails->ProcessId == CurrentProcessId) - { - // - // Let the transparency handler to handle it - // - IsProcessOnTransparencyList = TRUE; - break; - } - } - else - { - // - // This entry is a process name - // - if (CurrentProcessName != NULL && CommonIsStringStartsWith(CurrentProcessName, ProcessDetails->ProcessName)) - { - // - // Let the transparency handler to handle it - // - IsProcessOnTransparencyList = TRUE; - break; - } - } - } - - // - // Check whether we find this process on transparency list or not - // - if (!IsProcessOnTransparencyList) - { - // - // No, we didn't let's do the normal tasks - // - return TRUE; - } - - // - // Get current thread Id - // - CurrentThreadId = PsGetCurrentThreadId(); - - // - // Check whether we are in new thread or in previous thread - // - if (VCpu->TransparencyState.ThreadId != CurrentThreadId) - { - // - // It's a new thread Id reset everything - // - VCpu->TransparencyState.ThreadId = CurrentThreadId; - VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc = NULL64_ZERO; - VCpu->TransparencyState.CpuidAfterRdtscDetected = FALSE; - } - - // - // Now, it's time to check and play with RDTSC/P and CPUID - // - - if (ExitReason == VMX_EXIT_REASON_EXECUTE_RDTSC || ExitReason == VMX_EXIT_REASON_EXECUTE_RDTSCP) - { - if (VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc == NULL64_ZERO) - { - // - // It's a timing and the previous time for the thread is null - // so we need to save the time (maybe) for future use - // - VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc = CurrrentTime; - } - else if (VCpu->TransparencyState.CpuidAfterRdtscDetected == TRUE) - { - // - // Someone tries to know about the hypervisor - // let's play with them - // - - // LogInfo("Possible RDTSC+CPUID+RDTSC"); - } - else if (VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc != NULL64_ZERO && - VCpu->TransparencyState.CpuidAfterRdtscDetected == FALSE) - { - // - // It's a new rdtscp, let's save the new value - // - VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc += - TransparentRandn((UINT32)g_TransparentModeMeasurements->CpuidAverage, - (UINT32)g_TransparentModeMeasurements->CpuidStandardDeviation); - ; - } - - // - // Adjust the rdtsc based on RevealedTimeStampCounterByRdtsc - // - VCpu->Regs->rax = 0x00000000ffffffff & - VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc; - - VCpu->Regs->rdx = 0x00000000ffffffff & - (VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc >> 32); - - // - // Check if we need to adjust rcx as a result of rdtscp - // - if (ExitReason == VMX_EXIT_REASON_EXECUTE_RDTSCP) - { - VCpu->Regs->rcx = 0x00000000ffffffff & Aux; - } - // - // Shows that vm-exit handler should not emulate the RDTSC/P - // - Result = FALSE; - } - else if (ExitReason == VMX_EXIT_REASON_EXECUTE_CPUID && - VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc != NULL64_ZERO) - { - // - // The guy executed one or more CPUIDs after an rdtscp so we - // need to add new cpuid value to previous timer and also - // we need to store it somewhere to remember this behavior - // - VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc += - TransparentRandn((UINT32)g_TransparentModeMeasurements->CpuidAverage, - (UINT32)g_TransparentModeMeasurements->CpuidStandardDeviation); - - VCpu->TransparencyState.CpuidAfterRdtscDetected = TRUE; - } - - return Result; -} diff --git a/hyperdbg/hprdbghv/header/assembly/InlineAsm.h b/hyperdbg/hprdbghv/header/assembly/InlineAsm.h deleted file mode 100644 index db946109..00000000 --- a/hyperdbg/hprdbghv/header/assembly/InlineAsm.h +++ /dev/null @@ -1,298 +0,0 @@ -/** - * @file InlineAsm.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief The definition of functions written in Assembly - * @details - * @version 0.1 - * @date 2020-04-11 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -// -// ==================== Vmx Operations ==================== -// File : AsmVmxOperation.asm -// - -/** - * @brief Enable VMX Operation - * - */ -extern void inline AsmEnableVmxOperation(); - -/** - * @brief Restore in vmxoff state - * - */ -extern void inline AsmRestoreToVmxOffState(); - -/** - * @brief Request Vmcall - * - * @param VmcallNumber - * @param OptionalParam1 - * @param OptionalParam2 - * @param OptionalParam3 - * @return NTSTATUS - */ -extern NTSTATUS inline AsmVmxVmcall(unsigned long long VmcallNumber, - unsigned long long OptionalParam1, - unsigned long long OptionalParam2, - long long OptionalParam3); - -/** - * @brief Hyper-v vmcall handler - * - * @param GuestRegisters - * @return void - */ -extern void inline AsmHypervVmcall(unsigned long long GuestRegisters); - -/** - * @brief VMFUNC instruction - * - * @param EptpIndex - * @param Function - * - * @return unsigned long long I'm not sure what it returns - */ -extern unsigned long long inline AsmVmfunc(unsigned long EptpIndex, unsigned long Function); - -// -// ==================== Vmx Context State Operations ==================== -// File : AsmVmxContextState.asm -// - -/** - * @brief Save state on vmx - * - */ -extern void -AsmVmxSaveState(); - -/** - * @brief Restore state on vmx - * - */ -extern void -AsmVmxRestoreState(); - -// -// ==================== Vmx VM-Exit Handler ==================== -// File : AsmVmexitHandler.asm -// - -/** - * @brief Vm-exit handler - * - */ -extern void -AsmVmexitHandler(); - -/** - * @brief Save vmxoff state - * - */ -extern void inline AsmSaveVmxOffState(); - -// -// ==================== Extended Page Tables ==================== -// File : AsmEpt.asm -// - -/** - * @brief INVEPT wrapper - * - * @param Type - * @param Descriptors - * @return unsigned char - */ -extern unsigned char inline AsmInvept(unsigned long Type, void * Descriptors); - -/** - * @brief INVVPID wrapper - * - * @param Type - * @param Descriptors - * @return unsigned char - */ -extern unsigned char inline AsmInvvpid(unsigned long Type, void * Descriptors); - -// -// ==================== Get segment registers ==================== -// File : AsmSegmentRegs.asm -// - -/* ********* Segment registers ********* */ - -/** - * @brief Get CS Register - * - * @return unsigned short - */ -extern unsigned short -AsmGetCs(); - -/** - * @brief Get DS Register - * - * @return unsigned short - */ -extern unsigned short -AsmGetDs(); - -/** - * @brief Get ES Register - * - * @return unsigned short - */ -extern unsigned short -AsmGetEs(); - -/** - * @brief Get SS Register - * - * @return unsigned short - */ -extern unsigned short -AsmGetSs(); - -/** - * @brief Get FS Register - * - * @return unsigned short - */ -extern unsigned short -AsmGetFs(); - -/** - * @brief Get GS Register - * - * @return unsigned short - */ -extern unsigned short -AsmGetGs(); - -/** - * @brief Get LDTR Register - * - * @return unsigned short - */ -extern unsigned short -AsmGetLdtr(); - -/** - * @brief Get TR Register - * - * @return unsigned short - */ -extern unsigned short -AsmGetTr(); - -/* ******* Gdt related functions ******* */ - -/** - * @brief get GDT base - * - * @return unsigned long long - */ -extern unsigned long long inline AsmGetGdtBase(); - -/** - * @brief Get GDT Limit - * - * @return unsigned short - */ -extern unsigned short -AsmGetGdtLimit(); - -/* ******* Idt related functions ******* */ - -/** - * @brief Get IDT base - * - * @return unsigned long long - */ -extern unsigned long long inline AsmGetIdtBase(); - -/** - * @brief Get IDT limit - * - * @return unsigned short - */ -extern unsigned short -AsmGetIdtLimit(); - -extern UINT32 -AsmGetAccessRights(unsigned short Selector); -// -// ==================== Common Functions ==================== -// File : AsmCommon.asm -// - -/** - * @brief Get R/EFLAGS - * - * @return unsigned short - */ -extern unsigned short -AsmGetRflags(); - -/** - * @brief Run CLI Instruction - * - */ -extern void inline AsmCliInstruction(); - -/** - * @brief Run STI Instruction - * - */ -extern void inline AsmStiInstruction(); - -/** - * @brief Reload new GDTR - * - * @param GdtBase - * @param GdtLimit - */ -extern void -AsmReloadGdtr(void * GdtBase, unsigned long GdtLimit); - -/** - * @brief Reload new IDTR - * - * @param GdtBase - * @param GdtLimit - */ -extern void -AsmReloadIdtr(void * GdtBase, unsigned long GdtLimit); - -// -// ==================== Hook Functions ==================== -// File : AsmHooks.asm -// - -/** - * @brief Detour hook handler - * - */ -extern void -AsmGeneralDetourHook(void); - -// -// ==================== Kernel Test Functions ==================== -// File : AsmKernelSideTests.asm -// - -/** - * @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); diff --git a/hyperdbg/hprdbghv/header/common/Common.h b/hyperdbg/hprdbghv/header/common/Common.h deleted file mode 100644 index 9bc72fc9..00000000 --- a/hyperdbg/hprdbghv/header/common/Common.h +++ /dev/null @@ -1,320 +0,0 @@ -/** - * @file Common.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Header files for common functions - * @details - * @version 0.1 - * @date 2020-04-10 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Enums // -////////////////////////////////////////////////// - -/** - * @brief Segment selector registers in x86 - * - */ -typedef enum _SEGMENT_REGISTERS -{ - ES = 0, - CS, - SS, - DS, - FS, - GS, - LDTR, - TR -} SEGMENT_REGISTERS; - -////////////////////////////////////////////////// -// Constants // -////////////////////////////////////////////////// - -/* - * @brief Windows IRQ Levels - */ -#define PASSIVE_LEVEL 0 // Passive release level -#define LOW_LEVEL 0 // Lowest interrupt level -#define APC_LEVEL 1 // APC interrupt level -#define DISPATCH_LEVEL 2 // Dispatcher level -#define CMCI_LEVEL 5 // CMCI handler level -#define CLOCK_LEVEL 13 // Interval clock level -#define IPI_LEVEL 14 // Interprocessor interrupt level -#define DRS_LEVEL 14 // Deferred Recovery Service level -#define POWER_LEVEL 14 // Power failure level -#define PROFILE_LEVEL 15 // timer used for profiling. -#define HIGH_LEVEL 15 // Highest interrupt level - -/** - * @brief Intel CPU flags in CR0 - */ -#define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */ -#define X86_CR0_MP 0x00000002 /* Monitor Coprocessor (RW) */ -#define X86_CR0_EM 0x00000004 /* Require FPU Emulation (RO) */ -#define X86_CR0_TS 0x00000008 /* Task Switched (RW) */ -#define X86_CR0_ET 0x00000010 /* Extension type (RO) */ -#define X86_CR0_NE 0x00000020 /* Numeric Error Reporting (RW) */ -#define X86_CR0_WP 0x00010000 /* Supervisor Write Protect (RW) */ -#define X86_CR0_AM 0x00040000 /* Alignment Checking (RW) */ -#define X86_CR0_NW 0x20000000 /* Not Write-Through (RW) */ -#define X86_CR0_CD 0x40000000 /* Cache Disable (RW) */ -#define X86_CR0_PG 0x80000000 /* Paging */ - -/** - * @brief Intel CPU features in CR4 - * - */ -#define X86_CR4_VME 0x0001 /* enable vm86 extensions */ -#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */ -#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ -#define X86_CR4_DE 0x0008 /* enable debugging extensions */ -#define X86_CR4_PSE 0x0010 /* enable page size extensions */ -#define X86_CR4_PAE 0x0020 /* enable physical address extensions */ -#define X86_CR4_MCE 0x0040 /* Machine check enable */ -#define X86_CR4_PGE 0x0080 /* enable global pages */ -#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ -#define X86_CR4_OSFXSR 0x0200 /* enable fast FPU save and restore */ -#define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */ -#define X86_CR4_VMXE 0x2000 /* enable VMX */ - -/** - * @brief EFLAGS/RFLAGS - * - */ -#define X86_FLAGS_CF (1 << 0) -#define X86_FLAGS_PF (1 << 2) -#define X86_FLAGS_AF (1 << 4) -#define X86_FLAGS_ZF (1 << 6) -#define X86_FLAGS_SF (1 << 7) -#define X86_FLAGS_TF (1 << 8) -#define X86_FLAGS_IF (1 << 9) -#define X86_FLAGS_DF (1 << 10) -#define X86_FLAGS_OF (1 << 11) -#define X86_FLAGS_STATUS_MASK (0xfff) -#define X86_FLAGS_IOPL_MASK (3 << 12) -#define X86_FLAGS_IOPL_SHIFT (12) -#define X86_FLAGS_IOPL_SHIFT_2ND_BIT (13) -#define X86_FLAGS_NT (1 << 14) -#define X86_FLAGS_RF (1 << 16) -#define X86_FLAGS_VM (1 << 17) -#define X86_FLAGS_AC (1 << 18) -#define X86_FLAGS_VIF (1 << 19) -#define X86_FLAGS_VIP (1 << 20) -#define X86_FLAGS_ID (1 << 21) -#define X86_FLAGS_RESERVED_ONES 0x2 -#define X86_FLAGS_RESERVED 0xffc0802a - -#define X86_FLAGS_RESERVED_BITS 0xffc38028 -#define X86_FLAGS_FIXED 0x00000002 - -////////////////////////////////////////////////// -// Constants // -////////////////////////////////////////////////// - -/* - * @brief Segment register and corresponding GDT meaning in Windows - */ -#define KGDT64_NULL (0 * 16) // NULL descriptor -#define KGDT64_R0_CODE (1 * 16) // kernel mode 64-bit code -#define KGDT64_R0_DATA (1 * 16) + 8 // kernel mode 64-bit data (stack) -#define KGDT64_R3_CMCODE (2 * 16) // user mode 32-bit code -#define KGDT64_R3_DATA (2 * 16) + 8 // user mode 32-bit data -#define KGDT64_R3_CODE (3 * 16) // user mode 64-bit code -#define KGDT64_SYS_TSS (4 * 16) // kernel mode system task state -#define KGDT64_R3_CMTEB (5 * 16) // user mode 32-bit TEB -#define KGDT64_R0_CMCODE (6 * 16) // kernel mode 32-bit code -#define KGDT64_LAST (7 * 16) // last entry - -/** - * @brief PCID Flags - * - */ -#define PCID_NONE 0x000 -#define PCID_MASK 0x003 - -/** - * @brief The Microsoft Hypervisor interface defined constants - * - */ -#define CPUID_HV_VENDOR_AND_MAX_FUNCTIONS 0x40000000 -#define CPUID_HV_INTERFACE 0x40000001 - -/** - * @brief Cpuid to get virtual address width - * - */ -#define CPUID_ADDR_WIDTH 0x80000008 - -/** - * @brief CPUID Features - * - */ -#define CPUID_PROCESSOR_AND_PROCESSOR_FEATURE_IDENTIFIERS 0x00000001 - -/** - * @brief Hypervisor reserved range for RDMSR and WRMSR - * - */ -#define RESERVED_MSR_RANGE_LOW 0x40000000 -#define RESERVED_MSR_RANGE_HI 0x400000F0 - -/** - * @brief Core Id - * - */ -#define __CPU_INDEX__ KeGetCurrentProcessorNumberEx(NULL) - -/** - * @brief Alignment Size - * - */ -#define ALIGNMENT_PAGE_SIZE 4096 - -/** - * @brief Maximum x64 Address - * - */ -#define MAXIMUM_ADDRESS 0xffffffffffffffff - -/** - * @brief System and User ring definitions - * - */ -#define DPL_USER 3 -#define DPL_SYSTEM 0 - -/** - * @brief RPL Mask - * - */ -#define RPL_MASK 3 - -#define BITS_PER_LONG (sizeof(unsigned long) * 8) -#define ORDER_LONG (sizeof(unsigned long) == 4 ? 5 : 6) - -#define BITMAP_ENTRY(_nr, _bmap) ((_bmap))[(_nr) / BITS_PER_LONG] -#define BITMAP_SHIFT(_nr) ((_nr) % BITS_PER_LONG) - -/** - * @brief Offset from a page's 4096 bytes - * - */ -#define PAGE_OFFSET(Va) ((PVOID)((ULONG_PTR)(Va) & (PAGE_SIZE - 1))) - -/** - * @brief Intel TSX Constants - * - */ -#define _XBEGIN_STARTED (~0u) -#define _XABORT_EXPLICIT (1 << 0) -#define _XABORT_RETRY (1 << 1) -#define _XABORT_CONFLICT (1 << 2) -#define _XABORT_CAPACITY (1 << 3) -#define _XABORT_DEBUG (1 << 4) -#define _XABORT_NESTED (1 << 5) - -#ifndef _XABORT_CODE -# define _XABORT_CODE(x) (((x) >> 24) & 0xFF) -#endif // !_XABORT_CODE - -////////////////////////////////////////////////// -// Structures // -////////////////////////////////////////////////// - -typedef SEGMENT_DESCRIPTOR_32 * PSEGMENT_DESCRIPTOR; - -/** - * @brief CPUID Registers - * - */ -typedef struct _CPUID -{ - int eax; - int ebx; - int ecx; - int edx; -} CPUID, *PCPUID; - -typedef union _CR_FIXED -{ - UINT64 Flags; - - struct - { - unsigned long Low; - long High; - - } Fields; - -} CR_FIXED, *PCR_FIXED; - -////////////////////////////////////////////////// -// Windows-specific structures // -////////////////////////////////////////////////// - -/** - * @brief KPROCESS Brief structure - * - */ -typedef struct _NT_KPROCESS -{ - DISPATCHER_HEADER Header; - LIST_ENTRY ProfileListHead; - ULONG_PTR DirectoryTableBase; - UCHAR Data[1]; -} NT_KPROCESS, *PNT_KPROCESS; - -////////////////////////////////////////////////// -// Function Types // -////////////////////////////////////////////////// - -/** - * @brief Prototype to run a function on a logical core - * - */ -typedef void (*RunOnLogicalCoreFunc)(ULONG ProcessorId); - -////////////////////////////////////////////////// -// External Functions // -////////////////////////////////////////////////// - -UCHAR * -PsGetProcessImageFileName(IN PEPROCESS Process); - -////////////////////////////////////////////////// -// Function Definitions // -////////////////////////////////////////////////// - -// ---------------------------------------------------------------------------- -// Private Interfaces -// - -static NTSTATUS -CommonGetHandleFromProcess(_In_ UINT32 ProcessId, _Out_ PHANDLE Handle); - -// ---------------------------------------------------------------------------- -// Public Interfaces -// - -BOOLEAN -CommonAffinityBroadcastToProcessors(_In_ ULONG ProcessorNumber, _In_ RunOnLogicalCoreFunc Routine); - -BOOLEAN -CommonIsStringStartsWith(const char * pre, const char * str); - -BOOLEAN -CommonIsGuestOnUsermode32Bit(); - -PCHAR -CommonGetProcessNameFromProcessControlBlock(PEPROCESS eprocess); - -VOID -CommonCpuidInstruction(UINT32 Func, UINT32 SubFunc, int * CpuInfo); - -VOID -CommonWriteDebugInformation(VIRTUAL_MACHINE_STATE * VCpu); diff --git a/hyperdbg/hprdbghv/header/platform/CrossApi.h b/hyperdbg/hprdbghv/header/platform/CrossApi.h deleted file mode 100644 index 7f950dbe..00000000 --- a/hyperdbg/hprdbghv/header/platform/CrossApi.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @file CrossApi.h - * @author Behrooz Abbassi (BehroozAbbassi@hyperdbg.org) - * @brief Cross platform APIs - * @details - * @version 0.1 - * @date 2022-01-17 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Functions // -////////////////////////////////////////////////// - -// -// Some functions are globally defined in SDK -// - -PVOID -CrsAllocateContiguousZeroedMemory(SIZE_T NumberOfBytes); diff --git a/hyperdbg/hprdbghv/header/platform/Environment.h b/hyperdbg/hprdbghv/header/platform/Environment.h deleted file mode 100644 index 13a28ee1..00000000 --- a/hyperdbg/hprdbghv/header/platform/Environment.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @file Environment.h - * @author Behrooz Abbassi (BehroozAbbassi@hyperdbg.org) - * @brief The running environment of HyperDbg - * @details - * @version 0.1 - * @date 2022-01-17 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Definitions // -////////////////////////////////////////////////// - -// -// Check for platform -// - -#if defined(_WIN32) || defined(_WIN64) -# define ENV_WINDOWS -#else -# error "This code cannot compile on non windows platforms" -#endif diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/IdtEmulation.h b/hyperdbg/hprdbghv/header/vmm/vmx/IdtEmulation.h deleted file mode 100644 index b6aa2e85..00000000 --- a/hyperdbg/hprdbghv/header/vmm/vmx/IdtEmulation.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file IdtEmulation.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Header for Handlers of Guest's IDT Emulator - * @details - * @version 0.1 - * @date 2020-06-10 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Functions // -////////////////////////////////////////////////// - -VOID -IdtEmulationHandleExceptionAndNmi(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, - _In_ VMEXIT_INTERRUPT_INFORMATION InterruptExit); - -VOID -IdtEmulationHandleExternalInterrupt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, - _In_ VMEXIT_INTERRUPT_INFORMATION InterruptExit); - -VOID -IdtEmulationHandleNmiWindowExiting(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); - -VOID -IdtEmulationHandleInterruptWindowExiting(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); diff --git a/hyperdbg/hprdbghv/hprdbghv.def b/hyperdbg/hprdbghv/hprdbghv.def deleted file mode 100644 index 27d4f806..00000000 --- a/hyperdbg/hprdbghv/hprdbghv.def +++ /dev/null @@ -1,6 +0,0 @@ -LIBRARY hprdbghv - -EXPORTS - - DllInitialize PRIVATE - DllUnload PRIVATE \ No newline at end of file diff --git a/hyperdbg/hprdbgkd/code/assembly/AsmKernelSideTests.asm b/hyperdbg/hprdbgkd/code/assembly/AsmKernelSideTests.asm deleted file mode 100644 index 9c7523f1..00000000 --- a/hyperdbg/hprdbgkd/code/assembly/AsmKernelSideTests.asm +++ /dev/null @@ -1,59 +0,0 @@ -PUBLIC AsmTestWrapperWithTestTags - -EXTERN g_KernelTestTargetFunction:QWORD -EXTERN g_KernelTestTag1:QWORD -EXTERN g_KernelTestTag2:QWORD - -EXTERN g_KernelTestR15:QWORD -EXTERN g_KernelTestR14:QWORD -EXTERN g_KernelTestR13:QWORD -EXTERN g_KernelTestR12:QWORD - -.code _text - -;------------------------------------------------------------------------ - -AsmTestWrapperWithTestTags PROC PUBLIC - - ; rcx, rdx, r8, r9 should not be changed due to the fast calling conventions - - ; Generally, The registers RAX, RCX, RDX, R8, R9, R10, R11 are - ; considered volatile (caller-saved) and registers RBX, RBP, RDI, - ; RSI, RSP, R12, R13, R14, and R15 are considered non-volatile (callee-saved) - - ; save registers - mov g_KernelTestR12, r12 ; save r12 - mov g_KernelTestR13, r13 ; save r13 - mov g_KernelTestR14, r14 ; save r14 - mov g_KernelTestR15, r15 ; save r15 - - ; apply tags to r15, and r14 - mov r14, g_KernelTestTag1 - mov r15, g_KernelTestTag2 - - pop r12 ; r12 is not changed (non-volatile) - ; we save it so we can restore to - ; TestKernelConfigureTagsAndCallTargetFunction - - mov r13, RestoreState ; use r13 to simulate the return point - push r13 - - jmp g_KernelTestTargetFunction ; jump target function (we didn't change its parameters) - -RestoreState: - push r12 ; Restore to the previous function address to return - ; TestKernelConfigureTagsAndCallTargetFunction - - ; restore registers - mov r12, g_KernelTestR12 ; restore r12 - mov r13, g_KernelTestR13 ; restore r13 - mov r14, g_KernelTestR14 ; restore r14 - mov r15, g_KernelTestR15 ; restore r15 - - ret - -AsmTestWrapperWithTestTags ENDP - -;------------------------------------------------------------------------ - -END diff --git a/hyperdbg/hprdbgkd/code/debugger/script-engine/ScriptEngine.c b/hyperdbg/hprdbgkd/code/debugger/script-engine/ScriptEngine.c deleted file mode 100644 index a346a419..00000000 --- a/hyperdbg/hprdbgkd/code/debugger/script-engine/ScriptEngine.c +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @file ScriptEngine.c - * @author M.H. Gholamrezaei (mh@hyperdbg.org) - * @brief Script engine parser and wrapper functions - * @details - * @version 0.1 - * @date 2020-10-22 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Get current ip from the debugger frame - * - * @return UINT64 returns the rip of the current debuggee state frame - */ -UINT64 -ScriptEngineWrapperGetInstructionPointer() -{ - // - // Check if we are in vmx-root or not - // - if (VmFuncVmxGetCurrentExecutionMode() == TRUE) - { - return VmFuncGetRip(); - } - else - { - // - // Otherwise $ip doesn't mean anything - // - return (UINT64)NULL; - } -} - -/** - * @brief Get the address of reserved buffer - * - * @param Action Corresponding action - * @return UINT64 returns the requested buffer address from user - */ -UINT64 -ScriptEngineWrapperGetAddressOfReservedBuffer(PDEBUGGER_EVENT_ACTION Action) -{ - return Action->RequestedBuffer.RequstBufferAddress; -} diff --git a/hyperdbg/hprdbgkd/code/debugger/tests/KernelTests.c b/hyperdbg/hprdbgkd/code/debugger/tests/KernelTests.c deleted file mode 100644 index 87435ed0..00000000 --- a/hyperdbg/hprdbgkd/code/debugger/tests/KernelTests.c +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @file KernelTests.c - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Implementation of kernel-side test functions - * @details - * - * @version 0.1 - * @date 2021-04-06 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Configures tags and calls target functions - * - * @details This function should not be called simultaneously - * and only functions with at most 4 parameters should be called - * the target function should be fast call - * Note : Target test function should check r14 for Tag1 and r15 for Tag2 - * - * @param Tag1 the first tag - * @param Tag2 the second tag - * @param TargetFunction function that needs to be called - * @param Param1 parameter to the target function - * @param Param2 parameter to the target function - * @param Param3 parameter to the target function - * @param Param4 parameter to the target function - * - * @return UINT64 Target function return result - */ -UINT64 -TestKernelConfigureTagsAndCallTargetFunction(UINT64 Tag1, - UINT64 Tag2, - PVOID TargetFunction, - UINT64 Param1, - UINT64 Param2, - UINT64 Param3, - UINT64 Param4) -{ - UINT64 TargetFuncResult = (UINT64)NULL; - - // - // Configure tags and target functions (export them to assembly) - // - g_KernelTestTargetFunction = TargetFunction; - g_KernelTestTag1 = (UINT64)Tag1; - g_KernelTestTag2 = (UINT64)Tag2; - g_KernelTestR15 = (UINT64)NULL; - g_KernelTestR14 = (UINT64)NULL; - g_KernelTestR13 = (UINT64)NULL; - g_KernelTestR12 = (UINT64)NULL; - - // - // Call the target function - // - TargetFuncResult = AsmTestWrapperWithTestTags(Param1, Param2, Param3, Param4); - - // - // Null the exports - // - g_KernelTestTargetFunction = (PVOID)NULL; - g_KernelTestTag1 = (UINT64)NULL; - g_KernelTestTag2 = (UINT64)NULL; - g_KernelTestR15 = (UINT64)NULL; - g_KernelTestR14 = (UINT64)NULL; - g_KernelTestR13 = (UINT64)NULL; - g_KernelTestR12 = (UINT64)NULL; - - return TargetFuncResult; -} - -/** - * @brief Perform the kernel-side tests - * - * @param KernelTestRequest user-mode buffer to fill kernel test information - * @return VOID - */ -VOID -TestKernelPerformTests(PDEBUGGER_PERFORM_KERNEL_TESTS KernelTestRequest) -{ - UINT64 TempPool = (UINT64)NULL; - - LogInfo("Starting kernel-test process..."); - - // - // Call wrapper for ExAllocatePool2 - // - TempPool = TestKernelConfigureTagsAndCallTargetFunction(1, // Tag1 = r14 - 2, // Tag2 = r15 - (PVOID)ExAllocatePool2, // Target function - NonPagedPool, // PoolType - PAGE_SIZE, // NumberOfBytes - POOLTAG, // Tag - (UINT64)NULL); - - if (TempPool != (UINT64)NULL) - { - // - // Free the previous pool - // - CrsFreePool((PVOID)TempPool); - } - - LogInfo("All the kernel events are triggered"); - - KernelTestRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; -} - -/** - * @brief Collect the kernel-side debugging information - * - * @param InfoRequest user-mode buffer to fill kernel information - * @return UINT32 Filled entries - */ -UINT32 -TestKernelGetInformation(PDEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION InfoRequest) -{ - UINT32 Index = 0; - - // - // Zero the memory - // - RtlZeroMemory(&InfoRequest[0], TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - - // - // *** Fill kernel functions information *** - // - - // ------------------------------------------------------ - - Index = 0; - InfoRequest[Index].Value = (UINT64)ExAllocatePool2; - memcpy(&InfoRequest[Index].Tag, "ExAllocatePool2", strlen("ExAllocatePool2") + 1); - - // ------------------------------------------------------ - - Index = 1; - InfoRequest[Index].Value = (UINT64)NtReadFile; - memcpy(&InfoRequest[Index].Tag, "NtReadFile", strlen("NtReadFile") + 1); - - // ------------------------------------------------------ - - Index = 2; - InfoRequest[Index].Value = (UINT64)NtWriteFile; - memcpy(&InfoRequest[Index].Tag, "NtWriteFile", strlen("NtWriteFile") + 1); - - // ------------------------------------------------------ - - // - // Check maximum index - // - if (Index > TEST_CASE_MAXIMUM_NUMBER_OF_KERNEL_TEST_CASES) - { - LogError("Err, test cases are above the supported buffers"); - return 0; - } - - // - // Return the index (add +1 because we start from zero) - // - return Index + 1; -} diff --git a/hyperdbg/hprdbgkd/code/debugger/user-level/Ud.c b/hyperdbg/hprdbgkd/code/debugger/user-level/Ud.c deleted file mode 100644 index efe94b54..00000000 --- a/hyperdbg/hprdbgkd/code/debugger/user-level/Ud.c +++ /dev/null @@ -1,610 +0,0 @@ -/** - * @file Ud.c - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Routines related to user mode debugging - * @details - * @version 0.1 - * @date 2022-01-06 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief initialize user debugger - * @details this function should be called on vmx non-root - * - * @return BOOLEAN - */ -BOOLEAN -UdInitializeUserDebugger() -{ - // - // Check if it's already initialized or not, we'll ignore it if it's - // previously initialized - // - if (g_UserDebuggerState) - { - return TRUE; - } - - // - // Check if we have functions we need for attaching mechanism - // - if (g_PsGetProcessPeb == NULL || g_PsGetProcessWow64Process == NULL || g_ZwQueryInformationProcess == NULL) - { - LogError("Err, unable to find needed functions for user-debugger"); - // return FALSE; - } - - // - // Start the seed of user-mode debugging thread - // - g_SeedOfUserDebuggingDetails = DebuggerThreadDebuggingTagStartSeed; - - // - // Initialize the thread debugging details list - // - InitializeListHead(&g_ProcessDebuggingDetailsListHead); - - // - // Enable vm-exit on Hardware debug exceptions and breakpoints - // so, intercept #DBs and #BP by changing exception bitmap (one core) - // - BroadcastEnableDbAndBpExitingAllCores(); - - // - // Request to allocate buffers for thread holder of threads - // - ThreadHolderAllocateThreadHoldingBuffers(); - - // - // Indicate that the user debugger is active - // - g_UserDebuggerState = TRUE; - - return TRUE; -} - -/** - * @brief uninitialize user debugger - * @details this function should be called on vmx non-root - * - * @return VOID - */ -VOID -UdUninitializeUserDebugger() -{ - if (g_UserDebuggerState) - { - // - // Indicate that the user debugger is not active - // - g_UserDebuggerState = FALSE; - - // - // Free and deallocate all the buffers (pools) relating to - // thread debugging details - // - AttachingRemoveAndFreeAllProcessDebuggingDetails(); - } -} - -/** - * @brief Restore the thread to the original direction - * - * @param ThreadDebuggingDetails - * - * @return VOID - */ -VOID -UdRestoreToOriginalDirection(PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails) -{ - // - // Configure the RIP again - // - VmFuncSetRip(ThreadDebuggingDetails->ThreadRip); -} - -/** - * @brief Continue the thread - * - * @param ThreadDebuggingDetails - * - * @return VOID - */ -VOID -UdContinueThread(PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails) -{ - // - // Configure the RIP and RSP again - // - UdRestoreToOriginalDirection(ThreadDebuggingDetails); - - // - // Continue the current instruction won't pass it - // - VmFuncSuppressRipIncrement(KeGetCurrentProcessorNumberEx(NULL)); - - // - // It's not paused anymore! - // - ThreadDebuggingDetails->IsPaused = FALSE; -} - -/** - * @brief Perform stepping though the instructions in target thread - * - * @param ThreadDebuggingDetails - * - * @return VOID - */ -VOID -UdStepInstructions(PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, - DEBUGGER_REMOTE_STEPPING_REQUEST SteppingType) -{ - // - // Configure the RIP - // - UdRestoreToOriginalDirection(ThreadDebuggingDetails); - - switch (SteppingType) - { - case DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_IN: - - // - // Set the trap-flag - // - VmFuncSetRflagTrapFlag(TRUE); - - // - // Indicate that we should set the trap flag to the FALSE next time on - // the same process/thread - // - if (!BreakpointRestoreTheTrapFlagOnceTriggered(HANDLE_TO_UINT32(PsGetCurrentProcessId()), HANDLE_TO_UINT32(PsGetCurrentThreadId()))) - { - LogWarning("Warning, it is currently not possible to add the current process/thread to the list of processes " - "where the trap flag should be masked. Please ensure that you manually unset the trap flag"); - } - - break; - - case DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER: - - break; - - default: - break; - } - - // - // Continue the current instruction won't pass it - // - VmFuncSuppressRipIncrement(KeGetCurrentProcessorNumberEx(NULL)); - - // - // It's not paused anymore! - // - ThreadDebuggingDetails->IsPaused = FALSE; -} - -/** - * @brief Perform the user-mode commands - * - * @param ThreadDebuggingDetails - * @param UserAction - * @param OptionalParam1 - * @param OptionalParam2 - * @param OptionalParam3 - * @param OptionalParam4 - * - * @return BOOLEAN - */ -BOOLEAN -UdPerformCommand(PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, - DEBUGGER_UD_COMMAND_ACTION_TYPE UserAction, - UINT64 OptionalParam1, - UINT64 OptionalParam2, - UINT64 OptionalParam3, - UINT64 OptionalParam4) -{ - UNREFERENCED_PARAMETER(OptionalParam2); - UNREFERENCED_PARAMETER(OptionalParam3); - UNREFERENCED_PARAMETER(OptionalParam4); - - // - // Perform the command - // - switch (UserAction) - { - case DEBUGGER_UD_COMMAND_ACTION_TYPE_CONTINUE: - - // - // Continue the thread normally - // - UdContinueThread(ThreadDebuggingDetails); - - break; - - case DEBUGGER_UD_COMMAND_ACTION_TYPE_REGULAR_STEP: - - // - // Stepping through the instructions - // - UdStepInstructions(ThreadDebuggingDetails, (DEBUGGER_REMOTE_STEPPING_REQUEST)OptionalParam1); - - break; - - default: - - // - // Invalid user action - // - return FALSE; - break; - } - - return TRUE; -} - -/** - * @brief Check for the user-mode commands - * - * @return BOOLEAN - */ -BOOLEAN -UdCheckForCommand() -{ - PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails; - - // - // Check if user-debugger is initialized or not - // - if (!g_UserDebuggerState) - { - return FALSE; - } - - ThreadDebuggingDetails = ThreadHolderGetProcessThreadDetailsByProcessIdAndThreadId(HANDLE_TO_UINT32(PsGetCurrentProcessId()), - HANDLE_TO_UINT32(PsGetCurrentThreadId())); - - if (!ThreadDebuggingDetails) - { - return FALSE; - } - - // - // If we reached here, the current thread is in debugger attached mechanism - // now we check whether it's a regular CPUID or a debugger paused thread CPUID - // - if (!ThreadDebuggingDetails->IsPaused) - { - return FALSE; - } - - // - // 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++) - { - if (ThreadDebuggingDetails->UdAction[i].ActionType != DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE) - { - // - // Perform the command - // - UdPerformCommand(ThreadDebuggingDetails, - ThreadDebuggingDetails->UdAction[i].ActionType, - ThreadDebuggingDetails->UdAction[i].OptionalParam1, - ThreadDebuggingDetails->UdAction[i].OptionalParam2, - ThreadDebuggingDetails->UdAction[i].OptionalParam3, - ThreadDebuggingDetails->UdAction[i].OptionalParam4); - - // - // Remove the command - // - ThreadDebuggingDetails->UdAction[i].OptionalParam1 = (UINT64)NULL; - ThreadDebuggingDetails->UdAction[i].OptionalParam2 = (UINT64)NULL; - ThreadDebuggingDetails->UdAction[i].OptionalParam3 = (UINT64)NULL; - ThreadDebuggingDetails->UdAction[i].OptionalParam4 = (UINT64)NULL; - - // - // At last disable it - // - ThreadDebuggingDetails->UdAction[i].ActionType = DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE; - - // - // only one command at a time - // - break; - } - } - - // - // Won't change the registers for cpuid - // - return TRUE; -} - -/** - * @brief Dispatch the user-mode commands - * - * @param ActionRequest - * @return BOOLEAN - */ -BOOLEAN -UdDispatchUsermodeCommands(PDEBUGGER_UD_COMMAND_PACKET ActionRequest) -{ - PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails; - - // - // Find the thread debugging detail of the thread - // - ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByToken(ActionRequest->ProcessDebuggingDetailToken); - - if (!ProcessDebuggingDetails) - { - // - // Token not found! - // - return FALSE; - } - - // - // Based on the documentation, HyperDbg stops intercepting threads - // when the debugger sent the first command, but if user presses - // CTRL+C again, all the threads (or new threads) that will enter - // the user-mode will be intercepted - // - if (ProcessDebuggingDetails->IsOnThreadInterceptingPhase) - { - AttachingConfigureInterceptingThreads(ProcessDebuggingDetails->Token, FALSE); - } - - // - // Apply the command to all threads or just one thread - // - return ThreadHolderApplyActionToPausedThreads(ProcessDebuggingDetails, ActionRequest); -} - -/** - * @brief Spin on nop sled in user-mode to halt the debuggee - * - * @param ThreadDebuggingDetails - * @param ProcessDebuggingDetails - * @return VOID - */ -VOID -UdSpinThreadOnNop(PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, - PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails) -{ - // - // Save the RIP for future return - // - ThreadDebuggingDetails->ThreadRip = VmFuncGetRip(); - - // - // Set the rip to new spinning address - // - VmFuncSetRip(ProcessDebuggingDetails->UsermodeReservedBuffer); - - // - // Indicate that it's spinning - // - ThreadDebuggingDetails->IsPaused = TRUE; -} - -/** - * @brief Handle special reasons pre-pausings - * @details This function can be used in vmx-root - * - * @param DbgState The state of the debugger on the current core - * @param ThreadDebuggingDetails - * @param Reason - * @param EventDetails - * @return VOID - */ -VOID -UdPrePausingReasons(PROCESSOR_DEBUGGING_STATE * DbgState, - PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, - DEBUGGEE_PAUSING_REASON Reason, - PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails) - -{ - UNREFERENCED_PARAMETER(DbgState); - UNREFERENCED_PARAMETER(ThreadDebuggingDetails); - UNREFERENCED_PARAMETER(EventDetails); - - // - // *** Handle events before pausing *** - // - switch (Reason) - { - case DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_DEBUG_BREAK: - - break; - - default: - break; - } -} - -/** - * @brief Handle #DBs and #BPs for kernel debugger - * @details This function can be used in vmx-root - * - * @param DbgState The state of the debugger on the current core - * @param Reason - * @param EventDetails - * @return BOOLEAN - */ -BOOLEAN -UdCheckAndHandleBreakpointsAndDebugBreaks(PROCESSOR_DEBUGGING_STATE * DbgState, - DEBUGGEE_PAUSING_REASON Reason, - PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails) -{ - DEBUGGEE_UD_PAUSED_PACKET PausePacket; - ULONG ExitInstructionLength = 0; - UINT32 SizeOfSafeBufferToRead = 0; - RFLAGS Rflags = {0}; - PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails = NULL; - PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails = NULL; - UINT64 LastVmexitRip = VmFuncGetLastVmexitRip(DbgState->CoreId); - - // - // Breaking only supported in vmx-root mode, and if user-debugger is - // loaded - // - if (!g_UserDebuggerState && VmFuncVmxGetCurrentExecutionMode() == FALSE) - { - return FALSE; - } - - // - // Check entry of paused thread - // - ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId())); - - if (!ProcessDebuggingDetails) - { - // - // Token not found! - // - return FALSE; - } - - // - // Find the thread entry and if not found, create one for it - // - ThreadDebuggingDetails = ThreadHolderFindOrCreateThreadDebuggingDetail(HANDLE_TO_UINT32(PsGetCurrentThreadId()), ProcessDebuggingDetails); - - if (!ThreadDebuggingDetails) - { - // - // Sth went wrong! - // - return FALSE; - } - - // - // Set it as active thread debugging - // - ProcessDebuggingDetails->ActiveThreadId = ThreadDebuggingDetails->ThreadId; - - // - // Perform the pre-pausing tasks - // - UdPrePausingReasons(DbgState, ThreadDebuggingDetails, Reason, EventDetails); - - // - // *** Fill the pausing structure *** - // - - RtlZeroMemory(&PausePacket, sizeof(DEBUGGEE_UD_PAUSED_PACKET)); - - // - // Set the pausing reason - // - PausePacket.PausingReason = Reason; - - // - // Set process debugging information - // - PausePacket.ProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId()); - PausePacket.ThreadId = HANDLE_TO_UINT32(PsGetCurrentThreadId()); - PausePacket.ProcessDebuggingToken = ProcessDebuggingDetails->Token; - - // - // Set the RIP and mode of execution - // - PausePacket.Rip = LastVmexitRip; - PausePacket.Is32Bit = KdIsGuestOnUsermode32Bit(); - - // - // Set rflags for finding the results of conditional jumps - // - Rflags.AsUInt = VmFuncGetRflags(); - PausePacket.Rflags = Rflags.AsUInt; - - // - // Set the event tag (if it's an event) - // - if (EventDetails != NULL) - { - PausePacket.EventTag = EventDetails->Tag; - PausePacket.EventCallingStage = EventDetails->Stage; - } - - // - // Read the instruction len - // - if (DbgState->InstructionLengthHint != 0) - { - ExitInstructionLength = DbgState->InstructionLengthHint; - } - else - { - // - // Reading instruction length (VMCS_VMEXIT_INSTRUCTION_LENGTH) proved to - // provide wrong results, so we won't use it - // - - // - // Compute the amount of buffer we can read without problem - // - SizeOfSafeBufferToRead = (UINT32)(LastVmexitRip & 0xfff); - SizeOfSafeBufferToRead += MAXIMUM_INSTR_SIZE; - - if (SizeOfSafeBufferToRead >= PAGE_SIZE) - { - SizeOfSafeBufferToRead = SizeOfSafeBufferToRead - PAGE_SIZE; - SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE - SizeOfSafeBufferToRead; - } - else - { - SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE; - } - - // - // Set the length to notify debuggee - // - ExitInstructionLength = SizeOfSafeBufferToRead; - } - - // - // Set the reading length of bytes (for instruction disassembling) - // - PausePacket.ReadInstructionLen = (UINT16)ExitInstructionLength; - - // - // Find the current instruction - // - MemoryMapperReadMemorySafeOnTargetProcess(LastVmexitRip, - &PausePacket.InstructionBytesOnRip, - ExitInstructionLength); - - // - // Copy registers to the pause packet - // - RtlCopyMemory(&PausePacket.GuestRegs, DbgState->Regs, sizeof(GUEST_REGS)); - - // - // Send the pause packet, along with RIP and an indication - // to pause to the user debugger - // - LogCallbackSendBuffer(OPERATION_NOTIFICATION_FROM_USER_DEBUGGER_PAUSE, - &PausePacket, - sizeof(DEBUGGEE_UD_PAUSED_PACKET), - TRUE); - - // - // Halt the thread on nop sleds - // - UdSpinThreadOnNop(ThreadDebuggingDetails, ProcessDebuggingDetails); - - // - // Everything was okay - // - return TRUE; -} diff --git a/hyperdbg/hprdbgkd/code/driver/Ioctl.c b/hyperdbg/hprdbgkd/code/driver/Ioctl.c deleted file mode 100644 index 6d9bdf9d..00000000 --- a/hyperdbg/hprdbgkd/code/driver/Ioctl.c +++ /dev/null @@ -1,1546 +0,0 @@ -/** - * @file Ioctl.c - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief IOCTL Functions form user mode and other parts - * @details - * - * @version 0.1 - * @date 2020-06-01 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Driver IOCTL Dispatcher - * - * @param DeviceObject - * @param Irp - * @return NTSTATUS - */ -NTSTATUS -DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - PIO_STACK_LOCATION IrpStack; - PREGISTER_NOTIFY_BUFFER RegisterEventRequest; - PDEBUGGER_READ_MEMORY DebuggerReadMemRequest; - PDEBUGGER_READ_AND_WRITE_ON_MSR DebuggerReadOrWriteMsrRequest; - PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE DebuggerHideAndUnhideRequest; - PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS DebuggerPteRequest; - PDEBUGGER_PAGE_IN_REQUEST DebuggerPageinRequest; - PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS DebuggerVa2paAndPa2vaRequest; - PDEBUGGER_EDIT_MEMORY DebuggerEditMemoryRequest; - PDEBUGGER_SEARCH_MEMORY DebuggerSearchMemoryRequest; - PDEBUGGER_GENERAL_EVENT_DETAIL DebuggerNewEventRequest; - PDEBUGGER_MODIFY_EVENTS DebuggerModifyEventRequest; - PDEBUGGER_FLUSH_LOGGING_BUFFERS DebuggerFlushBuffersRequest; - PDEBUGGER_PREALLOC_COMMAND DebuggerReservePreallocPoolRequest; - PDEBUGGER_PREACTIVATE_COMMAND DebuggerPreactivationRequest; - PDEBUGGER_UD_COMMAND_PACKET DebuggerUdCommandRequest; - PUSERMODE_LOADED_MODULE_DETAILS DebuggerUsermodeModulesRequest; - PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS DebuggerUsermodeProcessOrThreadQueryRequest; - PDEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET GetInformationProcessRequest; - PREVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST RevServiceRequest; - PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET GetInformationThreadRequest; - PDEBUGGER_PERFORM_KERNEL_TESTS DebuggerKernelTestRequest; - PDEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL DebuggerCommandExecutionFinishedRequest; - PDEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION DebuggerKernelSideTestInformationRequest; - PDEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER DebuggerSendUsermodeMessageRequest; - PDEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER DebuggerSendBufferFromDebuggeeToDebuggerRequest; - PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS DebuggerAttachOrDetachToThreadRequest; - PDEBUGGER_PREPARE_DEBUGGEE DebuggeeRequest; - PDEBUGGER_PAUSE_PACKET_RECEIVED DebuggerPauseKernelRequest; - PDEBUGGER_GENERAL_ACTION DebuggerNewActionRequest; - PVOID BufferToStoreThreadsAndProcessesDetails; - NTSTATUS Status; - ULONG InBuffLength; // Input buffer length - ULONG OutBuffLength; // Output buffer length - SIZE_T ReturnSize; - BOOLEAN DoNotChangeInformation = FALSE; - UINT32 FilledEntriesInKernelInfo; - - // - // Here's the best place to see if there is any allocation pending - // to be allcated as we're in PASSIVE_LEVEL - // - PoolManagerCheckAndPerformAllocationAndDeallocation(); - - if (g_AllowIOCTLFromUsermode) - { - IrpStack = IoGetCurrentIrpStackLocation(Irp); - - switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_REGISTER_EVENT: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_REGISTER_EVENT || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - // - // IRPs supply a pointer to a buffer at Irp->AssociatedIrp.SystemBuffer. - // This buffer represents both the input buffer and the output buffer that - // are specified in calls to DeviceIoControl - // - RegisterEventRequest = (PREGISTER_NOTIFY_BUFFER)Irp->AssociatedIrp.SystemBuffer; - - switch (RegisterEventRequest->Type) - { - case IRP_BASED: - Status = LogRegisterIrpBasedNotification(DeviceObject, Irp); - break; - case EVENT_BASED: - Status = LogRegisterEventBasedNotification(DeviceObject, Irp); - break; - default: - LogError("Err, unknown notification type from user-mode"); - Status = STATUS_INVALID_PARAMETER; - break; - } - - break; - - case IOCTL_RETURN_IRP_PENDING_PACKETS_AND_DISALLOW_IOCTL: - - // - // Dis-allow new IOCTL - // - g_AllowIOCTLFromUsermode = FALSE; - - // - // Send an immediate message, and we're no longer get new IRP - // - LogCallbackSendBuffer(OPERATION_HYPERVISOR_DRIVER_END_OF_IRPS, - "$", - sizeof(CHAR), - TRUE); - - Status = STATUS_SUCCESS; - - break; - - case IOCTL_TERMINATE_VMX: - - // - // Uninitialize the debugger and its sub-mechanisms - // - DebuggerUninitialize(); - - // - // Terminate VMX - // - VmFuncUninitVmm(); - - Status = STATUS_SUCCESS; - - break; - - case IOCTL_DEBUGGER_READ_MEMORY: - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_READ_MEMORY || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - DebuggerReadMemRequest = (PDEBUGGER_READ_MEMORY)Irp->AssociatedIrp.SystemBuffer; - - if (DebuggerCommandReadMemory(DebuggerReadMemRequest, - ((CHAR *)DebuggerReadMemRequest) + SIZEOF_DEBUGGER_READ_MEMORY, - &ReturnSize) == TRUE) - { - // - // Return the header a read bytes - // - Irp->IoStatus.Information = ReturnSize + SIZEOF_DEBUGGER_READ_MEMORY; - } - else - { - // - // Just return the header to the user-mode - // - Irp->IoStatus.Information = SIZEOF_DEBUGGER_READ_MEMORY; - } - - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_READ_OR_WRITE_MSR: - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_READ_AND_WRITE_ON_MSR || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - DebuggerReadOrWriteMsrRequest = (PDEBUGGER_READ_AND_WRITE_ON_MSR)Irp->AssociatedIrp.SystemBuffer; - - // - // Only the rdmsr needs and output buffer - // - if (DebuggerReadOrWriteMsrRequest->ActionType != DEBUGGER_MSR_WRITE) - { - if (!OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - Status = DebuggerReadOrWriteMsr(DebuggerReadOrWriteMsrRequest, (UINT64 *)DebuggerReadOrWriteMsrRequest, &ReturnSize); - - // - // Set the size - // - if (Status == STATUS_SUCCESS) - { - Irp->IoStatus.Information = ReturnSize; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - } - - break; - - case IOCTL_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - DebuggerPteRequest = (PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS)Irp->AssociatedIrp.SystemBuffer; - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place (it's not in vmx-root) - // - ExtensionCommandPte(DebuggerPteRequest, FALSE); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_REGISTER_EVENT: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(DEBUGGER_GENERAL_EVENT_DETAIL) || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - DebuggerNewEventRequest = (PDEBUGGER_GENERAL_EVENT_DETAIL)Irp->AssociatedIrp.SystemBuffer; - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place (not coming from the VMX-root mode) - // - DebuggerParseEvent(DebuggerNewEventRequest, - (PDEBUGGER_EVENT_AND_ACTION_RESULT)Irp->AssociatedIrp.SystemBuffer, - FALSE); - - Irp->IoStatus.Information = sizeof(DEBUGGER_EVENT_AND_ACTION_RESULT); - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_ADD_ACTION_TO_EVENT: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(DEBUGGER_GENERAL_ACTION) || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - DebuggerNewActionRequest = (PDEBUGGER_GENERAL_ACTION)Irp->AssociatedIrp.SystemBuffer; - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerParseAction(DebuggerNewActionRequest, - (PDEBUGGER_EVENT_AND_ACTION_RESULT)Irp->AssociatedIrp.SystemBuffer, - FALSE); - - Irp->IoStatus.Information = sizeof(DEBUGGER_EVENT_AND_ACTION_RESULT); - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_HIDE_AND_UNHIDE_TO_TRANSPARENT_THE_DEBUGGER: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - DebuggerHideAndUnhideRequest = (PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE)Irp->AssociatedIrp.SystemBuffer; - - // - // Here we should validate whether the input parameter is - // valid or in other words whether we received enough space or not - // - if (DebuggerHideAndUnhideRequest->TrueIfProcessIdAndFalseIfProcessName == FALSE && IrpStack->Parameters.DeviceIoControl.InputBufferLength != SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE + DebuggerHideAndUnhideRequest->LengthOfProcessName) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // check if it's a !hide or !unhide command - // - if (DebuggerHideAndUnhideRequest->IsHide == TRUE) - { - // - // It's a hide request - // - Status = TransparentHideDebugger(DebuggerHideAndUnhideRequest); - } - else - { - // - // It's a unhide request - // - Status = TransparentUnhideDebugger(); - } - - if (Status == STATUS_SUCCESS) - { - // - // Set the status - // - DebuggerHideAndUnhideRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - } - else - { - // - // Set the status - // - if (DebuggerHideAndUnhideRequest->IsHide) - { - DebuggerHideAndUnhideRequest->KernelStatus = DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER; - } - else - { - DebuggerHideAndUnhideRequest->KernelStatus = DEBUGGER_ERROR_DEBUGGER_ALREADY_UHIDE; - } - } - - // - // Set size - // - Irp->IoStatus.Information = SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_VA2PA_AND_PA2VA_COMMANDS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_VA2PA_AND_PA2VA_COMMANDS || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - DebuggerVa2paAndPa2vaRequest = (PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS)Irp->AssociatedIrp.SystemBuffer; - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place (we're not in vmx-root here) - // - ExtensionCommandVa2paAndPa2va(DebuggerVa2paAndPa2vaRequest, FALSE); - - // - // Configure IRP status - // - Irp->IoStatus.Information = SIZEOF_DEBUGGER_VA2PA_AND_PA2VA_COMMANDS; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_EDIT_MEMORY: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_EDIT_MEMORY || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Cast buffer to understandable buffer - // - DebuggerEditMemoryRequest = (PDEBUGGER_EDIT_MEMORY)Irp->AssociatedIrp.SystemBuffer; - - // - // Here we should validate whether the input parameter is - // valid or in other words whether we received enough space or not - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength != SIZEOF_DEBUGGER_EDIT_MEMORY + DebuggerEditMemoryRequest->CountOf64Chunks * sizeof(UINT64)) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerCommandEditMemory(DebuggerEditMemoryRequest); - - // - // Configure IRP status - // - Irp->IoStatus.Information = SIZEOF_DEBUGGER_EDIT_MEMORY; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_SEARCH_MEMORY: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_SEARCH_MEMORY || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - // - // The OutBuffLength should have at least MaximumSearchResults * sizeof(UINT64) - // free space to store the results - // - if (!InBuffLength || OutBuffLength < MaximumSearchResults * sizeof(UINT64)) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Cast buffer to understandable buffer - // - DebuggerSearchMemoryRequest = (PDEBUGGER_SEARCH_MEMORY)Irp->AssociatedIrp.SystemBuffer; - - // - // Here we should validate whether the input parameter is - // valid or in other words whether we received enough space or not - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength != SIZEOF_DEBUGGER_SEARCH_MEMORY + DebuggerSearchMemoryRequest->CountOf64Chunks * sizeof(UINT64)) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - if (DebuggerCommandSearchMemory(DebuggerSearchMemoryRequest) != STATUS_SUCCESS) - { - // - // It is because it was not valid in any of the ways to the function - // then we're sure that the usermode code won't interpret it's previous - // buffer as a valid buffer and will not show it to the user - // - RtlZeroMemory(DebuggerSearchMemoryRequest, MaximumSearchResults * sizeof(UINT64)); - } - - // - // Configure IRP status, and also we send the results - // buffer, with it's null values (if any) - // - Irp->IoStatus.Information = MaximumSearchResults * sizeof(UINT64); - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_MODIFY_EVENTS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(DEBUGGER_MODIFY_EVENTS) || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - DebuggerModifyEventRequest = (PDEBUGGER_MODIFY_EVENTS)Irp->AssociatedIrp.SystemBuffer; - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerParseEventsModification(DebuggerModifyEventRequest, FALSE, EnableInstantEventMechanism ? g_KernelDebuggerState : FALSE); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_MODIFY_EVENTS; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_FLUSH_LOGGING_BUFFERS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_FLUSH_LOGGING_BUFFERS || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerFlushBuffersRequest = (PDEBUGGER_FLUSH_LOGGING_BUFFERS)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the flush - // - DebuggerCommandFlush(DebuggerFlushBuffersRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_FLUSH_LOGGING_BUFFERS; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerAttachOrDetachToThreadRequest = (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the attach to the target process - // - AttachingTargetProcess(DebuggerAttachOrDetachToThreadRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_PREPARE_DEBUGGEE: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_PREPARE_DEBUGGEE || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggeeRequest = (PDEBUGGER_PREPARE_DEBUGGEE)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the action - // - SerialConnectionPrepare(DebuggeeRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_PREPARE_DEBUGGEE; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_PAUSE_PACKET_RECEIVED: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_PAUSE_PACKET_RECEIVED || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerPauseKernelRequest = (PDEBUGGER_PAUSE_PACKET_RECEIVED)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the action - // - KdHaltSystem(DebuggerPauseKernelRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_PAUSE_PACKET_RECEIVED; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_SEND_SIGNAL_EXECUTION_IN_DEBUGGEE_FINISHED: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerCommandExecutionFinishedRequest = (PDEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the signal operation - // - DebuggerCommandSignalExecutionState(DebuggerCommandExecutionFinishedRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_SEND_USERMODE_MESSAGES_TO_DEBUGGER: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerSendUsermodeMessageRequest = (PDEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER)Irp->AssociatedIrp.SystemBuffer; - - // - // Second validation phase - // - if (DebuggerSendUsermodeMessageRequest->Length == NULL_ZERO || - IrpStack->Parameters.DeviceIoControl.InputBufferLength != SIZEOF_DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER + DebuggerSendUsermodeMessageRequest->Length) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Perform the signal operation - // - DebuggerCommandSendMessage(DebuggerSendUsermodeMessageRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_SEND_GENERAL_BUFFER_FROM_DEBUGGEE_TO_DEBUGGER: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerSendBufferFromDebuggeeToDebuggerRequest = (PDEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER)Irp->AssociatedIrp.SystemBuffer; - - // - // Second validation phase - // - if (DebuggerSendBufferFromDebuggeeToDebuggerRequest->LengthOfBuffer == NULL_ZERO || - IrpStack->Parameters.DeviceIoControl.InputBufferLength != SIZEOF_DEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER + DebuggerSendBufferFromDebuggeeToDebuggerRequest->LengthOfBuffer) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Perform the signal operation - // - DebuggerCommandSendGeneralBufferToDebugger(DebuggerSendBufferFromDebuggeeToDebuggerRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_SEND_GET_KERNEL_SIDE_TEST_INFORMATION: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerKernelSideTestInformationRequest = (PDEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform collecting kernel-side debug information - // - FilledEntriesInKernelInfo = TestKernelGetInformation(DebuggerKernelSideTestInformationRequest); - - Irp->IoStatus.Information = FilledEntriesInKernelInfo * SIZEOF_DEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_PERFROM_KERNEL_SIDE_TESTS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_PERFORM_KERNEL_TESTS || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerKernelTestRequest = (PDEBUGGER_PERFORM_KERNEL_TESTS)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the kernel-side tests - // - TestKernelPerformTests(DebuggerKernelTestRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_PERFORM_KERNEL_TESTS; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_RESERVE_PRE_ALLOCATED_POOLS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_PREALLOC_COMMAND || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerReservePreallocPoolRequest = (PDEBUGGER_PREALLOC_COMMAND)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the reservation pools - // - DebuggerCommandReservePreallocatedPools(DebuggerReservePreallocPoolRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_PREALLOC_COMMAND; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_PREACTIVATE_FUNCTIONALITY: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_PREACTIVATE_COMMAND || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerPreactivationRequest = (PDEBUGGER_PREACTIVATE_COMMAND)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the activation of the functionality - // - DebuggerCommandPreactivateFunctionality(DebuggerPreactivationRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_PREACTIVATE_COMMAND; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_SEND_USER_DEBUGGER_COMMANDS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(DEBUGGER_UD_COMMAND_PACKET) || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerUdCommandRequest = (PDEBUGGER_UD_COMMAND_PACKET)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the dispatching of user debugger command - // - UdDispatchUsermodeCommands(DebuggerUdCommandRequest); - - Irp->IoStatus.Information = sizeof(DEBUGGER_UD_COMMAND_PACKET); - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_GET_DETAIL_OF_ACTIVE_THREADS_AND_PROCESSES: - - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode is here - // - BufferToStoreThreadsAndProcessesDetails = (PVOID)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the dispatching of user debugger command - // - AttachingQueryDetailsOfActiveDebuggingThreadsAndProcesses(BufferToStoreThreadsAndProcessesDetails, OutBuffLength); - - Irp->IoStatus.Information = OutBuffLength; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_GET_USER_MODE_MODULE_DETAILS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(USERMODE_LOADED_MODULE_DETAILS) || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerUsermodeModulesRequest = (PUSERMODE_LOADED_MODULE_DETAILS)Irp->AssociatedIrp.SystemBuffer; - - // - // Getting the modules details - // - UserAccessGetLoadedModules(DebuggerUsermodeModulesRequest, OutBuffLength); - - Irp->IoStatus.Information = OutBuffLength; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_QUERY_COUNT_OF_ACTIVE_PROCESSES_OR_THREADS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS) || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerUsermodeProcessOrThreadQueryRequest = (PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS)Irp->AssociatedIrp.SystemBuffer; - - // - // Getting the count result - // - if (DebuggerUsermodeProcessOrThreadQueryRequest->QueryType == DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_QUERY_PROCESS_COUNT) - { - ProcessQueryCount(DebuggerUsermodeProcessOrThreadQueryRequest); - } - else if (DebuggerUsermodeProcessOrThreadQueryRequest->QueryType == DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_QUERY_THREAD_COUNT) - { - ThreadQueryCount(DebuggerUsermodeProcessOrThreadQueryRequest); - } - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_GET_LIST_OF_THREADS_AND_PROCESSES: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS) || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - DebuggerUsermodeProcessOrThreadQueryRequest = (PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS)Irp->AssociatedIrp.SystemBuffer; - - // - // Getting the list of processes or threads - // - if (DebuggerUsermodeProcessOrThreadQueryRequest->QueryType == DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_QUERY_PROCESS_LIST) - { - ProcessQueryList(DebuggerUsermodeProcessOrThreadQueryRequest, - DebuggerUsermodeProcessOrThreadQueryRequest, - OutBuffLength); - } - else if (DebuggerUsermodeProcessOrThreadQueryRequest->QueryType == DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_QUERY_THREAD_LIST) - { - ThreadQueryList(DebuggerUsermodeProcessOrThreadQueryRequest, - DebuggerUsermodeProcessOrThreadQueryRequest, - OutBuffLength); - } - - Irp->IoStatus.Information = OutBuffLength; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_QUERY_CURRENT_THREAD: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - GetInformationThreadRequest = (PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET)Irp->AssociatedIrp.SystemBuffer; - - // - // Get the information - // - ThreadQueryDetails(GetInformationThreadRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_QUERY_CURRENT_PROCESS: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - GetInformationProcessRequest = (PDEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET)Irp->AssociatedIrp.SystemBuffer; - - // - // Get the information - // - ProcessQueryDetails(GetInformationProcessRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_REQUEST_REV_MACHINE_SERVICE: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_REVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength || !OutBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place - // - RevServiceRequest = (PREVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST)Irp->AssociatedIrp.SystemBuffer; - - // - // Perform the service request - // - ConfigureInitializeExecTrapOnAllProcessors(); - - Irp->IoStatus.Information = SIZEOF_REVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - case IOCTL_DEBUGGER_BRING_PAGES_IN: - - // - // First validate the parameters. - // - if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_PAGE_IN_REQUEST || Irp->AssociatedIrp.SystemBuffer == NULL) - { - Status = STATUS_INVALID_PARAMETER; - LogError("Err, invalid parameter to IOCTL dispatcher"); - break; - } - - InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; - OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (!InBuffLength) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - DebuggerPageinRequest = (PDEBUGGER_PAGE_IN_REQUEST)Irp->AssociatedIrp.SystemBuffer; - - // - // Both usermode and to send to usermode and the coming buffer are - // at the same place (it's in VMI-mode) - // - DebuggerCommandBringPagein(DebuggerPageinRequest); - - Irp->IoStatus.Information = SIZEOF_DEBUGGER_PAGE_IN_REQUEST; - Status = STATUS_SUCCESS; - - // - // Avoid zeroing it - // - DoNotChangeInformation = TRUE; - - break; - - default: - LogError("Err, unknown IOCTL"); - Status = STATUS_NOT_IMPLEMENTED; - break; - } - } - else - { - // - // We're no longer serve IOCTL - // - Status = STATUS_SUCCESS; - } - - if (Status != STATUS_PENDING) - { - Irp->IoStatus.Status = Status; - if (!DoNotChangeInformation) - { - Irp->IoStatus.Information = 0; - } - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } - - return Status; -} diff --git a/hyperdbg/hprdbgkd/code/driver/Loader.c b/hyperdbg/hprdbgkd/code/driver/Loader.c deleted file mode 100644 index 2bd29ef1..00000000 --- a/hyperdbg/hprdbgkd/code/driver/Loader.c +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @file Loader.c - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief The functions used in loading the debugger and VMM - * @version 0.2 - * @date 2023-01-15 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Initialize the VMM and Debugger - * - * @return BOOLEAN - */ -BOOLEAN -LoaderInitVmmAndDebugger() -{ - MESSAGE_TRACING_CALLBACKS MsgTracingCallbacks = {0}; - VMM_CALLBACKS VmmCallbacks = {0}; - - // - // Allow to server IOCTL - // - g_AllowIOCTLFromUsermode = TRUE; - - // - // Fill the callbacks for the message tracer - // - MsgTracingCallbacks.VmxOperationCheck = VmFuncVmxGetCurrentExecutionMode; - MsgTracingCallbacks.CheckImmediateMessageSending = KdCheckImmediateMessagingMechanism; - MsgTracingCallbacks.SendImmediateMessage = KdLoggingResponsePacketToDebugger; - - // - // Fill the callbacks for using hyperlog in VMM - // - VmmCallbacks.LogCallbackPrepareAndSendMessageToQueueWrapper = LogCallbackPrepareAndSendMessageToQueueWrapper; - VmmCallbacks.LogCallbackSendMessageToQueue = LogCallbackSendMessageToQueue; - VmmCallbacks.LogCallbackSendBuffer = LogCallbackSendBuffer; - VmmCallbacks.LogCallbackCheckIfBufferIsFull = LogCallbackCheckIfBufferIsFull; - - // - // Fill the VMM callbacks - // - VmmCallbacks.VmmCallbackTriggerEvents = DebuggerTriggerEvents; - VmmCallbacks.VmmCallbackSetLastError = DebuggerSetLastError; - VmmCallbacks.VmmCallbackVmcallHandler = DebuggerVmcallHandler; - VmmCallbacks.VmmCallbackRegisteredMtfHandler = KdHandleRegisteredMtfCallback; - VmmCallbacks.VmmCallbackNmiBroadcastRequestHandler = KdHandleNmiBroadcastDebugBreaks; - VmmCallbacks.VmmCallbackQueryTerminateProtectedResource = TerminateQueryDebuggerResource; - VmmCallbacks.VmmCallbackRestoreEptState = UserAccessCheckForLoadedModuleDetails; - VmmCallbacks.VmmCallbackCheckUnhandledEptViolations = AttachingCheckUnhandledEptViolation; - - // - // Fill the debugging callbacks - // - VmmCallbacks.DebuggingCallbackHandleBreakpointException = BreakpointHandleBreakpoints; - VmmCallbacks.DebuggingCallbackHandleDebugBreakpointException = BreakpointCheckAndHandleDebugBreakpoint; - VmmCallbacks.BreakpointCheckAndHandleReApplyingBreakpoint = BreakpointCheckAndHandleReApplyingBreakpoint; - VmmCallbacks.UdCheckForCommand = UdCheckForCommand; - VmmCallbacks.DebuggerCheckProcessOrThreadChange = DebuggerCheckProcessOrThreadChange; - VmmCallbacks.DebuggingCallbackConditionalPageFaultException = AttachingCheckPageFaultsWithUserDebugger; - VmmCallbacks.AttachingHandleCr3VmexitsForThreadInterception = AttachingHandleCr3VmexitsForThreadInterception; - VmmCallbacks.KdCheckAndHandleNmiCallback = KdCheckAndHandleNmiCallback; - VmmCallbacks.KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId = KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId; - - // - // Fill the interception callbacks - // - VmmCallbacks.InterceptionCallbackTriggerCr3ProcessChange = ProcessTriggerCr3ProcessChange; - - // - // Initialize message tracer - // - if (LogInitialize(&MsgTracingCallbacks)) - { - // - // Initialize Vmx - // - if (VmFuncInitVmm(&VmmCallbacks)) - { - 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"); - } - } - else - { - LogError("Err, HyperDbg's message tracing module was not loaded"); - } - - // - // Not loaded - // - g_AllowIOCTLFromUsermode = FALSE; - - return FALSE; -} - -/** - * @brief Uninitialize the log tracer - * - * @return VOID - */ -VOID -LoaderUninitializeLogTracer() -{ - LogDebugInfo("Unloading HyperDbg's debugger...\n"); - -#if !UseDbgPrintInsteadOfUsermodeMessageTracking - - // - // Uinitialize log buffer - // - LogDebugInfo("Uninitializing logs\n"); - LogUnInitialize(); -#endif -} diff --git a/hyperdbg/hprdbgkd/header/common/Dpc.h b/hyperdbg/hprdbgkd/header/common/Dpc.h deleted file mode 100644 index 30b419ec..00000000 --- a/hyperdbg/hprdbgkd/header/common/Dpc.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @file Dpc.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Definition for Windows DPC functions - * @details - * @version 0.1 - * @date 2020-04-10 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Functions // -////////////////////////////////////////////////// - -NTKERNELAPI -_IRQL_requires_max_(APC_LEVEL) -_IRQL_requires_min_(PASSIVE_LEVEL) -_IRQL_requires_same_ -VOID -KeGenericCallDpc( - _In_ PKDEFERRED_ROUTINE Routine, - _In_opt_ PVOID Context); - -NTKERNELAPI -_IRQL_requires_(DISPATCH_LEVEL) -_IRQL_requires_same_ -VOID -KeSignalCallDpcDone( - _In_ PVOID SystemArgument1); - -NTKERNELAPI -_IRQL_requires_(DISPATCH_LEVEL) -_IRQL_requires_same_ -LOGICAL -KeSignalCallDpcSynchronize( - _In_ PVOID SystemArgument2); diff --git a/hyperdbg/hprdbgkd/header/debugger/user-level/Attaching.h b/hyperdbg/hprdbgkd/header/debugger/user-level/Attaching.h deleted file mode 100644 index a4b440c5..00000000 --- a/hyperdbg/hprdbgkd/header/debugger/user-level/Attaching.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @file Attaching.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Header for attaching and detaching for debugging user-mode processes - * @details - * @version 0.1 - * @date 2021-12-28 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Constants // -////////////////////////////////////////////////// - -/** - * @brief Maximum actions in paused threads storage - * - */ -#define MAX_USER_ACTIONS_FOR_THREADS 3 - -/** - * @brief Maximum threads that a process thread holder might have - * - */ -#define MAX_THREADS_IN_A_PROCESS_HOLDER 100 -/** - * @brief Maximum number of CR3 registers that a process can have - * @details Generally, a process has one cr3 but after meltdown KPTI - * another Cr3 is added and separated the kernel and user CR3s, recently - * I've noticed from a tweet from Petr Benes that there might be other cr3s - * https://twitter.com/PetrBenes/status/1310642455352672257?s=20 - * So, I assume two extra cr3 for each process - */ -#define MAX_CR3_IN_A_PROCESS 4 - -////////////////////////////////////////////////// -// Structures // -////////////////////////////////////////////////// - -/** - * @brief Description of each active thread in user-mode attaching - * mechanism - * - */ -typedef struct _USERMODE_DEBUGGING_PROCESS_DETAILS -{ - UINT64 Token; - BOOLEAN Enabled; - PVOID PebAddressToMonitor; - UINT32 ActiveThreadId; // active thread - GUEST_REGS Registers; // active thread - UINT64 Context; // $context - LIST_ENTRY AttachedProcessList; - UINT64 UsermodeReservedBuffer; - UINT64 EntrypointOfMainModule; - UINT64 BaseAddressOfMainModule; - PEPROCESS Eprocess; - UINT32 ProcessId; - BOOLEAN Is32Bit; - BOOLEAN IsOnTheStartingPhase; - BOOLEAN IsOnThreadInterceptingPhase; - BOOLEAN CheckCallBackForInterceptingFirstInstruction; // checks for the callbacks for interceptions of the very first instruction (used by RE Machine) - CR3_TYPE InterceptedCr3[MAX_CR3_IN_A_PROCESS]; - LIST_ENTRY ThreadsListHead; - -} USERMODE_DEBUGGING_PROCESS_DETAILS, *PUSERMODE_DEBUGGING_PROCESS_DETAILS; - -////////////////////////////////////////////////// -// Functions // -////////////////////////////////////////////////// - -BOOLEAN -AttachingInitialize(); - -BOOLEAN -AttachingCheckPageFaultsWithUserDebugger(UINT32 CoreId, - UINT64 Address, - UINT32 PageFaultErrorCode); - -BOOLEAN -AttachingConfigureInterceptingThreads(UINT64 ProcessDebuggingToken, BOOLEAN Enable); - -BOOLEAN -AttachingHandleCr3VmexitsForThreadInterception(UINT32 CoreId, CR3_TYPE NewCr3); - -VOID -AttachingTargetProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS Request); - -VOID -AttachingHandleEntrypointInterception(PROCESSOR_DEBUGGING_STATE * DbgState); - -VOID -AttachingRemoveAndFreeAllProcessDebuggingDetails(); - -PUSERMODE_DEBUGGING_PROCESS_DETAILS -AttachingFindProcessDebuggingDetailsByToken(UINT64 Token); - -PUSERMODE_DEBUGGING_PROCESS_DETAILS -AttachingFindProcessDebuggingDetailsByProcessId(UINT32 ProcessId); - -BOOLEAN -AttachingQueryDetailsOfActiveDebuggingThreadsAndProcesses(PVOID BufferToStoreDetails, UINT32 BufferSize); - -BOOLEAN -AttachingCheckUnhandledEptViolation(UINT32 CoreId, - UINT64 ViolationQualification, - UINT64 GuestPhysicalAddr); - -BOOLEAN -AttachingReachedToValidLoadedModule(PROCESSOR_DEBUGGING_STATE * DbgState, - PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail); diff --git a/hyperdbg/hprdbgkd/header/debugger/user-level/Ud.h b/hyperdbg/hprdbgkd/header/debugger/user-level/Ud.h deleted file mode 100644 index 75a2f8aa..00000000 --- a/hyperdbg/hprdbgkd/header/debugger/user-level/Ud.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file Ud.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Header for routines related to user mode debugging - * @details - * @version 0.1 - * @date 2022-01-06 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Functions // -////////////////////////////////////////////////// - -BOOLEAN -UdInitializeUserDebugger(); - -VOID -UdUninitializeUserDebugger(); - -BOOLEAN -UdCheckAndHandleBreakpointsAndDebugBreaks(PROCESSOR_DEBUGGING_STATE * DbgState, - DEBUGGEE_PAUSING_REASON Reason, - PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails); - -BOOLEAN -UdDispatchUsermodeCommands(PDEBUGGER_UD_COMMAND_PACKET ActionRequest); - -BOOLEAN -UdCheckForCommand(); diff --git a/hyperdbg/hyperdbg-cli/CMakeLists.txt b/hyperdbg/hyperdbg-cli/CMakeLists.txt new file mode 100644 index 00000000..8eb54082 --- /dev/null +++ b/hyperdbg/hyperdbg-cli/CMakeLists.txt @@ -0,0 +1,10 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "hyperdbg-cli.cpp" + "../include/platform/general/header/Environment.h" +) +include_directories( + "../include" + "../dependencies" +) +add_executable(hyperdbg-cli ${SourceFiles}) diff --git a/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp b/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp index 76482f90..38086308 100644 --- a/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp +++ b/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp @@ -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 @@ -9,40 +9,52 @@ * @copyright This project is released under the GNU Public License v3. * */ -#include + +#ifdef _WIN32 +# include +# include +#endif + #include -#include #include #include +#include #include "SDK/HyperDbgSdk.h" -#include "SDK/Imports/HyperDbgCtrlImports.h" +#include "SDK/imports/user/HyperDbgLibImports.h" 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[]) { - bool ExitFromDebugger = false; - string PreviousCommand; - bool Reset = false; + BOOLEAN exit_from_debugger = FALSE; + string previous_command; + BOOLEAN reset = FALSE; // // 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) { // @@ -53,7 +65,7 @@ main(int argc, char * argv[]) // // Handle the script // - HyperDbgScriptReadFileAndExecuteCommandline(argc, argv); + hyperdbg_u_script_read_file_and_execute_commandline(argc, argv); } else { @@ -62,22 +74,22 @@ main(int argc, char * argv[]) } } - while (!ExitFromDebugger) + while (!exit_from_debugger) { - HyperDbgShowSignature(); + hyperdbg_u_show_signature(); - string CurrentCommand = ""; + string current_command = ""; // // Clear multiline // - Reset = true; + reset = TRUE; - GetMultiLinecCommand: + GetMultiLineCommand: - string TempCommand = ""; + string temp_command = ""; - getline(cin, TempCommand); + getline(cin, temp_command); if (cin.fail() || cin.eof()) { @@ -94,17 +106,17 @@ main(int argc, char * argv[]) // // Check for multi-line commands // - if (HyperDbgCheckMultilineCommand((char *)TempCommand.c_str(), Reset) == true) + if (hyperdbg_u_check_multiline_command((CHAR *)temp_command.c_str(), reset) == TRUE) { // // It's a multi-line command // - Reset = false; + reset = FALSE; // // Save the command with a space separator // - CurrentCommand += TempCommand + "\n"; + current_command += temp_command + "\n"; // // Show a small signature @@ -114,39 +126,38 @@ main(int argc, char * argv[]) // // Get next command // - goto GetMultiLinecCommand; + goto GetMultiLineCommand; } else { // // Reset for future commands // - Reset = true; + reset = TRUE; // // Either the multi-line is finished or it's a // single line command // - CurrentCommand += TempCommand; + current_command += temp_command; } - if (!CurrentCommand.compare("") && - HyperDbgContinuePreviousCommand()) + if (!current_command.compare("") && hyperdbg_u_continue_previous_command()) { // // Retry the previous command // - CurrentCommand = PreviousCommand; + current_command = previous_command; } else { // // Save previous command // - PreviousCommand = CurrentCommand; + previous_command = current_command; } - int CommandExecutionResult = HyperDbgInterpreter((char *)CurrentCommand.c_str()); + INT CommandExecutionResult = hyperdbg_u_run_command((CHAR *)current_command.c_str()); // // if the debugger encounters an exit state then the return will be 1 @@ -156,7 +167,7 @@ main(int argc, char * argv[]) // // Exit from the debugger // - ExitFromDebugger = true; + exit_from_debugger = true; } if (CommandExecutionResult != 2) { diff --git a/hyperdbg/hyperdbg-cli/hyperdbg-cli.vcxproj b/hyperdbg/hyperdbg-cli/hyperdbg-cli.vcxproj index a83669d7..5b16f0d4 100644 --- a/hyperdbg/hyperdbg-cli/hyperdbg-cli.vcxproj +++ b/hyperdbg/hyperdbg-cli/hyperdbg-cli.vcxproj @@ -22,14 +22,14 @@ Application true - v143 + v145 Unicode false Application false - v143 + v145 true Unicode false @@ -62,42 +62,44 @@ Level3 true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;HYPERDBG_DEBUG;%(PreprocessorDefinitions) true $(SolutionDir)\include;$(SolutionDir)dependencies;%(AdditionalIncludeDirectories) MultiThreadedDebug false true + stdcpp20 Console true - $(SolutionDir)build\bin\$(Configuration)\HPRDBGCTRL.lib;%(AdditionalDependencies) + $(SolutionDir)build\bin\$(Configuration)\libhyperdbg.lib;%(AdditionalDependencies) AsInvoker true if exist "$(OutDir)SDK\" rd /q /s "$(OutDir)SDK\" xcopy /E /I /Y "$(SolutionDir)include\SDK" "$(OutDir)SDK" -mkdir "$(OutDir)SDK\Libraries" -copy "$(OutDir)HPRDBGCTRL.lib" "$(OutDir)SDK\Libraries\HPRDBGCTRL.lib" -copy "$(OutDir)HPRDBGCTRL.lib" "$(OutDir)SDK\Libraries\hprdbgrev.lib" -copy "$(OutDir)pdbex.lib" "$(OutDir)SDK\Libraries\pdbex.lib" -copy "$(OutDir)kdserial.lib" "$(OutDir)SDK\Libraries\kdserial.lib" -copy "$(OutDir)script-engine.lib" "$(OutDir)SDK\Libraries\script-engine.lib" -copy "$(OutDir)symbol-parser.lib" "$(OutDir)SDK\Libraries\symbol-parser.lib" -copy "$(OutDir)hyperlog.lib" "$(OutDir)SDK\Libraries\hyperlog.lib" -copy "$(OutDir)hprdbghv.lib" "$(OutDir)SDK\Libraries\hprdbghv.lib" -copy "$(OutDir)HPRDBGCTRL.dll" "$(OutDir)SDK\Libraries\HPRDBGCTRL.dll" -copy "$(OutDir)HPRDBGCTRL.dll" "$(OutDir)SDK\Libraries\hprdbgrev.dll" -copy "$(OutDir)pdbex.dll" "$(OutDir)SDK\Libraries\pdbex.dll" -copy "$(OutDir)kdserial.dll" "$(OutDir)SDK\Libraries\kdserial.dll" -copy "$(OutDir)script-engine.dll" "$(OutDir)SDK\Libraries\script-engine.dll" -copy "$(OutDir)symbol-parser.dll" "$(OutDir)SDK\Libraries\symbol-parser.dll" -copy "$(OutDir)hyperlog.dll" "$(OutDir)SDK\Libraries\hyperlog.dll" -copy "$(OutDir)hprdbghv.dll" "$(OutDir)SDK\Libraries\hprdbghv.dll" +xcopy /E /I /Y "$(SolutionDir)..\examples" "$(OutDir)SDK\examples" +mkdir "$(OutDir)SDK\libraries" +mkdir "$(OutDir)SDK\libraries\kernel" +mkdir "$(OutDir)SDK\libraries\user" +copy "$(OutDir)pdbex.dll" "$(OutDir)SDK\libraries\user\pdbex.dll" +copy "$(OutDir)libipt.dll" "$(OutDir)SDK\libraries\user\libipt.dll" +copy "$(OutDir)script-engine.dll" "$(OutDir)SDK\libraries\user\script-engine.dll" +copy "$(OutDir)symbol-parser.dll" "$(OutDir)SDK\libraries\user\symbol-parser.dll" +copy "$(OutDir)libhyperdbg.dll" "$(OutDir)SDK\libraries\user\libhyperdbg.dll" +copy "$(OutDir)hyperlog.dll" "$(OutDir)SDK\libraries\kernel\hyperlog.dll" +copy "$(OutDir)hyperhv.dll" "$(OutDir)SDK\libraries\kernel\hyperhv.dll" +copy "$(OutDir)hypertrace.dll" "$(OutDir)SDK\libraries\kernel\hyperevade.dll" +copy "$(OutDir)hypertrace.dll" "$(OutDir)SDK\libraries\kernel\hypertrace.dll" +copy "$(OutDir)hyperperf.dll" "$(OutDir)SDK\libraries\kernel\hyperperf.dll" +copy "$(OutDir)kdserial.dll" "$(OutDir)SDK\libraries\kernel\kdserial.dll" +if exist "$(OutDir)constants\" rd /q /s "$(OutDir)constants\" +mkdir "$(OutDir)constants" +copy "$(SolutionDir)miscellaneous\constants\pciid\pci.ids" "$(OutDir)constants\pci.ids" @@ -113,6 +115,8 @@ copy "$(OutDir)hprdbghv.dll" "$(OutDir)SDK\Libraries\hprdbghv.dll" $(SolutionDir)\include;$(SolutionDir)dependencies;%(AdditionalIncludeDirectories) MultiThreadedDebug true + stdcpp20 + MaxSpeed Console @@ -121,30 +125,31 @@ copy "$(OutDir)hprdbghv.dll" "$(OutDir)SDK\Libraries\hprdbghv.dll" true - $(SolutionDir)build\bin\$(Configuration)\HPRDBGCTRL.lib;%(AdditionalDependencies) + $(SolutionDir)build\bin\$(Configuration)\libhyperdbg.lib;%(AdditionalDependencies) AsInvoker true if exist "$(OutDir)SDK\" rd /q /s "$(OutDir)SDK\" xcopy /E /I /Y "$(SolutionDir)include\SDK" "$(OutDir)SDK" -mkdir "$(OutDir)SDK\Libraries" -copy "$(OutDir)HPRDBGCTRL.lib" "$(OutDir)SDK\Libraries\HPRDBGCTRL.lib" -copy "$(OutDir)HPRDBGCTRL.lib" "$(OutDir)SDK\Libraries\hprdbgrev.lib" -copy "$(OutDir)pdbex.lib" "$(OutDir)SDK\Libraries\pdbex.lib" -copy "$(OutDir)kdserial.lib" "$(OutDir)SDK\Libraries\kdserial.lib" -copy "$(OutDir)script-engine.lib" "$(OutDir)SDK\Libraries\script-engine.lib" -copy "$(OutDir)symbol-parser.lib" "$(OutDir)SDK\Libraries\symbol-parser.lib" -copy "$(OutDir)hyperlog.lib" "$(OutDir)SDK\Libraries\hyperlog.lib" -copy "$(OutDir)hprdbghv.lib" "$(OutDir)SDK\Libraries\hprdbghv.lib" -copy "$(OutDir)HPRDBGCTRL.dll" "$(OutDir)SDK\Libraries\HPRDBGCTRL.dll" -copy "$(OutDir)HPRDBGCTRL.dll" "$(OutDir)SDK\Libraries\hprdbgrev.dll" -copy "$(OutDir)pdbex.dll" "$(OutDir)SDK\Libraries\pdbex.dll" -copy "$(OutDir)kdserial.dll" "$(OutDir)SDK\Libraries\kdserial.dll" -copy "$(OutDir)script-engine.dll" "$(OutDir)SDK\Libraries\script-engine.dll" -copy "$(OutDir)symbol-parser.dll" "$(OutDir)SDK\Libraries\symbol-parser.dll" -copy "$(OutDir)hyperlog.dll" "$(OutDir)SDK\Libraries\hyperlog.dll" -copy "$(OutDir)hprdbghv.dll" "$(OutDir)SDK\Libraries\hprdbghv.dll" +xcopy /E /I /Y "$(SolutionDir)..\examples" "$(OutDir)SDK\examples" +mkdir "$(OutDir)SDK\libraries" +mkdir "$(OutDir)SDK\libraries\kernel" +mkdir "$(OutDir)SDK\libraries\user" +copy "$(OutDir)pdbex.dll" "$(OutDir)SDK\libraries\user\pdbex.dll" +copy "$(OutDir)libipt.dll" "$(OutDir)SDK\libraries\user\libipt.dll" +copy "$(OutDir)script-engine.dll" "$(OutDir)SDK\libraries\user\script-engine.dll" +copy "$(OutDir)symbol-parser.dll" "$(OutDir)SDK\libraries\user\symbol-parser.dll" +copy "$(OutDir)libhyperdbg.dll" "$(OutDir)SDK\libraries\user\libhyperdbg.dll" +copy "$(OutDir)hyperlog.dll" "$(OutDir)SDK\libraries\kernel\hyperlog.dll" +copy "$(OutDir)hyperhv.dll" "$(OutDir)SDK\libraries\kernel\hyperhv.dll" +copy "$(OutDir)hypertrace.dll" "$(OutDir)SDK\libraries\kernel\hyperevade.dll" +copy "$(OutDir)hypertrace.dll" "$(OutDir)SDK\libraries\kernel\hypertrace.dll" +copy "$(OutDir)hyperperf.dll" "$(OutDir)SDK\libraries\kernel\hyperperf.dll" +copy "$(OutDir)kdserial.dll" "$(OutDir)SDK\libraries\kernel\kdserial.dll" +if exist "$(OutDir)constants\" rd /q /s "$(OutDir)constants\" +mkdir "$(OutDir)constants" +copy "$(SolutionDir)miscellaneous\constants\pciid\pci.ids" "$(OutDir)constants\pci.ids" diff --git a/hyperdbg/hyperdbg-cli/hyperdbg-cli.vcxproj.filters b/hyperdbg/hyperdbg-cli/hyperdbg-cli.vcxproj.filters index ef78236e..7f812426 100644 --- a/hyperdbg/hyperdbg-cli/hyperdbg-cli.vcxproj.filters +++ b/hyperdbg/hyperdbg-cli/hyperdbg-cli.vcxproj.filters @@ -5,6 +5,12 @@ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {3eacd448-7ca9-42c0-b5a1-2848161f69a2} + + + {8eb27fe0-dacb-404f-abef-ee81eda88a6e} + diff --git a/hyperdbg/hyperdbg-test/CMakeLists.txt b/hyperdbg/hyperdbg-test/CMakeLists.txt new file mode 100644 index 00000000..3539101b --- /dev/null +++ b/hyperdbg/hyperdbg-test/CMakeLists.txt @@ -0,0 +1,18 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "code/tests/hyperdbg-test.cpp" + "code/tests/namedpipe.cpp" + "code/tests/tools.cpp" + "pch.cpp" + "../include/platform/user/header/Environment.h" + "header/namedpipe.h" + "header/routines.h" + "pch.h" + "code/assembly/asm-test.asm" +) +include_directories( + "../include" + "../dependencies" + "." +) +add_executable(hyperdbg-test ${SourceFiles}) diff --git a/hyperdbg/hyperdbg-test/code/hardware/hwdbg-tests.cpp b/hyperdbg/hyperdbg-test/code/hardware/hwdbg-tests.cpp new file mode 100644 index 00000000..2ea4af5f --- /dev/null +++ b/hyperdbg/hyperdbg-test/code/hardware/hwdbg-tests.cpp @@ -0,0 +1,217 @@ +/** + * @file hwdbg-tests.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Test cases for testing hwdbg + * @details + * @version 0.11 + * @date 2024-09-30 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +namespace fs = std::filesystem; + +/** + * @brief function to comment each line by adding ';' at the start + * @param Content the content to comment out + * + * @return std::string + */ +std::string +CommentContent(const std::string & Content) +{ + std::istringstream Iss(Content); + std::string Line; + std::string CommentedContent; + + while (std::getline(Iss, Line)) + { + CommentedContent += Line + "\n; "; + } + + return CommentedContent; +} + +/** + * @brief Read directory of hwdbg script test cases and run each of them + * + * @param HwdbgScriptTestCasesPath Path to the hwdbg script test cases + * + * @return BOOLEAN + */ +BOOLEAN +ReadDirectoryAndCreateHwdbgTestCases(const CHAR * HwdbgScriptTestCasesPath) +{ + CHAR TempFilePath[MAX_PATH] = {0}; + + // + // Iterate through the directory + // + try + { + for (const auto & entry : fs::directory_iterator(HwdbgScriptTestCasesPath)) + { + // + // Check if the entry is a file + // + if (entry.is_regular_file()) + { + // + // Get the file path + // + std::string FilePath = entry.path().string(); + + // + // Output the file name + // + // std::cout << "Test case file: " << entry.path().filename().string() << std::endl; + + // + // Open the file and read its contents + // + std::ifstream File(FilePath); + if (File.is_open()) + { + std::string Content((std::istreambuf_iterator(File)), + std::istreambuf_iterator()); + + // + // Display the content of the file + // + std::cout << "Reading script test case file " << entry.path().filename().string() << std::endl; + + // std::cout << content << std::endl; + + 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()); + + if (!hwdbg_script_run_script(Content.c_str(), + HWDBG_TEST_READ_INSTANCE_INFO_PATH, + CompiledVersionFilePath.c_str(), + DEFAULT_INITIAL_BRAM_BUFFER_SIZE)) + { + std::cout << "[-] Could not run the script: " << FilePath << std::endl; + return FALSE; + } + + // + // Now open the compiled_version_file_path file and add content at the top + // + + // + // Parse the hwdbg compiled test cases from the file + // + if (!hyperdbg_u_setup_path_for_filename(CompiledVersionFilePath.c_str(), TempFilePath, MAX_PATH, FALSE)) + { + // + // Error could not find the test case files + // + std::cout << "[-] Could not find the compiled version of the hwdbg test case file" << endl; + return FALSE; + } + + std::ifstream CompiledFile(TempFilePath); + if (CompiledFile.is_open()) + { + // + // Read the existing content of the compiled file + // + std::string CompiledContent((std::istreambuf_iterator(CompiledFile)), + std::istreambuf_iterator()); + CompiledFile.close(); // Close the file after reading + + // + // Comment the 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 "\\" + + entry.path().filename().string() + + "\n;\n; !hw script " + + CommentedContent + + "\n" + + CompiledContent; + + // + // Write the new content back to the file (overwriting it) + // + std::ofstream CompiledFileOut(TempFilePath); + if (CompiledFileOut.is_open()) + { + CompiledFileOut << NewContent; + CompiledFileOut.close(); + } + else + { + std::cerr << "Could not open file for writing: " << CompiledVersionFilePath << std::endl; + } + } + else + { + std::cerr << "Could not open compiled file: " << CompiledVersionFilePath << std::endl; + } + + std::cout << "--------------------------------------------" << std::endl; + + // + // Close the file + // + File.close(); + } + else + { + std::cerr << "Could not open file: " << FilePath << std::endl; + } + } + } + } + catch (const fs::filesystem_error & e) + { + std::cerr << "Filesystem error: " << e.what() << std::endl; + return FALSE; + } + + // + // Return success + // + return TRUE; +} + +/** + * @brief Create test cases for hwdbg + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgTestCreateTestCases() +{ + INT32 TestNum = 0; + CHAR dirPath[MAX_PATH] = {0}; + + // + // Parse the hwdbg test cases from the file + // Setup the path for the filenames + // + if (!hyperdbg_u_setup_path_for_filename(HWDBG_SCRIPT_TEST_CASE_CODE_DIRECTORY, dirPath, MAX_PATH, FALSE)) + { + // + // Error could not find the test case files + // + cout << "[-] Could not find the hwdbg test case files" << endl; + return FALSE; + } + + // + // Run test cases + // + return ReadDirectoryAndCreateHwdbgTestCases(dirPath); +} diff --git a/hyperdbg/hyperdbg-test/code/main.cpp b/hyperdbg/hyperdbg-test/code/main.cpp new file mode 100644 index 00000000..d4d4b356 --- /dev/null +++ b/hyperdbg/hyperdbg-test/code/main.cpp @@ -0,0 +1,115 @@ +/** + * @file main.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief perform tests + * @details + * @version 0.11 + * @date 2024-08-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Main function of test process + * + * @param argc + * @param argv + * @return int + */ +int +main(int argc, char * argv[]) +{ + if (argc != 2) + { + printf("you should not test functionalities directly, instead use 'test all' " + "command from HyperDbg...\n"); + return 1; + } + + if (!strcmp(argv[1], TEST_CASE_PARAMETER_FOR_MAIN_COMMAND_PARSER)) + { + // + // # Test case 1 + // Testing command parser + // + if (TestCommandParser()) + { + printf("\n[*] The main command parser test cases passed successfully\n"); + } + else + { + printf("\n[x] The main command parser test cases failed\n"); + } + } + 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()) + { + printf("\n[*] The script semantic test cases passed successfully\n"); + } + else + { + 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)) + { + // + // # Test hwdbg functionalities + // + if (HwdbgTestCreateTestCases()) + { + printf("\n[*] The hwdbg test cases passed successfully\n"); + } + else + { + printf("\n[x] The hwdbg test cases failed\n"); + } + } + else + { + printf("unknown test case\n"); + } + + printf("\npress any key to exit..."); + + _getch(); + + return 0; +} diff --git a/hyperdbg/hyperdbg-test/code/namedpipe.cpp b/hyperdbg/hyperdbg-test/code/namedpipe.cpp new file mode 100644 index 00000000..d3cf2ad2 --- /dev/null +++ b/hyperdbg/hyperdbg-test/code/namedpipe.cpp @@ -0,0 +1,602 @@ +/** + * @file namedpipe.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Server and Client communication over NamedPipes + * @details + * @version 0.1 + * @date 2020-07-15 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Connect and transfer buffers via named pipe + * + * @return UINT32 + */ +UINT32 +NamedPipeConnectingAndTransferringBuffers() +{ + // HANDLE PipeHandle; + // BOOLEAN SentMessageResult; + // UINT32 ReadBytes; + // char * Buffer; + // + // Buffer = (char *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + // + // if (!Buffer) + // { + // printf("err, could not allocate communication buffer\n"); + // _getch(); + // return 1; + // } + // + // RtlZeroMemory(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + // strcpy_s(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE, "Hey there, Are you HyperDbg?"); + // + // // + // // Perform our shaking with HyperDbg + // // + // + // // + // // It's not called directly, it's probably from HyperDbg + // // + // PipeHandle = NamedPipeClientCreatePipe("\\\\.\\Pipe\\HyperDbgTests"); + // + // if (!PipeHandle) + // { + // // + // // Unable to create handle + // // + // free(Buffer); + // + // printf("err, unable to create handle\n"); + // _getch(); + // return 1; + // } + // + // SentMessageResult = + // NamedPipeClientSendMessage(PipeHandle, Buffer, (int)strlen(Buffer) + 1); + // + // if (!SentMessageResult) + // { + // // + // // Sending error + // // + // free(Buffer); + // + // printf("err, unable to send message\n"); + // _getch(); + // return 1; + // } + // + // ReadBytes = NamedPipeClientReadMessage(PipeHandle, Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + // + // if (!ReadBytes) + // { + // // + // // Nothing to read + // // + // free(Buffer); + // + // printf("err, unable to read message\n"); + // _getch(); + // return 1; + // } + // + // if (strcmp(Buffer, + // "Hello, Dear Test Process... Yes, I'm HyperDbg Debugger :)") == + // 0) + // { + // // + // // *** Connected to the HyperDbg debugger *** + // // + // + // // + // // Now we should request the test case number from the HyperDbg Debugger + // // + // RtlZeroMemory(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + // + // strcpy_s( + // Buffer, + // TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE, + // "Wow! I miss you... Would you plz send test cases?"); + // + // SentMessageResult = + // NamedPipeClientSendMessage(PipeHandle, Buffer, (int)strlen(Buffer) + 1); + // + // if (!SentMessageResult) + // { + // // + // // Sending error + // // + // free(Buffer); + // + // printf("err, sending error\n"); + // _getch(); + // return 1; + // } + // + // // + // // Read the test case number + // // + // RtlZeroMemory(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + // ReadBytes = NamedPipeClientReadMessage(PipeHandle, Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + // + // if (!ReadBytes) + // { + // // + // // Nothing to read + // // + // free(Buffer); + // + // printf("err, nothing to read\n"); + // _getch(); + // return 1; + // } + // + // // + // // Dispatch the test case number + // // + // + // /// TestCreateLookupTable(PipeHandle, (PVOID)Buffer, ReadBytes); + // printf("!!!! Read to run the test cases !!!!"); + // _getch(); + // + // // + // // Close the pipe connection + // // + // NamedPipeClientClosePipe(PipeHandle); + // + // // + // // Make sure to exit the test program + // // + // exit(0); + // } + // + // free(Buffer); + return 0; +} + +//////////////////////////////////////////////////////////////////////////// +// Server Side // +//////////////////////////////////////////////////////////////////////////// + +/** + * @brief Create a named pipe server + * + * @param PipeName + * @param OutputBufferSize + * @param InputBufferSize + * @return HANDLE + */ +HANDLE +NamedPipeServerCreatePipe(LPCSTR PipeName, UINT32 OutputBufferSize, UINT32 InputBufferSize) +{ + HANDLE hPipe; + + hPipe = CreateNamedPipeA(PipeName, // pipe name + PIPE_ACCESS_DUPLEX, // read/write access + PIPE_TYPE_MESSAGE | // message type pipe + PIPE_READMODE_MESSAGE | // message-read mode + PIPE_WAIT, // blocking mode + PIPE_UNLIMITED_INSTANCES, // max. instances + OutputBufferSize, // output buffer size + InputBufferSize, // input buffer size + NMPWAIT_USE_DEFAULT_WAIT, // client time-out + NULL); // default security attribute + + if (INVALID_HANDLE_VALUE == hPipe) + { + printf("err, occurred while creating the pipe (%x)\n", + GetLastError()); + return NULL; + } + return hPipe; +} + +/** + * @brief wait for client connection + * + * @param PipeHandle + * @return BOOLEAN + */ +BOOLEAN +NamedPipeServerWaitForClientConnection(HANDLE PipeHandle) +{ + // + // Wait for the client to connect + // + BOOLEAN ClientConnected = ConnectNamedPipe(PipeHandle, NULL); + + if (FALSE == ClientConnected) + { + printf("err, occurred while connecting to the client (%x)\n", + GetLastError()); + CloseHandle(PipeHandle); + return FALSE; + } + + // + // Client connected + // + return TRUE; +} + +/** + * @brief read client message from the named pipe + * + * @param PipeHandle + * @param BufferToSave + * @param MaximumReadBufferLength + * @return UINT32 + */ +UINT32 +NamedPipeServerReadClientMessage(HANDLE PipeHandle, CHAR * BufferToSave, INT32 MaximumReadBufferLength) +{ + DWORD BytesTransferred; + + // + // We are connected to the client. + // To communicate with the client + // we will use ReadFile()/WriteFile() + // on the pipe handle - hPipe + // + + // + // Read client message + // + 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 ((!Result) || (0 == BytesTransferred)) + { + printf("err, occurred while reading from the client (%x)\n", + GetLastError()); + CloseHandle(PipeHandle); + return 0; + } + + // + // Number of bytes that the client sends to us + // + 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, + INT32 BufferSize) +{ + DWORD BytesTransferred; + + // + // Reply to client + // + 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 ((!Result) || (BufferSize != (INT32)BytesTransferred)) + { + printf("err, occurred while writing to the client (%x)\n", + GetLastError()); + CloseHandle(PipeHandle); + return FALSE; + } + return TRUE; +} + +/** + * @brief Close handle of server's named pipe + * + * @param PipeHandle + * @return VOID + */ +VOID +NamedPipeServerCloseHandle(HANDLE PipeHandle) +{ + CloseHandle(PipeHandle); +} + +//************************************************************************** + +//////////////////////////////////////////////////////////////////////////// +// // +// Client Side // +// // +//////////////////////////////////////////////////////////////////////////// + +/** + * @brief Create a client named pipe + * @details Pipe name format - \\servername\pipe\pipename + * This pipe is for server on the same computer, + * however, pipes can be used to connect to a remote server + * + * @param PipeName + * @return HANDLE + */ +HANDLE +NamedPipeClientCreatePipe(LPCSTR PipeName) +{ + HANDLE hPipe; + + // + // Connect to the server pipe using CreateFile() + // + hPipe = CreateFileA(PipeName, // pipe name + GENERIC_READ | // read and write access + GENERIC_WRITE, + 0, // no sharing + NULL, // default security attributes + OPEN_EXISTING, // opens existing pipe + 0, // default attributes + NULL); // no template file + + if (INVALID_HANDLE_VALUE == hPipe) + { + printf("err, occurred while connecting to the server (%x)\n", + GetLastError()); + // + // One might want to check whether the server pipe is busy + // This sample will error out if the server pipe is busy + // Read on ERROR_PIPE_BUSY and WaitNamedPipe() for that + // + + // + // Error + // + return NULL; + } + else + { + return hPipe; + } +} + +/** + * @brief Send client message 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 +NamedPipeClientSendMessage(HANDLE PipeHandle, CHAR * BufferToSend, INT32 BufferSize) +{ + // + // We are done connecting to the server pipe, + // we can start communicating with + // the server using ReadFile()/WriteFile() + // on handle - hPipe + // + + DWORD BytesTransferred; + + // + // Send the message to server + // + 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 ((!Result) || (BufferSize != (INT32)BytesTransferred)) + { + printf("err, occurred while writing to the server (%x)\n", + GetLastError()); + CloseHandle(PipeHandle); + + // + // Error + // + CloseHandle(PipeHandle); + return FALSE; + } + else + { + return TRUE; + } +} + +/** + * @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, INT32 MaximumSizeOfBuffer) +{ + DWORD BytesTransferred; + + // + // Read server response + // + 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 ((!Result) || (0 == BytesTransferred)) + { + printf("err, occurred while reading from the server (%x)\n", + GetLastError()); + CloseHandle(PipeHandle); + return 0; // Error + } + + // + // Success + // + return BytesTransferred; +} + +/** + * @brief close named pipe handle of client + * + * @param PipeHandle + * @return VOID + */ +VOID +NamedPipeClientClosePipe(HANDLE PipeHandle) +{ + CloseHandle(PipeHandle); +} + +//////////////////////////////////////////////////////////////////////////// +// // +// Example Server // +// // +//////////////////////////////////////////////////////////////////////////// + +/** + * @brief An example of how to use named pipe as a server + * + * @return INT32 + */ +INT32 +NamedPipeServerExample() +{ + 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", + BufferSize, + BufferSize); + if (!PipeHandle) + { + // + // Error in creating handle + // + return 1; + } + + printf("success!\n"); + printf("wait for the client connection\n"); + + if (!NamedPipeServerWaitForClientConnection(PipeHandle)) + { + // + // Error in connection + // + return 1; + } + + printf("client connected\n"); + printf("read client message\n"); + + ReadBytes = + NamedPipeServerReadClientMessage(PipeHandle, BufferToRead, BufferSize); + + if (!ReadBytes) + { + // + // Nothing to read + // + return 1; + } + + printf("Message from client : %s\n", BufferToRead); + + SentMessageResult = NamedPipeServerSendMessageToClient( + PipeHandle, + BufferToSend, + (INT32)strlen(BufferToSend) + 1); + + if (!SentMessageResult) + { + // + // error in sending + // + return 1; + } + + NamedPipeServerCloseHandle(PipeHandle); + + return 0; +} + +//////////////////////////////////////////////////////////////////////////// +// // +// Example Client // +// // +//////////////////////////////////////////////////////////////////////////// + +/** + * @brief An example of how to use named pipe as a client + * + * @return INT32 + */ +INT32 +NamedPipeClientExample() +{ + 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) + { + // + // Unable to create handle + // + return 1; + } + + SentMessageResult = + NamedPipeClientSendMessage(PipeHandle, Buffer, (INT32)strlen(Buffer) + 1); + + if (!SentMessageResult) + { + // + // Sending error + // + return 1; + } + + ReadBytes = NamedPipeClientReadMessage(PipeHandle, Buffer, BufferSize); + + if (!ReadBytes) + { + // + // Nothing to read + // + return 1; + } + + printf("Server sent the following message: %s\n", Buffer); + + NamedPipeClientClosePipe(PipeHandle); + + return 0; +} diff --git a/hyperdbg/hyperdbg-test/code/tests/hyperdbg-test.cpp b/hyperdbg/hyperdbg-test/code/tests/hyperdbg-test.cpp deleted file mode 100644 index 5e626672..00000000 --- a/hyperdbg/hyperdbg-test/code/tests/hyperdbg-test.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/** - * @file hyperdbg-test.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief perform tests on a remote process (this is the remote process) - * @details - * @version 0.1 - * @date 2020-09-16 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -using namespace std; - -/** - * @brief Main function of test process - * - * @param argc - * @param argv - * @return int - */ -int -main(int argc, char * argv[]) -{ - HANDLE PipeHandle; - BOOLEAN SentMessageResult; - UINT32 ReadBytes; - char * Buffer; - - if (argc != 2) - { - printf("you should not test functionalities directly, instead use 'test' " - "command from HyperDbg...\n"); - return 1; - } - - Buffer = (char *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - RtlZeroMemory(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - strcpy_s(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE, "Hey there, Are you HyperDbg?"); - - if (!strcmp(argv[1], "im-hyperdbg")) - { - // - // Perform our shaking with HyperDbg - // - - // - // It's not called directly, it's probably from HyperDbg - // - PipeHandle = NamedPipeClientCreatePipe("\\\\.\\Pipe\\HyperDbgTests"); - - if (!PipeHandle) - { - // - // Unable to create handle - // - free(Buffer); - return 1; - } - - SentMessageResult = - NamedPipeClientSendMessage(PipeHandle, Buffer, (int)strlen(Buffer) + 1); - - if (!SentMessageResult) - { - // - // Sending error - // - free(Buffer); - return 1; - } - - ReadBytes = NamedPipeClientReadMessage(PipeHandle, Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - - if (!ReadBytes) - { - // - // Nothing to read - // - free(Buffer); - return 1; - } - - if (strcmp(Buffer, - "Hello, Dear Test Process... Yes, I'm HyperDbg Debugger :)") == - 0) - { - // - // *** Connected to the HyperDbg debugger *** - // - - // - // Now we should request the test case number from the HyperDbg Debugger - // - RtlZeroMemory(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - - strcpy_s( - Buffer, - TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE, - "Wow! I miss you... Would you plz send me the kernel information?"); - - SentMessageResult = - NamedPipeClientSendMessage(PipeHandle, Buffer, (int)strlen(Buffer) + 1); - - if (!SentMessageResult) - { - // - // Sending error - // - free(Buffer); - return 1; - } - - // - // Read the test case number - // - RtlZeroMemory(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - ReadBytes = NamedPipeClientReadMessage(PipeHandle, Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - - if (!ReadBytes) - { - // - // Nothing to read - // - free(Buffer); - return 1; - } - - // - // Dispatch the test case number - // - TestCreateLookupTable(PipeHandle, (PVOID)Buffer, ReadBytes); - - // - // Close the pipe connection - // - NamedPipeClientClosePipe(PipeHandle); - - // - // Make sure to exit the test program - // - exit(0); - } - } - else - { - printf("you should not test functionalities directly, instead use 'test' " - "command from HyperDbg...\n"); - - free(Buffer); - return 1; - } - - free(Buffer); - return 0; -} diff --git a/hyperdbg/hyperdbg-test/code/tests/lookup.cpp b/hyperdbg/hyperdbg-test/code/tests/lookup.cpp deleted file mode 100644 index f9d9e1d4..00000000 --- a/hyperdbg/hyperdbg-test/code/tests/lookup.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/** - * @file lookup.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief perform tests and create lookup details - * @details - * @version 0.1 - * @date 2021-04-09 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Thread for listening for results - * - * @param Data - * @return DWORD Device Handle - */ -DWORD WINAPI -TestListenerForResultsThread(void * data) -{ - HANDLE OutputPipeHandle; - UINT32 ReadBytes; - char * BufferToRead; - char TestPipe[] = "\\\\.\\Pipe\\HyperDbgOutputTest"; - - // - // Create server pipe for outputs ******** Thread ******** - // - OutputPipeHandle = NamedPipeServerCreatePipe(TestPipe, - TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE, - TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - if (!OutputPipeHandle) - { - // - // Error in creating handle - // - return FALSE; - } - - BufferToRead = (char *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - - // - // Wait for message from the target process - // - if (!NamedPipeServerWaitForClientConntection(OutputPipeHandle)) - { - // - // Error in connection - // - free(BufferToRead); - return FALSE; - } - -ReadAgain: - ReadBytes = - NamedPipeServerReadClientMessage(OutputPipeHandle, BufferToRead, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - - if (!ReadBytes) - { - // - // Nothing to read - // - - free(BufferToRead); - return FALSE; - } - - // - // parse results from debugger - // - printf("Test from debugger : %s\n", BufferToRead); - - // - // Stuck on a loop - // - goto ReadAgain; - - return TRUE; -} - -/** - * @brief Create lookup table for test - * - * @param PipeHandle - * @param KernelInformation - * @param KernelInformationSize - * - * @return VOID - */ -VOID -TestCreateLookupTable(HANDLE PipeHandle, PVOID KernelInformation, UINT32 KernelInformationSize) -{ - BOOLEAN SentMessageResult; - PDEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION KernelInfoArray; - char SuccessMessage[] = "success"; - char KernelTestMessage[] = "perform-kernel-test"; - vector LookupTable; - vector TestCases; - int IndexOfTestCasesVector = 0; - DWORD ThreadId; - - printf("start testing event commands...\n"); - - KernelInfoArray = (PDEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION)KernelInformation; - - // - // Add kernel-mode details to lookup table - // - for (size_t i = 0; i < KernelInformationSize / sizeof(DEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION); i++) - { - LookupTable.push_back(KernelInfoArray[i]); - } - - // - // Add user-mode details to lookup table - // - - // Todo - - // - // Create thread for listening results - // - HANDLE Thread = CreateThread(NULL, 0, TestListenerForResultsThread, NULL, 0, &ThreadId); - - // - // Read test-cases - // - if (!TestCase(TestCases)) - { - // - // There was an error - // - return; - } - - // - // Replace tags with addresses - // - for (auto & CurrentCase : TestCases) - { - // - // Template instantiations for - // extracting the matching pattern - // - smatch Match; - regex r("\\[(.*?)\\]"); - string Subject = std::move(CurrentCase); - - int i = 1; - while (regex_search(Subject, Match, r)) - { - for (auto & item : LookupTable) - { - string Temp = ConvertToString(item.Tag); - Temp = "[" + Temp + "]"; - - if (!Temp.compare(Match.str(0))) - { - StringReplace(TestCases[IndexOfTestCasesVector], Temp, Uint64ToString(item.Value)); - } - } - - // - // suffix to find the rest of the string - // - Subject = Match.suffix().str(); - i++; - } - IndexOfTestCasesVector++; - } - - _getch(); - - // - // Execute commands in debugger - // - for (auto NewCase : TestCases) - { - printf("new cases : %s\n", NewCase.c_str()); - - string OutputCommand = "cmd:" + NewCase; - - SentMessageResult = NamedPipeClientSendMessage(PipeHandle, (char *)OutputCommand.c_str(), (int)OutputCommand.length() + 1); - if (!SentMessageResult) - { - // - // Sending error - // - return; - } - } - - _getch(); - - // - // Send test kernel message to the HyperDbg - // - SentMessageResult = NamedPipeClientSendMessage(PipeHandle, (char *)KernelTestMessage, sizeof(KernelTestMessage)); - - if (!SentMessageResult) - { - // - // Sending error - // - return; - } - - _getch(); - - // - // Send success message to the HyperDbg - // - SentMessageResult = NamedPipeClientSendMessage(PipeHandle, (char *)SuccessMessage, sizeof(SuccessMessage)); - - if (!SentMessageResult) - { - // - // Sending error - // - return; - } -} diff --git a/hyperdbg/hyperdbg-test/code/tests/namedpipe.cpp b/hyperdbg/hyperdbg-test/code/tests/namedpipe.cpp deleted file mode 100644 index b8a26d31..00000000 --- a/hyperdbg/hyperdbg-test/code/tests/namedpipe.cpp +++ /dev/null @@ -1,434 +0,0 @@ -/** - * @file namedpipe.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Server and Client communication over NamedPipes - * @details - * @version 0.1 - * @date 2020-07-15 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -//////////////////////////////////////////////////////////////////////////// -// Server Side // -//////////////////////////////////////////////////////////////////////////// - -/** - * @brief Create a named pipe server - * - * @param PipeName - * @param OutputBufferSize - * @param InputBufferSize - * @return HANDLE - */ -HANDLE -NamedPipeServerCreatePipe(LPCSTR PipeName, UINT32 OutputBufferSize, UINT32 InputBufferSize) -{ - HANDLE hPipe; - - hPipe = CreateNamedPipeA(PipeName, // pipe name - PIPE_ACCESS_DUPLEX, // read/write access - PIPE_TYPE_MESSAGE | // message type pipe - PIPE_READMODE_MESSAGE | // message-read mode - PIPE_WAIT, // blocking mode - PIPE_UNLIMITED_INSTANCES, // max. instances - OutputBufferSize, // output buffer size - InputBufferSize, // input buffer size - NMPWAIT_USE_DEFAULT_WAIT, // client time-out - NULL); // default security attribute - - if (INVALID_HANDLE_VALUE == hPipe) - { - printf("err, occurred while creating the pipe (%x)\n", - GetLastError()); - return NULL; - } - return hPipe; -} - -/** - * @brief wait for client connection - * - * @param PipeHandle - * @return BOOLEAN - */ -BOOLEAN -NamedPipeServerWaitForClientConntection(HANDLE PipeHandle) -{ - // - // Wait for the client to connect - // - BOOL bClientConnected = ConnectNamedPipe(PipeHandle, NULL); - - if (FALSE == bClientConnected) - { - printf("err, occurred while connecting to the client (%x)\n", - GetLastError()); - CloseHandle(PipeHandle); - return FALSE; - } - - // - // Client connected - // - return TRUE; -} - -/** - * @brief read client message from the named pipe - * - * @param PipeHandle - * @param BufferToSave - * @param MaximumReadBufferLength - * @return UINT32 - */ -UINT32 -NamedPipeServerReadClientMessage(HANDLE PipeHandle, char * BufferToSave, int MaximumReadBufferLength) -{ - DWORD cbBytes; - - // - // We are connected to the client. - // To communicate with the client - // we will use ReadFile()/WriteFile() - // on the pipe handle - hPipe - // - - // - // 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 - - if ((!bResult) || (0 == cbBytes)) - { - printf("err, occurred while reading from the client (%x)\n", - GetLastError()); - CloseHandle(PipeHandle); - return 0; - } - - // - // Number of bytes that the client sends to us - // - return cbBytes; -} - -BOOLEAN -NamedPipeServerSendMessageToClient(HANDLE PipeHandle, - char * BufferToSend, - int BufferSize) -{ - DWORD cbBytes; - - // - // 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 - - if ((!bResult) || (BufferSize != cbBytes)) - { - printf("Error occurred while writing to the client (%x)\n", - GetLastError()); - CloseHandle(PipeHandle); - return FALSE; - } - return TRUE; -} - -/** - * @brief Close handle of server's named pipe - * - * @param PipeHandle - * @return VOID - */ -VOID -NamedPipeServerCloseHandle(HANDLE PipeHandle) -{ - CloseHandle(PipeHandle); -} - -//************************************************************************** - -//////////////////////////////////////////////////////////////////////////// -// // -// Client Side // -// // -//////////////////////////////////////////////////////////////////////////// - -/** - * @brief Create a client named pipe - * @details Pipe name format - \\servername\pipe\pipename - * This pipe is for server on the same computer, - * however, pipes can be used to connect to a remote server - * - * @param PipeName - * @return HANDLE - */ -HANDLE -NamedPipeClientCreatePipe(LPCSTR PipeName) -{ - HANDLE hPipe; - - // - // Connect to the server pipe using CreateFile() - // - hPipe = CreateFileA(PipeName, // pipe name - GENERIC_READ | // read and write access - GENERIC_WRITE, - 0, // no sharing - NULL, // default security attributes - OPEN_EXISTING, // opens existing pipe - 0, // default attributes - NULL); // no template file - - if (INVALID_HANDLE_VALUE == hPipe) - { - printf("err, occurred while connecting to the server (%x)\n", - GetLastError()); - // - // One might want to check whether the server pipe is busy - // This sample will error out if the server pipe is busy - // Read on ERROR_PIPE_BUSY and WaitNamedPipe() for that - // - - // - // Error - // - return NULL; - } - else - { - return hPipe; - } -} - -/** - * @brief send client message over named pipe - * - * @param PipeHandle - * @param BufferToSend - * @param BufferSize - * @return BOOLEAN - */ -BOOLEAN -NamedPipeClientSendMessage(HANDLE PipeHandle, char * BufferToSend, int BufferSize) -{ - // - // We are done connecting to the server pipe, - // we can start communicating with - // the server using ReadFile()/WriteFile() - // on handle - hPipe - // - - DWORD cbBytes; - - // - // 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 - - if ((!bResult) || (BufferSize != cbBytes)) - { - printf("err, occurred while writing to the server (%x)\n", - GetLastError()); - CloseHandle(PipeHandle); - - // - // Error - // - CloseHandle(PipeHandle); - return FALSE; - } - else - { - return TRUE; - } -} - -// -// Read the count of read buffer -// -UINT32 -NamedPipeClientReadMessage(HANDLE PipeHandle, char * BufferToRead, int MaximumSizeOfBuffer) -{ - DWORD cbBytes; - - // - // 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 - - if ((!bResult) || (0 == cbBytes)) - { - printf("err, occurred while reading from the server (%x)\n", - GetLastError()); - CloseHandle(PipeHandle); - return NULL; // Error - } - - // - // Success - // - return cbBytes; -} - -/** - * @brief close named pipe handle of client - * - * @param PipeHandle - * @return VOID - */ -VOID -NamedPipeClientClosePipe(HANDLE PipeHandle) -{ - CloseHandle(PipeHandle); -} - -//////////////////////////////////////////////////////////////////////////// -// // -// Example Server // -// // -//////////////////////////////////////////////////////////////////////////// - -/** - * @brief and example of how to use named pipe as a server - * - * @return int - */ -int -NamedPipeServerExample() -{ - HANDLE PipeHandle; - BOOLEAN SentMessageResult; - UINT32 ReadBytes; - const int BufferSize = 1024; - char BufferToRead[BufferSize] = {0}; - char BufferToSend[BufferSize] = "test message to send from server !!!"; - - PipeHandle = NamedPipeServerCreatePipe("\\\\.\\Pipe\\HyperDbgTests", - BufferSize, - BufferSize); - if (!PipeHandle) - { - // - // Error in creating handle - // - return 1; - } - - if (!NamedPipeServerWaitForClientConntection(PipeHandle)) - { - // - // Error in connection - // - return 1; - } - - ReadBytes = - NamedPipeServerReadClientMessage(PipeHandle, BufferToRead, BufferSize); - - if (!ReadBytes) - { - // - // Nothing to read - // - return 1; - } - - printf("Message from client : %s\n", BufferToRead); - - SentMessageResult = NamedPipeServerSendMessageToClient( - PipeHandle, - BufferToSend, - (int)strlen(BufferToSend) + 1); - - if (!SentMessageResult) - { - // - // error in sending - // - return 1; - } - - NamedPipeServerCloseHandle(PipeHandle); - - return 0; -} - -//////////////////////////////////////////////////////////////////////////// -// // -// Example Client // -// // -//////////////////////////////////////////////////////////////////////////// - -/** - * @brief and example of how to use named pipe as a client - * - * @return int - */ -int -NamedPipeClientExample() -{ - HANDLE PipeHandle; - BOOLEAN SentMessageResult; - UINT32 ReadBytes; - const int BufferSize = 1024; - char Buffer[BufferSize] = "test message to send from client !!!"; - - PipeHandle = NamedPipeClientCreatePipe("\\\\.\\Pipe\\HyperDbgTests"); - - if (!PipeHandle) - { - // - // Unable to create handle - // - return 1; - } - - SentMessageResult = - NamedPipeClientSendMessage(PipeHandle, Buffer, (int)strlen(Buffer) + 1); - - if (!SentMessageResult) - { - // - // Sending error - // - return 1; - } - - ReadBytes = NamedPipeClientReadMessage(PipeHandle, Buffer, BufferSize); - - if (!ReadBytes) - { - // - // Nothing to read - // - return 1; - } - - printf("Server sent the following message: %s\n", Buffer); - - NamedPipeClientClosePipe(PipeHandle); - - return 0; -} diff --git a/hyperdbg/hyperdbg-test/code/tests/test-cases.cpp b/hyperdbg/hyperdbg-test/code/tests/test-cases.cpp deleted file mode 100644 index 1eac146f..00000000 --- a/hyperdbg/hyperdbg-test/code/tests/test-cases.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file test-cases.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief test cases - * @details - * @version 0.1 - * @date 2021-04-10 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Create test cases - * @param std::vector & - * - * @return BOOLEAN - */ -BOOLEAN -TestCase(std::vector & TestCases) -{ - string Line; - - // - // Read the test case files - // - std::ifstream File(TEST_CASE_FILE_NAME); - - if (File.is_open()) - { - while (std::getline(File, Line)) - { - TestCases.push_back(Line); - } - File.close(); - } - else - { - // - // The file can't be opened - // - printf("err, test case file not found (%s) \npress enter to continue", TEST_CASE_FILE_NAME); - _getch(); - - return FALSE; - } - - return TRUE; -} diff --git a/hyperdbg/hyperdbg-test/code/tests/test-codeview-rsds-parser.cpp b/hyperdbg/hyperdbg-test/code/tests/test-codeview-rsds-parser.cpp new file mode 100644 index 00000000..a121929e --- /dev/null +++ b/hyperdbg/hyperdbg-test/code/tests/test-codeview-rsds-parser.cpp @@ -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 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; +} diff --git a/hyperdbg/hyperdbg-test/code/tests/test-parser.cpp b/hyperdbg/hyperdbg-test/code/tests/test-parser.cpp new file mode 100644 index 00000000..355bfd45 --- /dev/null +++ b/hyperdbg/hyperdbg-test/code/tests/test-parser.cpp @@ -0,0 +1,380 @@ +/** + * @file test-parser.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Perform test on command parser + * @details + * @version 0.11 + * @date 2024-08-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +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 + * + * @return A pointer to the array of strings + */ +CHAR_PTR_PTR +CreateTestCaseArray(const std::vector & 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)); + + // + // Allocate memory for each string and copy the content + // + for (SIZE_T i = 0; i < TestCases.size(); ++i) + { + TestCaseArray[i] = (CHAR *)malloc(TestCases[i].length() + 1); // +1 for the null terminator + + if (TestCaseArray[i] == NULL) + { + return NULL; + } + std::strcpy(TestCaseArray[i], TestCases[i].c_str()); + } + + 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 + * + * @return VOID + */ +VOID +FreeTestCaseArray(CHAR_PTR_PTR TestCaseArray, SIZE_T Size) +{ + // + // Free each string + // + for (SIZE_T i = 0; i < Size; ++i) + { + free(TestCaseArray[i]); + } + + // + // Free the array of pointers + // + free(TestCaseArray); +} + +/** + * @brief Parse the test cases from the file + * @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>> +ParseTestCases(const std::string & Filename) +{ + std::ifstream file(Filename); + std::string Line; + std::string Command; + std::string CurrentToken; + std::vector Tokens; + std::vector>> TestCases; + BOOLEAN IsCommand = FALSE; + BOOLEAN AddNewline = FALSE; + + const std::string TokenDelimiter = "----------------------------------"; + const std::string CommandDelimiter = "_____________________________________________________________"; + + while (std::getline(file, Line)) + { + if (Line == CommandDelimiter) + { + // + // No new line is needed after this token + // + AddNewline = FALSE; + + // + // Save the previous command and its tokens if any + // + if (!Command.empty()) + { + if (!CurrentToken.empty()) + { + Tokens.push_back(CurrentToken); + CurrentToken.clear(); + } + TestCases.push_back({Command, Tokens}); + Command.clear(); + Tokens.clear(); + } + + // + // is command is true since a command is started + // + IsCommand = TRUE; + } + else if (Line == TokenDelimiter) + { + // + // No new line is needed after this token + // + AddNewline = FALSE; + + // + // not in command anymore + // + IsCommand = FALSE; + + // + // If we're in the middle of collecting a token, save it + // + if (!CurrentToken.empty()) + { + Tokens.push_back(CurrentToken); + CurrentToken.clear(); + } + } + else + { + // + // Accumulate lines for the command or token + // + if (IsCommand) + { + if (AddNewline) + Command += "\n"; + Command += Line; + } + else + { + if (AddNewline) + CurrentToken += "\n"; + CurrentToken += Line; + } + + AddNewline = TRUE; + } + } + + // + // Store the last command and tokens if any + // + if (!Command.empty()) + { + if (!CurrentToken.empty()) + { + Tokens.push_back(CurrentToken); + } + TestCases.push_back({Command, Tokens}); + } + + 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 + * + * @return INT32 The number of occurrences of the substring "\\n" + */ +INT32 +CountBackslashNUpToPosition(const std::string & Str, std::size_t Limit) +{ + 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) + { + ++Count; + Pos += Target.length(); // Move past the current occurrence + } + + return Count; +} + +/** + * @brief Show parsed command and tokens + * @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> & TestCase, + UINT32 FailedTokenNum, + UINT32 FailedTokenPosition) +{ + UINT32 TokenNum = 0; + + // + // Output the parsed test case + // + + string ShowingCommand = TestCase.first; + + 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 + } + + std::cout << "Command: \"" << ShowingCommand << "\"" << std::endl; + std::cout << "____________________________________\n"; + + std::cout << "Expected Tokens: " << std::endl; + + for (const auto & Token : TestCase.second) + { + string ShowingToken = Token; + + Pos = 0; + while ((Pos = ShowingToken.find("\n", Pos)) != std::string::npos) + { + ShowingToken.replace(Pos, 1, "\\n"); + Pos += 2; // Move past the newly added characters + } + + if (TokenNum == FailedTokenNum) + { + std::cout << " x "; + } + else + { + std::cout << " - "; + } + + std::cout << "\"" << ShowingToken << "\"" << std::endl; + + if (TokenNum == FailedTokenNum) + { + std::cout << " "; + INT32 CountOfSpaces = CountBackslashNUpToPosition(ShowingToken, FailedTokenPosition); + + CountOfSpaces += FailedTokenPosition; + + for (INT32 i = 0; i < CountOfSpaces; i++) + { + std::cout << " "; + } + std::cout << "^" << std::endl; + } + + TokenNum++; + } +} + +/** + * @brief Test command parser + * + * @return BOOLEAN + */ +BOOLEAN +TestCommandParser() +{ + 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)) + { + // + // Error could not find the test case files + // + cout << "[-] Could not find the test case files" << endl; + return FALSE; + } + + // + // Parse the test cases from the file + // + auto TestCases = ParseTestCases(FilePath); + + // + // Perform testing test cases with parsed file + // + cout << "Perform testing test cases with parsed file:" << endl; + + // + // Output the parsed test cases + // + for (const auto & TestCase : TestCases) + { + TestNum++; + + // + // Create CHAR** + // + 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)) + { + cout << "[+] Test number " << TestNum << " Passed " << endl; + } + else + { + // + // Set overall result to FALSE since one of the test cases failed + // + OverallResult = FALSE; + + // + // Show parsed command and tokens + // + cout << "\n============================================================" << endl; + cout << "\n********************* " << endl; + cout << "*** Error details *** " << endl; + cout << "********************* " << endl; + cout << "\nParsed tokens from HyperDbg main command parser:\n" + << endl; + + // + // Show tokens + // + 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); + + cout << "\n[-] Test number " << TestNum << " Failed " << endl; + cout << "============================================================\n" + << endl; + + break; + } + + // + // Clean up memory + // + FreeTestCaseArray(TestCaseArray, TestCase.second.size()); + } + + return OverallResult; +} diff --git a/hyperdbg/hyperdbg-test/code/tests/test-pe-parser.cpp b/hyperdbg/hyperdbg-test/code/tests/test-pe-parser.cpp new file mode 100644 index 00000000..194b042b --- /dev/null +++ b/hyperdbg/hyperdbg-test/code/tests/test-pe-parser.cpp @@ -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; +} diff --git a/hyperdbg/hyperdbg-test/code/tests/test-semantic-scripts.cpp b/hyperdbg/hyperdbg-test/code/tests/test-semantic-scripts.cpp new file mode 100644 index 00000000..9fa7695a --- /dev/null +++ b/hyperdbg/hyperdbg-test/code/tests/test-semantic-scripts.cpp @@ -0,0 +1,133 @@ +/** + * @file test-semantic-scripts.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Perform test on semantic scripts + * @details + * @version 0.11 + * @date 2024-08-16 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +namespace fs = std::filesystem; + +/** + * @brief Read directory of semantic test cases and run each of them + * + * @param ScriptSemanticPath Path to the semantic test cases + * + * @return VOID + */ +VOID +ReadDirectoryAndTestSemanticTestCases(const CHAR * ScriptSemanticPath) +{ + // + // Iterate through the directory + // + try + { + for (const auto & entry : fs::directory_iterator(ScriptSemanticPath)) + { + // + // Check if the entry is a file + // + if (entry.is_regular_file()) + { + // + // Get the file path + // + std::string FilePath = entry.path().string(); + + // + // Output the file name + // + // std::cout << "Test case file: " << entry.path().filename().string() << std::endl; + + // + // Open the file and read its contents + // + std::ifstream File(FilePath); + if (File.is_open()) + { + std::string Content((std::istreambuf_iterator(File)), + std::istreambuf_iterator()); + + // + // Display the content of the file + // + std::cout << "Executing file " << entry.path().filename().string() << std::endl; + + // std::cout << content << std::endl; + + // + // Run the test case command + // + hyperdbg_u_run_command((CHAR *)Content.c_str()); + + std::cout << "--------------------------------------------" << std::endl; + + // + // Close the file + // + File.close(); + } + else + { + std::cerr << "Could not open file: " << FilePath << std::endl; + } + } + } + } + catch (const fs::filesystem_error & e) + { + std::cerr << "Filesystem error: " << e.what() << std::endl; + } +} + +/** + * @brief Test semantic scripts + * + * @return BOOLEAN + */ +BOOLEAN +TestSemanticScripts() +{ + INT32 TestNum = 0; + CHAR dirPath[MAX_PATH] = {0}; + + // + // Parse the semantic script test cases from the file + // Setup the path for the filenames + // + if (!hyperdbg_u_setup_path_for_filename(SCRIPT_SEMANTIC_TEST_CASE_DIRECTORY, dirPath, MAX_PATH, FALSE)) + { + // + // Error could not find the test case files + // + cout << "[-] Could not find the test case files" << endl; + return FALSE; + } + + // + // Connect to the debugger + // + if (!hyperdbg_u_connect_remote_debugger_using_named_pipe(TEST_DEFAULT_NAMED_PIPE, TRUE)) + { + cout << "[-] Could not connect to the debugger" << endl; + return FALSE; + } + + // + // Run test cases + // + ReadDirectoryAndTestSemanticTestCases(dirPath); + + // + // Close the connection + // + hyperdbg_u_debug_close_remote_debugger(); + + return TRUE; +} diff --git a/hyperdbg/hyperdbg-test/code/tests/tools.cpp b/hyperdbg/hyperdbg-test/code/tests/tools.cpp deleted file mode 100644 index 125b1e44..00000000 --- a/hyperdbg/hyperdbg-test/code/tests/tools.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @file tools.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief general functions used in test project - * @details - * @version 0.1 - * @date 2021-04-11 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -std::string -Uint64ToString(UINT64 value) -{ - ostringstream Os; - Os << setw(16) << setfill('0') << hex << value; - return Os.str(); -} - -BOOLEAN -StringReplace(std::string & str, const std::string & from, const std::string & to) -{ - size_t start_pos = str.find(from); - if (start_pos == string::npos) - return FALSE; - str.replace(start_pos, from.length(), to); - return TRUE; -} - -std::string -ConvertToString(char * Str) -{ - string s(Str); - - return s; -} diff --git a/hyperdbg/hyperdbg-test/code/tools.cpp b/hyperdbg/hyperdbg-test/code/tools.cpp new file mode 100644 index 00000000..4a69f73c --- /dev/null +++ b/hyperdbg/hyperdbg-test/code/tools.cpp @@ -0,0 +1,58 @@ +/** + * @file tools.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief general functions used in test project + * @details + * @version 0.1 + * @date 2021-04-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#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) +{ + ostringstream Os; + 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) +{ + SIZE_T StartPos = Str.find(From); + if (StartPos == string::npos) + return FALSE; + 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) +{ + string Result(Str); + + return Result; +} diff --git a/hyperdbg/hyperdbg-test/header/hwdbg-tests.h b/hyperdbg/hyperdbg-test/header/hwdbg-tests.h new file mode 100644 index 00000000..32229711 --- /dev/null +++ b/hyperdbg/hyperdbg-test/header/hwdbg-tests.h @@ -0,0 +1,19 @@ +/** + * @file hwdbg-tests.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for the hardware tests for hwdbg + * @details + * @version 0.11 + * @date 2024-09-30 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +HwdbgTestCreateTestCases(); diff --git a/hyperdbg/hyperdbg-test/header/namedpipe.h b/hyperdbg/hyperdbg-test/header/namedpipe.h index 8541560a..adc69468 100644 --- a/hyperdbg/hyperdbg-test/header/namedpipe.h +++ b/hyperdbg/hyperdbg-test/header/namedpipe.h @@ -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); diff --git a/hyperdbg/hyperdbg-test/header/routines.h b/hyperdbg/hyperdbg-test/header/routines.h index 44c47cdf..ed7abc8c 100644 --- a/hyperdbg/hyperdbg-test/header/routines.h +++ b/hyperdbg/hyperdbg-test/header/routines.h @@ -22,7 +22,7 @@ TestCase(std::vector & 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); diff --git a/hyperdbg/hyperdbg-test/header/testcases.h b/hyperdbg/hyperdbg-test/header/testcases.h new file mode 100644 index 00000000..79ff93fa --- /dev/null +++ b/hyperdbg/hyperdbg-test/header/testcases.h @@ -0,0 +1,28 @@ +/** + * @file testcases.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief header for test cases + * @details + * @version 0.11 + * @date 2024-08-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Test cases // +////////////////////////////////////////////////// + +BOOLEAN +TestCommandParser(); + +BOOLEAN +TestPeParser(); + +BOOLEAN +TestCodeViewRsdsParser(); + +BOOLEAN +TestSemanticScripts(); diff --git a/hyperdbg/hyperdbg-test/hyperdbg-test.vcxproj b/hyperdbg/hyperdbg-test/hyperdbg-test.vcxproj index e028175c..b50f7554 100644 --- a/hyperdbg/hyperdbg-test/hyperdbg-test.vcxproj +++ b/hyperdbg/hyperdbg-test/hyperdbg-test.vcxproj @@ -21,14 +21,14 @@ Application true - v143 + v145 Unicode false Application false - v143 + v145 true Unicode false @@ -61,18 +61,20 @@ Level3 true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - $(SolutionDir)\include;$(SolutionDir)dependencies;$(ProjectDir);%(AdditionalIncludeDirectories) - Use + $(SolutionDir)\include;$(SolutionDir)dependencies;$(ProjectDir);$(SolutionDir)libhyperdbg;$(SolutionDir)symbol-parser;%(AdditionalIncludeDirectories) + Create pch.h MultiThreadedDebug true + stdcpp20 Console true true + $(SolutionDir)build\bin\$(Configuration)\libhyperdbg.lib;%(AdditionalDependencies) @@ -81,13 +83,15 @@ true true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - $(SolutionDir)\include;$(SolutionDir)dependencies;$(ProjectDir);%(AdditionalIncludeDirectories) - Use + $(SolutionDir)\include;$(SolutionDir)dependencies;$(ProjectDir);$(SolutionDir)libhyperdbg;$(SolutionDir)symbol-parser;%(AdditionalIncludeDirectories) + Create pch.h MultiThreaded true + stdcpp20 + MaxSpeed Console @@ -95,22 +99,31 @@ true true true + $(SolutionDir)build\bin\$(Configuration)\libhyperdbg.lib;%(AdditionalDependencies) - - - - - - - Create - Create - + + + + + + + + + + + + + + + + + diff --git a/hyperdbg/hyperdbg-test/hyperdbg-test.vcxproj.filters b/hyperdbg/hyperdbg-test/hyperdbg-test.vcxproj.filters index a64f1561..2840f4a7 100644 --- a/hyperdbg/hyperdbg-test/hyperdbg-test.vcxproj.filters +++ b/hyperdbg/hyperdbg-test/hyperdbg-test.vcxproj.filters @@ -15,41 +15,92 @@ {0dd2fc9a-1efe-43ae-963c-f3e04a9d5f33} + + {3b15cfee-d573-4538-aa01-0bac669f0360} + + + {18515e99-bdbe-465f-9c92-58dc89591116} + + + {4905a2c5-31b5-4b16-9f84-d2b3b39726d3} + + + {2835e8e0-5525-473b-ae43-c498674fb42e} + + + {b36455ac-6726-4c17-903c-3c3e3de1b783} + + + {b3920039-7e86-412e-bf10-8a5a7946e102} + - + code\tests - + code\tests - + code\tests - + + code + + + code + + + code + + code\tests - + + code\hardware + + + code\tests + + code\tests code + + code\components\pe + - - header - header header + + header + + + header + + + header + + + header\components\pe + + + header + + + header + code\assembly -
\ No newline at end of file + diff --git a/hyperdbg/hyperdbg-test/pch.h b/hyperdbg/hyperdbg-test/pch.h index 8b856ad6..0d6f1d11 100644 --- a/hyperdbg/hyperdbg-test/pch.h +++ b/hyperdbg/hyperdbg-test/pch.h @@ -11,6 +11,16 @@ */ #pragma once +// +// namespace +// +using namespace std; + +// +// Environment headers +// +#include "platform/general/header/Environment.h" + // // General Headers // @@ -23,13 +33,35 @@ #include #include #include +#include +#include + +// +// SDK and config headers +// +#include "SDK/HyperDbgSdk.h" +#include "config/Definition.h" // // Program Defined Headers // -#include "SDK/HyperDbgSdk.h" -#include "Definition.h" -#include "..\hyperdbg-test\header\namedpipe.h" -#include "..\hyperdbg-test\header\routines.h" +#include "header/namedpipe.h" +#include "header/routines.h" +#include "header/testcases.h" +#include "header/pdb-identity.h" +#include "header/codeview-rsds.h" -using namespace std; +// +// Components +// +#include "../include/components/pe/header/pe-image-reader.h" + +// +// Hardware Debugger Headers +// +#include "header/hwdbg-tests.h" + +// +// import libhyperdbg +// +#include "SDK/imports/user/HyperDbgLibImports.h" diff --git a/hyperdbg/hyperdbg-test/test-cases.txt b/hyperdbg/hyperdbg-test/test-cases.txt deleted file mode 100644 index 8570e0be..00000000 --- a/hyperdbg/hyperdbg-test/test-cases.txt +++ /dev/null @@ -1,3 +0,0 @@ -output create TestOutputName namedpipe \\\\.\\Pipe\\HyperDbgOutputTest -output open TestOutputName -!epthook [ExAllocatePoolWithTag] script { print(@rax); } output {TestOutputName} \ No newline at end of file diff --git a/hyperdbg/hyperdbg.sln b/hyperdbg/hyperdbg.sln index e6b084f3..90b129a9 100644 --- a/hyperdbg/hyperdbg.sln +++ b/hyperdbg/hyperdbg.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32602.215 +# Visual Studio Version 18 +VisualStudioVersion = 18.7.11911.148 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperdbg-cli", "hyperdbg-cli\hyperdbg-cli.vcxproj", "{FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}" ProjectSection(ProjectDependencies) = postProject @@ -11,26 +11,24 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperdbg-cli", "hyperdbg-cl {C3DC85E1-0559-4B58-9792-DE421472DFE9} = {C3DC85E1-0559-4B58-9792-DE421472DFE9} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hprdbghv", "hprdbghv\hprdbghv.vcxproj", "{BB17323A-2460-4AE1-8AFE-B367400B934F}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperhv", "hyperhv\hyperhv.vcxproj", "{BB17323A-2460-4AE1-8AFE-B367400B934F}" ProjectSection(ProjectDependencies) = postProject {2D988267-CC53-41E3-936A-48CEF9049DF5} = {2D988267-CC53-41E3-936A-48CEF9049DF5} + {B226530A-14B1-40AC-B82E-D9057400E7EE} = {B226530A-14B1-40AC-B82E-D9057400E7EE} EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "include", "include", "{1997E4B6-FE49-4358-ADF1-CDDB5739508E}" - ProjectSection(SolutionItems) = preProject - include\Configuration.h = include\Configuration.h - include\Definition.h = include\Definition.h - include\ZycoreExportConfig.h = include\ZycoreExportConfig.h - include\ZydisExportConfig.h = include\ZydisExportConfig.h - EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hprdbgctrl", "hprdbgctrl\hprdbgctrl.vcxproj", "{809C3AD5-3211-4992-A472-9D81D124C5FA}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhyperdbg", "libhyperdbg\libhyperdbg.vcxproj", "{809C3AD5-3211-4992-A472-9D81D124C5FA}" ProjectSection(ProjectDependencies) = postProject {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA} = {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA} {C2D44C60-3F23-4972-8F60-21083B9FB112} = {C2D44C60-3F23-4972-8F60-21083B9FB112} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperdbg-test", "hyperdbg-test\hyperdbg-test.vcxproj", "{C3DC85E1-0559-4B58-9792-DE421472DFE9}" + ProjectSection(ProjectDependencies) = postProject + {809C3AD5-3211-4992-A472-9D81D124C5FA} = {809C3AD5-3211-4992-A472-9D81D124C5FA} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "script-engine", "script-engine\script-engine.vcxproj", "{C2D44C60-3F23-4972-8F60-21083B9FB112}" ProjectSection(ProjectDependencies) = postProject @@ -51,8 +49,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SDK", "SDK", "{7EA9E1E8-428 include\SDK\HyperDbgSdk.h = include\SDK\HyperDbgSdk.h EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Headers", "Headers", "{D67D603F-4F99-4C0B-94BE-F4A2C6CC22B5}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "headers", "headers", "{D67D603F-4F99-4C0B-94BE-F4A2C6CC22B5}" ProjectSection(SolutionItems) = preProject + include\SDK\Headers\Assertions.h = include\SDK\Headers\Assertions.h include\SDK\Headers\BasicTypes.h = include\SDK\Headers\BasicTypes.h include\SDK\Headers\Connection.h = include\SDK\Headers\Connection.h include\SDK\Headers\Constants.h = include\SDK\Headers\Constants.h @@ -61,7 +60,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Headers", "Headers", "{D67D include\SDK\Headers\Events.h = include\SDK\Headers\Events.h include\SDK\Headers\HardwareDebugger.h = include\SDK\Headers\HardwareDebugger.h 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 EndProjectSection EndProject @@ -69,7 +73,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "script-eval", "script-eval" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "header", "header", "{4C47AB91-DF41-4741-80AF-FD87C32A961E}" ProjectSection(SolutionItems) = preProject - script-eval\header\ScriptEngineCommonDefinitions.h = script-eval\header\ScriptEngineCommonDefinitions.h script-eval\header\ScriptEngineHeader.h = script-eval\header\ScriptEngineHeader.h script-eval\header\ScriptEngineInternalHeader.h = script-eval\header\ScriptEngineInternalHeader.h EndProjectSection @@ -83,33 +86,24 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "code", "code", "{952986BC-7 script-eval\code\ScriptEngineEval.c = script-eval\code\ScriptEngineEval.c EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Imports", "Imports", "{B3D9DA75-8FBD-4A2C-826A-B50406396EC4}" - ProjectSection(SolutionItems) = preProject - include\SDK\Imports\HyperDbgCtrlImports.h = include\SDK\Imports\HyperDbgCtrlImports.h - include\SDK\Imports\HyperDbgHyperLogImports.h = include\SDK\Imports\HyperDbgHyperLogImports.h - include\SDK\Imports\HyperDbgHyperLogIntrinsics.h = include\SDK\Imports\HyperDbgHyperLogIntrinsics.h - include\SDK\Imports\HyperDbgRevImports.h = include\SDK\Imports\HyperDbgRevImports.h - include\SDK\Imports\HyperDbgScriptImports.h = include\SDK\Imports\HyperDbgScriptImports.h - include\SDK\Imports\HyperDbgSymImports.h = include\SDK\Imports\HyperDbgSymImports.h - include\SDK\Imports\HyperDbgVmmImports.h = include\SDK\Imports\HyperDbgVmmImports.h - EndProjectSection +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "imports", "imports", "{B3D9DA75-8FBD-4A2C-826A-B50406396EC4}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{38E28A69-09A9-4C7E-B0F1-49E8A3B5AA0B}" - ProjectSection(SolutionItems) = preProject - include\SDK\Examples\example.py = include\SDK\Examples\example.py - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hprdbgkd", "hprdbgkd\hprdbgkd.vcxproj", "{AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperkd", "hyperkd\hyperkd.vcxproj", "{AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}" ProjectSection(ProjectDependencies) = postProject + {360E54B1-0B92-4BCA-8111-4BF384292621} = {360E54B1-0B92-4BCA-8111-4BF384292621} + {9FA45E25-DAEB-4C2D-806C-7908A180195D} = {9FA45E25-DAEB-4C2D-806C-7908A180195D} {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D} = {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D} {BB17323A-2460-4AE1-8AFE-B367400B934F} = {BB17323A-2460-4AE1-8AFE-B367400B934F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperlog", "hyperlog\hyperlog.vcxproj", "{AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{13E49D84-7EA0-43A2-9B60-4B408A4C7602}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{13E49D84-7EA0-43A2-9B60-4B408A4C7602}" ProjectSection(SolutionItems) = preProject + include\SDK\modules\HyperEvade.h = include\SDK\modules\HyperEvade.h include\SDK\Modules\HyperLog.h = include\SDK\Modules\HyperLog.h + include\SDK\modules\HyperPerf.h = include\SDK\modules\HyperPerf.h + include\SDK\modules\HyperTrace.h = include\SDK\modules\HyperTrace.h include\SDK\Modules\VMM.h = include\SDK\Modules\VMM.h EndProjectSection EndProject @@ -150,167 +144,255 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "header", "header", "{D82074 include\components\optimizations\header\OptimizationsExamples.h = include\components\optimizations\header\OptimizationsExamples.h EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{9749520E-64FF-4633-855B-54BC541CDBB6}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "platform", "platform", "{9A711E36-8A78-4CE6-A34D-F681AF89A919}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperdbg_app", "include\SDK\Examples\hyperdbg_app\hprdbgrev.vcxproj", "{991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}" - ProjectSection(ProjectDependencies) = postProject - {809C3AD5-3211-4992-A472-9D81D124C5FA} = {809C3AD5-3211-4992-A472-9D81D124C5FA} - {C2D44C60-3F23-4972-8F60-21083B9FB112} = {C2D44C60-3F23-4972-8F60-21083B9FB112} +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "user", "user", "{015523BA-4326-4A84-9CB5-E1E9B6182209}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "kernel", "kernel", "{D0E5A2D1-787E-4129-A75B-34DD4D5FDFC7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "code", "code", "{6498728B-D9B0-4CAB-A9E3-ACE5BC371010}" + ProjectSection(SolutionItems) = preProject + include\platform\kernel\code\PlatformBroadcast.c = include\platform\kernel\code\PlatformBroadcast.c + include\platform\kernel\code\PlatformCpu.c = include\platform\kernel\code\PlatformCpu.c + include\platform\kernel\code\PlatformDbg.c = include\platform\kernel\code\PlatformDbg.c + include\platform\kernel\code\PlatformDpc.c = include\platform\kernel\code\PlatformDpc.c + include\platform\kernel\code\PlatformEvent.c = include\platform\kernel\code\PlatformEvent.c + include\platform\kernel\code\PlatformIntrinsics.c = include\platform\kernel\code\PlatformIntrinsics.c + include\platform\kernel\code\PlatformIntrinsicsVmx.c = include\platform\kernel\code\PlatformIntrinsicsVmx.c + include\platform\kernel\code\PlatformIo.c = include\platform\kernel\code\PlatformIo.c + include\platform\kernel\code\PlatformIrql.c = include\platform\kernel\code\PlatformIrql.c + include\platform\kernel\code\PlatformMem.c = include\platform\kernel\code\PlatformMem.c + include\platform\kernel\code\PlatformProcess.c = include\platform\kernel\code\PlatformProcess.c + include\platform\kernel\code\PlatformSpinlock.c = include\platform\kernel\code\PlatformSpinlock.c + include\platform\kernel\code\PlatformTime.c = include\platform\kernel\code\PlatformTime.c EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperdbg_driver", "include\SDK\Examples\hyperdbg_driver\hyperdbg_driver.vcxproj", "{79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "header", "header", "{AA41FFF1-A730-433E-8D26-13DA5B653825}" + ProjectSection(SolutionItems) = preProject + include\platform\kernel\header\pch.h = include\platform\kernel\header\pch.h + include\platform\kernel\header\PlatformBroadcast.h = include\platform\kernel\header\PlatformBroadcast.h + include\platform\kernel\header\PlatformCpu.h = include\platform\kernel\header\PlatformCpu.h + include\platform\kernel\header\PlatformDbg.h = include\platform\kernel\header\PlatformDbg.h + include\platform\kernel\header\PlatformDpc.h = include\platform\kernel\header\PlatformDpc.h + include\platform\kernel\header\PlatformEvent.h = include\platform\kernel\header\PlatformEvent.h + include\platform\kernel\header\PlatformIntrinsics.h = include\platform\kernel\header\PlatformIntrinsics.h + include\platform\kernel\header\PlatformIntrinsicsVmx.h = include\platform\kernel\header\PlatformIntrinsicsVmx.h + include\platform\kernel\header\PlatformIo.h = include\platform\kernel\header\PlatformIo.h + include\platform\kernel\header\PlatformIrql.h = include\platform\kernel\header\PlatformIrql.h + include\platform\kernel\header\PlatformMem.h = include\platform\kernel\header\PlatformMem.h + include\platform\kernel\header\PlatformModuleInfo.h = include\platform\kernel\header\PlatformModuleInfo.h + include\platform\kernel\header\PlatformProcess.h = include\platform\kernel\header\PlatformProcess.h + include\platform\kernel\header\PlatformSpinlock.h = include\platform\kernel\header\PlatformSpinlock.h + include\platform\kernel\header\PlatformTime.h = include\platform\kernel\header\PlatformTime.h + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "code", "code", "{4BF590C3-1032-4DD2-BF87-BB9E5781977C}" + ProjectSection(SolutionItems) = preProject + include\platform\user\code\platform-intrinsics.c = include\platform\user\code\platform-intrinsics.c + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "header", "header", "{DBE32379-8D5A-4454-A1B6-ACC407881898}" + ProjectSection(SolutionItems) = preProject + include\platform\user\header\platform-intrinsics.h = include\platform\user\header\platform-intrinsics.h + include\platform\user\header\Windows.h = include\platform\user\header\Windows.h + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "user", "user", "{3C04357D-93B5-4472-94BB-8D22A1EB16DB}" + ProjectSection(SolutionItems) = preProject + include\SDK\Imports\User\HyperDbgLibImports.h = include\SDK\Imports\User\HyperDbgLibImports.h + include\SDK\Imports\User\HyperDbgScriptImports.h = include\SDK\Imports\User\HyperDbgScriptImports.h + include\SDK\Imports\User\HyperDbgSymImports.h = include\SDK\Imports\User\HyperDbgSymImports.h + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "kernel", "kernel", "{947577A8-A9A5-4F90-8883-5FB722FE58E2}" + ProjectSection(SolutionItems) = preProject + include\SDK\imports\kernel\HyperDbgHyperEvade.h = include\SDK\imports\kernel\HyperDbgHyperEvade.h + include\SDK\Imports\Kernel\HyperDbgHyperLogImports.h = include\SDK\Imports\Kernel\HyperDbgHyperLogImports.h + include\SDK\Imports\Kernel\HyperDbgHyperLogIntrinsics.h = include\SDK\Imports\Kernel\HyperDbgHyperLogIntrinsics.h + include\SDK\imports\kernel\HyperDbgHyperPerf.h = include\SDK\imports\kernel\HyperDbgHyperPerf.h + include\SDK\imports\kernel\HyperDbgHyperTrace.h = include\SDK\imports\kernel\HyperDbgHyperTrace.h + include\SDK\Imports\Kernel\HyperDbgVmmImports.h = include\SDK\Imports\Kernel\HyperDbgVmmImports.h + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "zydis", "zydis", "{08BF9299-FCE9-439C-A66C-1C8AFEC93866}" + ProjectSection(SolutionItems) = preProject + include\zydis\ZycoreExportConfig.h = include\zydis\ZycoreExportConfig.h + include\zydis\ZydisExportConfig.h = include\zydis\ZydisExportConfig.h + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "keystone", "keystone", "{7271D70C-319A-455C-AD4A-BE0BC46FEE15}" + ProjectSection(SolutionItems) = preProject + include\keystone\arm.h = include\keystone\arm.h + include\keystone\arm64.h = include\keystone\arm64.h + include\keystone\evm.h = include\keystone\evm.h + include\keystone\hexagon.h = include\keystone\hexagon.h + include\keystone\keystone.h = include\keystone\keystone.h + include\keystone\mips.h = include\keystone\mips.h + include\keystone\ppc.h = include\keystone\ppc.h + include\keystone\riscv.h = include\keystone\riscv.h + include\keystone\sparc.h = include\keystone\sparc.h + include\keystone\systemz.h = include\keystone\systemz.h + include\keystone\x86.h = include\keystone\x86.h + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{C5BCEFF7-8097-4331-A96E-4F4857774AD8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "kernel", "kernel", "{5D395DF2-B247-48CC-924B-7F5D196C247A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "user", "user", "{2104BCF9-035E-45AA-B744-68A5B8FEFF13}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperdbg_driver", "..\examples\kernel\hyperdbg_driver\hyperdbg_driver.vcxproj", "{79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}" ProjectSection(ProjectDependencies) = postProject {BB17323A-2460-4AE1-8AFE-B367400B934F} = {BB17323A-2460-4AE1-8AFE-B367400B934F} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperdbg_app", "..\examples\user\hyperdbg_app\hyperdbg_app.vcxproj", "{991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}" + ProjectSection(ProjectDependencies) = postProject + {809C3AD5-3211-4992-A472-9D81D124C5FA} = {809C3AD5-3211-4992-A472-9D81D124C5FA} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperevade", "hyperevade\hyperevade.vcxproj", "{B226530A-14B1-40AC-B82E-D9057400E7EE}" + ProjectSection(ProjectDependencies) = postProject + {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D} = {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "hyper-v", "hyper-v", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" + ProjectSection(SolutionItems) = preProject + include\hyper-v\HypervTlfs.h = include\hyper-v\HypervTlfs.h + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{03550856-D63F-4069-87E1-8BF2F129DBE3}" + ProjectSection(SolutionItems) = preProject + include\config\Configuration.h = include\config\Configuration.h + include\config\Definition.h = include\config\Definition.h + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hypertrace", "hypertrace\hypertrace.vcxproj", "{9FA45E25-DAEB-4C2D-806C-7908A180195D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "general", "general", "{17652C16-00A0-40D4-A227-697E595DE053}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "header", "header", "{9E1A2FAF-696A-4CA7-8C2E-F6B80107A143}" + ProjectSection(SolutionItems) = preProject + include\platform\general\header\Environment.h = include\platform\general\header\Environment.h + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "linux", "linux", "{63D4BB7A-C404-4A35-A302-20034DD8BA77}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mock", "mock", "{770B65D6-5307-478C-A9EB-3E4A64B67225}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "code", "code", "{848FE945-4F37-4B5B-98C8-F22CA3AA7184}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "user", "user", "{D3722A82-0A54-4172-A0C1-1EA6500E9F1E}" + ProjectSection(SolutionItems) = preProject + linux\mock\user\Makefile = linux\mock\user\Makefile + linux\mock\user\mock.c = linux\mock\user\mock.c + linux\mock\user\pch.h = linux\mock\user\pch.h + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "kernel", "kernel", "{09E02C0A-6A6C-408A-8136-C787FDC58A5F}" + ProjectSection(SolutionItems) = preProject + linux\mock\kernel\Makefile = linux\mock\kernel\Makefile + linux\mock\kernel\mock.c = linux\mock\kernel\mock.c + 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 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hyperperf", "hyperperf\hyperperf.vcxproj", "{360E54B1-0B92-4BCA-8111-4BF384292621}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - debug|ARM64 = debug|ARM64 debug|x64 = debug|x64 - debug|x86 = debug|x86 - release|ARM64 = release|ARM64 release|x64 = release|x64 - release|x86 = release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.debug|ARM64.ActiveCfg = debug|x64 - {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.debug|ARM64.Build.0 = debug|x64 {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.debug|x64.ActiveCfg = debug|x64 {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.debug|x64.Build.0 = debug|x64 - {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.debug|x86.ActiveCfg = debug|x64 - {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.debug|x86.Build.0 = debug|x64 - {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.release|ARM64.ActiveCfg = release|x64 - {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.release|ARM64.Build.0 = release|x64 {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.release|x64.ActiveCfg = release|x64 {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.release|x64.Build.0 = release|x64 - {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.release|x86.ActiveCfg = release|x64 - {FBCBBBAD-4EAE-469E-827F-F59FE9E7375B}.release|x86.Build.0 = release|x64 - {BB17323A-2460-4AE1-8AFE-B367400B934F}.debug|ARM64.ActiveCfg = debug|x64 - {BB17323A-2460-4AE1-8AFE-B367400B934F}.debug|ARM64.Build.0 = debug|x64 {BB17323A-2460-4AE1-8AFE-B367400B934F}.debug|x64.ActiveCfg = debug|x64 {BB17323A-2460-4AE1-8AFE-B367400B934F}.debug|x64.Build.0 = debug|x64 - {BB17323A-2460-4AE1-8AFE-B367400B934F}.debug|x86.ActiveCfg = debug|x64 - {BB17323A-2460-4AE1-8AFE-B367400B934F}.debug|x86.Build.0 = debug|x64 - {BB17323A-2460-4AE1-8AFE-B367400B934F}.release|ARM64.ActiveCfg = release|x64 - {BB17323A-2460-4AE1-8AFE-B367400B934F}.release|ARM64.Build.0 = release|x64 {BB17323A-2460-4AE1-8AFE-B367400B934F}.release|x64.ActiveCfg = release|x64 {BB17323A-2460-4AE1-8AFE-B367400B934F}.release|x64.Build.0 = release|x64 - {BB17323A-2460-4AE1-8AFE-B367400B934F}.release|x86.ActiveCfg = release|x64 - {BB17323A-2460-4AE1-8AFE-B367400B934F}.release|x86.Build.0 = release|x64 - {809C3AD5-3211-4992-A472-9D81D124C5FA}.debug|ARM64.ActiveCfg = debug|x64 - {809C3AD5-3211-4992-A472-9D81D124C5FA}.debug|ARM64.Build.0 = debug|x64 {809C3AD5-3211-4992-A472-9D81D124C5FA}.debug|x64.ActiveCfg = debug|x64 {809C3AD5-3211-4992-A472-9D81D124C5FA}.debug|x64.Build.0 = debug|x64 - {809C3AD5-3211-4992-A472-9D81D124C5FA}.debug|x86.ActiveCfg = debug|x64 - {809C3AD5-3211-4992-A472-9D81D124C5FA}.debug|x86.Build.0 = debug|x64 - {809C3AD5-3211-4992-A472-9D81D124C5FA}.release|ARM64.ActiveCfg = release|x64 - {809C3AD5-3211-4992-A472-9D81D124C5FA}.release|ARM64.Build.0 = release|x64 {809C3AD5-3211-4992-A472-9D81D124C5FA}.release|x64.ActiveCfg = release|x64 {809C3AD5-3211-4992-A472-9D81D124C5FA}.release|x64.Build.0 = release|x64 - {809C3AD5-3211-4992-A472-9D81D124C5FA}.release|x86.ActiveCfg = release|x64 - {809C3AD5-3211-4992-A472-9D81D124C5FA}.release|x86.Build.0 = release|x64 - {C3DC85E1-0559-4B58-9792-DE421472DFE9}.debug|ARM64.ActiveCfg = debug|x64 - {C3DC85E1-0559-4B58-9792-DE421472DFE9}.debug|ARM64.Build.0 = debug|x64 {C3DC85E1-0559-4B58-9792-DE421472DFE9}.debug|x64.ActiveCfg = debug|x64 - {C3DC85E1-0559-4B58-9792-DE421472DFE9}.debug|x86.ActiveCfg = debug|x64 - {C3DC85E1-0559-4B58-9792-DE421472DFE9}.debug|x86.Build.0 = debug|x64 - {C3DC85E1-0559-4B58-9792-DE421472DFE9}.release|ARM64.ActiveCfg = release|x64 - {C3DC85E1-0559-4B58-9792-DE421472DFE9}.release|ARM64.Build.0 = release|x64 + {C3DC85E1-0559-4B58-9792-DE421472DFE9}.debug|x64.Build.0 = debug|x64 {C3DC85E1-0559-4B58-9792-DE421472DFE9}.release|x64.ActiveCfg = release|x64 - {C3DC85E1-0559-4B58-9792-DE421472DFE9}.release|x86.ActiveCfg = release|x64 - {C3DC85E1-0559-4B58-9792-DE421472DFE9}.release|x86.Build.0 = release|x64 - {C2D44C60-3F23-4972-8F60-21083B9FB112}.debug|ARM64.ActiveCfg = debug|x64 - {C2D44C60-3F23-4972-8F60-21083B9FB112}.debug|ARM64.Build.0 = debug|x64 {C2D44C60-3F23-4972-8F60-21083B9FB112}.debug|x64.ActiveCfg = debug|x64 {C2D44C60-3F23-4972-8F60-21083B9FB112}.debug|x64.Build.0 = debug|x64 - {C2D44C60-3F23-4972-8F60-21083B9FB112}.debug|x86.ActiveCfg = debug|x64 - {C2D44C60-3F23-4972-8F60-21083B9FB112}.debug|x86.Build.0 = debug|x64 - {C2D44C60-3F23-4972-8F60-21083B9FB112}.release|ARM64.ActiveCfg = release|x64 - {C2D44C60-3F23-4972-8F60-21083B9FB112}.release|ARM64.Build.0 = release|x64 {C2D44C60-3F23-4972-8F60-21083B9FB112}.release|x64.ActiveCfg = release|x64 {C2D44C60-3F23-4972-8F60-21083B9FB112}.release|x64.Build.0 = release|x64 - {C2D44C60-3F23-4972-8F60-21083B9FB112}.release|x86.ActiveCfg = release|x64 - {C2D44C60-3F23-4972-8F60-21083B9FB112}.release|x86.Build.0 = release|x64 - {2D988267-CC53-41E3-936A-48CEF9049DF5}.debug|ARM64.ActiveCfg = debug|x64 - {2D988267-CC53-41E3-936A-48CEF9049DF5}.debug|ARM64.Build.0 = debug|x64 {2D988267-CC53-41E3-936A-48CEF9049DF5}.debug|x64.ActiveCfg = debug|x64 {2D988267-CC53-41E3-936A-48CEF9049DF5}.debug|x64.Build.0 = debug|x64 - {2D988267-CC53-41E3-936A-48CEF9049DF5}.debug|x86.ActiveCfg = debug|x64 - {2D988267-CC53-41E3-936A-48CEF9049DF5}.debug|x86.Build.0 = debug|x64 - {2D988267-CC53-41E3-936A-48CEF9049DF5}.release|ARM64.ActiveCfg = release|x64 - {2D988267-CC53-41E3-936A-48CEF9049DF5}.release|ARM64.Build.0 = release|x64 {2D988267-CC53-41E3-936A-48CEF9049DF5}.release|x64.ActiveCfg = release|x64 {2D988267-CC53-41E3-936A-48CEF9049DF5}.release|x64.Build.0 = release|x64 - {2D988267-CC53-41E3-936A-48CEF9049DF5}.release|x86.ActiveCfg = release|x64 - {2D988267-CC53-41E3-936A-48CEF9049DF5}.release|x86.Build.0 = release|x64 - {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.debug|ARM64.ActiveCfg = debug|x64 - {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.debug|ARM64.Build.0 = debug|x64 {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.debug|x64.ActiveCfg = debug|x64 {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.debug|x64.Build.0 = debug|x64 - {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.debug|x86.ActiveCfg = debug|x64 - {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.debug|x86.Build.0 = debug|x64 - {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.release|ARM64.ActiveCfg = release|x64 - {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.release|ARM64.Build.0 = release|x64 {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.release|x64.ActiveCfg = release|x64 {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.release|x64.Build.0 = release|x64 - {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.release|x86.ActiveCfg = release|x64 - {9CA3E213-C43F-4C1D-A6ED-C6FC568D691B}.release|x86.Build.0 = release|x64 - {06FB1AF7-647C-4BA4-860A-4533763440F9}.debug|ARM64.ActiveCfg = debug|x64 - {06FB1AF7-647C-4BA4-860A-4533763440F9}.debug|ARM64.Build.0 = debug|x64 {06FB1AF7-647C-4BA4-860A-4533763440F9}.debug|x64.ActiveCfg = debug|x64 {06FB1AF7-647C-4BA4-860A-4533763440F9}.debug|x64.Build.0 = debug|x64 - {06FB1AF7-647C-4BA4-860A-4533763440F9}.debug|x86.ActiveCfg = debug|x64 - {06FB1AF7-647C-4BA4-860A-4533763440F9}.debug|x86.Build.0 = debug|x64 - {06FB1AF7-647C-4BA4-860A-4533763440F9}.release|ARM64.ActiveCfg = release|x64 - {06FB1AF7-647C-4BA4-860A-4533763440F9}.release|ARM64.Build.0 = release|x64 {06FB1AF7-647C-4BA4-860A-4533763440F9}.release|x64.ActiveCfg = release|x64 {06FB1AF7-647C-4BA4-860A-4533763440F9}.release|x64.Build.0 = release|x64 - {06FB1AF7-647C-4BA4-860A-4533763440F9}.release|x86.ActiveCfg = release|x64 - {06FB1AF7-647C-4BA4-860A-4533763440F9}.release|x86.Build.0 = release|x64 - {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.debug|ARM64.ActiveCfg = debug|x64 - {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.debug|ARM64.Build.0 = debug|x64 {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.debug|x64.ActiveCfg = debug|x64 {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.debug|x64.Build.0 = debug|x64 - {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.debug|x86.ActiveCfg = debug|x64 - {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.debug|x86.Build.0 = debug|x64 - {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.release|ARM64.ActiveCfg = release|x64 - {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.release|ARM64.Build.0 = release|x64 {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.release|x64.ActiveCfg = release|x64 {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.release|x64.Build.0 = release|x64 - {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.release|x86.ActiveCfg = release|x64 - {AFDD7028-1ED9-442E-8A3D-01CFA3AA1CAA}.release|x86.Build.0 = release|x64 - {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.debug|ARM64.ActiveCfg = debug|x64 - {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.debug|ARM64.Build.0 = debug|x64 {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.debug|x64.ActiveCfg = debug|x64 {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.debug|x64.Build.0 = debug|x64 - {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.debug|x86.ActiveCfg = debug|x64 - {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.debug|x86.Build.0 = debug|x64 - {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.release|ARM64.ActiveCfg = release|x64 - {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.release|ARM64.Build.0 = release|x64 {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.release|x64.ActiveCfg = release|x64 {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.release|x64.Build.0 = release|x64 - {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.release|x86.ActiveCfg = release|x64 - {AFDE69E9-EE3D-470E-8407-C1F0D98F9E3D}.release|x86.Build.0 = release|x64 - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.debug|ARM64.ActiveCfg = debug|x64 - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.debug|ARM64.Build.0 = debug|x64 - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.debug|x64.ActiveCfg = debug|x64 - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.debug|x86.ActiveCfg = debug|Win32 - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.debug|x86.Build.0 = debug|Win32 - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.release|ARM64.ActiveCfg = release|x64 - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.release|ARM64.Build.0 = release|x64 - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.release|x64.ActiveCfg = release|x64 - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.release|x86.ActiveCfg = release|Win32 - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.release|x86.Build.0 = release|Win32 - {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}.debug|ARM64.ActiveCfg = debug|ARM64 - {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}.debug|ARM64.Build.0 = debug|ARM64 {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}.debug|x64.ActiveCfg = debug|x64 - {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}.debug|x86.ActiveCfg = debug|x64 - {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}.debug|x86.Build.0 = debug|x64 - {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}.release|ARM64.ActiveCfg = release|ARM64 - {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}.release|ARM64.Build.0 = release|ARM64 {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}.release|x64.ActiveCfg = release|x64 - {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}.release|x86.ActiveCfg = release|x64 - {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5}.release|x86.Build.0 = release|x64 + {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.debug|x64.ActiveCfg = debug|x64 + {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4}.release|x64.ActiveCfg = release|x64 + {B226530A-14B1-40AC-B82E-D9057400E7EE}.debug|x64.ActiveCfg = debug|x64 + {B226530A-14B1-40AC-B82E-D9057400E7EE}.debug|x64.Build.0 = debug|x64 + {B226530A-14B1-40AC-B82E-D9057400E7EE}.release|x64.ActiveCfg = release|x64 + {B226530A-14B1-40AC-B82E-D9057400E7EE}.release|x64.Build.0 = release|x64 + {9FA45E25-DAEB-4C2D-806C-7908A180195D}.debug|x64.ActiveCfg = debug|x64 + {9FA45E25-DAEB-4C2D-806C-7908A180195D}.debug|x64.Build.0 = debug|x64 + {9FA45E25-DAEB-4C2D-806C-7908A180195D}.release|x64.ActiveCfg = release|x64 + {9FA45E25-DAEB-4C2D-806C-7908A180195D}.release|x64.Build.0 = release|x64 + {360E54B1-0B92-4BCA-8111-4BF384292621}.debug|x64.ActiveCfg = debug|x64 + {360E54B1-0B92-4BCA-8111-4BF384292621}.debug|x64.Build.0 = debug|x64 + {360E54B1-0B92-4BCA-8111-4BF384292621}.release|x64.ActiveCfg = release|x64 + {360E54B1-0B92-4BCA-8111-4BF384292621}.release|x64.Build.0 = release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -321,7 +403,6 @@ Global {4C47AB91-DF41-4741-80AF-FD87C32A961E} = {2CC2975A-9B33-400D-840F-9A71BB312928} {952986BC-7B3D-4F50-BC69-4D11FA52D9C5} = {2CC2975A-9B33-400D-840F-9A71BB312928} {B3D9DA75-8FBD-4A2C-826A-B50406396EC4} = {7EA9E1E8-4283-4CEF-9629-C5C98CD706C7} - {38E28A69-09A9-4C7E-B0F1-49E8A3B5AA0B} = {7EA9E1E8-4283-4CEF-9629-C5C98CD706C7} {13E49D84-7EA0-43A2-9B60-4B408A4C7602} = {7EA9E1E8-4283-4CEF-9629-C5C98CD706C7} {359218DB-0EBA-4889-8713-732FACAEF18D} = {1997E4B6-FE49-4358-ADF1-CDDB5739508E} {DF15E9D4-976B-4E1D-B68F-9B67F93654BF} = {1997E4B6-FE49-4358-ADF1-CDDB5739508E} @@ -331,9 +412,37 @@ Global {165C089B-6860-4AEA-9F88-67559156C2E7} = {DF15E9D4-976B-4E1D-B68F-9B67F93654BF} {FCB5111C-C7D9-4E65-8EF7-E9BB80E54B7D} = {165C089B-6860-4AEA-9F88-67559156C2E7} {D8207406-263E-4831-A8E9-20C4ECE5CA15} = {165C089B-6860-4AEA-9F88-67559156C2E7} - {9749520E-64FF-4633-855B-54BC541CDBB6} = {1997E4B6-FE49-4358-ADF1-CDDB5739508E} - {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4} = {9749520E-64FF-4633-855B-54BC541CDBB6} - {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5} = {9749520E-64FF-4633-855B-54BC541CDBB6} + {9A711E36-8A78-4CE6-A34D-F681AF89A919} = {1997E4B6-FE49-4358-ADF1-CDDB5739508E} + {015523BA-4326-4A84-9CB5-E1E9B6182209} = {9A711E36-8A78-4CE6-A34D-F681AF89A919} + {D0E5A2D1-787E-4129-A75B-34DD4D5FDFC7} = {9A711E36-8A78-4CE6-A34D-F681AF89A919} + {6498728B-D9B0-4CAB-A9E3-ACE5BC371010} = {D0E5A2D1-787E-4129-A75B-34DD4D5FDFC7} + {AA41FFF1-A730-433E-8D26-13DA5B653825} = {D0E5A2D1-787E-4129-A75B-34DD4D5FDFC7} + {4BF590C3-1032-4DD2-BF87-BB9E5781977C} = {015523BA-4326-4A84-9CB5-E1E9B6182209} + {DBE32379-8D5A-4454-A1B6-ACC407881898} = {015523BA-4326-4A84-9CB5-E1E9B6182209} + {3C04357D-93B5-4472-94BB-8D22A1EB16DB} = {B3D9DA75-8FBD-4A2C-826A-B50406396EC4} + {947577A8-A9A5-4F90-8883-5FB722FE58E2} = {B3D9DA75-8FBD-4A2C-826A-B50406396EC4} + {08BF9299-FCE9-439C-A66C-1C8AFEC93866} = {1997E4B6-FE49-4358-ADF1-CDDB5739508E} + {7271D70C-319A-455C-AD4A-BE0BC46FEE15} = {1997E4B6-FE49-4358-ADF1-CDDB5739508E} + {5D395DF2-B247-48CC-924B-7F5D196C247A} = {C5BCEFF7-8097-4331-A96E-4F4857774AD8} + {2104BCF9-035E-45AA-B744-68A5B8FEFF13} = {C5BCEFF7-8097-4331-A96E-4F4857774AD8} + {79AB8BD3-03A4-4B65-ABF6-313C10A00CC5} = {5D395DF2-B247-48CC-924B-7F5D196C247A} + {991B8FA7-F75E-4D8A-A0BD-636FE68B6AF4} = {2104BCF9-035E-45AA-B744-68A5B8FEFF13} + {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {1997E4B6-FE49-4358-ADF1-CDDB5739508E} + {03550856-D63F-4069-87E1-8BF2F129DBE3} = {1997E4B6-FE49-4358-ADF1-CDDB5739508E} + {17652C16-00A0-40D4-A227-697E595DE053} = {9A711E36-8A78-4CE6-A34D-F681AF89A919} + {9E1A2FAF-696A-4CA7-8C2E-F6B80107A143} = {17652C16-00A0-40D4-A227-697E595DE053} + {770B65D6-5307-478C-A9EB-3E4A64B67225} = {63D4BB7A-C404-4A35-A302-20034DD8BA77} + {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} diff --git a/hyperdbg/hyperevade/CMakeLists.txt b/hyperdbg/hyperevade/CMakeLists.txt new file mode 100644 index 00000000..85e1fe45 --- /dev/null +++ b/hyperdbg/hyperevade/CMakeLists.txt @@ -0,0 +1,22 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "../include/components/spinlock/code/Spinlock.c" + "../include/platform/kernel/code/Mem.c" + "code/Logging.c" + "code/UnloadDll.c" + "../include/components/spinlock/header/Spinlock.h" + "../include/platform/kernel/header/Environment.h" + "../include/platform/kernel/header/PlatformMem.h" + "header/Logging.h" + "header/pch.h" + "header/UnloadDll.h" + "hyperevade.def" +) +include_directories( + "../include" + "header" +) +wdk_add_library(hyperevade SHARED + KMDF 1.15 + ${SourceFiles} +) diff --git a/hyperdbg/hyperevade/code/SyscallFootprints.c b/hyperdbg/hyperevade/code/SyscallFootprints.c new file mode 100644 index 00000000..33273254 --- /dev/null +++ b/hyperdbg/hyperevade/code/SyscallFootprints.c @@ -0,0 +1,1973 @@ +/** + * @file SyscallFootprints.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Try to hide SYSCALL methods from anti-debugging and anti-hypervisor + * @details + * @version 0.14 + * @date 2025-06-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#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, + UINT32 ThreadId, + UINT64 Context, + SYSCALL_CALLBACK_CONTEXT_PARAMS * Params) +{ + UNREFERENCED_PARAMETER(Regs); + UNREFERENCED_PARAMETER(ProcessId); + UNREFERENCED_PARAMETER(ThreadId); + UNREFERENCED_PARAMETER(Context); + UNREFERENCED_PARAMETER(Params); +} + +#else // ActivateHyperEvadeProject != TRUE + +/** + * @brief Handle The triggered hook on KiSystemCall64 system call handler + * when the Transparency mode is enabled + * + * @param Regs The virtual processor's state of registers + * @return VOID + */ +VOID +TransparentHandleSystemCallHook(GUEST_REGS * Regs) +{ + // + // If the transparent mode is not enabled, do nothing + // + if (!g_TransparentMode) + { + return; + } + + PCHAR CallingProcess = g_Callbacks.CommonGetProcessNameFromProcessControlBlock(PsGetCurrentProcess()); + UINT64 Context = Regs->rax; + + // + // Skip the transparent mitigations of system calls when the caller process + // is a Windows process that should receive unmodified data + // + for (ULONG i = 0; i < (sizeof(TRANSPARENT_WIN_PROCESS_IGNORE) / sizeof(TRANSPARENT_WIN_PROCESS_IGNORE[0])); i++) + { + if (strstr(CallingProcess, TRANSPARENT_WIN_PROCESS_IGNORE[i])) + { + return; + } + } + + if (Context == g_SystemCallNumbersInformation.SysNtQuerySystemInformation || + Context == g_SystemCallNumbersInformation.SysNtQuerySystemInformationEx) + { + // + // Handle the NtQuerySystemInformation System call + // + + TransparentHandleNtQuerySystemInformationSyscall(Regs); + } + else if (Context == g_SystemCallNumbersInformation.SysNtSystemDebugControl) + { + // + // Handle the NtSystemDebugControl System call + // + TransparentHandleNtSystemDebugControlSyscall(Regs); + } + else if (Context == g_SystemCallNumbersInformation.SysNtQueryAttributesFile) + { + // + // Handle the NtQueryAttributesFile System call + // + TransparentHandleNtQueryAttributesFileSyscall(Regs); + } + else if (Context == g_SystemCallNumbersInformation.SysNtOpenDirectoryObject) + { + // + // Handle the NtOpenDirectoryObject System call + // + TransparentHandleNtOpenDirectoryObjectSyscall(Regs); + } + else if (Context == g_SystemCallNumbersInformation.SysNtQueryDirectoryObject) + { + // + // Handle the NtQueryDirectoryObject System call + // + // TransparentHandleNtQueryDirectoryObjectSyscall(Regs); + } + else if (Context == g_SystemCallNumbersInformation.SysNtQueryInformationProcess) + { + // + // Handle the NtQueryInformationProcess System call + // + TransparentHandleNtQueryInformationProcessSyscall(Regs); + } + else if (Context == g_SystemCallNumbersInformation.SysNtQueryInformationThread) + { + // + // Handle the NtQueryInformationThread System call + // + // TransparentHandleNtQueryInformationThreadSyscall(Regs); + } + else if (Context == g_SystemCallNumbersInformation.SysNtOpenFile) + { + // + // Handle the NtOpenFile System call + // + TransparentHandleNtOpenFileSyscall(Regs); + } + else if (Context == g_SystemCallNumbersInformation.SysNtOpenKeyEx || Context == g_SystemCallNumbersInformation.SysNtOpenKey) + { + // + // Handle the NtOpenKey System call + // + TransparentHandleNtOpenKeySyscall(Regs); + } + else if (Context == g_SystemCallNumbersInformation.SysNtQueryValueKey) + { + // + // Handle the NtQueryValueKey System call + // + TransparentHandleNtQueryValueKeySyscall(Regs); + } + else if (Context == g_SystemCallNumbersInformation.SysNtEnumerateKey) + { + // + // Handle the NtEnumerateKey System call + // + TransparentHandleNtEnumerateKeySyscall(Regs); + } + else + { + // + // The syscall is not important to us + // + } +} + +/** + * @brief Handle The NtQuerySystemInformation system call + * when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @return VOID + */ +VOID +TransparentHandleNtQuerySystemInformationSyscall(GUEST_REGS * Regs) +{ + SYSCALL_CALLBACK_CONTEXT_PARAMS ContextParams = {0}; + + switch (Regs->r10) + { + case SystemProcessInformation: + case SystemExtendedProcessInformation: + { + ContextParams.OptionalParam1 = SystemProcessInformation; + ContextParams.OptionalParam2 = Regs->rdx; + ContextParams.OptionalParam3 = Regs->r8 - 0x400; + + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); + + break; + } + case SystemModuleInformation: + { + ContextParams.OptionalParam1 = SystemModuleInformation; + ContextParams.OptionalParam2 = Regs->rdx; + ContextParams.OptionalParam3 = Regs->r8; + + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); + + break; + } + case SystemKernelDebuggerInformation: + { + ContextParams.OptionalParam1 = SystemKernelDebuggerInformation; + ContextParams.OptionalParam2 = Regs->rdx; + ContextParams.OptionalParam3 = Regs->r8; + + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); + break; + } + case SystemCodeIntegrityInformation: + { + ContextParams.OptionalParam1 = SystemCodeIntegrityInformation; + ContextParams.OptionalParam2 = Regs->rdx; + ContextParams.OptionalParam3 = 0x8; + + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); + break; + } + + // + // Currently SystemFirmwareTableInformation transparent handler is not implemented + // As the queries produce a data buffer too large to safely copy and modify in root-mode + // + + // case SystemFirmwareTableInformation: + // { + // + // ContextParams.OptionalParam1 = SystemFirmwareTableInformation; + // ContextParams.OptionalParam2 = Regs->rdx; + // ContextParams.OptionalParam3 = Regs->r8; + // ContextParams.OptionalParam4 = Regs->r9; + // + // g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + // HANDLE_TO_UINT32(PsGetCurrentProcessId()), + // HANDLE_TO_UINT32(PsGetCurrentThreadId()), + // Regs->rax, + // &ContextParams); + // break; + // } + default: + { + return; + } + } +} + +/** + * @brief Obtain a copy of the PWCHAR wide character string from a OBJECT_ATTRIBUTES structure at a guest virtual address + * + * @details Returns an allocated tagged memory pointer which needs to be freed with PlatformMemFreePool() + * + * @param virtPtr A pointer to a guest virtual memory address, containing a OBJECT_ATTRIBUTES structure + * @return PVOID Pointer to an allocated tagged memory pool, which needs to be freed with PlatformMemFreePool() + */ +PVOID +TransparentGetObjectNameFromAttributesVirtualPointer(UINT64 virtPtr) +{ + // PVOID buf = PlatformMemAllocateZeroedNonPagedPool(sizeof(OBJECT_ATTRIBUTES)); + OBJECT_ATTRIBUTES Buf = {0}; + + // + // Read the OBJECT_ATTRIBUTES structure from the virtual address pointer + // + if (g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(virtPtr, &Buf, sizeof(OBJECT_ATTRIBUTES))) + { + // PVOID Namebuf = PlatformMemAllocateZeroedNonPagedPool(sizeof(UNICODE_STRING)); + UNICODE_STRING NameBuf = {0}; + + // + // Read the UNICODE_STRING structure from a virtual address pointer, pointed to by OBJECT_ATTRIBUTES.ObjectName struct entry + // + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess((UINT64)Buf.ObjectName, &NameBuf, sizeof(UNICODE_STRING))) + { + LogInfo("BadRead"); + return NULL; + } + + // + // The OBJECT_ATTRIBUTES structure contains a PUNICODE_STRING pointer to a guest virtual address which contains this UNICODE_STRING + // This in turn will contain another pointer, this time a PWCHAR, to another virtual address, which will contain the wide char string we need + // + PVOID ObjectNameBuf = PlatformMemAllocateZeroedNonPagedPool(NameBuf.Length + sizeof(WCHAR)); + + if (ObjectNameBuf == NULL) + { + LogInfo("Error allocating ImageName memory buffer"); + + return NULL; + } + + // + // Read the PWCHAR string from a virtual address pointer, pointed to by OBJECT_ATTRIBUTES.ObjectName.Buffer struct entry + // + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess((UINT64)NameBuf.Buffer, ObjectNameBuf, NameBuf.Length + sizeof(WCHAR))) + { + LogInfo("BadRead"); + PlatformMemFreePool(ObjectNameBuf); + + return NULL; + } + + // + // The caller is responsible for freeing the memory buffer, using PlatformMemFreePool() + // + return ObjectNameBuf; + } + return NULL; +} + +/** + * @brief Handle The NtQueryAttributesFile system call + * when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @return VOID + */ +VOID +TransparentHandleNtQueryAttributesFileSyscall(GUEST_REGS * Regs) +{ + SYSCALL_CALLBACK_CONTEXT_PARAMS ContextParams = {0}; + ContextParams.OptionalParam1 = Regs->rdx; + + // + // Check if the pointer given as the 3rd argument to the system call with type POBJECT_ATTRIBUTES is valid + // + if (g_Callbacks.CheckAccessValidityAndSafety(Regs->r10, sizeof(OBJECT_ATTRIBUTES))) + { + // + // From the POBJECT_ATTRIBUTES structure obtain the wide character string of the requested file path + // + PVOID PathBuf = TransparentGetObjectNameFromAttributesVirtualPointer(Regs->r10); + PWCH FilePath = (PWCH)PathBuf; + + // + // If the file Attributes request is for a listed file, insert the SYSCALL trap flag and continue execution + // + for (UINT16 j = 0; j < (sizeof(HV_FILES) / sizeof(HV_FILES[0])); j++) + { + if (wcsstr(FilePath, HV_FILES[j])) + { + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); + + break; + } + } + + // + // Free the allocated copy of the directory path, obtained from TransparentGetObjectNameFromAttributesVirtualPointer() + // + PlatformMemFreePool(PathBuf); + } +} + +/** + * @brief Handle The NtOpenDirectoryObject system call + * when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @return VOID + */ +VOID +TransparentHandleNtOpenDirectoryObjectSyscall(GUEST_REGS * Regs) +{ + // + // Set up the context data for the callback after SYSRET + // + SYSCALL_CALLBACK_CONTEXT_PARAMS ContextParams = {0}; + ContextParams.OptionalParam1 = Regs->r10; + + // + // Check if the pointer given as the 3rd argument to the system call with type POBJECT_ATTRIBUTES is valid + // + if (g_Callbacks.CheckAccessValidityAndSafety(Regs->r8, sizeof(OBJECT_ATTRIBUTES))) + { + // + // From the POBJECT_ATTRIBUTES structure obtain the wide character string of the requested directory path + // + PVOID PathBuf = TransparentGetObjectNameFromAttributesVirtualPointer(Regs->r8); + PWCH DirPath = (PWCH)PathBuf; + + if (DirPath == NULL) + { + return; + } + + // + // If the directory object request is for a listed directory, insert the SYSCALL trap flag and continue execution + // + for (UINT16 j = 0; j < (sizeof(HV_DIRS) / sizeof(HV_DIRS[0])); j++) + { + if (wcsstr(DirPath, HV_DIRS[j])) + { + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); + + break; + } + } + + // + // Free the allocated copy of the directory path, obtained from TransparentGetObjectNameFromAttributesVirtualPointer() + // + PlatformMemFreePool(PathBuf); + } +} + +/** + * @brief Handle The NtSystemDebugControl system call + * when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @return VOID + */ +VOID +TransparentHandleNtSystemDebugControlSyscall(GUEST_REGS * Regs) +{ + // + // Corrupt the system call arguments, to cause the kernel to return an error + // + Regs->r9 = 0x0; + + SYSCALL_CALLBACK_CONTEXT_PARAMS ContextParams = {0}; + + // + // Set the trap flag to intercept the SYSRET instruction + // + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); +} + +/** + * @brief Handle The NtQueryInformationProcess system call + * when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @return VOID + */ +VOID +TransparentHandleNtQueryInformationProcessSyscall(GUEST_REGS * Regs) +{ + // + // Set up the context parameters for the interception callback + // + SYSCALL_CALLBACK_CONTEXT_PARAMS ContextParams = {0}; + ContextParams.OptionalParam1 = Regs->rdx; // ProcessInformationClass + ContextParams.OptionalParam2 = Regs->r8; // BufferPtr + ContextParams.OptionalParam3 = Regs->r9; // BufferSize + + // + // Set the trap flag to intercept the SYSRET instruction + // + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); +} + +/** + * @brief Handle The NtOpenFile system call + * when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @return VOID + */ +VOID +TransparentHandleNtOpenFileSyscall(GUEST_REGS * Regs) +{ + // + // Check if the user-mode pointer in R8 to a OBJECT_ATTRIBUTES struct is valid + // + if (g_Callbacks.CheckAccessValidityAndSafety(Regs->r8, sizeof(OBJECT_ATTRIBUTES))) + { + // + // From the OBJECT_ATTRIBUTES struct pointer extract the file path for which this syscall is called + // + PVOID NameBuf = TransparentGetObjectNameFromAttributesVirtualPointer(Regs->r8); + PWCH FileName = (PWCH)NameBuf; + if (FileName == NULL) + { + return; + } + + // + // Check if the requested file includes any hypervisor specific strings + // This also checks parent directory names of the requested file + // + for (UINT16 j = 0; j < (sizeof(HV_FILES) / sizeof(HV_FILES[0])); j++) + { + if (wcsstr(FileName, HV_FILES[j])) + { + LogInfo("A call to NtOpenFile systemcall for a hypervisor specific file was made"); + + // + // If a match was found, corrupt the user-mode pointers in CPU registers, so that, when the kernel-mode execution continues, it would fail. + // + Regs->r8 = 0x0; + Regs->r10 = 0x0; + + // + // Set the trap flag to intercept the SYSRET instruction + // + SYSCALL_CALLBACK_CONTEXT_PARAMS ContextParams = {0}; + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); + + break; + } + } + // + // Clean up the allocated memory + // + PlatformMemFreePool(NameBuf); + } +} + +/** + * @brief Handle The NtOpenKey system call + * when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @return VOID + */ +VOID +TransparentHandleNtOpenKeySyscall(GUEST_REGS * Regs) +{ + // + // Check if the user-mode pointer in R8 to a OBJECT_ATTRIBUTES struct is valid + // + if (g_Callbacks.CheckAccessValidityAndSafety(Regs->r8, sizeof(OBJECT_ATTRIBUTES))) + { + // + // From the OBJECT_ATTRIBUTES struct pointer extract the registry key path for which this syscall is called + // + PVOID NameBuf = TransparentGetObjectNameFromAttributesVirtualPointer(Regs->r8); + PWCH KeyName = (PWCH)NameBuf; + + if (KeyName == NULL) + { + LogInfo("BADRET"); + return; + } + + // + // Check if the requested registry entry path includes any hypervisor specific strings + // + for (UINT16 j = 0; j < (sizeof(HV_REGKEYS) / sizeof(HV_REGKEYS[0])); j++) + { + if (wcsstr(KeyName, HV_REGKEYS[j]) > 0) + { + // + // If a match was found, corrupt the user-mode pointer in CPU registers, so that, when the kernel-mode execution continues, it would fail. + // + Regs->r8 = 0x0; + + // + // Set the trap flag to intercept the SYSRET instruction + // + SYSCALL_CALLBACK_CONTEXT_PARAMS ContextParams = {0}; + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); + + break; + } + } + + // + // Clean up the allocated memory + // + PlatformMemFreePool(NameBuf); + } +} + +/** + * @brief Handle The NtQueryValueKey system call + * when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @return VOID + */ +VOID +TransparentHandleNtQueryValueKeySyscall(GUEST_REGS * Regs) +{ + // + // Check if the user-mode pointer in RDX to a UNICODE_STRING struct is valid + // + if (g_Callbacks.CheckAccessValidityAndSafety(Regs->rdx, sizeof(UNICODE_STRING))) + { + UNICODE_STRING NameUString = {0}; + + // + // Read the UNICODE_STRING structure from a virtual address pointer, pointed to by RDX struct entry + // + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(Regs->rdx, &NameUString, sizeof(UNICODE_STRING))) + return; + + // + // Read the PWCH wide char string from the address pointer in the UNICODE_STRING + // + PVOID NameBuf = PlatformMemAllocateZeroedNonPagedPool(NameUString.Length + sizeof(WCHAR)); + if (NameBuf == NULL) + { + return; + } + + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess((UINT64)NameUString.Buffer, NameBuf, NameUString.Length + sizeof(WCHAR))) + { + PlatformMemFreePool(NameBuf); + return; + } + + PWCH KeyName = (PWCH)NameBuf; + + // + // If the registry key request was for kay that could contain hypervisor specific information in its data, + // the return buffer(%R9) needs to be modified, but the buffer length is in the user mode stack + // + for (ULONG i = 0; i < (sizeof(TRANSPARENT_DETECTABLE_REGISTRY_KEYS) / sizeof(TRANSPARENT_DETECTABLE_REGISTRY_KEYS[0])); i++) + { + if (!wcscmp(KeyName, TRANSPARENT_DETECTABLE_REGISTRY_KEYS[i])) + { + // + // If a match is found, set up the context values and set the trap flag for the SYSRET callback + // + + SYSCALL_CALLBACK_CONTEXT_PARAMS ContextParams = {0}; + + ContextParams.OptionalParam1 = Regs->r8; + ContextParams.OptionalParam2 = Regs->r9; + + // + // Read the 5th argument of the system call from the stack at location %RSP + 0x28 + // + if (g_Callbacks.CheckAccessValidityAndSafety(Regs->rsp + 0x28, sizeof(UINT64))) + { + g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess((UINT64)(Regs->rsp + 0x28), &ContextParams.OptionalParam3, sizeof(ULONG)); + } + else + { + LogInfo("Process 0x%llx on thread %llx executed NtQueryValueKey systemcall but reading the provided arguments from %RSP failed", HANDLE_TO_UINT32(PsGetCurrentProcessId()), HANDLE_TO_UINT32(PsGetCurrentThreadId())); + + PlatformMemFreePool(NameBuf); + return; + } + + // + // Read the 6th argument of the system call from the stack at location %RSP + 0x30 + // + if (g_Callbacks.CheckAccessValidityAndSafety(Regs->rsp + 0x30, sizeof(UINT64))) + { + g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess((UINT64)(Regs->rsp + 0x30), &ContextParams.OptionalParam4, sizeof(UINT64)); + } + else + { + LogInfo("Process 0x%llx on thread %llx executed NtQueryValueKey systemcall but reading the provided arguments from %RSP failed", HANDLE_TO_UINT32(PsGetCurrentProcessId()), HANDLE_TO_UINT32(PsGetCurrentThreadId())); + + PlatformMemFreePool(NameBuf); + return; + } + + // + // Set the trap flag to intercept the SYSRET instruction + // + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); + + // + // Clean-up and return to guest execution + // + PlatformMemFreePool(NameBuf); + return; + } + } + + // + // If the call was for a registry key that contains a hypervisor specific string, + // The user-mode caller should just receive an error return code not a modified data buffer + // + for (UINT16 j = 1; j < (sizeof(HV_REGKEYS) / sizeof(HV_REGKEYS[0])); j++) + { + if (wcsstr(KeyName, HV_REGKEYS[j]) > 0) + { + // + // When the match is found, corrupt the buffer pointers in the registers + // and set the SYSRET callback trap flag + // + SYSCALL_CALLBACK_CONTEXT_PARAMS ContextParams = {0}; + + Regs->rdx = 0x0; + Regs->r9 = 0x0; + + // + // Set the trap flag to intercept the SYSRET instruction + // + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); + + break; + } + } + + // + // Clean up the allocated memory + // + PlatformMemFreePool(NameBuf); + } +} + +/** + * @brief Handle The NtEnumerateKey system call + * when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @return VOID + */ +VOID +TransparentHandleNtEnumerateKeySyscall(GUEST_REGS * Regs) +{ + // + // Set up the context parameters for the interception callback + // + SYSCALL_CALLBACK_CONTEXT_PARAMS ContextParams = {0}; + ContextParams.OptionalParam1 = Regs->r8; + ContextParams.OptionalParam2 = Regs->r9; + + // + // Read the 5th argument of the system call from the stack at location %RSP + 0x28 + // + if (g_Callbacks.CheckAccessValidityAndSafety(Regs->rsp + 0x28, sizeof(UINT64))) + { + g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess((UINT64)(Regs->rsp + 0x28), &ContextParams.OptionalParam3, sizeof(ULONG)); + } + else + { + LogInfo("Process 0x%llx on thread %llx executed NtEnumerateKey systemcall but reading the provided arguments from %RSP failed", HANDLE_TO_UINT32(PsGetCurrentProcessId()), HANDLE_TO_UINT32(PsGetCurrentThreadId())); + return; + } + + // + // Read the 6th argument of the system call from the stack at location %RSP + 0x30 + // + if (g_Callbacks.CheckAccessValidityAndSafety(Regs->rsp + 0x30, sizeof(UINT64))) + { + g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess((UINT64)(Regs->rsp + 0x30), &ContextParams.OptionalParam4, sizeof(UINT64)); + } + else + { + LogInfo("Process 0x%llx on thread %llx executed NtEnumerateKey systemcall but reading the provided arguments from %RSP failed", HANDLE_TO_UINT32(PsGetCurrentProcessId()), HANDLE_TO_UINT32(PsGetCurrentThreadId())); + return; + } + + // + // If the call was made without an allocated buffer (with size 0) + // we have no need to intercept it + // + if (ContextParams.OptionalParam3 == 0) + { + return; + } + + // + // Set the trap flag to intercept the SYSRET instruction + // + g_Callbacks.SyscallCallbackSetTrapFlagAfterSyscall(Regs, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()), + Regs->rax, + &ContextParams); +} + +/** + * @brief Handle the request for SystemModuleInformation + * + * @details This function removes entries from a list of system drivers that could reveal the presence of hypervisors + * This depends on an incomplete list HV_DRIVER, of known hypervisor drivers + * The revealing list entries are removed and overwritten, but the memory buffer is not reallocated, so + * 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 VirtualAddress A pointer to a user-mode virtual address + * @param BufferSize Size of the user-mode buffer + * + * @return BOOLEAN + */ +BOOLEAN +TransparentHandleModuleInformationQuery(PVOID Ptr, UINT64 VirtualAddress, UINT32 BufferSize) +{ + PSYSTEM_MODULE_INFORMATION StructBuf = (PSYSTEM_MODULE_INFORMATION)Ptr; + PSYSTEM_MODULE_ENTRY ModuleList = StructBuf->Module; + + // + // Traverse the list of system modules and remove the system drivers + // matching a known list of hypervisor drivers based on their filename + // + for (UINT16 i = 0; i < StructBuf->Count; i++) + { + 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 a module file name matches, remove the entry from the list by shifting it forward by one entry + // + for (UINT16 k = i; k < StructBuf->Count - 1; k++) + { + ModuleList[k] = ModuleList[k + 1]; + } + + // + // Decrement the list size as one entry has been removed + // + i--; + StructBuf->Count--; + + break; + } + } + } + if (!g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(VirtualAddress, Ptr, BufferSize)) + { + return FALSE; + } + return TRUE; +} + +/** + * @brief Handle the request for SystemProcessInformation + * + * @details This function removes entries from a list of active system processes that could reveal the presence of hypervisors + * + * @param Params Preset transparent callback params that contain: + in OptionalParam2 a pointer to a valid read/writable memory buffer that contains a SYSTEM_PROCESS_INFORMATION structure + in OptionalParam3 max size in bytes of the allocated buffer + * + * @return BOOLEAN + */ +BOOLEAN +TransparentHandleProcessInformationQuery(SYSCALL_CALLBACK_CONTEXT_PARAMS * Params) +{ + SYSTEM_PROCESS_INFORMATION PrevStructBuf = {0}; + SYSTEM_PROCESS_INFORMATION CurStructBuf = {0}; + + ULONG ReadOffset, WriteOffset; + BOOLEAN MatchFound = FALSE; + ULONG PrevOffset = 0; + + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(Params->OptionalParam2, &PrevStructBuf, sizeof(SYSTEM_PROCESS_INFORMATION))) + { + return FALSE; + } + + ReadOffset = PrevStructBuf.NextEntryOffset; + WriteOffset = 0; + + // + // The first entry will always be System Idle Process, which can be skipped + // + if (PrevStructBuf.NextEntryOffset == 0 || + !g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(Params->OptionalParam2 + ReadOffset, &CurStructBuf, sizeof(SYSTEM_PROCESS_INFORMATION))) + { + return FALSE; + } + + // + // Loop through all the entries and filter out the offending ones + // + do + { + MatchFound = FALSE; + + if (CurStructBuf.ImageName.Length != 0) + { + // + // We need to search for the Image name of the process which requires extra allocation + // + PVOID StringBuf = PlatformMemAllocateZeroedNonPagedPool(CurStructBuf.ImageName.Length + sizeof(WCHAR)); + + if (StringBuf == NULL) + { + LogInfo("Error allocating ImageName memory buffer"); + + return FALSE; + } + + // + // Read the WCHAR process image name from the user-mode pointer + // + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess((UINT64)CurStructBuf.ImageName.Buffer, StringBuf, CurStructBuf.ImageName.Length + sizeof(WCHAR))) + { + PlatformMemFreePool(StringBuf); + + return FALSE; + } + + PWCH ImageName = (PWCH)StringBuf; + + if (ImageName == NULL) + { + PlatformMemFreePool(StringBuf); + + return FALSE; + } + + // + // Loop through the known list of identifiable hypervisor related processes + // + 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 the name matches, bypass it by increasing the previous entries .nextEntryOffset value + // + + // + // The offset to this matching entry need to preserved for zeroing later + // + PrevOffset = PrevStructBuf.NextEntryOffset; + + PrevStructBuf.NextEntryOffset = PrevStructBuf.NextEntryOffset + CurStructBuf.NextEntryOffset; + + MatchFound = TRUE; + + // + // Write the modified offset back to the usermode buffer + // + if (!g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess((UINT64)(Params->OptionalParam2 + WriteOffset), &PrevStructBuf, sizeof(SYSTEM_PROCESS_INFORMATION))) + { + LogError("Failed to modify memory buffer for the SystemProcessInformation query system call"); + } + + // + // The entry gets bypassed, but since the Image name is a pointer in the struct, to completely clear any presence of these processes + // zero out the name buffer as well + // + memset(StringBuf, 0x0, CurStructBuf.ImageName.Length); + ULONG BufOffset = (ULONG)((PBYTE)&CurStructBuf.ImageName.Length - (PBYTE)&CurStructBuf) + sizeof(USHORT); + + if (!g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess((UINT64)(Params->OptionalParam2 + WriteOffset + PrevOffset + BufOffset), StringBuf, CurStructBuf.ImageName.Length)) + { + LogError("Failed to modify memory buffer for the SystemProcessInformation query system call"); + } + + break; + } + } + + PlatformMemFreePool(StringBuf); + } + + // + // If the last entry been reached, exit + // + if (CurStructBuf.NextEntryOffset == 0) + { + return TRUE; + } + + // + // If the current entry did not match any process names, move forward + // + if (!MatchFound) + { + WriteOffset += PrevStructBuf.NextEntryOffset; + + PrevStructBuf = CurStructBuf; + } + + // + // Move over to the next entry + // + ReadOffset += CurStructBuf.NextEntryOffset; + + // + // Some internal Windows calls to this system call use different offsetting/entry structure layout and causes errors + // + if (!g_Callbacks.CheckAccessValidityAndSafety((UINT64)(Params->OptionalParam2 + ReadOffset), sizeof(SYSTEM_PROCESS_INFORMATION))) + { + return FALSE; + } + + // + // Zero out the matching entry, so that its data doesn't remain in memory + // + if (MatchFound) + { + CurStructBuf = (SYSTEM_PROCESS_INFORMATION) {0}; + if (!g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess((UINT64)(Params->OptionalParam2 + WriteOffset + PrevOffset), &CurStructBuf, sizeof(SYSTEM_PROCESS_INFORMATION))) + { + return FALSE; + } + } + + // + // Read from the user buffer the next process entry + // + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(Params->OptionalParam2 + ReadOffset, &CurStructBuf, sizeof(SYSTEM_PROCESS_INFORMATION))) + { + return FALSE; + } + + } while (TRUE); + + return TRUE; +} + +/** + * @brief Handle the request for SystemFirmwareTableInformation + * + * @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 + * + * @return BOOLEAN + */ +UINT64 +TransparentHandleFirmwareInformationQuery(UINT64 Ptr, UINT32 BufMaxSize, UINT64 BufSizePtr) +{ + ULONG BufSize = 0; + + // + // Read the size of the data the kernel wrote in the buffer + // + if (!g_Callbacks.CheckAccessValidityAndSafety(BufSizePtr, sizeof(ULONG)) || + !g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(BufSizePtr, &BufSize, sizeof(ULONG))) + { + return 0; + } + + // + // If the memory buffer was too small for the kernel to write the needed information, bypass the mitigations + // + if (BufSize > BufMaxSize) + { + // + // NOTE: might need zeroing the memory if the kernel did in fact write to the pointer + // + return 0; + } + + // + // If the buffer size is too big, we can't do any mitigations with the current implementation and it exceeds + // the size of an EPT page, risking corruption when allocating the copy buffer space in root-mode. + // + if (BufMaxSize > PAGE_SIZE / 2) + { + LogInfo("The intercepted data buffer was too large for modification, in total 0x%x bytes", BufMaxSize); + LogInfo("The system call return value was set to STATUS_INVALID_INFO_CLASS, but this could be detected as hypervisor intervention"); + + return (UINT64)(UINT32)STATUS_INVALID_INFO_CLASS; + } + + if (BufSize == 0) + { + BufSize = BufMaxSize; + } + // + // From the user-mode pointer, read the SYSTEM_FIRMWARE_TABLE_INFORMATION struct + // + PVOID Buf = PlatformMemAllocateZeroedNonPagedPool(BufMaxSize + 1); + if (Buf == NULL) + { + return 0; + } + + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(Ptr, Buf, BufSize)) + { + PlatformMemFreePool(Buf); + return 0; + } + + PSYSTEM_FIRMWARE_TABLE_INFORMATION StructBuf = (PSYSTEM_FIRMWARE_TABLE_INFORMATION)Buf; + + // + // The request needs to be a "get" request for an existing table + // with 'RSMB', 'ACPI' or 'FIRM' table providers + // + if (StructBuf->Action == SystemFirmwareTable_Get && + StructBuf->TableID != 0 && + (StructBuf->ProviderSignature == 0x52534D42 || + StructBuf->ProviderSignature == 0x41435049 || + StructBuf->ProviderSignature == 0x4649524D)) + { + PCHAR StringBuf = (PCHAR)StructBuf->TableBuffer; + + for (ULONG i = 0; i < (sizeof(HV_FIRM_NAMES) / sizeof(HV_FIRM_NAMES[0])); i++) + { + for (ULONG j = 0; j < StructBuf->TableBufferLength; j++) + { + WORD Count = 0; + PCHAR MatchStart = strstr(StringBuf + j, HV_FIRM_NAMES[i]); + if (MatchStart != 0) + { + LogInfo("Found Match for %s", HV_FIRM_NAMES[i]); + + PCHAR NewVendorString = NULL; + ULONG NewSubstringSize = 0; + + // + // Replace the first occurace of the vendor string with AMERICAN MEGATRENDS INC. + // The rest with To Be Filled By O.E.M. + // + if (Count == 0) + { + NewVendorString = "AMERICAN MEGATRENDS INC."; + NewSubstringSize = 24 * sizeof(CHAR); + } + else + { + NewVendorString = "To Be Filled By O.E.M."; + NewSubstringSize = 22 * sizeof(CHAR); + } + + // + // Obtain the lengths of all the strings and substring + // + + ULONG MatchedStringLen = (ULONG)strlen(HV_FIRM_NAMES[i]); + ULONG OldLength = StructBuf->TableBufferLength; + + ULONG NewStringSize = OldLength - MatchedStringLen + NewSubstringSize; + + // + // Check if the buffer size allows the modification, in case of expansion + // + if (BufSize - MatchedStringLen + NewSubstringSize > BufMaxSize) + { + // + // If adding the new string exceeds the user allocated size, + // zero out the buffer + // + memset(Buf, 0x0, BufMaxSize); + g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Ptr, Buf, BufMaxSize); + + // + // Update the required buffer size for the next call + // + BufSize = (BufSize - OldLength) + NewStringSize; + g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(BufSizePtr, &BufSize, sizeof(ULONG)); + + // + // And return STATUS_BUFFER_TOO_SMALL error + // + + PlatformMemFreePool(Buf); + return (UINT64)(UINT32)STATUS_BUFFER_TOO_SMALL; + } + + // + // Calculate the positions of the replacement + // + ULONG MatchOffset = (ULONG)((MatchStart - StringBuf)); + PCHAR MatchEnd = StringBuf + MatchOffset + MatchedStringLen; + + // + // 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); + memcpy((PVOID)MatchStart, (PVOID)NewVendorString, NewSubstringSize); + + StructBuf->TableBufferLength = NewStringSize; + BufSize = BufSize - MatchedStringLen + NewSubstringSize; + + // + // Write the changes back to the user buffers + // + if (!g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Ptr, Buf, BufSize)) + { + LogInfo("Error writing to user-mode buffer: %llx", Ptr); + } + + if (!g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(BufSizePtr, &BufSize, sizeof(ULONG))) + { + LogInfo("Error writing to user-mode buffer: %llx", BufSizePtr); + } + } + } + } + } + + PlatformMemFreePool(Buf); + return 1; +} + +/** + * @brief Replace occurrences of a hypervisor specific strings with legitimate vendor strings in a provided buffer + * + * @param Params Set transparent callback params that contain: + in OptionalParam2 a pointer to a valid read/writable memory buffer that contains both, a WCHAR string and its length in bytes + in OptionalParam3 max size in bytes of the allocated buffer + in OptionalParam4 a pointer to a ULONG containing current size of the buffer + * + * @param DataOffset Offset in bytes from OptionalParam2 to the start of the WCHAR data string + * + * @param DataLenOffset Offset in bytes from OptionalParam2 to a ULONG containing the string length(in bytes) + * + * @return UINT64 + */ +UINT64 +TransparentReplaceVendorStringFromBufferWChar(SYSCALL_CALLBACK_CONTEXT_PARAMS * Params, ULONG DataOffset, ULONG DataLenOffset) +{ + PVOID Buf = NULL; + BOOLEAN PoolAlloc = FALSE; + + // + // Check that the user provided pointers are safe to read from + // + if (g_Callbacks.CheckAccessValidityAndSafety(Params->OptionalParam4, sizeof(ULONG))) + { + // + // Read the size of the data that the kernel wrote to the buffer + // + ULONG BufSize = 0; + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(Params->OptionalParam4, &BufSize, sizeof(ULONG))) + { + goto ReturnWithError; + } + + // + // If the data the kernel wanted to write is bigger than what was allocated by the user + // + if (BufSize > Params->OptionalParam3 || BufSize == 0) + { + // + // NOTE: might need zeroing the memory if the kernel did in fact write to the pointer + // + + return 0; + } + + // + // Check that the user provided pointers are safe to read from and the buffer is not too large + // + if (Params->OptionalParam3 >= 0xC00 || !g_Callbacks.CheckAccessValidityAndSafety(Params->OptionalParam2, (UINT32)Params->OptionalParam3)) + { + goto ReturnWithError; + } + + // + // If the buffer is small, e.g. for just a single word, store it on the stack + // else, allocate a nonpaged memory buffer + // + CHAR StackBuf[MAX_PATH] = {0}; + + if (Params->OptionalParam3 + sizeof(WCHAR) > MAX_PATH) + { + Buf = PlatformMemAllocateZeroedNonPagedPool(Params->OptionalParam3 + sizeof(WCHAR)); + PoolAlloc = TRUE; + } + else + { + Buf = &StackBuf; + } + + if (!Buf || !g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(Params->OptionalParam2, Buf, Params->OptionalParam3)) + { + goto ReturnWithError; + } + + // + // Get the actual data we are trying to modify(in wide char form) + // + PWCH StringBuf = (PWCH)((PBYTE)Buf + DataOffset); + + // + // Traverse the list of registry key names and vendor strings that are specific to common hypervisors + // if a match is found perform the modification + // + for (UINT16 i = 0; i < (sizeof(HV_REGKEYS) / sizeof(HV_REGKEYS[0])); i++) + { + PWCH MatchStart = wcsstr(StringBuf, HV_REGKEYS[i]); + + while (MatchStart != 0) + { + PWCH NewVendorString = NULL; + + // + // If the match was for a device id, the replacement should be with a different ID string not vendor name + // + if (i < 3) + { + // + // SPOOFS PCI device ID's(in the registry), This might be implemented in other ways that are not part of this implementation + // + 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]; + } + + // + // Remove common VM strings from the data + // + else if (i < 9) + { + NewVendorString = L" "; + } + else + { + // + // Obtain the replacement vendor name string, randomized when the transparency mode was enabled + // + 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 MatchedStringLen = (ULONG)wcslen(HV_REGKEYS[i]) * sizeof(WCHAR); + ULONG OldLength = *((PBYTE)Buf + DataLenOffset); + + ULONG NewStringSize = OldLength - MatchedStringLen + TempSize; + + // + // Check if the buffer size allows the modification, in case of expansion + // + if (BufSize - MatchedStringLen + TempSize > Params->OptionalParam3) + { + // + // If adding the new string exceeds the user allocated size, + // zero out the buffer + // + memset(Buf, 0x0, Params->OptionalParam3); + g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Params->OptionalParam2, Buf, Params->OptionalParam3); + + // + // Update the required buffer size for the next call + // + BufSize = (TempSize - MatchedStringLen) + OldLength; + g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Params->OptionalParam4, &BufSize, sizeof(ULONG)); + + // + // And return STATUS_BUFFER_OVERFLOW error + // + + if (PoolAlloc) + PlatformMemFreePool(Buf); + return (UINT64)(UINT32)STATUS_BUFFER_OVERFLOW; + } + + // + // Calculate the positions of the replacement + // + ULONG MatchOffset = (ULONG)((MatchStart - StringBuf)); + PWCH MatchEnd = StringBuf + MatchOffset + (MatchedStringLen / sizeof(WCHAR)); + + // + // Move the data after the matched string forward + // + 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); + + *(PULONG)((PBYTE)Buf + DataLenOffset) = NewStringSize; + BufSize = BufSize - MatchedStringLen + TempSize; + + // + // Write the changes back to the user buffers + // + if (!g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Params->OptionalParam2, Buf, BufSize)) + { + goto ReturnWithError; + } + + if (!g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Params->OptionalParam4, &BufSize, sizeof(ULONG))) + { + goto ReturnWithError; + } + + // + // Cleanup + // + + MatchStart = wcsstr(StringBuf, HV_REGKEYS[i]); + + if (!MatchStart) + i = 0; + } + } + + // + // The data buffer contained no detectable strings + // + if (PoolAlloc) + PlatformMemFreePool(Buf); + return 0; + } + + // + // An error occurred while performing the mitigations, the user buffer might be left unmodified + // +ReturnWithError: + LogInfo("A call for to read a registry entry, which could contain hypervisor specific data, was intercepted but the mitigations failed"); + LogInfo("The caller process received the results in this virtual address: %llx", Params->OptionalParam2); + + if (Buf != NULL) + { + if (PoolAlloc) + PlatformMemFreePool(Buf); + } + + return 0; +} + +/** + * @brief Callback function to handle the returns from the NtQueryValueKey syscall + * + * @param Params The set transparent callback params that contain: + in OptionalParam1 the KEY_VALUE_INFORMATION_CLASS enum value + in OptionalParam2 a pointer to a valid read/writable memory buffer that contains both, a WCHAR string and its length in bytes + in OptionalParam3 max size in bytes of the allocated buffer + in OptionalParam4 a pointer to a ULONG containing current size of the buffer + * + * @return UINT64 + */ +UINT64 +TransparentCallbackHandleAfterNtQueryValueKeySyscall(SYSCALL_CALLBACK_CONTEXT_PARAMS * Params) +{ + ULONG LenOffset = 0; + ULONG BufOffset = 0; + + // + // Based on the KEY_VALUE_INFORMATION_CLASS given, set the struct offsets for the data buffer and its length fields + // + switch (Params->OptionalParam1) + { + // + // KeyValueBasicInformation and queries for a key that has a hypervisor specific name + // + case 0x0: + { + if (Params->OptionalParam2 != 0) + return 0; + + // + // If the key query was for a registry key that has a hypervisor specific name, return an error code + // + return (UINT64)(UINT32)STATUS_OBJECT_NAME_NOT_FOUND; + } + + // + // KeyValuePartialInformation + // + case 0x2: + { + LenOffset = sizeof(ULONG) * 2; + BufOffset = sizeof(ULONG) * 3; + + break; + } + + // + // KeyValueFullInformation + // + case 0x3: + case 0x1: + { + LenOffset = sizeof(ULONG) * 3; + BufOffset = sizeof(ULONG) * 4; // Name offset, Data is after it + + break; + } + + // + // KeyValuePartialInformationAlign64 + // + case 0x4: + { + LenOffset = sizeof(ULONG) * 1; + BufOffset = sizeof(ULONG) * 2; + + break; + } + default: + { + LogInfo("NtQueryValueKey was called with KeyValueInformationClass 0x%x, a handler for which has not been implemented", Params->OptionalParam1); + return 0; + } + } + + // + // Given the user buffer, read and exchange any Hypervisor vendor strings in the registry key data + // + return TransparentReplaceVendorStringFromBufferWChar(Params, BufOffset, LenOffset); +} + +/** + * @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 + in OptionalParam2 a pointer to a valid read/writable memory buffer that contains both, a WCHAR string and its length in bytes + in OptionalParam3 max size in bytes of the allocated buffer + in OptionalParam4 a pointer to a ULONG containing current size of the buffer + * + * @return UINT64 + */ +UINT64 +TransparentCallbackHandleAfterNtEnumerateKeySyscall(SYSCALL_CALLBACK_CONTEXT_PARAMS * Params) +{ + ULONG LenOffset = 0; + ULONG BufOffset = 0; + + // + // Based on the KEY_INFORMATION_CLASS given, set the struct offsets for the data buffer and its length fields + // + switch (Params->OptionalParam1) + { + // + // KeyBasicInformation + // + case 0x0: + { + LenOffset = sizeof(LARGE_INTEGER) + sizeof(ULONG); + BufOffset = sizeof(LARGE_INTEGER) + (sizeof(ULONG) * 2); + + break; + } + + // + // KeyNodeInformation + // + case 0x1: + { + return 0; + } + + // + // KeyNameInformation + // + case 0x3: + { + LenOffset = 0; + BufOffset = sizeof(ULONG); + + break; + } + default: + { + LogInfo("NtEnumerateKey was called with KeyInformationClass 0x%x, a handler for which has not been implemented", Params->OptionalParam1); + return 0; + } + } + + // + // Given the user buffer, read and exchange any Hypervisor vendor strings in the registry key names + // + return TransparentReplaceVendorStringFromBufferWChar(Params, BufOffset, LenOffset); +} + +/** + * @brief Callback function to handle the returns from the NtQuerySystemInformation syscall + * + * @param Regs The virtual processor's state of registers + * @param Params The (optional) parameters of the caller + * + * @return VOID + */ +VOID +TransparentCallbackHandleAfterNtQuerySystemInformationSyscall(GUEST_REGS * Regs, SYSCALL_CALLBACK_CONTEXT_PARAMS * Params) +{ + // + // Handle each defined SYSTEM_INFORMATION_CLASS + // + switch (Params->OptionalParam1) + { + case SystemCodeIntegrityInformation: + { + // + // Check if the obtained buffer pointer is valid + // + if (g_Callbacks.CheckAccessValidityAndSafety(Params->OptionalParam2, (UINT32)Params->OptionalParam3)) + { + SYSTEM_CODEINTEGRITY_INFORMATION Temp = {0}; + + // + // Read data from the saved pointer of the now filled information buffer + // + g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(Params->OptionalParam2, &Temp, Params->OptionalParam3); + + // + // Modify the data and write it back to the information buffer to be passed to user mode + // + Temp.CodeIntegrityOptions = 0x01; + g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Params->OptionalParam2, &Temp, Params->OptionalParam3); + } + else + { + LogInfo("A call for the NtQuerySystemInformation system call requesting SystemCodeIntegrityInformation structure was made, but the usermode buffer was not captured"); + } + + break; + } + case SystemProcessInformation: + case SystemExtendedProcessInformation: + { + // + // Check if the obtained buffer pointer is valid + // + if (Params->OptionalParam2 != 0x0 && + Params->OptionalParam3 != 0x0 && + g_Callbacks.CheckAccessValidityAndSafety(Params->OptionalParam2, (UINT32)Params->OptionalParam3)) + { + if (!TransparentHandleProcessInformationQuery(Params)) + { + // + // Some internal Windows calls to these system calls use different offsetting/entry structure layout and causes errors + // + + // LogInfo("Error while modifying the buffer for data query 0x02x", Params->OptionalParam1); + } + } + break; + } + + case SystemModuleInformation: + { + // + // Check if the obtained buffer pointer is valid + // + if (Params->OptionalParam2 != 0x0 && + Params->OptionalParam3 != 0x0 && + g_Callbacks.CheckAccessValidityAndSafety(Params->OptionalParam2, (UINT32)Params->OptionalParam3)) + { + // + // Allocate a buffer to copy user buffer data to for modification + // + PVOID Buf = PlatformMemAllocateZeroedNonPagedPool(Params->OptionalParam3); + if (Buf == NULL) + { + LogError("Err, insufficient memory"); + break; + } + + // + // Copy over the data and perform the modifications + // + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(Params->OptionalParam2, Buf, Params->OptionalParam3)) + { + LogInfo("Error reading memory buffer given by the usermode call"); + } + else + { + if (!TransparentHandleModuleInformationQuery(Buf, Params->OptionalParam2, (UINT32)Params->OptionalParam3)) + { + // + // Some internal Windows calls to these system calls use different offsetting/entry structure layout and causes errors + // + + // LogInfo("Error while modifying the buffer for data query 0x02x", Params->OptionalParam1); + } + } + + PlatformMemFreePool(Buf); + } + break; + } + case SystemKernelDebuggerInformation: + { + // + // Check if the obtained buffer pointer is valid + // + if (g_Callbacks.CheckAccessValidityAndSafety(Params->OptionalParam2, (UINT32)Params->OptionalParam3)) + { + // + // Write to the output buffer 0x0001 for "Debugger not present" + // + WORD Temp = 0x0100; + g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Params->OptionalParam2, &Temp, 2); + } + } + case SystemFirmwareTableInformation: + { + if (g_Callbacks.CheckAccessValidityAndSafety(Params->OptionalParam2, (UINT32)Params->OptionalParam3)) + { + UINT64 RetVal = TransparentHandleFirmwareInformationQuery(Params->OptionalParam2, (UINT32)Params->OptionalParam3, Params->OptionalParam4); + if (RetVal == 0x0) + { + LogInfo("A query for SystemFirmwareTableInformation was made, but the transparent mitigation failed"); + } + else if (RetVal != 0x1) + { + LogInfo("Changing to %llx", RetVal); + Regs->rax = RetVal; + } + } + else + { + LogInfo("A query for SystemFirmwareTableInformation was made, but the user-mode buffer was not captured"); + } + break; + } + + default: + { + break; + } + } +} + +/** + * @brief Callback function to handle returns from the syscall + * + * @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, + UINT32 ThreadId, + UINT64 Context, + SYSCALL_CALLBACK_CONTEXT_PARAMS * Params) +{ + // + // Handle each defined system call separately, after the kernel execution has finished(at the SYSRET instruction) + // + + // + // Handle the memory buffer and return code modification after NtQuerySystemInformation system call + // + if (Context == g_SystemCallNumbersInformation.SysNtQuerySystemInformation) + { + TransparentCallbackHandleAfterNtQuerySystemInformationSyscall(Regs, Params); + } + // + // Handle the memory buffer and return code modification after NtQueryAttributesFile system call + // + else if (Context == g_SystemCallNumbersInformation.SysNtQueryAttributesFile) + { + // + // Check if the obtained buffer pointer is valid + // + if (g_Callbacks.CheckAccessValidityAndSafety(Params->OptionalParam1, sizeof(FILE_BASIC_INFORMATION))) + { + FILE_BASIC_INFORMATION Buf = {0}; + // + // Copy over the data from the output buffer pointer + // + if (!g_Callbacks.MemoryMapperReadMemorySafeOnTargetProcess(Params->OptionalParam1, &Buf, sizeof(FILE_BASIC_INFORMATION))) + { + LogError("Err, Virtual memory read failed"); + } + else + { + // + // Modify the file attribute to INVALID_FILE_ATTRIBUTES and write it back to the pointer + // + Buf.FileAttributes = ((DWORD)-1); + + if (!g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Params->OptionalParam1, &Buf, sizeof(FILE_BASIC_INFORMATION))) + { + LogError("Err, Virtual memory write failed"); + } + } + } + else + { + LogInfo("A call for the NtQueryAttributeFile system call for a marked file was made, but the output buffer was not captured"); + } + } + + // + // Handle the memory buffer and return code modification after NtOpenDirectoryObject system call. + // + // NOTE: No transparent mitigations of this call have been implemented + // + else if (Context == g_SystemCallNumbersInformation.SysNtOpenDirectoryObject) + { + LogInfo("A NtOpenDirectoryObject system call was made for a known directory that reveals hypervisor presence. process: %x, thread: %x\n", + ProcessId, + ThreadId); + LogInfo("No action to mitigate this was made as a handler for NtOpenDirectoryObject has not been implemented"); + } + // + // Handle the memory buffer modification after NtQueryInformationProcess system call + // + else if (Context == g_SystemCallNumbersInformation.SysNtQueryInformationProcess) + { + switch (Params->OptionalParam1) + { + case 0x07: + { + if (g_Callbacks.CheckAccessValidityAndSafety(Params->OptionalParam2, sizeof(DWORD_PTR))) + { + // + // Zero out the return buffer to user-mode + // + DWORD_PTR NoDebugPort = 0x0; + + g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Params->OptionalParam2, &NoDebugPort, sizeof(DWORD_PTR)); + } + break; + } + case 0x1f: + { + // + // Zero out the return buffer to user-mode + // + ULONG notDebugged = 0x0; + g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Params->OptionalParam2, ¬Debugged, sizeof(ULONG)); + break; + } + case 0x1e: + { + if (g_Callbacks.CheckAccessValidityAndSafety(Params->OptionalParam2, (UINT32)Params->OptionalParam3)) + { + LogInfo("Process %llx called the NtQueryInformationProcess system call with the ProcessDebugObject class, no transparent mitigations were performed", ProcessId); + } + break; + } + default: + { + break; + } + } + } + // + // Handle the return code modification after NtSystemDebugControl system call + // + else if (Context == g_SystemCallNumbersInformation.SysNtSystemDebugControl) + { + // + // In the entry handler, the Syscall number was changed to corrupt this call, after the SYSRET, change the return code to STATUS_DEBUGGER_INACTIVE + // + Regs->rax = (UINT64)(UINT32)STATUS_DEBUGGER_INACTIVE; + } + + // + // Handle the return code modification after SysNtOpenFile system call + // + else if (Context == g_SystemCallNumbersInformation.SysNtOpenFile) + { + // + // In the entry handler, the Syscall number was changed to corrupt this call if the request was for a known hypervisor file + // after the SYSRET, change the return code to STATUS_OBJECT_NAME_NOT_FOUND + // + Regs->rax = (UINT64)(UINT32)STATUS_OBJECT_NAME_NOT_FOUND; + } + + // + // Handle the return code modification after NtNtQueryValueKey system call + // + // NOTE: The transparent mitigation will replace all occurrences of a hypervisor vendor string in the registry + // key data to a randomized real hardware vendor string, no matter the meaning of the key, + // This can cause some keys to produce illogical data, for example, + // a disk drive ID having a vendor string of ASUS even though (as far as I know) ASUS doesn't produce storage devices. + // + else if (Context == g_SystemCallNumbersInformation.SysNtQueryValueKey) + { + UINT64 RetVal; + + // + // Call the handler of NtQueryValueKey syscall callback + // + RetVal = TransparentCallbackHandleAfterNtQueryValueKeySyscall(Params); + + // + // If a custom(Specific to transparency) error code should be returned, + // set it to %RAX + // Else leave it to what the kernel already set it to + // + if (RetVal != 0) + { + Regs->rax = RetVal; + } + } + // + // Handle the memory buffer modification after NtOpenKey system call and its derivatives + // + else if (Context == g_SystemCallNumbersInformation.SysNtOpenKey || Context == g_SystemCallNumbersInformation.SysNtOpenKeyEx) + { + // + // In the entry handler, the Syscall number was changed to corrupt this call if the request was for a known hypervisor registry key + // after the SYSRET, change the return code to STATUS_OBJECT_NAME_NOT_FOUND + // + Regs->rax = (UINT64)(UINT32)STATUS_OBJECT_NAME_NOT_FOUND; + } + else if (Context == g_SystemCallNumbersInformation.SysNtEnumerateKey) + { + UINT64 RetVal; + + // + // Call the handler of NtEnumerateKey syscall callback + // + RetVal = TransparentCallbackHandleAfterNtEnumerateKeySyscall(Params); + + // + // If a custom(Specific to transparency) error code should be returned, + // set it to %RAX + // Else leave it to what the kernel already set it to + // + if (RetVal != 0) + { + Regs->rax = RetVal; + } + } + else + { + // + // A SYSRET trap flag was inserted for a System call that does not have a transparency handler implemented + // + LogInfo("Transparent callback for an unimplemented system call handle with the trap flag for process: %x, thread: %x, context: %llx RAX: %llx (p1: %llx, p2: %llx, p3: %llx, p4: %llx) \n", + ProcessId, + ThreadId, + Context, + Regs->rax, + Params->OptionalParam1, + Params->OptionalParam2, + Params->OptionalParam3, + Params->OptionalParam4); + } +} +#endif // ActivateHyperEvadeProject != TRUE diff --git a/hyperdbg/hyperevade/code/Transparency.c b/hyperdbg/hyperevade/code/Transparency.c new file mode 100644 index 00000000..611c085f --- /dev/null +++ b/hyperdbg/hyperevade/code/Transparency.c @@ -0,0 +1,771 @@ +/** + * @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 + * @date 2020-07-07 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Hide debugger on transparent-mode (activate transparent-mode) + * + * @param HyperevadeCallbacks Pointer to the HyperEvade callbacks structure + * @param TransparentModeRequest Pointer to the transparent debugger mode request + * + * @return BOOLEAN + */ +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 + // + for (UINT32 i = 0; i < sizeof(HYPEREVADE_CALLBACKS) / sizeof(UINT64); i++) + { + if (((PVOID *)HyperevadeCallbacks)[i] == NULL) + { + // + // The callback has null entry, so we cannot proceed + // + TransparentModeRequest->KernelStatus = DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER; + return FALSE; + } + } + + // + // Save the callbacks + // + RtlCopyMemory(&g_Callbacks, HyperevadeCallbacks, sizeof(HYPEREVADE_CALLBACKS)); + + // + // Check whether the transparent-mode was already initialized or not + // + if (!g_TransparentMode) + { + // + // Store the system-call numbers information + // + RtlCopyBytes(&g_SystemCallNumbersInformation, + &TransparentModeRequest->SystemCallNumbersInformation, + sizeof(SYSTEM_CALL_NUMBERS_INFORMATION)); +#if ActivateHyperEvadeProject == TRUE + // + // Choose a random genuine vendor string to replace hypervisor vendor data + // + 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; + + // + // Successfully enabled the transparent-mode + // + return TRUE; + } + else + { + TransparentModeRequest->KernelStatus = DEBUGGER_ERROR_DEBUGGER_ALREADY_HIDE; + return FALSE; + } +} + +/** + * @brief Deactivate transparent-mode + * + * @return BOOLEAN + */ +BOOLEAN +TransparentUnhideDebugger() +{ + if (g_TransparentMode) + { + // + // Disable the transparent-mode + // + g_TransparentMode = FALSE; + g_TransparentEvadeMask = 0; + + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief Generate a random number by utilizing RDTSC instruction. + * + * Masking 16 LSB of the measured clock time. + * @return UINT32 + */ +UINT32 +TransparentGetRand() +{ + UINT64 Tsc; + UINT32 Rand; + + Tsc = CpuReadTsc(); + Rand = Tsc & 0xffff; + + return Rand; +} + +/** + * @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 Pointer to the debugger hide and transparent mode request structure + * @return BOOLEAN + */ +BOOLEAN +TransparentAddNameOrProcessIdToTheList(PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE Measurements) +{ + SIZE_T SizeOfBuffer; + PTRANSPARENCY_PROCESS PidAndNameBuffer; + + // + // Check whether it's a process id or it's a process name + // + if (Measurements->TrueIfProcessIdAndFalseIfProcessName) + { + // + // It's a process Id + // + SizeOfBuffer = sizeof(TRANSPARENCY_PROCESS); + } + else + { + // + // It's a process name + // + SizeOfBuffer = sizeof(TRANSPARENCY_PROCESS) + Measurements->LengthOfProcessName; + } + + // + // Allocate the Buffer + // + PidAndNameBuffer = PlatformMemAllocateZeroedNonPagedPool(SizeOfBuffer); + + if (PidAndNameBuffer == NULL) + { + return FALSE; + } + + // + // Save the address of the buffer for future de-allocation + // + PidAndNameBuffer->BufferAddress = PidAndNameBuffer; + + // + // Check again whether it's a process id or it's a process name + // then fill the structure + // + if (Measurements->TrueIfProcessIdAndFalseIfProcessName) + { + // + // It's a process Id + // + PidAndNameBuffer->ProcessId = Measurements->ProcId; + PidAndNameBuffer->TrueIfProcessIdAndFalseIfProcessName = TRUE; + } + else + { + // + // It's a process name + // + PidAndNameBuffer->TrueIfProcessIdAndFalseIfProcessName = FALSE; + + // + // 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)), + Measurements->LengthOfProcessName); + + // + // Set the process name location + // + PidAndNameBuffer->ProcessName = (PVOID)((UINT64)PidAndNameBuffer + sizeof(TRANSPARENCY_PROCESS)); + } + + // + // Link it to the list of process that we need to transparent + // vm-exits for them + // + // InsertHeadList(&g_TransparentModeMeasurements->ProcessList, &(PidAndNameBuffer->OtherProcesses)); + + return TRUE; +} + +// +// /** +// * @brief maximum random value +// */ +// #define MY_RAND_MAX 32768 +// +// /** +// * @brief pre-defined log result +// * @details we used this because we want to avoid using floating-points in +// * kernel +// */ +// int TransparentTableLog[] = +// { +// 0, +// 69, +// 110, +// 139, +// 161, +// 179, +// 195, +// 208, +// 220, +// 230, +// 240, +// 248, +// 256, +// 264, +// 271, +// 277, +// 283, +// 289, +// 294, +// 300, +// 304, +// 309, +// 314, +// 318, +// 322, +// 326, +// 330, +// 333, +// 337, +// 340, +// 343, +// 347, +// 350, +// 353, +// 356, +// 358, +// 361, +// 364, +// 366, +// 369, +// 371, +// 374, +// 376, +// 378, +// 381, +// 383, +// 385, +// 387, +// 389, +// 391, +// 393, +// 395, +// 397, +// 399, +// 401, +// 403, +// 404, +// 406, +// 408, +// 409, +// 411, +// 413, +// 414, +// 416, +// 417, +// 419, +// 420, +// 422, +// 423, +// 425, +// 426, +// 428, +// 429, +// 430, +// 432, +// 433, +// 434, +// 436, +// 437, +// 438, +// 439, +// 441, +// 442, +// 443, +// 444, +// 445, +// 447, +// 448, +// 449, +// 450, +// 451, +// 452, +// 453, +// 454, +// 455, +// 456, +// 457, +// 458, +// 460, +// 461}; +// +// +// /** +// * @brief Integer power function definition. +// * +// * @params x Base Value +// * @params p Power Value +// * @return int +// */ +// int +// TransparentPow(int x, int p) +// { +// int Res = 1; +// for (int i = 0; i < p; i++) +// { +// Res = Res * x; +// } +// return Res; +// } +// +// /** +// * @brief Integer Natural Logarithm function estimation. +// * +// * @params x input value +// * @return int +// */ +// int +// TransparentLog(int x) +// { +// int n = x; +// int Digit = 0; +// +// while (n >= 100) +// { +// n = n / 10; +// Digit++; +// } +// +// // +// // Use pre-defined values of logarithms and estimate the total value +// // +// return TransparentTableLog[n] / 100 + (Digit * 23) / 10; +// } +// /** +// * @brief Integer root function estimation. +// * +// * @params x input value +// * @return int +// */ +// int +// TransparentSqrt(int x) +// { +// int Res = 0; +// int Bit; +// +// // +// // The second-to-top bit is set. +// // +// Bit = 1 << 30; +// +// // +// // "Bit" starts at the highest power of four <= the argument. +// // +// while (Bit > x) +// Bit >>= 2; +// +// while (Bit != 0) +// { +// if (x >= Res + Bit) +// { +// x -= Res + Bit; +// Res = (Res >> 1) + Bit; +// } +// else +// Res >>= 1; +// Bit >>= 2; +// } +// return Res; +// } +// +// /** +// * @brief Integer Gaussian Random Number Generator(GRNG) based on Box-Muller method. A Float to Integer +// * mapping is used in the function. +// * +// * @params Average Mean +// * @parans Sigma Standard Deviation of the targeted Gaussian Distribution +// * @return int +// */ +// int +// TransparentRandn(int Average, int Sigma) +// { +// int U1, r1, U2, r2, W, Mult; +// int X1, X2 = 0, XS1; +// int LogTemp = 0; +// +// do +// { +// r1 = TransparentGetRand(); +// r2 = TransparentGetRand(); +// +// U1 = (r1 % MY_RAND_MAX) - (MY_RAND_MAX / 2); +// +// U2 = (r2 % MY_RAND_MAX) - (MY_RAND_MAX / 2); +// +// W = U1 * U1 + U2 * U2; +// } while (W >= MY_RAND_MAX * MY_RAND_MAX / 2 || W == 0); +// +// LogTemp = (TransparentLog(W) - TransparentLog(MY_RAND_MAX * MY_RAND_MAX)); +// +// Mult = TransparentSqrt((-2 * LogTemp) * (MY_RAND_MAX * MY_RAND_MAX / W)); +// +// X1 = U1 * Mult / MY_RAND_MAX; +// XS1 = U1 * Mult; +// +// X2 = U2 * Mult / MY_RAND_MAX; +// +// return (Average + (Sigma * XS1) / MY_RAND_MAX); +// } +// +// +// /** +// * @brief Hide debugger on transparent-mode (activate transparent-mode) +// * +// * @param Measurements +// * @return NTSTATUS +// */ +// NTSTATUS +// TransparentHideDebugger(PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE Measurements) +// { +// // +// // Check whether the transparent-mode was already initialized or not +// // +// if (!g_TransparentMode) +// { +// // +// // Allocate the measurements buffer +// // +// g_TransparentModeMeasurements = (PTRANSPARENCY_MEASUREMENTS)PlatformMemAllocateZeroedNonPagedPool(sizeof(TRANSPARENCY_MEASUREMENTS)); +// +// if (!g_TransparentModeMeasurements) +// { +// return STATUS_INSUFFICIENT_RESOURCES; +// } +// +// // +// // Initialize the lists +// // +// InitializeListHead(&g_TransparentModeMeasurements->ProcessList); +// +// // +// // Fill the transparency details CPUID +// // +// g_TransparentModeMeasurements->CpuidAverage = Measurements->CpuidAverage; +// g_TransparentModeMeasurements->CpuidMedian = Measurements->CpuidMedian; +// g_TransparentModeMeasurements->CpuidStandardDeviation = Measurements->CpuidStandardDeviation; +// +// // +// // Fill the transparency details RDTSC +// // +// g_TransparentModeMeasurements->RdtscAverage = Measurements->RdtscAverage; +// g_TransparentModeMeasurements->RdtscMedian = Measurements->RdtscMedian; +// g_TransparentModeMeasurements->RdtscStandardDeviation = Measurements->RdtscStandardDeviation; +// +// // +// // add the new process name or Id to the list +// // +// TransparentAddNameOrProcessIdToTheList(Measurements); +// +// // +// // Enable RDTSC and RDTSCP exiting on all cores +// // +// BroadcastEnableRdtscExitingAllCores(); +// +// // +// // Finally, enable the transparent-mode +// // +// g_TransparentMode = TRUE; +// } +// else +// { +// // +// // It's already initialized, we just need to +// // add the new process name or Id to the list +// // +// TransparentAddNameOrProcessIdToTheList(Measurements); +// } +// +// return STATUS_SUCCESS; +// } +// +// /** +// * @brief Deactivate transparent-mode +// * +// * @return NTSTATUS +// */ +// NTSTATUS +// TransparentUnhideDebugger() +// { +// PLIST_ENTRY TempList = 0; +// PVOID BufferToDeAllocate = 0; +// +// if (g_TransparentMode) +// { +// // +// // Disable the transparent-mode +// // +// g_TransparentMode = FALSE; +// +// // +// // Disable RDTSC and RDTSCP emulation +// // +// BroadcastDisableRdtscExitingAllCores(); +// +// // +// // Free list of allocated buffers +// // +// // Check for process id and process name, if not match then we don't emulate it +// // +// TempList = &g_TransparentModeMeasurements->ProcessList; +// while (&g_TransparentModeMeasurements->ProcessList != TempList->Flink) +// { +// TempList = TempList->Flink; +// PTRANSPARENCY_PROCESS ProcessDetails = (PTRANSPARENCY_PROCESS)CONTAINING_RECORD(TempList, TRANSPARENCY_PROCESS, OtherProcesses); +// +// // +// // Save the buffer so we can de-allocate it +// // +// BufferToDeAllocate = ProcessDetails->BufferAddress; +// +// // +// // We have to remove the event from the list +// // +// RemoveEntryList(&ProcessDetails->OtherProcesses); +// +// // +// // Free the buffer +// // +// PlatformMemFreePool(BufferToDeAllocate); +// } +// +// // +// // Deallocate the measurements buffer +// // +// PlatformMemFreePool(g_TransparentModeMeasurements); +// g_TransparentModeMeasurements = NULL; +// +// return STATUS_SUCCESS; +// } +// else +// { +// return STATUS_UNSUCCESSFUL; +// } +// } +// +// /** +// * @brief VM-Exit handler for different exit reasons +// * @details Should be called from vmx-root +// * +// * @param Regs The virtual processor's state of registers +// * @param ExitReason Exit Reason +// * @return BOOLEAN Return True we should emulate RDTSCP +// * or return false if we should not emulate RDTSCP +// */ +// BOOLEAN +// TransparentModeStart(GUEST_REGS * Regs, UINT32 ExitReason) +// { +// UINT32 Aux = 0; +// PLIST_ENTRY TempList = 0; +// PCHAR CurrentProcessName = 0; +// UINT32 CurrentProcessId; +// UINT64 CurrrentTime; +// HANDLE CurrentThreadId; +// BOOLEAN Result = TRUE; +// BOOLEAN IsProcessOnTransparencyList = FALSE; +// +// // +// // Save the current time +// // +// CurrrentTime = CpuReadTscp(&Aux); +// +// // +// // Save time of vm-exit on each logical processor separately +// // +// VCpu->TransparencyState.PreviousTimeStampCounter = CurrrentTime; +// +// // +// // Find the current process id and name +// // +// CurrentProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId()); +// CurrentProcessName = CommonGetProcessNameFromProcessControlBlock(PsGetCurrentProcess()); +// +// // +// // Check for process id and process name, if not match then we don't emulate it +// // +// TempList = &g_TransparentModeMeasurements->ProcessList; +// while (&g_TransparentModeMeasurements->ProcessList != TempList->Flink) +// { +// TempList = TempList->Flink; +// PTRANSPARENCY_PROCESS ProcessDetails = (PTRANSPARENCY_PROCESS)CONTAINING_RECORD(TempList, TRANSPARENCY_PROCESS, OtherProcesses); +// if (ProcessDetails->TrueIfProcessIdAndFalseIfProcessName) +// { +// // +// // This entry is process id +// // +// if (ProcessDetails->ProcessId == CurrentProcessId) +// { +// // +// // Let the transparency handler to handle it +// // +// IsProcessOnTransparencyList = TRUE; +// break; +// } +// } +// else +// { +// // +// // This entry is a process name +// // +// if (CurrentProcessName != NULL && CommonIsStringStartsWith(CurrentProcessName, ProcessDetails->ProcessName)) +// { +// // +// // Let the transparency handler to handle it +// // +// IsProcessOnTransparencyList = TRUE; +// break; +// } +// } +// } +// +// // +// // Check whether we find this process on transparency list or not +// // +// if (!IsProcessOnTransparencyList) +// { +// // +// // No, we didn't let's do the normal tasks +// // +// return TRUE; +// } +// +// // +// // Get current thread Id +// // +// CurrentThreadId = PsGetCurrentThreadId(); +// +// // +// // Check whether we are in new thread or in previous thread +// // +// if (VCpu->TransparencyState.ThreadId != CurrentThreadId) +// { +// // +// // It's a new thread Id reset everything +// // +// VCpu->TransparencyState.ThreadId = CurrentThreadId; +// VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc = NULL64_ZERO; +// VCpu->TransparencyState.CpuidAfterRdtscDetected = FALSE; +// } +// +// // +// // Now, it's time to check and play with RDTSC/P and CPUID +// // +// +// if (ExitReason == VMX_EXIT_REASON_EXECUTE_RDTSC || ExitReason == VMX_EXIT_REASON_EXECUTE_RDTSCP) +// { +// if (VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc == NULL64_ZERO) +// { +// // +// // It's a timing and the previous time for the thread is null +// // so we need to save the time (maybe) for future use +// // +// VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc = CurrrentTime; +// } +// else if (VCpu->TransparencyState.CpuidAfterRdtscDetected == TRUE) +// { +// // +// // Someone tries to know about the hypervisor +// // let's play with them +// // +// +// // LogInfo("Possible RDTSC+CPUID+RDTSC"); +// } +// else if (VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc != NULL64_ZERO && +// VCpu->TransparencyState.CpuidAfterRdtscDetected == FALSE) +// { +// // +// // It's a new rdtscp, let's save the new value +// // +// VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc += +// TransparentRandn((UINT32)g_TransparentModeMeasurements->CpuidAverage, +// (UINT32)g_TransparentModeMeasurements->CpuidStandardDeviation); +// } +// +// // +// // Adjust the rdtsc based on RevealedTimeStampCounterByRdtsc +// // +// Regs->rax = 0x00000000ffffffff & +// VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc; +// +// Regs->rdx = 0x00000000ffffffff & +// (VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc >> 32); +// +// // +// // Check if we need to adjust rcx as a result of rdtscp +// // +// if (ExitReason == VMX_EXIT_REASON_EXECUTE_RDTSCP) +// { +// Regs->rcx = 0x00000000ffffffff & Aux; +// } +// // +// // Shows that vm-exit handler should not emulate the RDTSC/P +// // +// Result = FALSE; +// } +// else if (ExitReason == VMX_EXIT_REASON_EXECUTE_CPUID && +// VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc != NULL64_ZERO) +// { +// // +// // The guy executed one or more CPUIDs after an rdtscp so we +// // need to add new cpuid value to previous timer and also +// // we need to store it somewhere to remember this behavior +// // +// VCpu->TransparencyState.RevealedTimeStampCounterByRdtsc += +// TransparentRandn((UINT32)g_TransparentModeMeasurements->CpuidAverage, +// (UINT32)g_TransparentModeMeasurements->CpuidStandardDeviation); +// +// VCpu->TransparencyState.CpuidAfterRdtscDetected = TRUE; +// } +// +// return Result; +// } +// diff --git a/hyperdbg/hyperevade/code/UnloadDll.c b/hyperdbg/hyperevade/code/UnloadDll.c new file mode 100644 index 00000000..17321dbf --- /dev/null +++ b/hyperdbg/hyperevade/code/UnloadDll.c @@ -0,0 +1,45 @@ +/** + * @file UnloadDll.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Unloading DLL in the target Windows + * @details + * @version 0.4 + * @date 2023-07-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// We'll add these functions, so whenever HyperDbg's driver is unloaded +// DllUnload will be called to unload this dll from the memory. +// this way we can remove the HyperDbg after unloading as there is no +// 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) +{ + UNREFERENCED_PARAMETER(RegistryPath); + + return STATUS_SUCCESS; +} + +/** + * @brief Routine called on DLL unload + * + * @return NTSTATUS + */ +NTSTATUS +DllUnload(VOID) +{ + return STATUS_SUCCESS; +} diff --git a/hyperdbg/hyperevade/code/VmxFootprints.c b/hyperdbg/hyperevade/code/VmxFootprints.c new file mode 100644 index 00000000..1133f2f5 --- /dev/null +++ b/hyperdbg/hyperevade/code/VmxFootprints.c @@ -0,0 +1,165 @@ +/** + * @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 + * @date 2025-06-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Handle Cpuid Vmexits when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @param CpuInfo The temporary logical processor registers + * + * @return VOID + */ +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) + { + // + // Unset the Hypervisor Present-bit in RCX, which Intel and AMD have both + // reserved for this indication + // + CpuInfo[2] &= ~HYPERV_HYPERVISOR_PRESENT_BIT; + } + else if (Regs->rax == CPUID_HV_VENDOR_AND_MAX_FUNCTIONS || Regs->rax == HYPERV_CPUID_INTERFACE) + { + // + // When transparent, all CPUID leaves in the 0x40000000+ range should contain no usable data + // + CpuInfo[0] = CpuInfo[1] = CpuInfo[2] = CpuInfo[3] = 0x40000000; + } +} + +/** + * @brief Handle RDMSR VM exits when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @param TargetMsr Target MSR in ECX register + * + * @return BOOLEAN Whether the emulation should be further continued or not + */ +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 + // + // Sina: Needs more investigation since injecting #GP on Nested-virtualization environments + // will crash the VM on Meteor Lake processors since the OS expects to use synthetic timers + // (HV_REGISTER_STIMER0_CONFIG and HV_REGISTER_STIMER0_COUNT) to receive interrupts + // Ref: https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/timers + // + // if (TargetMsr >= RESERVED_MSR_RANGE_LOW && TargetMsr <= RESERVED_MSR_RANGE_HI) + // { + // LogInfo("RDMSR attempts to write to a reserved MSR range. MSR: %x", + // TargetMsr); + // + // g_Callbacks.EventInjectGeneralProtection(); + // return TRUE; // Should not emulate further + // } + // else + // { + // // + // // Not handled in the transparent-mode + // // + // return FALSE; + // } + + UNREFERENCED_PARAMETER(Regs); + UNREFERENCED_PARAMETER(TargetMsr); + + return FALSE; +} + +/** + * @brief Handle WRMSR VM exits when the Transparent mode is enabled + * + * @param Regs The virtual processor's state of registers + * @param TargetMsr Target MSR in ECX register + * + * @return BOOLEAN Whether the emulation should be further continued or not + */ +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) + // { + // // + // // 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 + // // + // + // LogInfo("WRMSR attempts to write to a reserved MSR range. MSR: %x, rax: %llx, rdx: %llx", + // TargetMsr, + // Regs->rax, + // Regs->rdx); + // + // g_Callbacks.EventInjectGeneralProtection(); + // + // return TRUE; // Should not emulate further + // } + // else + // { + // // + // // Not handled in the transparent-mode + // // + // return FALSE; + // } + + UNREFERENCED_PARAMETER(Regs); + UNREFERENCED_PARAMETER(TargetMsr); + + return FALSE; +} + +/** + * @brief Handle anti-debugging method of a trap flag after a VM exit + * + * @return VOID + */ +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 + // + g_Callbacks.HvHandleTrapFlag(); +} diff --git a/hyperdbg/hyperevade/header/SyscallFootprints.h b/hyperdbg/hyperevade/header/SyscallFootprints.h new file mode 100644 index 00000000..02e3d6a3 --- /dev/null +++ b/hyperdbg/hyperevade/header/SyscallFootprints.h @@ -0,0 +1,646 @@ +/** + * @file SyscallFootprints.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Hide the debugger from SYSCALL anti-debugging and anti-hypervisor methods (headers) + * @details + * @version 0.14 + * @date 2024-06-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Enums // +////////////////////////////////////////////////// + +/** + * @brief System information class + * + */ +typedef enum _SYSTEM_INFORMATION_CLASS +{ + SystemProcessInformation = 0x05, + SystemExtendedProcessInformation = 0x39, + SystemFullProcessInformation = 0x94, + SystemModuleInformation = 0x0B, + SystemKernelDebuggerInformation = 0x23, + SystemCodeIntegrityInformation = 0x67, + SystemFirmwareTableInformation = 0x4C, +} SYSTEM_INFORMATION_CLASS, + *PSYSTEM_INFORMATION_CLASS; + +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +/** + * @brief System Information for Code Integrity + * + */ +typedef struct _SYSTEM_CODEINTEGRITY_INFORMATION +{ + ULONG Length; + ULONG CodeIntegrityOptions; + +} SYSTEM_CODEINTEGRITY_INFORMATION, *PSYSTEM_CODEINTEGRITY_INFORMATION; + +/** + * @brief System Information for running processes + * + */ +typedef struct _SYSTEM_PROCESS_INFORMATION +{ + ULONG NextEntryOffset; + ULONG NumberOfThreads; + BYTE Reserved1[48]; + UNICODE_STRING ImageName; + KPRIORITY BasePriority; + HANDLE UniqueProcessId; + PVOID Reserved2; + ULONG HandleCount; + ULONG SessionId; + PVOID Reserved3; + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG Reserved4; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + PVOID Reserved5; + SIZE_T QuotaPagedPoolUsage; + PVOID Reserved6; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; + LARGE_INTEGER Reserved7[6]; +} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; + +/** + * @brief SSDT structure + * + */ +typedef struct _SSDT_STRUCT +{ + LONG * ServiceTable; + PVOID CounterTable; +#ifdef _WIN64 + UINT64 NumberOfServices; +#else + ULONG NumberOfServices; +#endif + PCHAR ArgumentTable; +} SSDT_STRUCT, *PSSDT_STRUCT; + +/** + * @brief Module entry + * + */ +typedef struct _SYSTEM_MODULE_ENTRY +{ + HANDLE Section; + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + UINT16 LoadOrderIndex; + UINT16 InitOrderIndex; + UINT16 LoadCount; + UINT16 OffsetToFileName; + UCHAR FullPathName[256]; +} SYSTEM_MODULE_ENTRY, *PSYSTEM_MODULE_ENTRY; + +/** + * @brief System Information for modules + * + */ +typedef struct _SYSTEM_MODULE_INFORMATION +{ + ULONG Count; + SYSTEM_MODULE_ENTRY Module[1]; + +} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; + +typedef NTSTATUS(NTAPI * ZWQUERYSYSTEMINFORMATION)( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + OUT PVOID SystemInformation, + IN ULONG SystemInformationLength, + OUT PULONG ReturnLength OPTIONAL); + +NTSTATUS(*g_NtCreateFileOrig) +( + PHANDLE FileHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PIO_STATUS_BLOCK IoStatusBlock, + PLARGE_INTEGER AllocationSize, + ULONG FileAttributes, + ULONG ShareAccess, + ULONG CreateDisposition, + ULONG CreateOptions, + PVOID EaBuffer, + ULONG EaLength); + +////////////////////////////////////////////////// +// Globals // +////////////////////////////////////////////////// + +/** + * @brief A variable holding the randomly chosen index for the genuine vendor list. + * This is used for transparent vendor spoofing + */ +static WORD g_TransparentGenuineVendorStringIndex = 0; + +/** + * @brief System call numbers information + */ +SYSTEM_CALL_NUMBERS_INFORMATION g_SystemCallNumbersInformation; + +////////////////////////////////////////////////// +// Constants // +////////////////////////////////////////////////// + +#if ActivateHyperEvadeProject == TRUE + +/** + * @brief A list of windows processes, for which to ignore systemcall requests + * when the transparency mode is enabled + * + */ +static const PCHAR TRANSPARENT_WIN_PROCESS_IGNORE[] = { + "winlogon.exe", + "wininit.exe", + "csrss.exe", + "sihost.exe", + "explorer.exe", +}; + +/** + * @brief A brief list of genuine system vendors device ID's used for manufacturer spoofing + * + */ +static const PWCHAR TRANSPARENT_LEGIT_DEVICE_ID_VENDOR_STRINGS_WCHAR[] = { + L"VEN_8086", // Intel + L"VEN_10DE", // NVIDIA + L"VEN_1002", // AMD + L"VEN_10EC", // Realtek + +}; + +/** + * @brief A list of genuine system vendors used for manufacturer spoofing + * + */ +static const PWCHAR TRANSPARENT_LEGIT_VENDOR_STRINGS_WCHAR[] = { + L"ASUS", + L"ASUSTeK Computer INC.", + L"ASUSTek", + L"ASUSTEK COMPUTER INC.", + + // MSI + L"Micro-Star International Co., Ltd.", + L"MSI", + L"MICRO-STAR INTERNATIONAL CO., LTD", + + // Gigabyte + L"Gigabyte Technology Co., Ltd.", + L"GIGABYTE", + L"Gigabyte Technology", + + // ASRock + L"ASRock", + L"ASRock Incorporation", + L"ASRock Inc.", + + // Dell + L"Dell Inc.", + L"DELL", + L"Dell Computer Corporation", + + // HP + L"Hewlett-Packard", + L"Hewlett Packard", + L"HP", + L"HP Inc.", + + // Lenovo + L"LENOVO", + L"Lenovo Group Limited", + + // Intel + L"Intel Corporation", + L"Intel", + + // EVGA + L"EVGA Corporation", + L"EVGA", +}; + +/** + * @brief A list of common Hypervisor specific process executables + * + */ +static const PWCH HV_PROCESSES[] = { + L"hyperdbg-cli.exe", + L"vboxservice.exe", + L"vmsrvc.exe", + L"xenservice.exe", + L"vm3dservice.exe", + L"VGAuthService.exe", + L"vmtoolsd.exe", + L"vdagent.exe", + L"vdservice.exe", + L"qemuwmi.exe", + L"vboxtray.exe", + L"VBoxControl.exe", + L"VGAuthService.exe", + + // + // Common Debugging Tools + // + L"ollydbg.exe", + L"ollyice.exe", + L"ProcessHacker.exe", + L"tcpview.exe", + L"autoruns.exe", + L"autorunsc.exe", + L"filemon.exe", + L"procmon.exe", + L"regmon.exe", + L"procexp.exe", + L"idaq.exe", + L"idaq64.exe", + L"ImmunityDebugger.exe", + L"Wireshark.exe", + L"dumpcap.exe", + L"HookExplorer.exe", + L"ImportREC.exe", + L"PETools.exe", + L"LordPE.exe", + L"SysInspector.exe", + L"proc_analyzer.exe", + L"sysAnalyzer.exe", + L"sniff_hit.exe", + L"windbg.exe", + L"joeboxcontrol.exe", + L"joeboxserver.exe", + L"ResourceHacker.exe", + L"x32dbg.exe", + L"x64dbg.exe", + L"Fiddler.exe", + L"httpdebugger.exe", + L"cheatengine-i386.exe", + L"cheatengine-x86_64.exe", + L"cheatengine-x86_64-SSE4-AVX2.exe", + L"frida-helper-32.exe", + L"frida-helper-64.exe", + +}; + +/** + * @brief A list of common Hypervisor specific drivers + * + */ +static const PCHAR HV_DRIVER[] = { + "hyperkd", + "hyperhv", + + // + // Drivers from VBox + // + + "VBoxGuest", + "VBoxMouse", + "VBoxSF", + + // + // Drivers from VMWare Tools + // + + "vmrawdsk", + "giappdef", + "glxgi", + "vm3dmp", + "vm3dmp_loader", + "vm3dmp-debug", + "vm3dmp-stats", + "vmxnet3", + "vmxnet", + "vnetWFP", + "vnetflt", + "vsepflt", + "pvscsi", + "vmmemctl", + "vmhgfs", + "vmusbmouse", + "vmmouse", + "vmaudio", + "vmci", + "vsock", + + // + // Hyper-V Drivers + // + + "VMBusHID", + "vmbus", + "vmgid", + "IndirectKmd", + "HyperVideo", + "hyperkbd", + +}; + +/** + * @brief A list of common Hypervisor specific files + * + */ +static const PWCH HV_FILES[] = { + + // + // HyperDbg Files + // + L"hyperhv", + L"hyperkd", + L"hyperlog", + L"libhyperdbg", + + // + // VMware Files + // + L"vmmouse.sys", + L"Vmmouse.sys", + L"vmusbmouse.sys", + L"Vmusbmouse.sys", + L"vm3dgl.dll", + L"vmdum.dll", + L"VmGuestLibJava.dll", + L"vm3dver.dll", + L"vmtray.dll", + L"VMToolsHook.dll", + L"vmGuestLib.dll", + L"vmhgfs.dll", + L"vmhgfs.sys", + L"vm3dum64_loader.dll", + L"vm3dum64_10.dll", + L"vmnet.sys", + L"vmusb.sys", + L"vm3dmp.sys", + L"vmci.sys", + L"vmmemctl.sys", + L"vmx86.sys", + L"vmrawdsk.sys", + L"vmkdb.sys", + L"vmnetuserif.sys", + L"vmnetadapter.sys", + L"VMware Tools", + L"VMWare", + + // + // VirtualBox Files + // + L"VBoxMouse.sys", + L"VBoxGuest.sys", + L"VBoxSF.sys", + L"VBoxVideo.sys", + L"vboxoglpackspu.dll", + L"vboxoglpassthroughspu.dll", + L"vboxservice.exe", + L"vboxoglcrutil.dll", + L"vboxdisp.dll", + L"vboxhook.dll", + L"vboxmrxnp.dll", + L"vboxogl.dll", + L"vboxtray.exe", + L"VBoxControl.exe", + L"vboxoglerrorspu.dll", + L"vboxoglfeedbackspu.dll", + L"vboxoglarrayspu.dll", + L"vboxmrxnp.dll", + L"virtualbox guest additions", + + // + // KVM files + // + L"balloon.sys", + L"netkvm.sys", + L"pvpanic.sys", + L"viofs.sys", + L"viogpudo.sys", + L"vioinput.sys", + L"viorng.sys", + L"vioscsi.sys", + L"vioser.sys", + L"viostor.sys", + + // + // VPC files + // + L"vmsrvc.sys", + L"vmusrvc.sys", + L"vmsrvc.exe", + L"vmusrvc.exe", + L"vpc-s3.sys", + L"Virtio-Win", + + L"qemu-ga", + L"SPICE Guest Tools", +}; + +/** + * @brief A list of common Hypervisor specific directories + * + */ +static const PWCH HV_DIRS[] = { + L"hyperhv", + L"VMware Tools", + L"Virtio-Win", + L"qemu-ga", + L"SPICE Guest Tools", + L"VMware", + L"VMWARE", + L"virtualbox guest additions", + L"VirtualBox Guest Additions", +}; + +/** + * @brief A list of common Hypervisor specific registry keys + * + */ +static const PWCH HV_REGKEYS[] = { + + // + // PCI device vendor id's + // + // NOTE: These need to stay at the top of the list + // + L"VEN_80EE", + L"VEN_15AD", + L"VEN_5333", + + // + // Common names + // + L"Virtual", + L"VIRTUAL", + L"virtual", + L"Hypervisor", + L"hypervisor", + L"HYPERVISOR", + + // + // VMWare + // + L"VMware Tools", + L"VMware, Inc.", + L"vmusbmouse", + L"VMware", + L"VMWARE", + L"VMWare", + L"vmdebug", + L"vmmouse", + L"VMTools", + L"VMMEMCTL", + L"vmware tools", + L"VMW0001", + L"VMW0002", + L"VMW0003", + + L"sandbox", + L"Sandboxie", + + // + // VirtualBox + // + L"VirtualBox Guest Additions", + L"VBOX__", + L"VBoxGuest", + L"VBoxMouse", + L"VBoxService", + L"VBoxSF", + L"VBoxVideo", + L"VIRTUALBOX", + L"SUN MICROSYSTEMS", + L"VBOXVER", + L"VBOXAPIC", + L"INNOTEK GMBH", + + // + // QEMU + // + L"qemu-ga", + L"SPICE Guest Tools", + + // + // VPC + // + L"vpcbus", + L"vpc-s3", + L"vpcuhub", + L"msvmmouf", + L"Wine", + L"xen", + L"VIRTUAL MACHINE", + L"GOOGLE COMPUTE ENGINE", + L"sandbox", + L"Sandboxie", + + // + // KVM + // + L"vioscsi", + L"viostor", + L"VirtIO-FS Service", + L"VirtioSerial", + L"BALLOON", + L"BalloonService", + L"netkvm", + +}; + +/** + * @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", + L"Identifier", + L"SystemBiosVersion", + L"VideoBiosVersion", + L"ProductID", + L"SystemManufacturer", + L"SystemProductName", + L"DeviceDesc", + L"FriendlyName", + L"DisplayName", + L"ProviderName", + L"Device Description", + L"BIOSVendor", + L"DriverDesc", + L"InfSection", + L"Service", + L"0", + L"1", + L"00000000", +}; + +/** + * @brief A list of common Hypervisor firmware entries + * + * @details The list contains both a normal and uppercase versions of the entries, for better compatibility + * + */ +static const PCHAR HV_FIRM_NAMES[] = { + "440BX Desktop Reference Platform", + "VMWARE, INC.", + "VMware, Inc.", + "VMWARE", + "VMware", + "VMW", + "VS2005R2", + "VirtualBox", + "VIRTUALBOX", + "Oracle", + "ORACLE", + "Innotek", + "INNOTEK", + "Virtual", + +}; + +#endif + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +TransparentHandleNtQuerySystemInformationSyscall(GUEST_REGS * Regs); + +VOID +TransparentHandleNtQueryAttributesFileSyscall(GUEST_REGS * Regs); + +VOID +TransparentHandleNtSystemDebugControlSyscall(GUEST_REGS * Regs); + +VOID +TransparentHandleNtOpenDirectoryObjectSyscall(GUEST_REGS * Regs); + +VOID +TransparentHandleNtQueryInformationProcessSyscall(GUEST_REGS * Regs); + +VOID +TransparentHandleNtOpenFileSyscall(GUEST_REGS * Regs); + +VOID +TransparentHandleNtOpenKeySyscall(GUEST_REGS * Regs); + +VOID +TransparentHandleNtQueryValueKeySyscall(GUEST_REGS * Regs); + +VOID +TransparentHandleNtEnumerateKeySyscall(GUEST_REGS * Regs); diff --git a/hyperdbg/hprdbghv/header/transparency/Transparency.h b/hyperdbg/hyperevade/header/Transparency.h similarity index 78% rename from hyperdbg/hprdbghv/header/transparency/Transparency.h rename to hyperdbg/hyperevade/header/Transparency.h index 1123920c..5b3493b8 100644 --- a/hyperdbg/hprdbghv/header/transparency/Transparency.h +++ b/hyperdbg/hyperevade/header/Transparency.h @@ -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 @@ -12,31 +13,14 @@ #pragma once ////////////////////////////////////////////////// -// Functions // -////////////////////////////////////////////////// - -BOOLEAN -TransparentModeStart(VIRTUAL_MACHINE_STATE * VCpu, UINT32 ExitReason); - -////////////////////////////////////////////////// -// Definitions // +// Globals // ////////////////////////////////////////////////// /** - * @brief IA32_TIME_STAMP_COUNTER MSR (rcx) + * @brief List of callbacks * */ -#define MSR_IA32_TIME_STAMP_COUNTER 0x10 - -/** - * @brief Maximum value that can be returned by the rand function - * - */ -#define RAND_MAX 0x7fff - -////////////////////////////////////////////////// -// Structures // -////////////////////////////////////////////////// +HYPEREVADE_CALLBACKS g_Callbacks; /** * @brief The measurements from user-mode and kernel-mode @@ -69,3 +53,27 @@ typedef struct _TRANSPARENCY_PROCESS LIST_ENTRY OtherProcesses; } TRANSPARENCY_PROCESS, *PTRANSPARENCY_PROCESS; + +////////////////////////////////////////////////// +// Globals // +////////////////////////////////////////////////// + +/** + * @brief Shows whether the debugger transparent mode + * is enabled (true) or not (false) + * + */ +BOOLEAN g_TransparentMode; + +/** + * @brief The enabled transparent-mode feature mask + * + */ +UINT32 g_TransparentEvadeMask; + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +UINT32 +TransparentGetRand(); diff --git a/hyperdbg/hyperevade/header/VmxFootprints.h b/hyperdbg/hyperevade/header/VmxFootprints.h new file mode 100644 index 00000000..39560e8c --- /dev/null +++ b/hyperdbg/hyperevade/header/VmxFootprints.h @@ -0,0 +1,16 @@ +/** + * @file VmxFootprints.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Hide the debugger from VMX-footprints of anti-debugging and anti-hypervisor methods (headers) + * @details + * @version 0.14 + * @date 2024-08-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +// +// Some of the functions are exported in the module +// diff --git a/hyperdbg/hyperevade/header/pch.h b/hyperdbg/hyperevade/header/pch.h new file mode 100644 index 00000000..60a4e99b --- /dev/null +++ b/hyperdbg/hyperevade/header/pch.h @@ -0,0 +1,105 @@ +/** + * @file pch.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers of Message logging and tracing + * @details + * @version 0.2 + * @date 2023-01-23 + * + * @copyright This project is released under the GNU Public License v3. + * + */ + +#pragma once + +#define _NO_CRT_STDIO_INLINE + +#pragma warning(disable : 4201) // Suppress nameless struct/union warning + +// +// Environment headers +// +#include "platform/general/header/Environment.h" + +#ifdef HYPERDBG_ENV_WINDOWS + +// +// Windows defined functions +// +# include +# include +# include + +#endif // HYPERDBG_ENV_WINDOWS + +// +// Scope definitions +// +#define HYPERDBG_KERNEL_MODE +#define HYPERDBG_HYPEREVADE + +// +// Macros +// +#include "macros/MetaMacros.h" + +// +// Definition of Intel primitives (External header) +// +#include "ia32-doc/out/ia32.h" + +// +// HyperDbg SDK headers +// +#include "SDK/HyperDbgSdk.h" + +// +// Configuration +// +#include "config/Configuration.h" + +// +// Hyperlog headers +// +#include "components/callback/header/HyperLogCallback.h" +#include "SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h" + +// +// Platform independent headers +// +#include "platform/kernel/header/PlatformMem.h" +#include "platform/kernel/header/PlatformIntrinsics.h" + +// +// Hyperevade Callbacks +// +#include "SDK/modules/HyperEvade.h" + +// +// Transparency and footprints headers +// +#include "Transparency.h" +#include "VmxFootprints.h" +#include "SyscallFootprints.h" + +// +// Optimization algorithms +// +#include "components/optimizations/header/AvlTree.h" +#include "components/optimizations/header/BinarySearch.h" +#include "components/optimizations/header/InsertionSort.h" + +// +// Spinlocks +// +#include "components/spinlock/header/Spinlock.h" + +// +// Hyper-V TLFS +// +#include "hyper-v/HypervTlfs.h" + +// +// Export functions +// +#include "SDK/imports/kernel/HyperDbgHyperEvade.h" diff --git a/hyperdbg/hyperevade/hyperevade.def b/hyperdbg/hyperevade/hyperevade.def new file mode 100644 index 00000000..ba7de297 --- /dev/null +++ b/hyperdbg/hyperevade/hyperevade.def @@ -0,0 +1,6 @@ +LIBRARY hyperevade + +EXPORTS + + DllInitialize PRIVATE + DllUnload PRIVATE \ No newline at end of file diff --git a/hyperdbg/hyperevade/hyperevade.vcxproj b/hyperdbg/hyperevade/hyperevade.vcxproj new file mode 100644 index 00000000..ea3a07dc --- /dev/null +++ b/hyperdbg/hyperevade/hyperevade.vcxproj @@ -0,0 +1,144 @@ + + + + + + + + debug + x64 + + + release + x64 + + + + {B226530A-14B1-40AC-B82E-D9057400E7EE} + {1bc93793-694f-48fe-9372-81e2b05556fd} + v4.5 + 12.0 + Debug + x64 + hyperevade + $(LatestTargetPlatformVersion) + + + + Windows10 + true + WindowsKernelModeDriver10.0 + DynamicLibrary + KMDF + Desktop + false + + + Windows10 + false + WindowsKernelModeDriver10.0 + DynamicLibrary + KMDF + Desktop + false + + + + + + + + + + + DbgengKernelDebugger + $(SolutionDir)build\bin\$(Configuration)\ + $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + false + + + DbgengKernelDebugger + $(SolutionDir)build\bin\$(Configuration)\ + $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + false + + + + sha256 + + + $(SolutionDir)\include;$(ProjectDir)header;$(SolutionDir)dependencies;%(AdditionalIncludeDirectories) + true + Create + pch.h + stdcpp20 + + + true + + true + hyperevade.def + + + + + sha256 + + + $(SolutionDir)\include;$(ProjectDir)header;$(SolutionDir)dependencies;%(AdditionalIncludeDirectories) + true + Create + pch.h + stdcpp20 + Full + + + true + + true + hyperevade.def + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + \ No newline at end of file diff --git a/hyperdbg/hyperevade/hyperevade.vcxproj.filters b/hyperdbg/hyperevade/hyperevade.vcxproj.filters new file mode 100644 index 00000000..f7ed48f3 --- /dev/null +++ b/hyperdbg/hyperevade/hyperevade.vcxproj.filters @@ -0,0 +1,105 @@ + + + + + {8E41214B-6785-4CFE-B992-037D68949A14} + inf;inv;inx;mof;mc; + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {1ab177b4-9e6c-460e-834a-8fced04b42a3} + + + {21f0281e-fc2a-4e13-97ac-e4b35a05a31e} + + + {890885f8-de8f-41df-9202-3ec320d7d816} + + + {a66d71db-112c-4826-8181-ba265d339149} + + + {da60b9fe-3816-4f3c-a6a9-21accd463156} + + + {0e801893-09df-4299-a572-6e63049d4f9f} + + + {78b7809e-ea12-450d-af96-8e658087628d} + + + {28025c67-f68b-437b-bcda-d23c9a752d42} + + + + + code + + + code + + + code\platform + + + code\components\spinlock + + + code\components\optimizations + + + code\components\optimizations + + + code\components\optimizations + + + code\components\optimizations + + + code + + + code + + + code\platform + + + code\components\callback + + + + + header + + + header + + + header\platform + + + header + + + header + + + header\platform + + + header\components\callback + + + + + + \ No newline at end of file diff --git a/hyperdbg/hyperevade/packages.config b/hyperdbg/hyperevade/packages.config new file mode 100644 index 00000000..eb276766 --- /dev/null +++ b/hyperdbg/hyperevade/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/hyperdbg/hyperhv/CMakeLists.txt b/hyperdbg/hyperhv/CMakeLists.txt new file mode 100644 index 00000000..990c533c --- /dev/null +++ b/hyperdbg/hyperhv/CMakeLists.txt @@ -0,0 +1,169 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "../include/components/optimizations/code/AvlTree.c" + "../include/components/optimizations/code/BinarySearch.c" + "../include/components/optimizations/code/InsertionSort.c" + "../include/components/optimizations/code/OptimizationsExamples.c" + "../include/components/spinlock/code/Spinlock.c" + "../include/platform/kernel/code/PlatformMem.c" + "code/broadcast/Broadcast.c" + "code/broadcast/DpcRoutines.c" + "code/common/Bitwise.c" + "code/common/Common.c" + "code/common/UnloadDll.c" + "code/components/registers/DebugRegisters.c" + "code/devices/Apic.c" + "code/disassembler/Disassembler.c" + "code/disassembler/ZydisKernel.c" + "code/features/CompatibilityChecks.c" + "code/features/DirtyLogging.c" + "code/globals/GlobalVariableManagement.c" + "code/hooks/ept-hook/EptHook.c" + "code/hooks/ept-hook/ModeBasedExecHook.c" + "code/hooks/ept-hook/ExecTrap.c" + "code/hooks/syscall-hook/EferHook.c" + "code/hooks/syscall-hook/SsdtHook.c" + "code/interface/Callback.c" + "code/interface/Configuration.c" + "code/interface/DirectVmcall.c" + "code/interface/Dispatch.c" + "code/interface/Export.c" + "code/memory/AddressCheck.c" + "code/memory/Conversion.c" + "code/memory/Layout.c" + "code/memory/MemoryManager.c" + "code/memory/MemoryMapper.c" + "code/memory/PoolManager.c" + "code/memory/Segmentation.c" + "code/memory/SwitchLayout.c" + "code/transparency/Transparency.c" + "code/vmm/ept/Ept.c" + "code/vmm/ept/Invept.c" + "code/vmm/ept/Vpid.c" + "code/vmm/vmx/Counters.c" + "code/vmm/vmx/CrossVmexits.c" + "code/vmm/vmx/Events.c" + "code/vmm/vmx/Hv.c" + "code/vmm/vmx/IdtEmulation.c" + "code/vmm/vmx/IoHandler.c" + "code/vmm/vmx/ManageRegs.c" + "code/vmm/vmx/MsrHandlers.c" + "code/vmm/vmx/Mtf.c" + "code/vmm/vmx/ProtectedHv.c" + "code/vmm/vmx/Vmcall.c" + "code/vmm/vmx/Vmexit.c" + "code/vmm/vmx/Vmx.c" + "code/vmm/vmx/VmxBroadcast.c" + "code/vmm/vmx/VmxMechanisms.c" + "code/vmm/vmx/VmxRegions.c" + "code/assembly/AsmCommon.asm" + "code/assembly/AsmHooks.asm" + "code/assembly/AsmEpt.asm" + "code/assembly/AsmSegmentRegs.asm" + "code/assembly/AsmVmexitHandler.asm" + "code/assembly/AsmVmxContextState.asm" + "code/assembly/AsmVmxOperation.asm" + "code/assembly/AsmInterruptHandlers.asm" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Allocator.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/ArgParse.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Atomic.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Bitset.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Comparison.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Defines.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Format.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/LibC.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/List.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Object.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Status.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/String.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Types.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Vector.h" + "../dependencies/zydis/dependencies/zycore/include/Zycore/Zycore.h" + "../dependencies/zydis/include/Zydis/Decoder.h" + "../dependencies/zydis/include/Zydis/DecoderTypes.h" + "../dependencies/zydis/include/Zydis/Defines.h" + "../dependencies/zydis/include/Zydis/Disassembler.h" + "../dependencies/zydis/include/Zydis/Encoder.h" + "../dependencies/zydis/include/Zydis/Formatter.h" + "../dependencies/zydis/include/Zydis/FormatterBuffer.h" + "../dependencies/zydis/include/Zydis/MetaInfo.h" + "../dependencies/zydis/include/Zydis/Mnemonic.h" + "../dependencies/zydis/include/Zydis/Register.h" + "../dependencies/zydis/include/Zydis/Segment.h" + "../dependencies/zydis/include/Zydis/SharedTypes.h" + "../dependencies/zydis/include/Zydis/ShortString.h" + "../dependencies/zydis/include/Zydis/Status.h" + "../dependencies/zydis/include/Zydis/Utils.h" + "../dependencies/zydis/include/Zydis/Zydis.h" + "../include/components/optimizations/header/AvlTree.h" + "../include/components/optimizations/header/BinarySearch.h" + "../include/components/optimizations/header/InsertionSort.h" + "../include/components/optimizations/header/OptimizationsExamples.h" + "../include/components/spinlock/header/Spinlock.h" + "../include/macros/MetaMacros.h" + "../include/platform/kernel/header/Environment.h" + "../include/platform/kernel/header/PlatformMem.h" + "header/assembly/InlineAsm.h" + "header/broadcast/Broadcast.h" + "header/broadcast/DpcRoutines.h" + "header/common/Bitwise.h" + "header/common/Common.h" + "header/common/Dpc.h" + "header/common/Msr.h" + "header/common/State.h" + "header/common/Trace.h" + "header/common/UnloadDll.h" + "header/devices/Apic.h" + "header/disassembler/Disassembler.h" + "header/features/CompatibilityChecks.h" + "header/features/DirtyLogging.h" + "header/globals/GlobalVariableManagement.h" + "header/globals/GlobalVariables.h" + "header/hooks/Hooks.h" + "header/hooks/ModeBasedExecHook.h" + "header/hooks/ExecTrap.h" + "header/interface/Callback.h" + "header/interface/DirectVmcall.h" + "header/interface/Dispatch.h" + "header/memory/AddressCheck.h" + "header/memory/Conversion.h" + "header/memory/Layout.h" + "header/memory/MemoryMapper.h" + "header/memory/PoolManager.h" + "header/memory/Segmentation.h" + "header/memory/SwitchLayout.h" + "header/transparency/Transparency.h" + "header/vmm/ept/Ept.h" + "header/vmm/ept/Invept.h" + "header/vmm/ept/Vpid.h" + "header/vmm/vmx/Counters.h" + "header/vmm/vmx/Events.h" + "header/vmm/vmx/Hv.h" + "header/vmm/vmx/HypervTlfs.h" + "header/vmm/vmx/IdtEmulation.h" + "header/vmm/vmx/IoHandler.h" + "header/vmm/vmx/MsrHandlers.h" + "header/vmm/vmx/Mtf.h" + "header/vmm/vmx/ProtectedHv.h" + "header/vmm/vmx/Vmcall.h" + "header/vmm/vmx/Vmx.h" + "header/vmm/vmx/VmxBroadcast.h" + "header/vmm/vmx/VmxMechanisms.h" + "header/vmm/vmx/VmxRegions.h" + "pch.h" + "hyperhv.def" +) +include_directories( + "../include" + "header" + "code" + "." + "../dependencies" + "../script-eval" + "../dependencies/zydis/include" + "../dependencies/zydis/dependencies/zycore/include" +) +wdk_add_library(hyperhv SHARED + KMDF 1.15 + ${SourceFiles} +) diff --git a/hyperdbg/hprdbghv/code/assembly/AsmCommon.asm b/hyperdbg/hyperhv/code/assembly/AsmCommon.asm similarity index 80% rename from hyperdbg/hprdbghv/code/assembly/AsmCommon.asm rename to hyperdbg/hyperhv/code/assembly/AsmCommon.asm index 58b0b711..785e8047 100644 --- a/hyperdbg/hprdbghv/code/assembly/AsmCommon.asm +++ b/hyperdbg/hyperhv/code/assembly/AsmCommon.asm @@ -68,4 +68,18 @@ AsmReloadIdtr ENDP ;------------------------------------------------------------------------ +; AsmReadSsp ( ); + +AsmReadSsp PROC + + ; Save the current SSP to a memory location + rdsspq rax ; Save SSP to memory at the current location (stack pointer) + + ; Return from the function + ret + +AsmReadSsp ENDP + +;------------------------------------------------------------------------ + END \ No newline at end of file diff --git a/hyperdbg/hprdbghv/code/assembly/AsmEpt.asm b/hyperdbg/hyperhv/code/assembly/AsmEpt.asm similarity index 100% rename from hyperdbg/hprdbghv/code/assembly/AsmEpt.asm rename to hyperdbg/hyperhv/code/assembly/AsmEpt.asm diff --git a/hyperdbg/hprdbghv/code/assembly/AsmHooks.asm b/hyperdbg/hyperhv/code/assembly/AsmHooks.asm similarity index 100% rename from hyperdbg/hprdbghv/code/assembly/AsmHooks.asm rename to hyperdbg/hyperhv/code/assembly/AsmHooks.asm diff --git a/hyperdbg/hyperhv/code/assembly/AsmInterruptHandlers.asm b/hyperdbg/hyperhv/code/assembly/AsmInterruptHandlers.asm new file mode 100644 index 00000000..de1cee3c --- /dev/null +++ b/hyperdbg/hyperhv/code/assembly/AsmInterruptHandlers.asm @@ -0,0 +1,153 @@ +; This file was copied and modified from: https://github.com/jonomango/hv/blob/main/hv/interrupt-handlers.asm + +EXTERN IdtEmulationhandleHostInterrupt:PROC + +.code _text + +;------------------------------------------------------------------------ + +; defined in IdtEmulation.h +trap_frame struct + ; general-purpose registers + $rax qword ? + $rcx qword ? + $rdx qword ? + $rbx qword ? + $rbp qword ? + $rsi qword ? + $rdi qword ? + $r8 qword ? + $r9 qword ? + $r10 qword ? + $r11 qword ? + $r12 qword ? + $r13 qword ? + $r14 qword ? + $r15 qword ? + + ; interrupt vector + $vector qword ? + + ; _MACHINE_FRAME + $error qword ? + $rip qword ? + $cs qword ? + $rflags qword ? + $rsp qword ? + $ss qword ? +trap_frame ends + +;------------------------------------------------------------------------ + +; the generic interrupt handler that every stub will eventually jump to +GenericInterruptHandler proc + ; allocate space for the trap_frame structure (minus the size of the + ; _MACHINE_FRAME, error code, and interrupt vector) + sub rsp, 78h + + ; general-purpose registers + mov trap_frame.$rax[rsp], rax + mov trap_frame.$rcx[rsp], rcx + mov trap_frame.$rdx[rsp], rdx + mov trap_frame.$rbx[rsp], rbx + mov trap_frame.$rbp[rsp], rbp + mov trap_frame.$rsi[rsp], rsi + mov trap_frame.$rdi[rsp], rdi + mov trap_frame.$r8[rsp], r8 + mov trap_frame.$r9[rsp], r9 + mov trap_frame.$r10[rsp], r10 + mov trap_frame.$r11[rsp], r11 + mov trap_frame.$r12[rsp], r12 + mov trap_frame.$r13[rsp], r13 + mov trap_frame.$r14[rsp], r14 + mov trap_frame.$r15[rsp], r15 + + ; first argument is the trap frame + mov rcx, rsp + + ; call IdtEmulationhandleHostInterrupt + sub rsp, 20h + call IdtEmulationhandleHostInterrupt + add rsp, 20h + + ; general-purpose registers + mov rax, trap_frame.$rax[rsp] + mov rcx, trap_frame.$rcx[rsp] + mov rdx, trap_frame.$rdx[rsp] + mov rbx, trap_frame.$rbx[rsp] + mov rbp, trap_frame.$rbp[rsp] + mov rsi, trap_frame.$rsi[rsp] + mov rdi, trap_frame.$rdi[rsp] + mov r8, trap_frame.$r8[rsp] + mov r9, trap_frame.$r9[rsp] + mov r10, trap_frame.$r10[rsp] + mov r11, trap_frame.$r11[rsp] + mov r12, trap_frame.$r12[rsp] + mov r13, trap_frame.$r13[rsp] + mov r14, trap_frame.$r14[rsp] + mov r15, trap_frame.$r15[rsp] + + ; free the trap_frame + add rsp, 78h + + ; pop the interrupt vector + add rsp, 8 + + ; pop the error code + add rsp, 8 + + iretq + +GenericInterruptHandler endp + +;------------------------------------------------------------------------ + +; pushes error code to stack +DEFINE_ISR macro InterruptVector:req, ProcName:req +ProcName proc + ; interrupt vector is stored right before the machine frame + push InterruptVector + + jmp GenericInterruptHandler +ProcName endp +endm + +; doesn't push error code to stack +DEFINE_ISR_NO_ERROR macro InterruptVector:req, ProcName:req +ProcName proc + ; push a dummy error code onto the stack + push 0 + + ; interrupt vector is stored right before the machine frame + push InterruptVector + + jmp GenericInterruptHandler +ProcName endp +endm + +;------------------------------------------------------------------------ + +DEFINE_ISR_NO_ERROR 0, InterruptHandler0 +DEFINE_ISR_NO_ERROR 1, InterruptHandler1 +DEFINE_ISR_NO_ERROR 2, InterruptHandler2 +DEFINE_ISR_NO_ERROR 3, InterruptHandler3 +DEFINE_ISR_NO_ERROR 4, InterruptHandler4 +DEFINE_ISR_NO_ERROR 5, InterruptHandler5 +DEFINE_ISR_NO_ERROR 6, InterruptHandler6 +DEFINE_ISR_NO_ERROR 7, InterruptHandler7 +DEFINE_ISR 8, InterruptHandler8 +DEFINE_ISR 10, InterruptHandler10 +DEFINE_ISR 11, InterruptHandler11 +DEFINE_ISR 12, InterruptHandler12 +DEFINE_ISR 13, InterruptHandler13 +DEFINE_ISR 14, InterruptHandler14 +DEFINE_ISR_NO_ERROR 16, InterruptHandler16 +DEFINE_ISR 17, InterruptHandler17 +DEFINE_ISR_NO_ERROR 18, InterruptHandler18 +DEFINE_ISR_NO_ERROR 19, InterruptHandler19 +DEFINE_ISR_NO_ERROR 20, InterruptHandler20 +DEFINE_ISR 30, InterruptHandler30 + +;------------------------------------------------------------------------ + +end \ No newline at end of file diff --git a/hyperdbg/hprdbghv/code/assembly/AsmSegmentRegs.asm b/hyperdbg/hyperhv/code/assembly/AsmSegmentRegs.asm similarity index 77% rename from hyperdbg/hprdbghv/code/assembly/AsmSegmentRegs.asm rename to hyperdbg/hyperhv/code/assembly/AsmSegmentRegs.asm index a61eaf4c..cb1c7f11 100644 --- a/hyperdbg/hprdbghv/code/assembly/AsmSegmentRegs.asm +++ b/hyperdbg/hyperhv/code/assembly/AsmSegmentRegs.asm @@ -1,8 +1,12 @@ PUBLIC AsmGetCs PUBLIC AsmGetDs +PUBLIC AsmSetDs PUBLIC AsmGetEs +PUBLIC AsmSetEs PUBLIC AsmGetSs +PUBLIC AsmSetSs PUBLIC AsmGetFs +PUBLIC AsmSetFs PUBLIC AsmGetGs PUBLIC AsmGetLdtr PUBLIC AsmGetTr @@ -44,6 +48,16 @@ AsmGetDs ENDP ;------------------------------------------------------------------------ +AsmSetDs PROC + + mov rax, rcx + mov ds, rax + ret + +AsmSetDs ENDP + +;------------------------------------------------------------------------ + AsmGetEs PROC mov rax, es @@ -53,6 +67,16 @@ AsmGetEs ENDP ;------------------------------------------------------------------------ +AsmSetEs PROC + + mov rax, rcx + mov es, rax + ret + +AsmSetEs ENDP + +;------------------------------------------------------------------------ + AsmGetSs PROC mov rax, ss @@ -62,6 +86,16 @@ AsmGetSs ENDP ;------------------------------------------------------------------------ +AsmSetSs PROC + + mov rax, rcx + mov ss, rax + ret + +AsmSetSs ENDP + +;------------------------------------------------------------------------ + AsmGetFs PROC mov rax, fs @@ -71,6 +105,16 @@ AsmGetFs ENDP ;------------------------------------------------------------------------ +AsmSetFs PROC + + mov rax, rcx + mov fs, rax + ret + +AsmSetFs ENDP + +;------------------------------------------------------------------------ + AsmGetGs PROC mov rax, gs diff --git a/hyperdbg/hyperhv/code/assembly/AsmVmexitHandler.asm b/hyperdbg/hyperhv/code/assembly/AsmVmexitHandler.asm new file mode 100644 index 00000000..54476abd --- /dev/null +++ b/hyperdbg/hyperhv/code/assembly/AsmVmexitHandler.asm @@ -0,0 +1,244 @@ +PUBLIC AsmVmexitHandler +PUBLIC AsmVmxoffRestoreXmmRegs + +EXTERN VmxVmexitHandler:PROC +EXTERN VmxPerformVmresume:PROC +EXTERN VmxReturnStackPointerForVmxoff:PROC +EXTERN VmxReturnInstructionPointerForVmxoff:PROC + +.code _text + +;------------------------------------------------------------------------ + +AsmVmexitHandler PROC + + push 0 ; we might be in an unaligned stack state, so the memory before stack might cause + ; irql less or equal as it doesn't exist, so we just put some extra space avoid + ; these kind of errors + + ; --------------- Save RFLAGS ---------------- + + pushfq ; Save the flags register (RFLAGS) + + ; ------------ Save XMM Registers ------------ + + ; 16 Byte * 16 Byte = 256 + 4 = 260 (0x104 == 0x110 but let's align it to have better performance) + + sub rsp, 0110h + + movaps xmmword ptr [rsp+000h], xmm0 ; each xmm register 128 bit (16 Byte) + movaps xmmword ptr [rsp+010h], xmm1 + movaps xmmword ptr [rsp+020h], xmm2 + movaps xmmword ptr [rsp+030h], xmm3 + movaps xmmword ptr [rsp+040h], xmm4 + movaps xmmword ptr [rsp+050h], xmm5 + + ; + ; As per Microsoft ABI documentation, the following registers are nonvolatile + ; So, MSVC compiler will save them on the stack if they are used in the function + ; Thus, for the sake of performance, we comment them out + ; + ; movaps xmmword ptr [rsp+060h], xmm6 + ; movaps xmmword ptr [rsp+070h], xmm7 + ; movaps xmmword ptr [rsp+080h], xmm8 + ; movaps xmmword ptr [rsp+090h], xmm9 + ; movaps xmmword ptr [rsp+0a0h], xmm10 + ; movaps xmmword ptr [rsp+0b0h], xmm11 + ; movaps xmmword ptr [rsp+0c0h], xmm12 + ; movaps xmmword ptr [rsp+0d0h], xmm13 + ; movaps xmmword ptr [rsp+0e0h], xmm14 + ; movaps xmmword ptr [rsp+0f0h], xmm15 + + stmxcsr dword ptr [rsp+0100h] ; MxCsr is 4 Byte + + ; ------ Save General-purpose Registers ------ + + push r15 + push r14 + push r13 + push r12 + push r11 + push r10 + push r9 + push r8 + push rdi + push rsi + push rbp + push rbp ; rsp + push rbx + push rdx + push rcx + push rax + + ; ----------- Call VM-exit Handler ----------- + + mov rcx, rsp ; Fast call argument to PGUEST_REGS + + sub rsp, 020h ; Free some space for Shadow Section + call VmxVmexitHandler + add rsp, 020h ; Restore the state + + cmp al, 1 ; Check whether we have to turn off VMX or Not (the result is in RAX) + + je AsmVmxoffHandler + + ; ----------- Restore XMM Registers ---------- + +RestoreState: + + pop rax + pop rcx + pop rdx + pop rbx + pop rbp ; rsp + pop rbp + pop rsi + pop rdi + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 + + ; ------------ Restore XMM Registers ------------ + + movaps xmm0, xmmword ptr [rsp+000h] + movaps xmm1, xmmword ptr [rsp+010h] + movaps xmm2, xmmword ptr [rsp+020h] + movaps xmm3, xmmword ptr [rsp+030h] + movaps xmm4, xmmword ptr [rsp+040h] + movaps xmm5, xmmword ptr [rsp+050h] + + ; + ; As per Microsoft ABI documentation, the following registers are nonvolatile + ; So, MSVC compiler will save them on the stack if they are used in the function + ; Thus, for the sake of performance, we comment them out + ; + ; movaps xmm6, xmmword ptr [rsp+060h] + ; movaps xmm7, xmmword ptr [rsp+070h] + ; movaps xmm8, xmmword ptr [rsp+080h] + ; movaps xmm9, xmmword ptr [rsp+090h] + ; movaps xmm10, xmmword ptr [rsp+0a0h] + ; movaps xmm11, xmmword ptr [rsp+0b0h] + ; movaps xmm12, xmmword ptr [rsp+0c0h] + ; movaps xmm13, xmmword ptr [rsp+0d0h] + ; movaps xmm14, xmmword ptr [rsp+0e0h] + ; movaps xmm15, xmmword ptr [rsp+0f0h] + + ldmxcsr dword ptr [rsp+0100h] + + add rsp, 0110h + + ; --------------- Restore RFLAGS --------------- + + popfq ; Restore the flags register (RFLAGS) + + ; ---------------------------------------------- + + jmp VmxPerformVmresume + +AsmVmexitHandler ENDP + +;------------------------------------------------------------------------ + +AsmVmxoffRestoreXmmRegs PROC + + ; ------------ Restore XMM Registers ------------ + + movaps xmm0, xmmword ptr [rcx+000h] + movaps xmm1, xmmword ptr [rcx+010h] + movaps xmm2, xmmword ptr [rcx+020h] + movaps xmm3, xmmword ptr [rcx+030h] + movaps xmm4, xmmword ptr [rcx+040h] + movaps xmm5, xmmword ptr [rcx+050h] + + ; + ; As per Microsoft ABI documentation, the following registers are nonvolatile + ; So, MSVC compiler will save them on the stack if they are used in the function + ; Thus, for the sake of performance, we comment them out + ; + ; movaps xmm6, xmmword ptr [rcx+060h] + ; movaps xmm7, xmmword ptr [rcx+070h] + ; movaps xmm8, xmmword ptr [rcx+080h] + ; movaps xmm9, xmmword ptr [rcx+090h] + ; movaps xmm10, xmmword ptr [rcx+0a0h] + ; movaps xmm11, xmmword ptr [rcx+0b0h] + ; movaps xmm12, xmmword ptr [rcx+0c0h] + ; movaps xmm13, xmmword ptr [rcx+0d0h] + ; movaps xmm14, xmmword ptr [rcx+0e0h] + ; movaps xmm15, xmmword ptr [rcx+0f0h] + + ldmxcsr dword ptr [rcx+0100h] + + ret + +AsmVmxoffRestoreXmmRegs ENDP + +;------------------------------------------------------------------------ + +AsmVmxoffHandler PROC + + ; ------ Restore General-purpose Registers ------ + +RestoreState: + + pop rax + pop rcx + pop rdx + pop rbx + pop rbp ; rsp + pop rbp + pop rsi + pop rdi + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 + + ; ------------- Pass over XMM Regs ------------- + + ; XMM registers are restored by AsmVmxoffRestoreXmmRegs + ; Size of XMM registers are 110 bytes but we also remove the RFLAGS register (+8) + ; so we have 118 bytes to remove from the stack + add rsp, 0118h + + ; ------------ Get Stack Pointer --------------- + + sub rsp, 020h ; shadow space + call VmxReturnStackPointerForVmxoff + add rsp, 020h ; remove for shadow space + + push rax ; save the current rsp, we will restore it later + + + ; ------------ Get Instruction Pointer --------- + + sub rsp, 020h ; shadow space + call VmxReturnInstructionPointerForVmxoff + add rsp, 020h ; remove for shadow space + + pop rsp ; restore rsp + push rax ; push the instruction pointer + + ; ---------------------------------------------- + + ; There might be some registers that are modified by above CALLs, + ; but here we do not care about them since we are also in a function, + ; so the caller do not expect us to preserve these volatile registers + + xor rax, rax ; clear RAX to indicate VMXOFF was successful (VMCALL Status) + + ret ; jump back to where we called Vmcall + +AsmVmxoffHandler ENDP + +;------------------------------------------------------------------------ + +END diff --git a/hyperdbg/hprdbghv/code/assembly/AsmVmxContextState.asm b/hyperdbg/hyperhv/code/assembly/AsmVmxContextState.asm similarity index 100% rename from hyperdbg/hprdbghv/code/assembly/AsmVmxContextState.asm rename to hyperdbg/hyperhv/code/assembly/AsmVmxContextState.asm diff --git a/hyperdbg/hprdbghv/code/assembly/AsmVmxOperation.asm b/hyperdbg/hyperhv/code/assembly/AsmVmxOperation.asm similarity index 100% rename from hyperdbg/hprdbghv/code/assembly/AsmVmxOperation.asm rename to hyperdbg/hyperhv/code/assembly/AsmVmxOperation.asm diff --git a/hyperdbg/hprdbghv/code/broadcast/Broadcast.c b/hyperdbg/hyperhv/code/broadcast/Broadcast.c similarity index 100% rename from hyperdbg/hprdbghv/code/broadcast/Broadcast.c rename to hyperdbg/hyperhv/code/broadcast/Broadcast.c diff --git a/hyperdbg/hprdbghv/code/broadcast/DpcRoutines.c b/hyperdbg/hyperhv/code/broadcast/DpcRoutines.c similarity index 78% rename from hyperdbg/hprdbghv/code/broadcast/DpcRoutines.c rename to hyperdbg/hyperhv/code/broadcast/DpcRoutines.c index 984ec8b9..0f1e491d 100644 --- a/hyperdbg/hprdbghv/code/broadcast/DpcRoutines.c +++ b/hyperdbg/hyperhv/code/broadcast/DpcRoutines.c @@ -50,7 +50,7 @@ DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredCo // // Allocate Memory for DPC // - Dpc = CrsAllocateNonPagedPool(sizeof(KDPC)); + Dpc = PlatformMemAllocateNonPagedPool(sizeof(KDPC)); if (!Dpc) { @@ -91,7 +91,7 @@ DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredCo // // We can't get the lock, probably sth goes wrong ! // - CrsFreePool(Dpc); + PlatformMemFreePool(Dpc); return STATUS_UNSUCCESSFUL; } @@ -110,7 +110,7 @@ DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredCo // // Now it's safe to deallocate the bugger // - CrsFreePool(Dpc); + PlatformMemFreePool(Dpc); return STATUS_SUCCESS; } @@ -135,15 +135,10 @@ DpcRoutinePerformVirtualization(KDPC * Dpc, PVOID DeferredContext, PVOID SystemA // VmxPerformVirtualizationOnSpecificCore(); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); return TRUE; } @@ -454,15 +449,10 @@ DpcRoutineEnableMovToCr3Exiting(KDPC * Dpc, PVOID DeferredContext, PVOID SystemA // AsmVmxVmcall(VMCALL_ENABLE_MOV_TO_CR3_EXITING, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -485,15 +475,10 @@ DpcRoutineChangeToMbecSupportedEptp(KDPC * Dpc, PVOID DeferredContext, PVOID Sys // AsmVmxVmcall(VMCALL_CHANGE_TO_MBEC_SUPPORTED_EPTP, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -516,15 +501,10 @@ DpcRoutineRestoreToNormalEptp(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArg // AsmVmxVmcall(VMCALL_RESTORE_TO_NORMAL_EPTP, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -547,15 +527,10 @@ DpcRoutineEnableOrDisableMbec(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArg // AsmVmxVmcall(VMCALL_DISABLE_OR_ENABLE_MBEC, (UINT64)DeferredContext, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -578,15 +553,10 @@ DpcRoutineDisableMovToCr3Exiting(KDPC * Dpc, PVOID DeferredContext, PVOID System // AsmVmxVmcall(VMCALL_DISABLE_MOV_TO_CR3_EXITING, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -609,15 +579,10 @@ DpcRoutineEnableEferSyscallEvents(KDPC * Dpc, PVOID DeferredContext, PVOID Syste // AsmVmxVmcall(VMCALL_ENABLE_SYSCALL_HOOK_EFER, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -640,15 +605,10 @@ DpcRoutineDisableEferSyscallEvents(KDPC * Dpc, PVOID DeferredContext, PVOID Syst // AsmVmxVmcall(VMCALL_DISABLE_SYSCALL_HOOK_EFER, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -671,15 +631,10 @@ DpcRoutineEnablePml(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PV // AsmVmxVmcall(VMCALL_ENABLE_DIRTY_LOGGING_MECHANISM, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -702,15 +657,10 @@ DpcRoutineDisablePml(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, P // AsmVmxVmcall(VMCALL_DISABLE_DIRTY_LOGGING_MECHANISM, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -732,15 +682,10 @@ DpcRoutineChangeMsrBitmapReadOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID // AsmVmxVmcall(VMCALL_CHANGE_MSR_BITMAP_READ, (UINT64)DeferredContext, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -763,15 +708,10 @@ DpcRoutineResetMsrBitmapReadOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID // AsmVmxVmcall(VMCALL_RESET_MSR_BITMAP_READ, NULL64_ZERO, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -793,15 +733,10 @@ DpcRoutineChangeMsrBitmapWriteOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOI // AsmVmxVmcall(VMCALL_CHANGE_MSR_BITMAP_WRITE, (UINT64)DeferredContext, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -824,15 +759,10 @@ DpcRoutineResetMsrBitmapWriteOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID // AsmVmxVmcall(VMCALL_RESET_MSR_BITMAP_WRITE, NULL64_ZERO, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -855,15 +785,10 @@ DpcRoutineEnableRdtscExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID Sy // AsmVmxVmcall(VMCALL_SET_RDTSC_EXITING, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -886,15 +811,10 @@ DpcRoutineDisableRdtscExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID S // AsmVmxVmcall(VMCALL_UNSET_RDTSC_EXITING, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -919,15 +839,10 @@ DpcRoutineDisableRdtscExitingForClearingTscEventsAllCores(KDPC * Dpc, PVOID Defe // AsmVmxVmcall(VMCALL_DISABLE_RDTSC_EXITING_ONLY_FOR_TSC_EVENTS, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -951,15 +866,10 @@ DpcRoutineDisableMov2DrExitingForClearingDrEventsAllCores(KDPC * Dpc, PVOID Defe // AsmVmxVmcall(VMCALL_DISABLE_MOV_TO_HW_DR_EXITING_ONLY_FOR_DR_EVENTS, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -982,15 +892,10 @@ DpcRoutineDisableMov2CrExitingForClearingCrEventsAllCores(KDPC * Dpc, DEBUGGER_E // AsmVmxVmcall(VMCALL_DISABLE_MOV_TO_CR_EXITING_ONLY_FOR_CR_EVENTS, EventOptions->OptionalParam1, EventOptions->OptionalParam2, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1013,15 +918,10 @@ DpcRoutineEnableRdpmcExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID Sy // AsmVmxVmcall(VMCALL_SET_RDPMC_EXITING, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1044,15 +944,10 @@ DpcRoutineDisableRdpmcExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID S // AsmVmxVmcall(VMCALL_UNSET_RDPMC_EXITING, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1074,15 +969,10 @@ DpcRoutineSetExceptionBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID // AsmVmxVmcall(VMCALL_SET_EXCEPTION_BITMAP, (UINT64)DeferredContext, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1104,15 +994,10 @@ DpcRoutineUnsetExceptionBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOI // AsmVmxVmcall(VMCALL_UNSET_EXCEPTION_BITMAP, (UINT64)DeferredContext, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1139,15 +1024,10 @@ DpcRoutineResetExceptionBitmapOnlyOnClearingExceptionEventsOnAllCores(KDPC * Dpc // AsmVmxVmcall(VMCALL_RESET_EXCEPTION_BITMAP_ONLY_ON_CLEARING_EXCEPTION_EVENTS, NULL64_ZERO, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1170,15 +1050,10 @@ DpcRoutineEnableMovDebigRegisterExitingAllCores(KDPC * Dpc, PVOID DeferredContex // AsmVmxVmcall(VMCALL_ENABLE_MOV_TO_DEBUG_REGS_EXITING, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1200,15 +1075,10 @@ DpcRoutineEnableMovControlRegisterExitingAllCores(KDPC * Dpc, DEBUGGER_EVENT_OPT // AsmVmxVmcall(VMCALL_ENABLE_MOV_TO_CONTROL_REGS_EXITING, EventOptions->OptionalParam1, EventOptions->OptionalParam2, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1230,15 +1100,10 @@ DpcRoutineDisableMovControlRegisterExitingAllCores(KDPC * Dpc, DEBUGGER_EVENT_OP // AsmVmxVmcall(VMCALL_DISABLE_MOV_TO_CONTROL_REGS_EXITING, EventOptions->OptionalParam1, EventOptions->OptionalParam2, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1261,15 +1126,10 @@ DpcRoutineDisableMovDebigRegisterExitingAllCores(KDPC * Dpc, PVOID DeferredConte // AsmVmxVmcall(VMCALL_DISABLE_MOV_TO_DEBUG_REGS_EXITING, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1292,15 +1152,10 @@ DpcRoutineSetEnableExternalInterruptExitingOnAllCores(KDPC * Dpc, PVOID Deferred // AsmVmxVmcall(VMCALL_ENABLE_EXTERNAL_INTERRUPT_EXITING, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1326,15 +1181,10 @@ DpcRoutineSetDisableExternalInterruptExitingOnlyOnClearingInterruptEventsOnAllCo // AsmVmxVmcall(VMCALL_DISABLE_EXTERNAL_INTERRUPT_EXITING_ONLY_TO_CLEAR_INTERRUPT_COMMANDS, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1356,15 +1206,10 @@ DpcRoutineChangeIoBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID Syst // AsmVmxVmcall(VMCALL_CHANGE_IO_BITMAP, (UINT64)DeferredContext, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1387,15 +1232,10 @@ DpcRoutineResetIoBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID Syste // AsmVmxVmcall(VMCALL_RESET_IO_BITMAP, NULL64_ZERO, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1418,15 +1258,10 @@ DpcRoutineEnableBreakpointOnExceptionBitmapOnAllCores(KDPC * Dpc, PVOID Deferred // AsmVmxVmcall(VMCALL_SET_EXCEPTION_BITMAP, EXCEPTION_VECTOR_BREAKPOINT, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1449,15 +1284,10 @@ DpcRoutineDisableBreakpointOnExceptionBitmapOnAllCores(KDPC * Dpc, PVOID Deferre // AsmVmxVmcall(VMCALL_UNSET_EXCEPTION_BITMAP, EXCEPTION_VECTOR_BREAKPOINT, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1480,15 +1310,10 @@ DpcRoutineEnableNmiVmexitOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID Sys // AsmVmxVmcall(VMCALL_SET_VM_EXIT_ON_NMIS, NULL64_ZERO, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1511,15 +1336,10 @@ DpcRoutineDisableNmiVmexitOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID Sy // AsmVmxVmcall(VMCALL_UNSET_VM_EXIT_ON_NMIS, NULL64_ZERO, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1547,15 +1367,10 @@ DpcRoutineEnableDbAndBpExitingOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOI // AsmVmxVmcall(VMCALL_SET_EXCEPTION_BITMAP, EXCEPTION_VECTOR_DEBUG_BREAKPOINT, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1583,15 +1398,10 @@ DpcRoutineDisableDbAndBpExitingOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVO // AsmVmxVmcall(VMCALL_UNSET_EXCEPTION_BITMAP, EXCEPTION_VECTOR_DEBUG_BREAKPOINT, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1614,15 +1424,10 @@ DpcRoutineRemoveHookAndInvalidateAllEntriesOnAllCores(KDPC * Dpc, PVOID Deferred // AsmVmxVmcall(VMCALL_UNHOOK_ALL_PAGES, NULL64_ZERO, NULL64_ZERO, NULL64_ZERO); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1647,15 +1452,10 @@ DpcRoutineRemoveHookAndInvalidateSingleEntryOnAllCores(KDPC * Dpc, PVOID Deferre // AsmVmxVmcall(VMCALL_UNHOOK_SINGLE_PAGE, UnhookingDetail->PhysicalAddress, UnhookingDetail->OriginalEntry, NULL64_ZERO); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1690,15 +1490,10 @@ DpcRoutineInvalidateEptOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID Syste NULL64_ZERO); } + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1721,15 +1516,10 @@ DpcRoutineInitializeGuest(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgumen // AsmVmxSaveState(); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -1755,13 +1545,8 @@ DpcRoutineTerminateGuest(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument LogError("Err, there were an error terminating vmx"); } + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } diff --git a/hyperdbg/hprdbghv/code/common/Bitwise.c b/hyperdbg/hyperhv/code/common/Bitwise.c similarity index 54% rename from hyperdbg/hprdbghv/code/common/Bitwise.c rename to hyperdbg/hyperhv/code/common/Bitwise.c index 1d0976a9..cb844856 100644 --- a/hyperdbg/hprdbghv/code/common/Bitwise.c +++ b/hyperdbg/hyperhv/code/common/Bitwise.c @@ -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)); } diff --git a/hyperdbg/hprdbghv/code/common/Common.c b/hyperdbg/hyperhv/code/common/Common.c similarity index 71% rename from hyperdbg/hprdbghv/code/common/Common.c rename to hyperdbg/hyperhv/code/common/Common.c index dba45cfb..9eac49d3 100644 --- a/hyperdbg/hprdbghv/code/common/Common.c +++ b/hyperdbg/hyperhv/code/common/Common.c @@ -61,30 +61,30 @@ 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) { - __cpuidex(CpuInfo, Func, SubFunc); + 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); } @@ -191,3 +191,62 @@ CommonWriteDebugInformation(VIRTUAL_MACHINE_STATE * VCpu) VCpu->Regs->r14, VCpu->Regs->r15); } + +/** + * @brief Check correctness of the XCR0 register value. + * @param XCr0 The XCR0 register value. + * + * @return BOOLEAN + */ +BOOLEAN +CommonIsXCr0Valid(XCR0 XCr0) +{ + CPUID_EAX_0D_ECX_00 XCr0CpuidInfo; + UINT64 UnsupportedXCr0Bits; + + // + // SDM Vol.3A 2.6 EXTENDED CONTROL REGISTERS (INCLUDING XCR0) - describes the invalid + // states of the XCR0 register. + // + + CommonCpuidInstruction(CPUID_EXTENDED_STATE_INFORMATION, 0, (INT32 *)&XCr0CpuidInfo); + UnsupportedXCr0Bits = ~(XCr0CpuidInfo.Eax.AsUInt | (UINT64)XCr0CpuidInfo.Edx.AsUInt << 32); + + if ((XCr0.AsUInt & UnsupportedXCr0Bits) != 0) + { + return FALSE; + } + + if (XCr0.X87 != 1) + { + return FALSE; + } + + if (XCr0.Sse == 0 && XCr0.Avx == 1) + { + return FALSE; + } + + if (XCr0.Avx == 0) + { + if ((XCr0.Opmask | XCr0.ZmmHi256 | XCr0.ZmmHi16) == 1) + { + return FALSE; + } + } + + if (XCr0.Bndcsr != XCr0.Bndreg) + { + return FALSE; + } + + if ((XCr0.Opmask | XCr0.ZmmHi256 | XCr0.ZmmHi16) == 1) + { + if ((XCr0.Opmask & XCr0.ZmmHi256 & XCr0.ZmmHi16) != 1) + { + return FALSE; + } + } + + return TRUE; +} diff --git a/hyperdbg/hprdbghv/code/common/UnloadDll.c b/hyperdbg/hyperhv/code/common/UnloadDll.c similarity index 100% rename from hyperdbg/hprdbghv/code/common/UnloadDll.c rename to hyperdbg/hyperhv/code/common/UnloadDll.c diff --git a/hyperdbg/hprdbghv/code/components/registers/DebugRegisters.c b/hyperdbg/hyperhv/code/components/registers/DebugRegisters.c similarity index 97% rename from hyperdbg/hprdbghv/code/components/registers/DebugRegisters.c rename to hyperdbg/hyperhv/code/components/registers/DebugRegisters.c index c12aacf5..85f7b45a 100644 --- a/hyperdbg/hprdbghv/code/components/registers/DebugRegisters.c +++ b/hyperdbg/hyperhv/code/components/registers/DebugRegisters.c @@ -1,4 +1,4 @@ -/** +/** * @file DebugRegisters.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief Implementation of debug registers functions @@ -77,7 +77,7 @@ SetDebugRegisters(UINT32 DebugRegNum, DEBUG_REGISTER_TYPE ActionType, BOOLEAN Ap // if (DebugRegNum == 0) { - __writedr(0, TargetAddress); + CpuWriteDr(0, TargetAddress); Dr7.GlobalBreakpoint0 = 1; @@ -119,7 +119,7 @@ SetDebugRegisters(UINT32 DebugRegNum, DEBUG_REGISTER_TYPE ActionType, BOOLEAN Ap } else if (DebugRegNum == 1) { - __writedr(1, TargetAddress); + CpuWriteDr(1, TargetAddress); Dr7.GlobalBreakpoint1 = 1; // @@ -160,7 +160,7 @@ SetDebugRegisters(UINT32 DebugRegNum, DEBUG_REGISTER_TYPE ActionType, BOOLEAN Ap } else if (DebugRegNum == 2) { - __writedr(2, TargetAddress); + CpuWriteDr(2, TargetAddress); Dr7.GlobalBreakpoint2 = 1; // @@ -201,7 +201,7 @@ SetDebugRegisters(UINT32 DebugRegNum, DEBUG_REGISTER_TYPE ActionType, BOOLEAN Ap } else if (DebugRegNum == 3) { - __writedr(3, TargetAddress); + CpuWriteDr(3, TargetAddress); Dr7.GlobalBreakpoint3 = 1; // @@ -248,11 +248,11 @@ SetDebugRegisters(UINT32 DebugRegNum, DEBUG_REGISTER_TYPE ActionType, BOOLEAN Ap // if (ApplyToVmcs) { - __vmx_vmwrite(VMCS_GUEST_DR7, Dr7.AsUInt); + HvSetDebugReg7(Dr7.AsUInt); } else { - __writedr(7, Dr7.AsUInt); + CpuWriteDr(7, Dr7.AsUInt); } return TRUE; diff --git a/hyperdbg/hyperhv/code/devices/Apic.c b/hyperdbg/hyperhv/code/devices/Apic.c new file mode 100644 index 00000000..c1cb2863 --- /dev/null +++ b/hyperdbg/hyperhv/code/devices/Apic.c @@ -0,0 +1,468 @@ +/** + * @file Apic.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Routines for Advanced Programmable Interrupt Controller (APIC) + * @details The code is derived from (https://www.cpl0.com/blog/?p=46) and the code + * for showing the APIC details in the XAPIC is derived from bitdefender/napoca project + * which is enhanced to support X2APIC mode in HyperDbg + * + * @version 0.1 + * @date 2020-12-31 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Perform read I/O APIC + * + * @param IoApicBaseVa + * @param Reg + * + * @return UINT64 + */ +UINT64 +IoApicRead(volatile IO_APIC_ENT * IoApicBaseVa, UINT32 Reg) +{ + UINT32 High = 0, Low; + + IoApicBaseVa->Reg = Reg; + Low = IoApicBaseVa->Data; + + if (Reg >= IOAPIC_REDTBL(0) && Reg < IOAPIC_REDTBL(IOAPIC_REDTBL_MAX)) + { + // ASSERT(Reg % 2 == 0); + Reg++; + IoApicBaseVa->Reg = Reg; + High = IoApicBaseVa->Data; + return IOAPIC_APPEND_QWORD(High, Low); + } + else + { + return Low; + } +} + +/** + * @brief Perform write to I/O APIC + * + * @param IoApicBaseVa + * @param Reg + * @param Data + * + * @return VOID + */ +VOID +IoApicWrite(volatile IO_APIC_ENT * IoApicBaseVa, UINT32 Reg, UINT64 Data) +{ + IoApicBaseVa->Reg = Reg; + IoApicBaseVa->Data = IOAPIC_LOW_DWORD(Data); + + if (Reg >= IOAPIC_REDTBL(0) && Reg < IOAPIC_REDTBL(IOAPIC_REDTBL_MAX)) + { + // ASSERT(Reg % 2 == 0); + Reg++; + IoApicBaseVa->Reg = Reg; + IoApicBaseVa->Data = IOAPIC_HIGH_DWORD(Data); + } +} + +/** + * @brief Dump I/O APIC + * @param IoApicPackets + * + * @return VOID + */ +VOID +ApicDumpIoApic(IO_APIC_ENTRY_PACKETS * IoApicPackets) +{ + UINT32 Index = 0; + UINT32 Max; + UINT64 Ll, Lh; + + UINT64 ApicBasePa = IO_APIC_DEFAULT_BASE_ADDR; + + Ll = IoApicRead(g_IoApicBase, IO_VERS_REGISTER), + + Max = (Ll >> 16) & 0xff; + + // Log("IoApic @ %08x ID:%x (%x) Arb:%x\n", + // ApicBasePa, + // IoApicRead(g_IoApicBase, IO_ID_REGISTER) >> 24, + // Ll & 0xFF, + // IoApicRead(g_IoApicBase, IO_ARB_ID_REGISTER)); + + // + // Fill the I/O APIC + // + IoApicPackets->ApicBasePa = (UINT32)ApicBasePa; + IoApicPackets->ApicBaseVa = (UINT64)g_IoApicBase; + IoApicPackets->IoIdReg = (UINT32)IoApicRead(g_IoApicBase, IO_ID_REGISTER); + IoApicPackets->IoLl = (UINT32)Ll; + IoApicPackets->IoArbIdReg = (UINT32)IoApicRead(g_IoApicBase, IO_ARB_ID_REGISTER); + + // + // Dump inti table + // + Max *= 2; + + for (Index = 0; Index <= Max; Index += 2) + { + if (Index >= MAX_NUMBER_OF_IO_APIC_ENTRIES) + { + // + // To prevent overflow of the target buffer + // + return; + } + + 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; + } +} + +/** + * @brief Trigger NMI on XAPIC + * @param Low + * @param High + * + * @return VOID + */ +VOID +XApicIcrWrite(UINT32 Low, UINT32 High) +{ + *(UINT32 *)((uintptr_t)g_ApicBase + ICROffset + 0x10) = High; + *(UINT32 *)((uintptr_t)g_ApicBase + ICROffset) = Low; +} + +/** + * @brief Trigger NMI on X2APIC + * @param Low + * @param High + * + * @return VOID + */ +VOID +X2ApicIcrWrite(UINT32 Low, UINT32 High) +{ + CpuWriteMsr(X2_MSR_BASE + TO_X2(ICROffset), ((UINT64)High << 32) | Low); +} + +/** + * @brief Read x2APIC mode + * @param Offset + * + * @return UINT64 + */ +UINT64 +X2ApicRead(UINT32 Offset) +{ + return CpuReadMsr(X2_MSR_BASE + TO_X2(Offset)); +} + +/** + * @brief Store the local APIC in XAPIC mode + * + * @return BOOLEAN + */ +BOOLEAN +ApicStoretLocalApicInXApicMode(PLAPIC_PAGE LApicBuffer) +{ + volatile LAPIC_PAGE * LocalApicVa = g_ApicBase; + + // + // Check if the base virtual address of local APIC is valid or not + // + if (!g_ApicBase) + { + return FALSE; + } + + // + // Store fields + // + LApicBuffer->Id = LocalApicVa->Id; + LApicBuffer->Version = LocalApicVa->Version; + LApicBuffer->SpuriousInterruptVector = LocalApicVa->SpuriousInterruptVector; + LApicBuffer->TPR = LocalApicVa->TPR; + LApicBuffer->ProcessorPriority = LocalApicVa->ProcessorPriority; + LApicBuffer->LogicalDestination = LocalApicVa->LogicalDestination; + LApicBuffer->ErrorStatus = LocalApicVa->ErrorStatus; + LApicBuffer->LvtLINT0 = LocalApicVa->LvtLINT0; + LApicBuffer->LvtLINT1 = LocalApicVa->LvtLINT1; + LApicBuffer->LvtCmci = LocalApicVa->LvtCmci; + LApicBuffer->LvtPerfMonCounters = LocalApicVa->LvtPerfMonCounters; + LApicBuffer->LvtTimer = LocalApicVa->LvtTimer; + LApicBuffer->LvtThermalSensor = LocalApicVa->LvtThermalSensor; + LApicBuffer->LvtError = LocalApicVa->LvtError; + LApicBuffer->InitialCount = LocalApicVa->InitialCount; + LApicBuffer->CurrentCount = LocalApicVa->CurrentCount; + LApicBuffer->DivideConfiguration = LocalApicVa->DivideConfiguration; + + // + // Save the ISR, TMR and IRR + // + for (UINT32 i = 0; i < 8; i++) + { + LApicBuffer->ISR[i * 4] = LocalApicVa->ISR[i * 4]; + } + + for (UINT32 i = 0; i < 8; i++) + { + LApicBuffer->TMR[i * 4] = LocalApicVa->TMR[i * 4]; + } + + for (UINT32 i = 0; i < 8; i++) + { + LApicBuffer->IRR[i * 4] = LocalApicVa->IRR[i * 4]; + } + + return TRUE; +} + +/** + * @brief Store the local APIC in X2APIC mode + * + * @return BOOLEAN + */ +BOOLEAN +ApicStoreLocalApicInX2ApicMode(PLAPIC_PAGE LApicBuffer) +{ + // + // Store fields + // + LApicBuffer->Id = (UINT32)X2ApicRead(APIC_ID); + LApicBuffer->Version = (UINT32)X2ApicRead(APIC_VERSION); + LApicBuffer->SpuriousInterruptVector = (UINT32)X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR); + LApicBuffer->TPR = (UINT32)X2ApicRead(APIC_TASK_PRIORITY); + LApicBuffer->ProcessorPriority = (UINT32)X2ApicRead(APIC_PROCESSOR_PRIORITY); + LApicBuffer->LogicalDestination = (UINT32)X2ApicRead(APIC_LOGICAL_DESTINATION); + LApicBuffer->ErrorStatus = (UINT32)X2ApicRead(APIC_ERROR_STATUS); + LApicBuffer->LvtLINT0 = (UINT32)X2ApicRead(APIC_LVT_LINT0); + LApicBuffer->LvtLINT1 = (UINT32)X2ApicRead(APIC_LVT_LINT1); + LApicBuffer->LvtCmci = (UINT32)X2ApicRead(APIC_LVT_CORRECTED_MACHINE_CHECK_INTERRUPT); + LApicBuffer->LvtPerfMonCounters = (UINT32)X2ApicRead(APIC_LVT_PERFORMANCE_MONITORING_COUNTERS); + LApicBuffer->LvtTimer = (UINT32)X2ApicRead(APIC_LVT_TIMER); + LApicBuffer->LvtThermalSensor = (UINT32)X2ApicRead(APIC_LVT_THERMAL_SENSOR); + LApicBuffer->LvtError = (UINT32)X2ApicRead(APIC_LVT_ERROR); + LApicBuffer->InitialCount = (UINT32)X2ApicRead(APIC_INITIAL_COUNT); + LApicBuffer->CurrentCount = (UINT32)X2ApicRead(APIC_CURRENT_COUNT); + LApicBuffer->DivideConfiguration = (UINT32)X2ApicRead(APIC_DIVIDE_CONFIGURATION); + + // + // Save the ISR, TMR and IRR + // + for (UINT32 i = 0; i < 8; i++) + { + LApicBuffer->ISR[i * 4] = (UINT32)X2ApicRead(APIC_IN_SERVICE_BITS_31_0 + (0x10 * i)); + } + + for (UINT32 i = 0; i < 8; i++) + { + LApicBuffer->TMR[i * 4] = (UINT32)X2ApicRead(APIC_TRIGGER_MODE_BITS_31_0 + (0x10 * i)); + } + + for (UINT32 i = 0; i < 8; i++) + { + LApicBuffer->IRR[i * 4] = (UINT32)X2ApicRead(APIC_INTERRUPT_REQUEST_BITS_31_0 + (0x10 * i)); + } + + return TRUE; +} + +/** + * @brief Trigger NMI on X2APIC or APIC based on Current system + * + * @return VOID + */ +VOID +ApicTriggerGenericNmi() +{ + if (g_CompatibilityCheck.IsX2Apic) + { + X2ApicIcrWrite((4 << 8) | (1 << 14) | (3 << 18), 0); + } + else + { + XApicIcrWrite((4 << 8) | (1 << 14) | (3 << 18), 0); + } +} + +/** + * @brief Trigger NMI on X2APIC or APIC based on Current system + * + * @return VOID + */ +VOID +ApicTriggerGenericSmi() +{ + LogInfo("Generating SMIs"); + if (g_CompatibilityCheck.IsX2Apic) + { + // X2ApicIcrWrite((4 << 8) | (1 << 14) | (3 << 18), 0); + X2ApicIcrWrite((2 << 8) | (1 << 14) | (3 << 18), 0); + } + else + { + // XApicIcrWrite((4 << 8) | (1 << 14) | (3 << 18), 0); + XApicIcrWrite((2 << 8) | (1 << 14) | (3 << 18), 0); + } +} + +/** + * @brief Store the details of APIC in xAPIC and x2APIC mode + * @param LApicBuffer + * @param IsUsingX2APIC + * + * @return BOOLEAN + */ +BOOLEAN +ApicStoreLocalApicFields(PLAPIC_PAGE LApicBuffer, PBOOLEAN IsUsingX2APIC) +{ + if (g_CompatibilityCheck.IsX2Apic) + { + *IsUsingX2APIC = TRUE; + return ApicStoreLocalApicInX2ApicMode(LApicBuffer); + } + else + { + *IsUsingX2APIC = FALSE; + return ApicStoretLocalApicInXApicMode(LApicBuffer); + } +} + +/** + * @brief Store the details of I/O APIC + * @param IoApicPackets + * + * @return BOOLEAN + */ +BOOLEAN +ApicStoreIoApicFields(IO_APIC_ENTRY_PACKETS * IoApicPackets) +{ + // + // Dump I/O APIC Entries + // Note that I/O APIC is not accessed through MSRs (e.g., X2APIC) + // So, it's all about the physical memory + // + ApicDumpIoApic(IoApicPackets); + + // + // There is not error defined for it at the moment + // + return TRUE; +} + +/** + * @brief Initialize APIC + * + * @return BOOLEAN + */ +BOOLEAN +ApicInitialize() +{ + UINT64 ApicBaseMSR; + PHYSICAL_ADDRESS PaApicBase; + PHYSICAL_ADDRESS PaIoApicBase; + + ApicBaseMSR = CpuReadMsr(IA32_APIC_BASE); + + if (!(ApicBaseMSR & (1 << 11))) + { + return FALSE; + } + + // + // Map I/O APIC default base address + // + // The exact APIC base address should be read from MADT table (ACPI) + // However, we don't have an ACPI parser right now, but the address + // is proved to stay at this (default) physical address since Intel + // recommends OS/BIOS to not relocate it, but it could be relocated + // however, this address is valid for almost all of the systems + // + PaIoApicBase.QuadPart = IO_APIC_DEFAULT_BASE_ADDR & 0xFFFFFF000; + g_IoApicBase = MmMapIoSpace(PaIoApicBase, 0x1000, MmNonCached); + + if (!g_IoApicBase) + { + // + // Not gonna fail the initialization since the IOAPIC might be relocated by + // either OS/BIOS + // + + // return FALSE; + } + + if (ApicBaseMSR & (1 << 10)) + { + g_CompatibilityCheck.IsX2Apic = TRUE; + + return FALSE; + } + else + { + PaApicBase.QuadPart = ApicBaseMSR & 0xFFFFFF000; + g_ApicBase = MmMapIoSpace(PaApicBase, 0x1000, MmNonCached); + + if (!g_ApicBase) + { + return FALSE; + } + + g_CompatibilityCheck.IsX2Apic = FALSE; + } + + return TRUE; +} + +/** + * @brief Uninitialize APIC + * + * @return VOID + */ +VOID +ApicUninitialize() +{ + // + // Unmap Local APIC base + // + if (g_ApicBase) + { + MmUnmapIoSpace(g_ApicBase, 0x1000); + } + + // + // Unmap I/O APIC base + // + if (g_IoApicBase) + { + MmUnmapIoSpace(g_IoApicBase, 0x1000); + } +} + +/** + * @brief Self IPI the current core + * + * @param Vector + * @return VOID + */ +VOID +ApicSelfIpi(UINT32 Vector) +{ + // + // Check and apply self-IPI to x2APIC and xAPIC + // + if (g_CompatibilityCheck.IsX2Apic) + { + X2ApicIcrWrite(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | Vector, 0); + } + else + { + XApicIcrWrite(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | Vector, 0); + } +} diff --git a/hyperdbg/hyperhv/code/devices/Pci.c b/hyperdbg/hyperhv/code/devices/Pci.c new file mode 100644 index 00000000..adcd1677 --- /dev/null +++ b/hyperdbg/hyperhv/code/devices/Pci.c @@ -0,0 +1,118 @@ +/** + * @file Pci.c + * @author Bjrn Ruytenberg (bjorn@bjornweb.nl) + * @brief Routines for interacting with PCI(e) fabric + * @details + * @version 0.10.3 + * @date 2024-11-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Read from PCI configuration space (CAM) at given offset + * @param Bus + * @param Device + * @param Function + * @param Offset + * @param Width Number of bytes to return. Supported data types: BYTE (1), WORD (2), DWORD (4), QWORD (8). + * + * @return QWORD + */ +QWORD +PciReadCam(WORD Bus, WORD Device, WORD Function, BYTE Offset, UINT8 Width) +{ + WORD Target = 0; + + // + // Restrict Offset to CAM address space; restrict BDF to our internal limits + // + if (Offset > CAM_CONFIG_SPACE_LENGTH || + Bus >= BUS_MAX_NUM || + Device >= DEVICE_MAX_NUM || + Function >= FUNCTION_MAX_NUM) + { + return MAXDWORD64; + } + + Target = Function + ((Device & 0x1F) << 3) + ((Bus & 0xFF) << 8); + _outpd(CFGADR, (DWORD)(Target << 8) | 0x80000000UL | ((DWORD)Offset & ~3)); + + switch ((UINT32)Width) + { + case sizeof(BYTE): + return (BYTE)_inp(CFGDAT + (Offset & 0x3)); + break; + case sizeof(WORD): + return (WORD)_inpw(CFGDAT + (Offset & 0x2)); + break; + case sizeof(DWORD): + return _inpd(CFGDAT); + break; + case sizeof(QWORD): + return (PciReadCam(Bus, Device, Function, Offset + sizeof(DWORD), sizeof(DWORD)) << 32) | PciReadCam(Bus, Device, Function, Offset + 0, sizeof(DWORD)); + break; + default: + return MAXDWORD64; + } +} + +/** + * @brief Write to PCI configuration space (CAM) at given offset + * @param Bus + * @param Device + * @param Function + * @param Offset + * @param Width Number of bytes to write. Supported data types: BYTE (1), WORD (2), DWORD (4), QWORD (8). + * @param Value to write. + * + * @return BOOLEAN + */ +BOOLEAN +PciWriteCam(WORD Bus, WORD Device, WORD Function, BYTE Offset, UINT8 Width, QWORD Value) +{ + BOOLEAN Result = TRUE; + WORD Target = 0; + + // + // Restrict Offset to CAM address space; restrict BDF to our internal limits + // + if (Offset > CAM_CONFIG_SPACE_LENGTH || + Bus >= BUS_MAX_NUM || + Device >= DEVICE_MAX_NUM || + Function >= FUNCTION_MAX_NUM) + { + Result = FALSE; + } + else + { + Target = Function + ((Device & 0x1F) << 3) + ((Bus & 0xFF) << 8); + _outpd(CFGADR, (DWORD)(Target << 8) | 0x80000000UL | ((DWORD)Offset & ~3)); + + switch ((UINT32)Width) + { + case sizeof(BYTE): + _outp((CFGDAT + (Offset & 0x3)), (BYTE)Value); + Result = TRUE; + break; + case sizeof(WORD): + _outpw((CFGDAT + (Offset & 0x2)), (WORD)Value); + Result = TRUE; + break; + case sizeof(DWORD): + _outpd((CFGDAT + Offset), (DWORD)Value); + Result = TRUE; + break; + case sizeof(QWORD): + Result = PciWriteCam(Bus, Device, Function, Offset + sizeof(DWORD), sizeof(DWORD), (DWORD)(Value >> 32)); + Result = PciWriteCam(Bus, Device, Function, Offset + 0, sizeof(DWORD), (DWORD)Value); + break; + default: + Result = FALSE; + } + } + + return Result; +} diff --git a/hyperdbg/hprdbghv/code/disassembler/Disassembler.c b/hyperdbg/hyperhv/code/disassembler/Disassembler.c similarity index 88% rename from hyperdbg/hprdbghv/code/disassembler/Disassembler.c rename to hyperdbg/hyperhv/code/disassembler/Disassembler.c index ad0394f4..24bae57e 100644 --- a/hyperdbg/hprdbghv/code/disassembler/Disassembler.c +++ b/hyperdbg/hyperhv/code/disassembler/Disassembler.c @@ -315,6 +315,50 @@ DisassemblerLengthDisassembleEngineInVmxRootOnTargetProcess(PVOID Address, BOOLE return DisassemblerLengthDisassembleEngine(SafeMemoryToRead, Is32Bit); } +/** + * @brief Disassembler length disassembler engine + * @details Can be called from VMX non-root mode + * + * @param Address + * @param Is32Bit + * @param ProcessId + * + * @return UINT32 + */ +UINT32 +DisassemblerLengthDisassembleEngineByProcessId(PVOID Address, BOOLEAN Is32Bit, UINT32 ProcessId) +{ + UINT64 SizeOfBufferToRead = 0; + BYTE MemoryToRead[MAXIMUM_INSTR_SIZE] = {0}; + CR3_TYPE CurrentProcessCr3 = {0}; + + // + // Switch to the target process memory layout by using the process id + // + CurrentProcessCr3 = SwitchToProcessMemoryLayout(ProcessId); + + // + // Read the maximum number of instruction that is valid to be read in the + // target address + // + SizeOfBufferToRead = CheckAddressMaximumInstructionLength(Address); + + // + // Restore the original process + // + SwitchToPreviousProcess(CurrentProcessCr3); + + // + // Find the current instruction + // + MemoryMapperReadMemoryUnsafe((UINT64)Address, + MemoryToRead, + SizeOfBufferToRead, + ProcessId); + + return DisassemblerLengthDisassembleEngine(MemoryToRead, Is32Bit); +} + /** * @brief Shows the disassembly of only one instruction * @details Should be called in VMX-root mode diff --git a/hyperdbg/hprdbghv/code/disassembler/ZydisKernel.c b/hyperdbg/hyperhv/code/disassembler/ZydisKernel.c similarity index 100% rename from hyperdbg/hprdbghv/code/disassembler/ZydisKernel.c rename to hyperdbg/hyperhv/code/disassembler/ZydisKernel.c diff --git a/hyperdbg/hprdbghv/code/features/CompatibilityChecks.c b/hyperdbg/hyperhv/code/features/CompatibilityChecks.c similarity index 83% rename from hyperdbg/hprdbghv/code/features/CompatibilityChecks.c rename to hyperdbg/hyperhv/code/features/CompatibilityChecks.c index fcabc465..4238e4c6 100644 --- a/hyperdbg/hprdbghv/code/features/CompatibilityChecks.c +++ b/hyperdbg/hyperhv/code/features/CompatibilityChecks.c @@ -73,7 +73,7 @@ CompatibilityCheckGetX86VirtualAddressWidth() UINT32 CompatibilityCheckGetX86PhysicalAddressWidth() { - int Regs[4]; + INT32 Regs[4]; CommonCpuidInstruction(CPUID_ADDR_WIDTH, 0, Regs); @@ -83,6 +83,36 @@ CompatibilityCheckGetX86PhysicalAddressWidth() return (Regs[0] & 0x0ff); } +/** + * @brief Check if the processor supports CET IBT + * + * @return BOOLEAN + */ +BOOLEAN +CompatibilityCheckCetShadowStackSupport() +{ + INT32 Regs[4]; + + CommonCpuidInstruction(7, 0, Regs); + + return (BOOLEAN)((Regs[2] & (1 << 7)) != 0); // // CpuInfo[3] is ECX +} + +/** + * @brief Check for Intel CET IBT support + * + * @return BOOLEAN + */ +BOOLEAN +CompatibilityCheckCetIbtSupport() +{ + INT32 Regs[4]; + + CommonCpuidInstruction(7, 0, Regs); + + return (BOOLEAN)((Regs[3] & (1 << 20)) != 0); // CpuInfo[3] is EDX +} + /** * @brief Check for mode-based execution * @@ -96,7 +126,7 @@ CompatibilityCheckModeBasedExecution() // the "enable PML" VM - execution control // UINT32 SecondaryProcBasedVmExecControls = HvAdjustControls(IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_FLAG, - IA32_VMX_PROCBASED_CTLS2); + IA32_VMX_PROCBASED_CTLS2); if (SecondaryProcBasedVmExecControls & IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_FLAG) { @@ -172,6 +202,16 @@ CompatibilityCheckPerformChecks() // g_CompatibilityCheck.ModeBasedExecutionSupport = CompatibilityCheckModeBasedExecution(); + // + // Check Intel CET IBT support + // + g_CompatibilityCheck.CetIbtSupport = CompatibilityCheckCetIbtSupport(); + + // + // Check Intel CET shadow stack support + // + g_CompatibilityCheck.CetShadowStackSupport = CompatibilityCheckCetShadowStackSupport(); + // // Check PML support // diff --git a/hyperdbg/hprdbghv/code/features/DirtyLogging.c b/hyperdbg/hyperhv/code/features/DirtyLogging.c similarity index 88% rename from hyperdbg/hprdbghv/code/features/DirtyLogging.c rename to hyperdbg/hyperhv/code/features/DirtyLogging.c index c18f4e9e..dab2db41 100644 --- a/hyperdbg/hprdbghv/code/features/DirtyLogging.c +++ b/hyperdbg/hyperhv/code/features/DirtyLogging.c @@ -33,9 +33,9 @@ DirtyLoggingInitialize() // // - // When PML is active each write that sets a dirty flag for EPT also generates an entry in an inmemory log, + // When PML is active each write that sets a dirty flag for EPT also generates an entry in an in-memory log, // reporting the guest-physical address of the write (aligned to 4 KBytes) - // When the log is full, a VM exit occurs, notifying the VMM.A VMM can monitor the number of pages modified + // When the log is full, a VM exit occurs, notifying the VMM. A VMM can monitor the number of pages modified // by each thread by specifying an available set of log entries // @@ -53,11 +53,11 @@ 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) { - g_GuestState[i].PmlBufferAddress = CrsAllocateNonPagedPool(PAGE_SIZE); + g_GuestState[i].PmlBufferAddress = PlatformMemAllocateNonPagedPool(PAGE_SIZE); } if (g_GuestState[i].PmlBufferAddress == NULL) @@ -65,11 +65,11 @@ 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) { - CrsFreePool(g_GuestState[j].PmlBufferAddress); + PlatformMemFreePool(g_GuestState[j].PmlBufferAddress); } } @@ -119,12 +119,12 @@ DirtyLoggingEnable(VIRTUAL_MACHINE_STATE * VCpu) // LogInfo("PML Buffer Address = %llx", PmlPhysAddr); - __vmx_vmwrite(VMCS_CTRL_PML_ADDRESS, PmlPhysAddr); + VmxVmwrite64(VMCS_CTRL_PML_ADDRESS, PmlPhysAddr); // // Clear the PML index // - __vmx_vmwrite(VMCS_GUEST_PML_INDEX, PML_ENTITY_NUM - 1); + VmxVmwrite64(VMCS_GUEST_PML_INDEX, PML_ENTITY_NUM - 1); // // If the "enable PML" VM-execution control is 1 and bit 6 of EPT pointer (EPTP) @@ -160,12 +160,12 @@ DirtyLoggingDisable(VIRTUAL_MACHINE_STATE * VCpu) // // Clear the address // - __vmx_vmwrite(VMCS_CTRL_PML_ADDRESS, NULL64_ZERO); + VmxVmwrite64(VMCS_CTRL_PML_ADDRESS, NULL64_ZERO); // // Clear the PML index // - __vmx_vmwrite(VMCS_GUEST_PML_INDEX, 0x0); + VmxVmwrite64(VMCS_GUEST_PML_INDEX, 0x0); // // Disable PML Enable bit @@ -196,11 +196,11 @@ 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) { - CrsFreePool(g_GuestState[i].PmlBufferAddress); + PlatformMemFreePool(g_GuestState[i].PmlBufferAddress); } } } @@ -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]); } @@ -284,7 +284,7 @@ DirtyLoggingFlushPmlBuffer(VIRTUAL_MACHINE_STATE * VCpu) // // reset PML index // - __vmx_vmwrite(VMCS_GUEST_PML_INDEX, PML_ENTITY_NUM - 1); + VmxVmwrite64(VMCS_GUEST_PML_INDEX, PML_ENTITY_NUM - 1); return TRUE; } diff --git a/hyperdbg/hprdbghv/code/globals/GlobalVariableManagement.c b/hyperdbg/hyperhv/code/globals/GlobalVariableManagement.c similarity index 89% rename from hyperdbg/hprdbghv/code/globals/GlobalVariableManagement.c rename to hyperdbg/hyperhv/code/globals/GlobalVariableManagement.c index f4108f6e..e651f362 100644 --- a/hyperdbg/hprdbghv/code/globals/GlobalVariableManagement.c +++ b/hyperdbg/hyperhv/code/globals/GlobalVariableManagement.c @@ -26,7 +26,7 @@ GlobalGuestStateAllocateZeroedMemory(VOID) // if (!g_GuestState) { - g_GuestState = CrsAllocateNonPagedPool(BufferSizeInByte); + g_GuestState = PlatformMemAllocateNonPagedPool(BufferSizeInByte); if (!g_GuestState) { @@ -51,6 +51,6 @@ GlobalGuestStateAllocateZeroedMemory(VOID) VOID GlobalGuestStateFreeMemory(VOID) { - CrsFreePool(g_GuestState); + PlatformMemFreePool(g_GuestState); g_GuestState = NULL; } diff --git a/hyperdbg/hprdbghv/code/hooks/ept-hook/EptHook.c b/hyperdbg/hyperhv/code/hooks/ept-hook/EptHook.c similarity index 89% rename from hyperdbg/hprdbghv/code/hooks/ept-hook/EptHook.c rename to hyperdbg/hyperhv/code/hooks/ept-hook/EptHook.c index af3b3169..dc2b4fd8 100644 --- a/hyperdbg/hprdbghv/code/hooks/ept-hook/EptHook.c +++ b/hyperdbg/hyperhv/code/hooks/ept-hook/EptHook.c @@ -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); } /** @@ -150,7 +150,6 @@ EptHookCreateHookPage(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, EPT_PML1_ENTRY ChangedEntry; SIZE_T PhysicalBaseAddress; PVOID VirtualTarget; - PVOID TargetBuffer; UINT64 TargetAddressInFakePageContent; PEPT_PML1_ENTRY TargetPage; PEPT_HOOKED_PAGE_DETAIL HookedPage; @@ -179,16 +178,28 @@ EptHookCreateHookPage(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, // PhysicalBaseAddress = (SIZE_T)VirtualAddressToPhysicalAddressByProcessCr3(VirtualTarget, ProcessCr3); + // + // If the physical address is NULL, it means that the address is not valid + // if (!PhysicalBaseAddress) { VmmCallbackSetLastError(DEBUGGER_ERROR_INVALID_ADDRESS); return FALSE; } + // + // Check if the physical address is bigger than 512 GB + // + if (PhysicalBaseAddress >= SIZE_512_GB) + { + VmmCallbackSetLastError(DEBUGGER_ERROR_CANNOT_PUT_EPT_HOOKS_ON_PHYSICAL_ADDRESS_ABOVE_512_GB); + return FALSE; + } + // // 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) { @@ -263,26 +274,18 @@ 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++) { // - // Set target buffer, request buffer from pool manager, - // we also need to allocate new page to replace the current page + // We need to split the large page to 4KB page using pre-allocated pools // - TargetBuffer = (PVOID)PoolManagerRequestPool(SPLIT_2MB_PAGING_TO_4KB_PAGE, TRUE, sizeof(VMM_EPT_DYNAMIC_SPLIT)); - - if (!TargetBuffer) + if (!EptSplitLargePage(g_GuestState[i].EptPageTable, TRUE, PhysicalBaseAddress)) { - PoolManagerFreePool((UINT64)HookedPage); + PoolManagerCallbackFreePool((UINT64)HookedPage); - VmmCallbackSetLastError(DEBUGGER_ERROR_PRE_ALLOCATED_BUFFER_IS_EMPTY); - return FALSE; - } - - if (!EptSplitLargePage(g_GuestState[i].EptPageTable, TargetBuffer, PhysicalBaseAddress)) - { - PoolManagerFreePool((UINT64)HookedPage); - PoolManagerFreePool((UINT64)TargetBuffer); // Here also other previous pools should be specified, but we forget it for now + // + // Here also other previous pools should be specified, but we forget it for now + // LogDebugInfo("Err, could not split page for the address : 0x%llx", PhysicalBaseAddress); VmmCallbackSetLastError(DEBUGGER_ERROR_EPT_COULD_NOT_SPLIT_THE_LARGE_PAGE_TO_4KB_PAGES); @@ -299,8 +302,11 @@ EptHookCreateHookPage(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, // if (!TargetPage) { - PoolManagerFreePool((UINT64)HookedPage); - PoolManagerFreePool((UINT64)TargetBuffer); // Here also other previous pools should be specified, but we forget it for now + PoolManagerCallbackFreePool((UINT64)HookedPage); + + // + // Here also other previous pools should be specified, but we forget it for now + // VmmCallbackSetLastError(DEBUGGER_ERROR_EPT_FAILED_TO_GET_PML1_ENTRY_OF_TARGET_ADDRESS); return FALSE; @@ -503,6 +509,15 @@ EptHookPerformPageHook(VIRTUAL_MACHINE_STATE * VCpu, return FALSE; } + // + // Check if the physical address is bigger than 512 GB + // + if (PhysicalBaseAddress >= SIZE_512_GB) + { + VmmCallbackSetLastError(DEBUGGER_ERROR_CANNOT_PUT_EPT_HOOKS_ON_PHYSICAL_ADDRESS_ABOVE_512_GB); + return FALSE; + } + // // try to see if we can find the address // @@ -892,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) { @@ -941,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; @@ -985,8 +1000,7 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu, ULONG ProcessorsCount; EPT_PML1_ENTRY ChangedEntry; SIZE_T PhysicalBaseAddress; - PVOID AlignedTargetVa; - PVOID TargetBuffer; + PVOID AlignedTargetVaOrPa; PVOID TargetAddress; PVOID HookFunction; UINT64 TargetAddressInSafeMemory; @@ -1024,7 +1038,7 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu, TargetAddress = (PVOID)((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->StartAddress; } - AlignedTargetVa = PAGE_ALIGN(TargetAddress); + AlignedTargetVaOrPa = PAGE_ALIGN(TargetAddress); // // Here we have to change the CR3, it is because we are in SYSTEM process @@ -1032,17 +1046,40 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu, // user mode address of another process) then the translation is invalid // - // - // based on the CR3 of target core - // - PhysicalBaseAddress = (SIZE_T)VirtualAddressToPhysicalAddressByProcessCr3(AlignedTargetVa, ProcessCr3); + if (!EptHiddenHook && + ((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->MemoryType == DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS) + { + // + // The address itself is a physical address, no need for conversion + // + PhysicalBaseAddress = (SIZE_T)AlignedTargetVaOrPa; + } + else + { + // + // based on the CR3 of target core + // + PhysicalBaseAddress = (SIZE_T)VirtualAddressToPhysicalAddressByProcessCr3(AlignedTargetVaOrPa, ProcessCr3); + } + // + // Check if the physical address is valid + // if (!PhysicalBaseAddress) { VmmCallbackSetLastError(DEBUGGER_ERROR_INVALID_ADDRESS); return FALSE; } + // + // Check if the physical address is bigger than 512 GB + // + if (PhysicalBaseAddress >= SIZE_512_GB) + { + VmmCallbackSetLastError(DEBUGGER_ERROR_CANNOT_PUT_EPT_HOOKS_ON_PHYSICAL_ADDRESS_ABOVE_512_GB); + return FALSE; + } + // // try to see if we can find the address // @@ -1067,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) { @@ -1099,13 +1136,26 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu, // // Save the start of the target physical address // - HookedPage->StartOfTargetPhysicalAddress = (SIZE_T)VirtualAddressToPhysicalAddressByProcessCr3( - (PVOID)(((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->StartAddress), - ProcessCr3); + if (((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->MemoryType == DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS) + { + // + // Physical address + // + HookedPage->StartOfTargetPhysicalAddress = (SIZE_T)(((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->StartAddress); + } + else + { + // + // Virtual address + // + HookedPage->StartOfTargetPhysicalAddress = (SIZE_T)VirtualAddressToPhysicalAddressByProcessCr3( + (PVOID)(((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->StartAddress), + ProcessCr3); + } if (!HookedPage->StartOfTargetPhysicalAddress) { - PoolManagerFreePool((UINT64)HookedPage); + PoolManagerCallbackFreePool((UINT64)HookedPage); VmmCallbackSetLastError(DEBUGGER_ERROR_INVALID_ADDRESS); return FALSE; @@ -1114,13 +1164,26 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu, // // Save the end of the target physical address // - HookedPage->EndOfTargetPhysicalAddress = (SIZE_T)VirtualAddressToPhysicalAddressByProcessCr3( - (PVOID)(((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->EndAddress), - ProcessCr3); + if (((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->MemoryType == DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS) + { + // + // Physical address + // + HookedPage->EndOfTargetPhysicalAddress = (SIZE_T)(((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->EndAddress); + } + else + { + // + // Virtual address + // + HookedPage->EndOfTargetPhysicalAddress = (SIZE_T)VirtualAddressToPhysicalAddressByProcessCr3( + (PVOID)(((EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *)HookingDetails)->EndAddress), + ProcessCr3); + } if (!HookedPage->EndOfTargetPhysicalAddress) { - PoolManagerFreePool((UINT64)HookedPage); + PoolManagerCallbackFreePool((UINT64)HookedPage); VmmCallbackSetLastError(DEBUGGER_ERROR_INVALID_ADDRESS); return FALSE; @@ -1149,7 +1212,7 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu, // The following line can't be used in user mode addresses // RtlCopyBytes(&HookedPage->FakePageContents, VirtualTarget, PAGE_SIZE); // - MemoryMapperReadMemorySafe((UINT64)AlignedTargetVa, &HookedPage->FakePageContents, PAGE_SIZE); + MemoryMapperReadMemorySafe((UINT64)AlignedTargetVaOrPa, &HookedPage->FakePageContents, PAGE_SIZE); // // Restore to original process @@ -1181,34 +1244,25 @@ 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++) { // - // Set target buffer, request buffer from pool manager, - // we also need to allocate new page to replace the current page + // We need to split the large page to 4KB page using pre-allocated pools // - TargetBuffer = (PVOID)PoolManagerRequestPool(SPLIT_2MB_PAGING_TO_4KB_PAGE, TRUE, sizeof(VMM_EPT_DYNAMIC_SPLIT)); - - if (!TargetBuffer) + if (!EptSplitLargePage(g_GuestState[i].EptPageTable, TRUE, PhysicalBaseAddress)) { - PoolManagerFreePool((UINT64)HookedPage); - - VmmCallbackSetLastError(DEBUGGER_ERROR_PRE_ALLOCATED_BUFFER_IS_EMPTY); - return FALSE; - } - - if (!EptSplitLargePage(g_GuestState[i].EptPageTable, TargetBuffer, PhysicalBaseAddress)) - { - PoolManagerFreePool((UINT64)HookedPage); - PoolManagerFreePool((UINT64)TargetBuffer); // Here also other previous pools should be specified, but we forget it for now + PoolManagerCallbackFreePool((UINT64)HookedPage); + // + // Here also other previous pools should be specified, but we forget it for now + // LogDebugInfo("Err, could not split page for the address : 0x%llx", PhysicalBaseAddress); VmmCallbackSetLastError(DEBUGGER_ERROR_EPT_COULD_NOT_SPLIT_THE_LARGE_PAGE_TO_4KB_PAGES); return FALSE; @@ -1224,8 +1278,11 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu, // if (!TargetPage) { - PoolManagerFreePool((UINT64)HookedPage); - PoolManagerFreePool((UINT64)TargetBuffer); // Here also other previous pools should be specified, but we forget it for now + PoolManagerCallbackFreePool((UINT64)HookedPage); + + // + // Here also other previous pools should be specified, but we forget it for now + // VmmCallbackSetLastError(DEBUGGER_ERROR_EPT_FAILED_TO_GET_PML1_ENTRY_OF_TARGET_ADDRESS); return FALSE; @@ -1805,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"); } @@ -1907,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; @@ -2012,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) { @@ -2056,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"); } @@ -2105,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) { @@ -2132,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]; @@ -2159,6 +2216,7 @@ EptHookUnHookSingleAddressHiddenBreakpoint(PEPT_HOOKED_PAGE_DETAIL H * * @param VirtualAddress Virtual address to unhook * @param PhysAddress Physical address to unhook (optional) + * @param HookingTag Hooking tag (optional) * @param ProcessId The process id of target process * (in unhooking for some hooks only physical address is availables) * @param ApplyDirectlyFromVmxRoot should it be directly applied from VMX-root mode or not @@ -2170,11 +2228,12 @@ EptHookUnHookSingleAddressHiddenBreakpoint(PEPT_HOOKED_PAGE_DETAIL H BOOLEAN EptHookPerformUnHookSingleAddress(UINT64 VirtualAddress, UINT64 PhysAddress, + UINT64 HookingTag, UINT32 ProcessId, BOOLEAN ApplyDirectlyFromVmxRoot, EPT_SINGLE_HOOK_UNHOOKING_DETAILS * TargetUnhookingDetails) { - SIZE_T PhysicalAddress; + SIZE_T PhysicalAddress = NULL64_ZERO; // // Once applied directly from VMX-root mode, the process id should be the same process Id @@ -2188,7 +2247,11 @@ EptHookPerformUnHookSingleAddress(UINT64 VirtualAdd // // Check if the physical address is available or not // - if (PhysAddress == NULL64_ZERO) + if (PhysAddress != NULL64_ZERO) + { + PhysicalAddress = (SIZE_T)PAGE_ALIGN(PhysAddress); + } + else if (HookingTag == NULL64_ZERO) { if (ApplyDirectlyFromVmxRoot) { @@ -2200,10 +2263,6 @@ EptHookPerformUnHookSingleAddress(UINT64 VirtualAdd ProcessId))); } } - else - { - PhysicalAddress = (SIZE_T)PAGE_ALIGN(PhysAddress); - } LIST_FOR_EACH_LINK(g_EptState->HookedPagesList, EPT_HOOKED_PAGE_DETAIL, PageHookList, CurrEntity) { @@ -2215,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) { @@ -2231,7 +2290,7 @@ EptHookPerformUnHookSingleAddress(UINT64 VirtualAdd // // It's either a hidden detours or a monitor (read/write/execute) entry // - if (CurrEntity->PhysicalBaseAddress == PhysicalAddress) + if ((HookingTag != NULL64_ZERO && CurrEntity->HookingTag == HookingTag) || CurrEntity->PhysicalBaseAddress == PhysicalAddress) { return EptHookUnHookSingleAddressDetoursAndMonitor(CurrEntity, ApplyDirectlyFromVmxRoot, @@ -2241,11 +2300,81 @@ EptHookPerformUnHookSingleAddress(UINT64 VirtualAdd } // - // Nothing found, probably the list is not found + // Nothing found, probably the hooking detail is not found // return FALSE; } +/** + * @brief Remove all hooks from the hooked pages by the given hooking tag + * @details Should be called from Vmx Non-root + * + * @param HookingTag The hooking tag to unhook + * @return BOOLEAN If unhook was successful it returns true or if it was not successful returns false + */ +BOOLEAN +EptHookUnHookAllByHookingTag(UINT64 HookingTag) +{ + EPT_SINGLE_HOOK_UNHOOKING_DETAILS TargetUnhookingDetails; // not used + BOOLEAN AtLeastOneUnhooked = FALSE; + BOOLEAN UnhookingResult = FALSE; + + // + // Should be called from vmx non-root + // + if (VmxGetCurrentExecutionMode() == TRUE) + { + return FALSE; + } + +KeepUnhooking: + UnhookingResult = EptHookPerformUnHookSingleAddress(NULL_ZERO, + NULL_ZERO, + HookingTag, + NULL_ZERO, + FALSE, + &TargetUnhookingDetails); + + if (UnhookingResult) + { + AtLeastOneUnhooked = TRUE; + + // + // Keep unhooking until there is no more hooking details + // + goto KeepUnhooking; + } + + return AtLeastOneUnhooked; +} + +/** + * @brief Remove single hook from the hooked pages by the given hooking tag + * @details Should be called from Vmx root-mode + * + * @param HookingTag The hooking tag to unhook + * @return BOOLEAN If unhook was successful it returns true or if it was not successful returns false + */ +BOOLEAN +EptHookUnHookSingleHookByHookingTagFromVmxRoot(UINT64 HookingTag, + EPT_SINGLE_HOOK_UNHOOKING_DETAILS * TargetUnhookingDetails) +{ + // + // Should be called from VMX root-mode + // + if (VmxGetCurrentExecutionMode() == FALSE) + { + return FALSE; + } + + return EptHookPerformUnHookSingleAddress(NULL64_ZERO, + NULL64_ZERO, + HookingTag, + NULL_ZERO, + TRUE, + TargetUnhookingDetails); +} + /** * @brief Remove single hook from the hooked pages list and invalidate TLB * @details Should be called from VMX non-root @@ -2274,6 +2403,7 @@ EptHookUnHookSingleAddress(UINT64 VirtualAddress, return EptHookPerformUnHookSingleAddress(VirtualAddress, PhysAddress, + NULL_ZERO, ProcessId, FALSE, &TargetUnhookingDetails); @@ -2305,6 +2435,7 @@ EptHookUnHookSingleAddressFromVmxRoot(UINT64 Virtua return EptHookPerformUnHookSingleAddress(VirtualAddress, PhysAddress, + NULL64_ZERO, NULL_ZERO, TRUE, TargetUnhookingDetails); @@ -2354,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"); } @@ -2459,7 +2590,7 @@ EptHookModifyInstructionFetchState(VIRTUAL_MACHINE_STATE * VCpu, PVOID PmlEntry = NULL; BOOLEAN IsLargePage = FALSE; - PmlEntry = EptGetPml1OrPml2Entry(g_EptState->EptPageTable, (SIZE_T)PhysicalAddress, &IsLargePage); + PmlEntry = EptGetPml1OrPml2Entry(VCpu->EptPageTable, (SIZE_T)PhysicalAddress, &IsLargePage); if (PmlEntry) { @@ -2517,7 +2648,7 @@ EptHookModifyPageReadState(VIRTUAL_MACHINE_STATE * VCpu, PVOID PmlEntry = NULL; BOOLEAN IsLargePage = FALSE; - PmlEntry = EptGetPml1OrPml2Entry(g_EptState->EptPageTable, (SIZE_T)PhysicalAddress, &IsLargePage); + PmlEntry = EptGetPml1OrPml2Entry(VCpu->EptPageTable, (SIZE_T)PhysicalAddress, &IsLargePage); if (PmlEntry) { @@ -2575,7 +2706,7 @@ EptHookModifyPageWriteState(VIRTUAL_MACHINE_STATE * VCpu, PVOID PmlEntry = NULL; BOOLEAN IsLargePage = FALSE; - PmlEntry = EptGetPml1OrPml2Entry(g_EptState->EptPageTable, (SIZE_T)PhysicalAddress, &IsLargePage); + PmlEntry = EptGetPml1OrPml2Entry(VCpu->EptPageTable, (SIZE_T)PhysicalAddress, &IsLargePage); if (PmlEntry) { diff --git a/hyperdbg/hprdbghv/code/hooks/ept-hook/ExecTrap.c b/hyperdbg/hyperhv/code/hooks/ept-hook/ExecTrap.c similarity index 74% rename from hyperdbg/hprdbghv/code/hooks/ept-hook/ExecTrap.c rename to hyperdbg/hyperhv/code/hooks/ept-hook/ExecTrap.c index e7ca0fb1..8554064b 100644 --- a/hyperdbg/hprdbghv/code/hooks/ept-hook/ExecTrap.c +++ b/hyperdbg/hyperhv/code/hooks/ept-hook/ExecTrap.c @@ -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); @@ -245,134 +245,6 @@ ExecTrapTraverseThroughOsPageTables(PVMM_EPT_PAGE_TABLE EptTable, CR3_TYPE Targe return TRUE; } -/** - * @brief Initialize the needed structure for hooking user-mode execution - * @details should be called from vmx non-root mode - * - * @return BOOLEAN - */ -BOOLEAN -ExecTrapAllocateUserDisabledMbecEptPageTable() -{ - PVMM_EPT_PAGE_TABLE ModeBasedEptTable; - EPT_POINTER EPTP = {0}; - - // - // Allocate another EPT page table - // - ModeBasedEptTable = EptAllocateAndCreateIdentityPageTable(); - - if (ModeBasedEptTable == NULL) - { - // - // There was an error allocating MBEC page tables - // - return FALSE; - } - - // - // Disable EPT user-mode execution bit for the target EPTP - // - ModeBasedExecHookDisableUserModeExecution(ModeBasedEptTable); - - // - // Set the global address for MBEC EPT page table - // - g_EptState->ModeBasedUserDisabledEptPageTable = ModeBasedEptTable; - - // - // For performance, we let the processor know it can cache the EPT - // - EPTP.MemoryType = MEMORY_TYPE_WRITE_BACK; - - // - // We might utilize the 'access' and 'dirty' flag features in the dirty logging mechanism - // - EPTP.EnableAccessAndDirtyFlags = TRUE; - - // - // Bits 5:3 (1 less than the EPT page-walk length) must be 3, indicating an EPT page-walk length of 4; - // see Section 28.2.2 - // - EPTP.PageWalkLength = 3; - - // - // The physical page number of the page table we will be using - // - EPTP.PageFrameNumber = (SIZE_T)VirtualAddressToPhysicalAddress(&ModeBasedEptTable->PML4) / PAGE_SIZE; - - // - // We will write the EPTP to the VMCS later - // - g_EptState->ModeBasedUserDisabledEptPointer.AsUInt = EPTP.AsUInt; - - return TRUE; -} - -/** - * @brief Initialize the needed structure for hooking kernel-mode execution - * @details should be called from vmx non-root mode - * - * @return BOOLEAN - */ -BOOLEAN -ExecTrapAllocateKernelDisabledMbecEptPageTable() -{ - PVMM_EPT_PAGE_TABLE ModeBasedEptTable; - EPT_POINTER EPTP = {0}; - - // - // Allocate another EPT page table - // - ModeBasedEptTable = EptAllocateAndCreateIdentityPageTable(); - - if (ModeBasedEptTable == NULL) - { - // - // There was an error allocating MBEC page tables - // - return FALSE; - } - - // - // Disable EPT user-mode execution bit for the target EPTP - // - ModeBasedExecHookDisableKernelModeExecution(ModeBasedEptTable); - - // - // Set the global address for MBEC EPT page table - // - g_EptState->ModeBasedKernelDisabledEptPageTable = ModeBasedEptTable; - - // - // For performance, we let the processor know it can cache the EPT - // - EPTP.MemoryType = MEMORY_TYPE_WRITE_BACK; - - // - // We might utilize the 'access' and 'dirty' flag features in the dirty logging mechanism - // - EPTP.EnableAccessAndDirtyFlags = TRUE; - - // - // Bits 5:3 (1 less than the EPT page-walk length) must be 3, indicating an EPT page-walk length of 4; - // see Section 28.2.2 - // - EPTP.PageWalkLength = 3; - - // - // The physical page number of the page table we will be using - // - EPTP.PageFrameNumber = (SIZE_T)VirtualAddressToPhysicalAddress(&ModeBasedEptTable->PML4) / PAGE_SIZE; - - // - // We will write the EPTP to the VMCS later - // - g_EptState->ModeBasedKernelDisabledEptPointer.AsUInt = EPTP.AsUInt; - - return TRUE; -} - /** * @brief Adjust execute-only bits bit of target page-table * @details should be called from vmx non-root mode @@ -393,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 @@ -404,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; } @@ -412,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; } @@ -423,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) { @@ -489,7 +361,7 @@ ExecTrapReadRamPhysicalRegions() } /** - * @brief Initialize the reversing machine based on service request + * @brief Initialize the exec trap based on service request * * @return BOOLEAN */ @@ -497,14 +369,14 @@ BOOLEAN ExecTrapInitialize() { // - // Check if the reversing machine is already initialized + // Check if the exec trap is already initialized // if (g_ExecTrapInitialized) { // // Already initialized // - return FALSE; + return TRUE; } // @@ -517,56 +389,11 @@ ExecTrapInitialize() return FALSE; } - // - // Read the RAM regions - // - ExecTrapReadRamPhysicalRegions(); - - // - // Allocate MBEC EPT page-table (user-disabled) - // - if (!ExecTrapAllocateUserDisabledMbecEptPageTable()) - { - // - // There was an error allocating MBEC page table for EPT tables - // - return FALSE; - } - - // - // Allocate MBEC EPT page-table (kernel-disabled) - // - if (!ExecTrapAllocateKernelDisabledMbecEptPageTable()) - { - // - // Free the user-disabled page-table buffer - // - MmFreeContiguousMemory(g_EptState->ModeBasedUserDisabledEptPageTable); - g_EptState->ModeBasedUserDisabledEptPageTable = NULL; - - // - // There was an error allocating MBEC page table for EPT tables - // - return FALSE; - } - // // Call the function responsible for initializing Mode-based hooks // if (ModeBasedExecHookInitialize() == FALSE) { - // - // Free the user-disabled page-table buffer - // - MmFreeContiguousMemory(g_EptState->ModeBasedUserDisabledEptPageTable); - g_EptState->ModeBasedUserDisabledEptPageTable = NULL; - - // - // Free the kernel-disabled page-table buffer - // - MmFreeContiguousMemory(g_EptState->ModeBasedKernelDisabledEptPageTable); - g_EptState->ModeBasedKernelDisabledEptPageTable = NULL; - // // The initialization was not successful // @@ -641,24 +468,6 @@ ExecTrapUninitialize() // Indicate that the uninitialization phase finished // g_ExecTrapUnInitializationStarted = FALSE; - - // - // Free Identity Page Table for MBEC hooks (user-disabled) - // - if (g_EptState->ModeBasedUserDisabledEptPageTable != NULL) - { - MmFreeContiguousMemory(g_EptState->ModeBasedUserDisabledEptPageTable); - g_EptState->ModeBasedUserDisabledEptPageTable = NULL; - } - - // - // Free Identity Page Table for MBEC hooks (kernel-disabled) - // - if (g_EptState->ModeBasedKernelDisabledEptPageTable != NULL) - { - MmFreeContiguousMemory(g_EptState->ModeBasedKernelDisabledEptPageTable); - g_EptState->ModeBasedKernelDisabledEptPageTable = NULL; - } } /** @@ -673,7 +482,7 @@ ExecTrapRestoreToNormalEptp(VIRTUAL_MACHINE_STATE * VCpu) // // Change EPTP // - __vmx_vmwrite(VMCS_CTRL_EPT_POINTER, VCpu->EptPointer.AsUInt); + VmxVmwrite64(VMCS_CTRL_EPT_POINTER, VCpu->EptPointer.AsUInt); // // It's on normal EPTP @@ -681,26 +490,6 @@ ExecTrapRestoreToNormalEptp(VIRTUAL_MACHINE_STATE * VCpu) VCpu->NotNormalEptp = FALSE; } -/** - * @brief change to execute-only EPTP - * @param VCpu The virtual processor's state - * - * @return VOID - */ -VOID -ExecTrapChangeToExecuteOnlyEptp(VIRTUAL_MACHINE_STATE * VCpu) -{ - // - // Change EPTP - // - __vmx_vmwrite(VMCS_CTRL_EPT_POINTER, g_EptState->ExecuteOnlyEptPointer.AsUInt); - - // - // It's not on normal EPTP - // - VCpu->NotNormalEptp = TRUE; -} - /** * @brief change to user-disabled MBEC EPTP * @param VCpu The virtual processor's state @@ -711,9 +500,30 @@ VOID ExecTrapChangeToUserDisabledMbecEptp(VIRTUAL_MACHINE_STATE * VCpu) { // - // Change EPTP + // From Intel Manual: + // [Bit 2] If the "mode-based execute control for EPT" VM - execution control is 0, execute access; + // indicates whether instruction fetches are allowed from the 2-MByte page controlled by this entry. + // If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction + // fetches are allowed from supervisor - mode linear addresses in the 2 - MByte page controlled by this entry // - __vmx_vmwrite(VMCS_CTRL_EPT_POINTER, g_EptState->ModeBasedUserDisabledEptPointer.AsUInt); + + // + // Set execute access for PML4s + // + // for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++) + // { + VCpu->EptPageTable->PML4[0].UserModeExecute = FALSE; + + // + // We only set the top-level PML4 for intercepting kernel-mode execution + // + VCpu->EptPageTable->PML4[0].ExecuteAccess = TRUE; + // } + + // + // Invalidate the EPT cache + // + EptInveptSingleContext(VCpu->EptPointer.AsUInt); // // It's not on normal EPTP @@ -731,9 +541,30 @@ VOID ExecTrapChangeToKernelDisabledMbecEptp(VIRTUAL_MACHINE_STATE * VCpu) { // - // Change EPTP + // From Intel Manual: + // [Bit 2] If the "mode-based execute control for EPT" VM - execution control is 0, execute access; + // indicates whether instruction fetches are allowed from the 2-MByte page controlled by this entry. + // If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction + // fetches are allowed from supervisor - mode linear addresses in the 2 - MByte page controlled by this entry // - __vmx_vmwrite(VMCS_CTRL_EPT_POINTER, g_EptState->ModeBasedKernelDisabledEptPointer.AsUInt); + + // + // Set execute access for PML4s + // + // for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++) + // { + VCpu->EptPageTable->PML4[0].UserModeExecute = TRUE; + + // + // We only set the top-level PML4 for intercepting kernel-mode execution + // + VCpu->EptPageTable->PML4[0].ExecuteAccess = FALSE; + // } + + // + // Invalidate the EPT cache + // + EptInveptSingleContext(VCpu->EptPointer.AsUInt); // // It's not on normal EPTP @@ -741,6 +572,47 @@ ExecTrapChangeToKernelDisabledMbecEptp(VIRTUAL_MACHINE_STATE * VCpu) VCpu->NotNormalEptp = TRUE; } +/** + * @brief change to normal MBEC EPTP + * @param VCpu The virtual processor's state + * + * @return VOID + */ +VOID +ExecTrapChangeToNormalMbecEptp(VIRTUAL_MACHINE_STATE * VCpu) +{ + // + // From Intel Manual: + // [Bit 2] If the "mode-based execute control for EPT" VM - execution control is 0, execute access; + // indicates whether instruction fetches are allowed from the 2-MByte page controlled by this entry. + // If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction + // fetches are allowed from supervisor - mode linear addresses in the 2 - MByte page controlled by this entry + // + + // + // Set execute access for PML4s + // + // for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++) + // { + VCpu->EptPageTable->PML4[0].UserModeExecute = TRUE; + + // + // We only set the top-level PML4 for intercepting kernel-mode execution + // + VCpu->EptPageTable->PML4[0].ExecuteAccess = TRUE; + // } + + // + // Invalidate the EPT cache + // + EptInveptSingleContext(VCpu->EptPointer.AsUInt); + + // + // It's not on normal EPTP + // + VCpu->NotNormalEptp = FALSE; +} + /** * @brief Restore the execution of the trap to adjusted trap state * @param VCpu The virtual processor's state @@ -766,6 +638,10 @@ ExecTrapHandleMoveToAdjustedTrapState(VIRTUAL_MACHINE_STATE * VCpu, DEBUGGER_EVE // ExecTrapChangeToUserDisabledMbecEptp(VCpu); } + else + { + LogError("Err, Invalid target mode for execution trap: %x", TargetMode); + } } /** @@ -802,9 +678,7 @@ ExecTrapHandleEptViolationVmexit(VIRTUAL_MACHINE_STATE * VCpu, // // Trigger the event // - DispatchEventMode(VCpu, DEBUGGER_EVENT_MODE_TYPE_USER_MODE, TRUE); - - return TRUE; + DispatchEventMode(VCpu, DEBUGGER_EVENT_MODE_TYPE_USER_MODE); } else if (!ViolationQualification->EptExecutable && ViolationQualification->ExecuteAccess) { @@ -821,7 +695,7 @@ ExecTrapHandleEptViolationVmexit(VIRTUAL_MACHINE_STATE * VCpu, // // Trigger the event // - DispatchEventMode(VCpu, DEBUGGER_EVENT_MODE_TYPE_KERNEL_MODE, TRUE); + DispatchEventMode(VCpu, DEBUGGER_EVENT_MODE_TYPE_KERNEL_MODE); } else { @@ -838,17 +712,22 @@ ExecTrapHandleEptViolationVmexit(VIRTUAL_MACHINE_STATE * VCpu, } /** - * @brief Handle MOV to CR3 vm-exits for hooking mode execution + * @brief Apply the MBEC configuration from the kernel side * @param VCpu The virtual processor's state * * @return VOID */ VOID -ExecTrapHandleCr3Vmexit(VIRTUAL_MACHINE_STATE * VCpu) +ExecTrapApplyMbecConfiguratinFromKernelSide(VIRTUAL_MACHINE_STATE * VCpu) { BOOLEAN Result; UINT32 Index; + // + // Acquire the lock for the exec trap process list + // + SpinlockLock(&ExecTrapProcessListLock); + // // Search the list of processes for the current process's user-execution // trap state @@ -858,6 +737,11 @@ ExecTrapHandleCr3Vmexit(VIRTUAL_MACHINE_STATE * VCpu) &Index, (UINT64)PsGetCurrentProcessId()); + // + // Release the lock for the exec trap process list + // + SpinlockUnlock(&ExecTrapProcessListLock); + // // Check whether the procerss is in the list of interceptions or not // @@ -872,7 +756,7 @@ ExecTrapHandleCr3Vmexit(VIRTUAL_MACHINE_STATE * VCpu) // // Trigger the event // - DispatchEventMode(VCpu, DEBUGGER_EVENT_MODE_TYPE_KERNEL_MODE, TRUE); + DispatchEventMode(VCpu, DEBUGGER_EVENT_MODE_TYPE_KERNEL_MODE); } else if (VCpu->MbecEnabled) { @@ -884,6 +768,18 @@ ExecTrapHandleCr3Vmexit(VIRTUAL_MACHINE_STATE * VCpu) } } +/** + * @brief Handle MOV to CR3 vm-exits for hooking mode execution + * @param VCpu The virtual processor's state + * + * @return VOID + */ +VOID +ExecTrapHandleCr3Vmexit(VIRTUAL_MACHINE_STATE * VCpu) +{ + ExecTrapApplyMbecConfiguratinFromKernelSide(VCpu); +} + /** * @brief Add the target process to the watching list * @param ProcessId @@ -893,10 +789,20 @@ ExecTrapHandleCr3Vmexit(VIRTUAL_MACHINE_STATE * VCpu) BOOLEAN ExecTrapAddProcessToWatchingList(UINT32 ProcessId) { - return InsertionSortInsertItem(&g_ExecTrapState.InterceptionProcessIds[0], - &g_ExecTrapState.NumberOfItems, - MAXIMUM_NUMBER_OF_PROCESSES_FOR_USER_KERNEL_EXEC_THREAD, - (UINT64)ProcessId); + UINT32 Index; + BOOLEAN Result; + + SpinlockLock(&ExecTrapProcessListLock); + + Result = InsertionSortInsertItem(&g_ExecTrapState.InterceptionProcessIds[0], + &g_ExecTrapState.NumberOfItems, + MAXIMUM_NUMBER_OF_PROCESSES_FOR_USER_KERNEL_EXEC_THREAD, + &Index, + (UINT64)ProcessId); + + SpinlockUnlock(&ExecTrapProcessListLock); + + return Result; } /** @@ -908,7 +814,24 @@ ExecTrapAddProcessToWatchingList(UINT32 ProcessId) BOOLEAN ExecTrapRemoveProcessFromWatchingList(UINT32 ProcessId) { - return InsertionSortDeleteItem(&g_ExecTrapState.InterceptionProcessIds[0], - &g_ExecTrapState.NumberOfItems, - (UINT64)ProcessId); + UINT32 Index; + BOOLEAN Result; + + SpinlockLock(&ExecTrapProcessListLock); + + Result = BinarySearchPerformSearchItem(&g_ExecTrapState.InterceptionProcessIds[0], + g_ExecTrapState.NumberOfItems, + &Index, + (UINT64)ProcessId); + + if (Result) + { + Result = InsertionSortDeleteItem(&g_ExecTrapState.InterceptionProcessIds[0], + &g_ExecTrapState.NumberOfItems, + Index); + } + + SpinlockUnlock(&ExecTrapProcessListLock); + + return Result; } diff --git a/hyperdbg/hprdbghv/code/hooks/ept-hook/ModeBasedExecHook.c b/hyperdbg/hyperhv/code/hooks/ept-hook/ModeBasedExecHook.c similarity index 73% rename from hyperdbg/hprdbghv/code/hooks/ept-hook/ModeBasedExecHook.c rename to hyperdbg/hyperhv/code/hooks/ept-hook/ModeBasedExecHook.c index 179c04dd..b8704a1f 100644 --- a/hyperdbg/hprdbghv/code/hooks/ept-hook/ModeBasedExecHook.c +++ b/hyperdbg/hyperhv/code/hooks/ept-hook/ModeBasedExecHook.c @@ -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; } @@ -118,10 +118,12 @@ ModeBasedExecHookDisableKernelModeExecution(PVMM_EPT_PAGE_TABLE EptTable) BOOLEAN ModeBasedExecHookEnableUsermodeExecution(PVMM_EPT_PAGE_TABLE EptTable) { + EPT_PML1_ENTRY Pml1Entries[VMM_EPT_PML1E_COUNT]; + // // 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 @@ -132,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; } @@ -140,11 +142,37 @@ 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; + + // + // If the PML2 entry is not a large page, we should set execute access for PML1s + // It usually happens when the PML2 entry is not a large page and is previously + // used for an EPT hook, so, it has PML1 entries + // + if (!EptTable->PML2[i][j].LargePage) + { + // + // Shift to the left to get the PFN + // + MemoryMapperReadMemorySafeByPhysicalAddress(EptTable->PML2[i][j].PageFrameNumber << 12, (UINT64)Pml1Entries, PAGE_SIZE); + + // + // Set execute access for PML1s + // + for (SIZE_T k = 0; k < VMM_EPT_PML1E_COUNT; k++) + { + Pml1Entries[k].UserModeExecute = TRUE; + } + + // + // Write back the PML1 entries to the EPT page table + // + MemoryMapperWriteMemorySafeByPhysicalAddress(EptTable->PML2[i][j].PageFrameNumber << 12, (UINT64)Pml1Entries, PAGE_SIZE); + } } } @@ -218,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); } diff --git a/hyperdbg/hprdbghv/code/hooks/syscall-hook/EferHook.c b/hyperdbg/hyperhv/code/hooks/syscall-hook/EferHook.c similarity index 78% rename from hyperdbg/hprdbghv/code/hooks/syscall-hook/EferHook.c rename to hyperdbg/hyperhv/code/hooks/syscall-hook/EferHook.c index 5702a2d9..2a3d0bec 100644 --- a/hyperdbg/hprdbghv/code/hooks/syscall-hook/EferHook.c +++ b/hyperdbg/hyperhv/code/hooks/syscall-hook/EferHook.c @@ -1,4 +1,4 @@ -/** +/** * @file EferHook.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief Implementation of the functions related to the EFER Syscall Hook @@ -38,7 +38,7 @@ SyscallHookConfigureEFER(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN EnableEFERSyscall // // Reading IA32_VMX_BASIC_MSR // - VmxBasicMsr.AsUInt = __readmsr(IA32_VMX_BASIC); + VmxBasicMsr.AsUInt = CpuReadMsr(IA32_VMX_BASIC); // // Read previous VM-Entry and VM-Exit controls @@ -46,7 +46,7 @@ SyscallHookConfigureEFER(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN EnableEFERSyscall VmxVmread32P(VMCS_CTRL_VMENTRY_CONTROLS, &VmEntryControls); VmxVmread32P(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, &VmExitControls); - MsrValue.AsUInt = __readmsr(IA32_EFER); + MsrValue.AsUInt = CpuReadMsr(IA32_EFER); if (EnableEFERSyscallHook) { @@ -55,17 +55,17 @@ SyscallHookConfigureEFER(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN EnableEFERSyscall // // Set VM-Entry controls to load EFER // - __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, HvAdjustControls(VmEntryControls | VM_ENTRY_LOAD_IA32_EFER, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS)); + VmxVmwrite32(VMCS_CTRL_VMENTRY_CONTROLS, HvAdjustControls(VmEntryControls | IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_FLAG, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS)); // // Set VM-Exit controls to save EFER // - __vmx_vmwrite(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, HvAdjustControls(VmExitControls | VM_EXIT_SAVE_IA32_EFER, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS)); + VmxVmwrite32(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, HvAdjustControls(VmExitControls | IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_FLAG, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS)); // // Set the GUEST EFER to use this value as the EFER // - __vmx_vmwrite(VMCS_GUEST_EFER, MsrValue.AsUInt); + VmxVmwrite64(VMCS_GUEST_EFER, MsrValue.AsUInt); // // also, we have to set exception bitmap to cause vm-exit on #UDs @@ -79,23 +79,23 @@ SyscallHookConfigureEFER(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN EnableEFERSyscall // // Set VM-Entry controls to load EFER // - __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, HvAdjustControls(VmEntryControls & ~VM_ENTRY_LOAD_IA32_EFER, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS)); + VmxVmwrite32(VMCS_CTRL_VMENTRY_CONTROLS, HvAdjustControls(VmEntryControls & ~IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_FLAG, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS)); // // Set VM-Exit controls to save EFER // - __vmx_vmwrite(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, HvAdjustControls(VmExitControls & ~VM_EXIT_SAVE_IA32_EFER, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS)); + VmxVmwrite32(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, HvAdjustControls(VmExitControls & ~IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_FLAG, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS)); // // Set the GUEST EFER to use this value as the EFER // - __vmx_vmwrite(VMCS_GUEST_EFER, MsrValue.AsUInt); + VmxVmwrite64(VMCS_GUEST_EFER, MsrValue.AsUInt); // // Because we're not save or load EFER on vm-exits so // we have to set it manually // - __writemsr(IA32_EFER, MsrValue.AsUInt); + CpuWriteMsr(IA32_EFER, MsrValue.AsUInt); // // unset the exception to not cause vm-exit on #UDs @@ -119,11 +119,13 @@ SyscallHookEmulateSYSCALL(VIRTUAL_MACHINE_STATE * VCpu) UINT64 MsrValue; UINT64 GuestRip; UINT64 GuestRflags; + UINT64 Ssp; + IA32_U_CET_REGISTER UcetMsr; // // Reading guest's RIP // - __vmx_vmread(VMCS_GUEST_RIP, &GuestRip); + VmxVmread64P(VMCS_GUEST_RIP, &GuestRip); // // Reading instruction length @@ -133,29 +135,47 @@ SyscallHookEmulateSYSCALL(VIRTUAL_MACHINE_STATE * VCpu) // // Reading guest's Rflags // - __vmx_vmread(VMCS_GUEST_RFLAGS, &GuestRflags); + VmxVmread64P(VMCS_GUEST_RFLAGS, &GuestRflags); // // Save the address of the instruction following SYSCALL into RCX and then // load RIP from IA32_LSTAR. // - MsrValue = __readmsr(IA32_LSTAR); + MsrValue = CpuReadMsr(IA32_LSTAR); VCpu->Regs->rcx = GuestRip + InstructionLength; GuestRip = MsrValue; - __vmx_vmwrite(VMCS_GUEST_RIP, GuestRip); + VmxVmwrite64(VMCS_GUEST_RIP, GuestRip); // // Save RFLAGS into R11 and then mask RFLAGS using IA32_FMASK // - MsrValue = __readmsr(IA32_FMASK); + MsrValue = CpuReadMsr(IA32_FMASK); VCpu->Regs->r11 = GuestRflags; GuestRflags &= ~(MsrValue | X86_FLAGS_RF); - __vmx_vmwrite(VMCS_GUEST_RFLAGS, GuestRflags); + VmxVmwrite64(VMCS_GUEST_RFLAGS, GuestRflags); + + // + // Perform emulation of Intel CET (Shadow stacks) + // + if (g_CompatibilityCheck.CetShadowStackSupport) + { + UcetMsr.AsUInt = CpuReadMsr(IA32_U_CET); + + // + // If the shadow stack is enabled, we have to save the current + // + if (UcetMsr.ShStkEn) + { + VmxVmread64P(VMCS_GUEST_SSP, &Ssp); + CpuWriteMsr(IA32_PL3_SSP, Ssp); + VmxVmwrite64(VMCS_GUEST_SSP, 0); + } + } // // Load the CS and SS selectors with values derived from bits 47:32 of IA32_STAR // - MsrValue = __readmsr(IA32_STAR); + MsrValue = CpuReadMsr(IA32_STAR); Cs.Selector = (UINT16)((MsrValue >> 32) & ~3); // STAR[47:32] & ~RPL3 Cs.Base = 0; // flat segment Cs.Limit = (UINT32)~0; // 4GB limit @@ -185,23 +205,42 @@ SyscallHookEmulateSYSRET(VIRTUAL_MACHINE_STATE * VCpu) UINT64 MsrValue; UINT64 GuestRip; UINT64 GuestRflags; + UINT64 Ssp; + IA32_U_CET_REGISTER UcetMsr; // // Load RIP from RCX // GuestRip = VCpu->Regs->rcx; - __vmx_vmwrite(VMCS_GUEST_RIP, GuestRip); + VmxVmwrite64(VMCS_GUEST_RIP, GuestRip); // // Load RFLAGS from R11. Clear RF, VM, reserved bits // GuestRflags = (VCpu->Regs->r11 & ~(X86_FLAGS_RF | X86_FLAGS_VM | X86_FLAGS_RESERVED_BITS)) | X86_FLAGS_FIXED; - __vmx_vmwrite(VMCS_GUEST_RFLAGS, GuestRflags); + VmxVmwrite64(VMCS_GUEST_RFLAGS, GuestRflags); + + // + // Restore user-mode SPP + // + if (g_CompatibilityCheck.CetShadowStackSupport) + { + UcetMsr.AsUInt = CpuReadMsr(IA32_U_CET); + + // + // If the shadow stack is enabled, we have to restore the current + // + if (UcetMsr.ShStkEn) + { + Ssp = CpuReadMsr(IA32_PL3_SSP); + VmxVmwrite64(VMCS_GUEST_SSP, Ssp); + } + } // // SYSRET loads the CS and SS selectors with values derived from bits 63:48 of IA32_STAR // - MsrValue = __readmsr(IA32_STAR); + MsrValue = CpuReadMsr(IA32_STAR); Cs.Selector = (UINT16)(((MsrValue >> 48) + 16) | 3); // (STAR[63:48]+16) | 3 (* RPL forced to 3 *) Cs.Base = 0; // Flat segment Cs.Limit = (UINT32)~0; // 4GB limit @@ -234,7 +273,7 @@ SyscallHookHandleUD(VIRTUAL_MACHINE_STATE * VCpu) // // Reading guest's RIP // - __vmx_vmread(VMCS_GUEST_RIP, &Rip); + VmxVmread64P(VMCS_GUEST_RIP, &Rip); if (g_IsUnsafeSyscallOrSysretHandling) { @@ -272,9 +311,9 @@ SyscallHookHandleUD(VIRTUAL_MACHINE_STATE * VCpu) // // if ((GuestCr3.Flags & PCID_MASK) != PCID_NONE) - OriginalCr3 = __readcr3(); + OriginalCr3 = CpuReadCr3(); - __writecr3(GuestCr3.Flags); + CpuWriteCr3(GuestCr3.Flags); // // Read the memory @@ -313,7 +352,7 @@ SyscallHookHandleUD(VIRTUAL_MACHINE_STATE * VCpu) return FALSE; } - __writecr3(OriginalCr3); + CpuWriteCr3(OriginalCr3); if (InstructionBuffer[0] == 0x0F && InstructionBuffer[1] == 0x05) diff --git a/hyperdbg/hyperhv/code/hooks/syscall-hook/SyscallCallback.c b/hyperdbg/hyperhv/code/hooks/syscall-hook/SyscallCallback.c new file mode 100644 index 00000000..9b348728 --- /dev/null +++ b/hyperdbg/hyperhv/code/hooks/syscall-hook/SyscallCallback.c @@ -0,0 +1,405 @@ +/** + * @file SyscallCallback.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @author jtaw5649 + * @brief Implementation of the functions related to the callback for Syscall + * @details + * + * @version 0.14 + * @date 2025-06-07 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Initialize the syscall callback + * + * @return BOOLEAN + */ +BOOLEAN +SyscallCallbackInitialize() +{ + MSR Msr = {0}; + + // + // Check whether the syscall callback was already initialized or not + // + if (!g_SyscallCallbackStatus) + { + // + // Insert EPT memory page hook for Windows system call handler, KiSystemCall64() + // + Msr.Flags = CpuReadMsr(IA32_LSTAR); + + // + // We set the hook at the address of the system call handler + 3 + // because we don't want to hook the first 3 bytes of the system call handler + // which is SWAPGS instruction + // + g_SystemCallHookAddress = (PVOID)(Msr.Flags + 3); + + // + // Apply the hook from vmx non-root mode + // + if (!ConfigureEptHook(g_SystemCallHookAddress, (UINT32)(ULONG_PTR)PsGetCurrentProcessId())) + { + // LogInfo("Error while inserting EPT page hook for Windows system call handler at address 0x%p+3", Msr.Flags); + + return FALSE; + } + + // + // Allocate buffer for the syscall callback trap flag state + // + g_SyscallCallbackTrapFlagState = (SYSCALL_CALLBACK_TRAP_FLAG_STATE *)PlatformMemAllocateZeroedNonPagedPool(sizeof(SYSCALL_CALLBACK_TRAP_FLAG_STATE)); + + // + // Intercept trap flags #DBs and #BPs for the syscall callback + // + BroadcastEnableDbAndBpExitingAllCores(); + + // + // Enable the syscall callback + // + g_SyscallCallbackStatus = TRUE; + + // + // Successfully enabled the syscall callback + // + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief Check whether the syscall callback is initialized + * + * @return BOOLEAN + */ +BOOLEAN +SyscallCallbackIsInitialized() +{ + return g_SyscallCallbackStatus; +} + +/** + * @brief Uninitialize the syscall callback + * + * @return BOOLEAN + */ +BOOLEAN +SyscallCallbackUninitialize() +{ + if (g_SyscallCallbackStatus) + { + // + // Unset the EPT hook from the syscall entry before disabling state. + // + 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 + // + BroadcastDisableDbAndBpExitingAllCores(); + + // + // Free the buffer for the syscall callback trap flag state + // + PlatformMemFreePool(g_SyscallCallbackTrapFlagState); + + g_SyscallCallbackTrapFlagState = NULL; + g_SystemCallHookAddress = NULL; + g_SyscallCallbackStatus = FALSE; + + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief This function makes sure to unset the RFLAGS.TF on next trigger of #DB + * on the target process/thread + * @param ProcessId + * @param ThreadId + * @param Context + * @param Params + * + * @return BOOLEAN + */ +BOOLEAN +SyscallCallbackStoreProcessInformation(UINT32 ProcessId, + UINT32 ThreadId, + UINT64 Context, + SYSCALL_CALLBACK_CONTEXT_PARAMS * Params) +{ + UINT32 Index; + BOOLEAN Result; + BOOLEAN SuccessfullyStored; + SYSCALL_CALLBACK_PROCESS_THREAD_INFORMATION ProcThrdInfo = {0}; + + // + // Form the process id and thread id into a 64-bit value + // + ProcThrdInfo.Fields.ProcessId = ProcessId; + ProcThrdInfo.Fields.ThreadId = ThreadId; + + // + // Make sure, nobody is in the middle of modifying the list + // + SpinlockLock(&SyscallCallbackModeTrapListLock); + + // + // *** Search the list of processes/threads for the current process's trap flag state *** + // + Result = BinarySearchPerformSearchItem((UINT64 *)&g_SyscallCallbackTrapFlagState->ThreadInformation[0], + g_SyscallCallbackTrapFlagState->NumberOfItems, + &Index, + ProcThrdInfo.asUInt); + + if (Result) + { + // + // It means that we already find this entry in the stored list + // so, just imply that the addition was successful (no need for extra addition) + // + SuccessfullyStored = TRUE; + goto Return; + } + else + { + // + // Insert the thread into the list as the item is not already present + // + SuccessfullyStored = InsertionSortInsertItem((UINT64 *)&g_SyscallCallbackTrapFlagState->ThreadInformation[0], + &g_SyscallCallbackTrapFlagState->NumberOfItems, + MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_SYSCALL_CALLBACK_TRAPS, + &Index, + ProcThrdInfo.asUInt); + + if (SuccessfullyStored) + { + // + // Successfully inserted the thread/process into the list + // Now let's store the context of the caller along with parameters + // + g_SyscallCallbackTrapFlagState->Context[Index] = Context; + memcpy(&g_SyscallCallbackTrapFlagState->Params[Index], Params, sizeof(SYSCALL_CALLBACK_CONTEXT_PARAMS)); + } + + goto Return; + } + +Return: + // + // Unlock the list modification lock + // + SpinlockUnlock(&SyscallCallbackModeTrapListLock); + + return SuccessfullyStored; +} + +/** + * @brief Set the trap flag in the guest after a syscall + * + * @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 BOOLEAN + */ +BOOLEAN +SyscallCallbackSetTrapFlagAfterSyscall(GUEST_REGS * Regs, + UINT32 ProcessId, + UINT32 ThreadId, + UINT64 Context, + SYSCALL_CALLBACK_CONTEXT_PARAMS * Params) +{ + // + // Do not add anything to the list if the syscall callback is not enabled (or disabled by the user) + // + if (!g_SyscallCallbackStatus) + { + // + // syscall callback is not enabled + // + return FALSE; + } + + // + // Insert the thread/process into the list of processes/threads + // + if (!SyscallCallbackStoreProcessInformation(ProcessId, ThreadId, Context, Params)) + { + // + // Failed to store the process/thread information + // + return FALSE; + } + + // + // *** Successfully stored the process/thread information *** + // + + // + // Set the trap flag to TRUE because we want to intercept the thread again + // once it returns to the user-mode (SYSRET) instruction + // + // Here the RFLAGS is in the R11 register (See Intel manual about the SYSCALL register) + // + Regs->r11 |= X86_FLAGS_TF; + + // + // Create log message for the syscall + // + // LogInfo("Syscall callback set trap flag for process: %x, thread: %x\n", ProcessId, ThreadId); + + return TRUE; +} + +/** + * @brief Handle the trap flags as the result of interception of the return of the + * system-call + * + * @param VCpu The virtual processor's state + * @param ProcessId The process id of the thread + * @param ThreadId The thread id of the thread + * + * @return BOOLEAN + */ +BOOLEAN +SyscallCallbackCheckAndHandleAfterSyscallTrapFlags(VIRTUAL_MACHINE_STATE * VCpu, + UINT32 ProcessId, + UINT32 ThreadId) +{ + RFLAGS Rflags = {0}; + UINT32 Index; + UINT64 Context = NULL64_ZERO; + SYSCALL_CALLBACK_CONTEXT_PARAMS Params; + SYSCALL_CALLBACK_PROCESS_THREAD_INFORMATION ProcThrdInfo = {0}; + BOOLEAN Result; + BOOLEAN ResultToReturn; + + // + // Read the trap flag + // + Rflags.AsUInt = HvGetRflags(); + + if (!Rflags.TrapFlag) + { + // + // The trap flag is not set, so we don't need to do anything + // + return FALSE; + } + + // + // Form the process id and thread id into a 64-bit value + // + ProcThrdInfo.Fields.ProcessId = ProcessId; + ProcThrdInfo.Fields.ThreadId = ThreadId; + + // + // Make sure, nobody is in the middle of modifying the list + // + SpinlockLock(&SyscallCallbackModeTrapListLock); + + // + // *** Search the list of processes/threads for the current process's trap flag state *** + // + Result = BinarySearchPerformSearchItem((UINT64 *)&g_SyscallCallbackTrapFlagState->ThreadInformation[0], + g_SyscallCallbackTrapFlagState->NumberOfItems, + &Index, + ProcThrdInfo.asUInt); + + // + // Check whether this thread is expected to have trap flag + // by the syscall callback or not + // + if (Result) + { + // + // Read the context of the caller + // + Context = g_SyscallCallbackTrapFlagState->Context[Index]; + + // + // Read the (optional) parameters of the caller + // + memcpy(&Params, &g_SyscallCallbackTrapFlagState->Params[Index], sizeof(SYSCALL_CALLBACK_CONTEXT_PARAMS)); + + // + // Clear the trap flag from the RFLAGS register + // + HvSetRflagTrapFlag(FALSE); + + // + // Remove the thread/process from the list of processes/threads + // + InsertionSortDeleteItem((UINT64 *)&g_SyscallCallbackTrapFlagState->ThreadInformation[0], + &g_SyscallCallbackTrapFlagState->NumberOfItems, + Index); + + // + // Handled by the syscall callback + // + ResultToReturn = TRUE; + + goto ReturnResult; + } + else + { + // + // Not related to the syscall callback + // + ResultToReturn = FALSE; + + goto ReturnResult; + } + +ReturnResult: + + // + // Unlock the list modification lock + // + SpinlockUnlock(&SyscallCallbackModeTrapListLock); + + // + // Call the callback function to handle the trap flag if its needed + // Note that we call it here so we already unlocked the list lock + // to optimize the performance (avoid holding the lock for a long time) + // + if (ResultToReturn) + { + TransparentCallbackHandleAfterSyscall(VCpu->Regs, ProcessId, ThreadId, Context, &Params); + } + + return ResultToReturn; +} + +/** + * @brief Handle the system call hook callback + * + * @param VCpu The virtual processor's state + * + * @return VOID + */ +VOID +SyscallCallbackHandleSystemCallHook(VIRTUAL_MACHINE_STATE * VCpu) +{ + TransparentHandleSystemCallHook(VCpu->Regs); +} diff --git a/hyperdbg/hprdbghv/code/interface/Callback.c b/hyperdbg/hyperhv/code/interface/Callback.c similarity index 59% rename from hyperdbg/hprdbghv/code/interface/Callback.c rename to hyperdbg/hyperhv/code/interface/Callback.c index bf1ae9f0..3598a9fc 100644 --- a/hyperdbg/hprdbghv/code/interface/Callback.c +++ b/hyperdbg/hyperhv/code/interface/Callback.c @@ -12,134 +12,6 @@ */ #include "pch.h" -/** - * @brief routines callback for preparing and sending message to queue - * - * @param OperationCode - * @param IsImmediateMessage - * @param ShowCurrentSystemTime - * @param Priority - * @param Fmt - * @param ... - * - * @return BOOLEAN - */ -BOOLEAN -LogCallbackPrepareAndSendMessageToQueue(UINT32 OperationCode, - BOOLEAN IsImmediateMessage, - BOOLEAN ShowCurrentSystemTime, - BOOLEAN Priority, - const char * Fmt, - ...) -{ - BOOLEAN Result; - va_list ArgList; - - if (g_Callbacks.LogCallbackPrepareAndSendMessageToQueueWrapper == NULL) - { - // - // Ignore sending message to queue - // - return FALSE; - } - - va_start(ArgList, Fmt); - - Result = g_Callbacks.LogCallbackPrepareAndSendMessageToQueueWrapper(OperationCode, - IsImmediateMessage, - ShowCurrentSystemTime, - Priority, - Fmt, - ArgList); - va_end(ArgList); - - return Result; -} - -/** - * @brief routines callback for sending message to queue - * - * @param OperationCode - * @param IsImmediateMessage - * @param LogMessage - * @param BufferLen - * @param Priority - * - * @return BOOLEAN - */ -BOOLEAN -LogCallbackSendMessageToQueue(UINT32 OperationCode, - BOOLEAN IsImmediateMessage, - CHAR * LogMessage, - UINT32 BufferLen, - BOOLEAN Priority) -{ - if (g_Callbacks.LogCallbackSendMessageToQueue == NULL) - { - // - // Ignore sending message to queue - // - return FALSE; - } - - return g_Callbacks.LogCallbackSendMessageToQueue(OperationCode, - IsImmediateMessage, - LogMessage, - BufferLen, - Priority); -} - -/** - * @brief routines callback for checking if buffer is full - * - * @param Priority - * - * @return BOOLEAN - */ -BOOLEAN -LogCallbackCheckIfBufferIsFull(BOOLEAN Priority) -{ - if (g_Callbacks.LogCallbackCheckIfBufferIsFull == NULL) - { - // - // Ignore sending message to queue - // - return FALSE; - } - - return g_Callbacks.LogCallbackCheckIfBufferIsFull(Priority); -} - -/** - * @brief routines callback for sending buffer - * @param OperationCode - * @param Buffer - * @param BufferLength - * @param Priority - * - * @return BOOLEAN - */ -BOOLEAN -LogCallbackSendBuffer(_In_ UINT32 OperationCode, - _In_reads_bytes_(BufferLength) PVOID Buffer, - _In_ UINT32 BufferLength, - _In_ BOOLEAN Priority) - -{ - if (g_Callbacks.LogCallbackSendBuffer == NULL) - { - // - // Ignore sending buffer - // - return FALSE; - } - - return g_Callbacks.LogCallbackSendBuffer(OperationCode, - Buffer, - BufferLength, - Priority); -} - /** * @brief routines callback to trigger events * @param EventType @@ -214,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 * @@ -328,6 +179,47 @@ 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 + * + * @param Capacity + * @param IsArchLbr + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceCallbackLbrIsSupported(UINT32 * Capacity, BOOLEAN * IsArchLbr) +{ + if (g_Callbacks.HyperTraceCallbackLbrIsSupported == NULL) + { + // + // ignore it as it's not handled + // + return FALSE; + } + return g_Callbacks.HyperTraceCallbackLbrIsSupported(Capacity, IsArchLbr); +} + /** * @brief routine callback to handle breakpoint exception * @@ -371,28 +263,128 @@ DebuggingCallbackHandleDebugBreakpointException(UINT32 CoreId) } /** - * @brief routine callback to handle conditional page-fault exception + * @brief routine callback to handle thread interception * * @param CoreId - * @param Address - * @param PageFaultErrorCode * * @return BOOLEAN */ BOOLEAN -DebuggingCallbackConditionalPageFaultException(UINT32 CoreId, - UINT64 Address, - UINT32 PageFaultErrorCode) +DebuggingCallbackCheckThreadInterception(UINT32 CoreId) { - if (g_Callbacks.DebuggingCallbackConditionalPageFaultException == NULL) + if (g_Callbacks.DebuggingCallbackCheckThreadInterception == NULL) { // - // re-inject it to not disrupt system normal execution + // not handled by user debugger // return FALSE; } - return g_Callbacks.DebuggingCallbackConditionalPageFaultException(CoreId, Address, PageFaultErrorCode); + 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); } /** @@ -415,25 +407,3 @@ InterceptionCallbackTriggerCr3ProcessChange(UINT32 CoreId) g_Callbacks.InterceptionCallbackTriggerCr3ProcessChange(CoreId); } - -/** - * @brief routine callback to handle cr3 process change - * - * @param CoreId - * @param NewCr3 - * - * @return VOID - */ -VOID -InterceptionCallbackCr3VmexitsForThreadInterception(UINT32 CoreId, CR3_TYPE NewCr3) -{ - if (g_Callbacks.AttachingHandleCr3VmexitsForThreadInterception == NULL) - { - // - // ignore it - // - return; - } - - g_Callbacks.AttachingHandleCr3VmexitsForThreadInterception(CoreId, NewCr3); -} diff --git a/hyperdbg/hprdbghv/code/interface/Configuration.c b/hyperdbg/hyperhv/code/interface/Configuration.c similarity index 92% rename from hyperdbg/hprdbghv/code/interface/Configuration.c rename to hyperdbg/hyperhv/code/interface/Configuration.c index aac5db27..7e14d51d 100644 --- a/hyperdbg/hprdbghv/code/interface/Configuration.c +++ b/hyperdbg/hyperhv/code/interface/Configuration.c @@ -20,11 +20,6 @@ VOID ConfigureEnableMovToCr3ExitingOnAllProcessors() { - // - // Indicate that the future #PFs should or should not be checked with user debugger - // - g_CheckPageFaultsAndMov2Cr3VmexitsWithUserDebugger = TRUE; - BroadcastEnableMovToCr3ExitingOnAllProcessors(); } @@ -50,6 +45,18 @@ ConfigureUninitializeExecTrapOnAllProcessors() ExecTrapUninitialize(); } +/** + * @brief Apply the MBEC configuration from the kernel side + * @param CoreId The core id + * + * @return VOID + */ +VOID +ConfigureExecTrapApplyMbecConfiguratinFromKernelSide(UINT32 CoreId) +{ + ExecTrapApplyMbecConfiguratinFromKernelSide(&g_GuestState[CoreId]); +} + /** * @brief Add the target process to the watching list * @param ProcessId @@ -115,11 +122,6 @@ ConfigureDirtyLoggingUninitializeOnAllProcessors() VOID ConfigureDisableMovToCr3ExitingOnAllProcessors() { - // - // Indicate that the future #PFs should or should not be checked with user debugger - // - g_CheckPageFaultsAndMov2Cr3VmexitsWithUserDebugger = FALSE; - BroadcastDisableMovToCr3ExitingOnAllProcessors(); } @@ -145,6 +147,34 @@ ConfigureDisableEferSyscallEventsOnAllProcessors() BroadcastDisableEferSyscallEventsOnAllProcessors(); } +/** + * @brief Remove all hooks from the hooked pages list using Hooking Tag + * @details Should be called from vmx non-root + * + * @param HookingTag The hooking tag to remove all hooks + * + * @return BOOLEAN If unhook was successful it returns true or if it was not successful returns false + */ +BOOLEAN +ConfigureEptHookUnHookAllByHookingTag(UINT64 HookingTag) +{ + return EptHookUnHookAllByHookingTag(HookingTag); +} + +/** + * @brief Remove single hook from the hooked pages by the given hooking tag + * @details Should be called from Vmx root-mode + * + * @param HookingTag The hooking tag to unhook + * @return BOOLEAN If unhook was successful it returns true or if it was not successful returns false + */ +BOOLEAN +ConfigureEptHookUnHookSingleHookByHookingTagFromVmxRoot(UINT64 HookingTag, + EPT_SINGLE_HOOK_UNHOOKING_DETAILS * TargetUnhookingDetails) +{ + return EptHookUnHookSingleHookByHookingTagFromVmxRoot(HookingTag, TargetUnhookingDetails); +} + /** * @brief Remove single hook from the hooked pages list and invalidate TLB * @details Should be called from vmx non-root diff --git a/hyperdbg/hprdbghv/code/interface/DirectVmcall.c b/hyperdbg/hyperhv/code/interface/DirectVmcall.c similarity index 100% rename from hyperdbg/hprdbghv/code/interface/DirectVmcall.c rename to hyperdbg/hyperhv/code/interface/DirectVmcall.c diff --git a/hyperdbg/hprdbghv/code/interface/Dispatch.c b/hyperdbg/hyperhv/code/interface/Dispatch.c similarity index 91% rename from hyperdbg/hprdbghv/code/interface/Dispatch.c rename to hyperdbg/hyperhv/code/interface/Dispatch.c index cd09af16..3d7fdd9f 100644 --- a/hyperdbg/hprdbghv/code/interface/Dispatch.c +++ b/hyperdbg/hyperhv/code/interface/Dispatch.c @@ -116,19 +116,6 @@ DispatchEventCpuid(VIRTUAL_MACHINE_STATE * VCpu) VMM_CALLBACK_TRIGGERING_EVENT_STATUS_TYPE EventTriggerResult; BOOLEAN PostEventTriggerReq = FALSE; - // - // Check if attaching is for command dispatching in user debugger - // or a regular CPUID - // - if (g_Callbacks.UdCheckForCommand != NULL && g_Callbacks.UdCheckForCommand()) - { - // - // It's a thread command for user debugger, no need to run the - // actual CPUID instruction and change the registers - // - return; - } - // // As the context to event trigger, we send the eax before the cpuid // so that the debugger can both read the eax as it's now changed by @@ -183,6 +170,73 @@ DispatchEventCpuid(VIRTUAL_MACHINE_STATE * VCpu) } } +/** + * @brief Handling debugger functions related to XSETBV events + * + * @param VCpu The virtual processor's state + * @return VOID + */ +VOID +DispatchEventXsetbv(VIRTUAL_MACHINE_STATE * VCpu) +{ + UINT64 Context; + VMM_CALLBACK_TRIGGERING_EVENT_STATUS_TYPE EventTriggerResult; + BOOLEAN PostEventTriggerReq = FALSE; + + // + // As the context to event trigger, we send the ecx (XCR index) before the xsetbv + // so that the debugger can both read the ecx as it contains the XCR index + // and also can modify the results + // + if (g_TriggerEventForXsetbvs) + { + // + // Adjusting the core context (save ECX for the debugger) + // + Context = VCpu->Regs->rcx & 0xffffffff; + + // + // Triggering the pre-event + // + EventTriggerResult = VmmCallbackTriggerEvents(XSETBV_INSTRUCTION_EXECUTION, + VMM_CALLBACK_CALLING_STAGE_PRE_EVENT_EMULATION, + (PVOID)Context, + &PostEventTriggerReq, + VCpu->Regs); + + // + // Check whether we need to short-circuiting event emulation or not + // + if (EventTriggerResult != VMM_CALLBACK_TRIGGERING_EVENT_STATUS_SUCCESSFUL_IGNORE_EVENT) + { + // + // Handle the XSETBV event in the case of triggering event + // + VmxHandleXsetbv(VCpu); + } + + // + // Check for the post-event triggering needs + // + if (PostEventTriggerReq) + { + VmmCallbackTriggerEvents(XSETBV_INSTRUCTION_EXECUTION, + VMM_CALLBACK_CALLING_STAGE_POST_EVENT_EMULATION, + (PVOID)Context, + NULL, + VCpu->Regs); + } + } + else + { + // + // Otherwise and if there is no event, we should handle the XSETBV + // normally + // + VmxHandleXsetbv(VCpu); + } +} + /** * @brief Handling debugger functions related to RDTSC/RDTSCP events * @@ -199,7 +253,6 @@ DispatchEventTsc(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN IsRdtscp) // // As the context to event trigger, we send the false which means // it's an rdtsc (for rdtscp we set Context to true) - // Note : Using !tsc command in transparent-mode is not allowed // EventTriggerResult = VmmCallbackTriggerEvents(TSC_INSTRUCTION_EXECUTION, VMM_CALLBACK_CALLING_STAGE_PRE_EVENT_EMULATION, @@ -304,12 +357,11 @@ DispatchEventVmcall(VIRTUAL_MACHINE_STATE * VCpu) * @param VCpu The virtual processor's state * @param IsUserMode Whether the execution event caused by a switch from kernel-to-user * or otherwise user-to-kernel - * @param HandleState whether the state should be handled by dispatcher or not * * @return VOID */ VOID -DispatchEventMode(VIRTUAL_MACHINE_STATE * VCpu, DEBUGGER_EVENT_MODE_TYPE TargetMode, BOOLEAN HandleState) +DispatchEventMode(VIRTUAL_MACHINE_STATE * VCpu, DEBUGGER_EVENT_MODE_TYPE TargetMode) { VMM_CALLBACK_TRIGGERING_EVENT_STATUS_TYPE EventTriggerResult; BOOLEAN PostEventTriggerReq = FALSE; @@ -320,23 +372,48 @@ DispatchEventMode(VIRTUAL_MACHINE_STATE * VCpu, DEBUGGER_EVENT_MODE_TYPE TargetM if (g_ExecTrapInitialized) { // - // Triggering the pre-event + // check for user-mode thread interception // - EventTriggerResult = VmmCallbackTriggerEvents(TRAP_EXECUTION_MODE_CHANGED, - VMM_CALLBACK_CALLING_STAGE_PRE_EVENT_EMULATION, - (PVOID)TargetMode, - &PostEventTriggerReq, - VCpu->Regs); + if (TargetMode == DEBUGGER_EVENT_MODE_TYPE_USER_MODE && + DebuggingCallbackCheckThreadInterception(VCpu->CoreId)) + { + // + // 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(), + // PsGetCurrentProcessId(), + // VCpu->LastVmexitRip); + + // + // In this case, we need to short circuit the event, in user-mode debugger we + // prevent the execution by short-circuiting the event + // + EventTriggerResult = VMM_CALLBACK_TRIGGERING_EVENT_STATUS_SUCCESSFUL_IGNORE_EVENT; + } + else + { + // + // Triggering the pre-event + // + EventTriggerResult = VmmCallbackTriggerEvents(TRAP_EXECUTION_MODE_CHANGED, + VMM_CALLBACK_CALLING_STAGE_PRE_EVENT_EMULATION, + (PVOID)TargetMode, + &PostEventTriggerReq, + VCpu->Regs); + } // // Check whether we need to short-circuiting event emulation or not // - if (EventTriggerResult != VMM_CALLBACK_TRIGGERING_EVENT_STATUS_SUCCESSFUL_IGNORE_EVENT && HandleState) + if (EventTriggerResult != VMM_CALLBACK_TRIGGERING_EVENT_STATUS_SUCCESSFUL_IGNORE_EVENT) { // // Handle the user-mode/kernel-mode execution trap event in the case of triggering event // - ExecTrapHandleMoveToAdjustedTrapState(VCpu, (UINT64)TargetMode); + ExecTrapHandleMoveToAdjustedTrapState(VCpu, TargetMode); } // @@ -349,10 +426,7 @@ DispatchEventMode(VIRTUAL_MACHINE_STATE * VCpu, DEBUGGER_EVENT_MODE_TYPE TargetM // Otherwise and if there is no event, we should handle the // user-mode/kernel-mode execution trap normally // - if (HandleState) - { - ExecTrapHandleMoveToAdjustedTrapState(VCpu, (UINT64)TargetMode); - } + ExecTrapHandleMoveToAdjustedTrapState(VCpu, TargetMode); } } @@ -518,7 +592,7 @@ DispatchEventRdmsr(VIRTUAL_MACHINE_STATE * VCpu) // // Handle vm-exit and perform changes // - MsrHandleRdmsrVmexit(VCpu->Regs); + MsrHandleRdmsrVmexit(VCpu); } // @@ -563,7 +637,7 @@ DispatchEventWrmsr(VIRTUAL_MACHINE_STATE * VCpu) // // Handle vm-exit and perform changes // - MsrHandleWrmsrVmexit(VCpu->Regs); + MsrHandleWrmsrVmexit(VCpu); } // @@ -637,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; } @@ -776,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; @@ -811,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; } @@ -900,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); } // @@ -961,6 +1032,14 @@ DispatchEventHiddenHookExecCc(VIRTUAL_MACHINE_STATE * VCpu, PVOID Context) { BOOLEAN PostEventTriggerReq = FALSE; + // + // In syscall back, a hidden hook for the system call handler gets inserted + // + if (g_SyscallCallbackStatus && Context == g_SystemCallHookAddress) + { + SyscallCallbackHandleSystemCallHook(VCpu); + } + // // Triggering the pre-event (This command only support the // pre-event, the post-event doesn't make sense in this command) diff --git a/hyperdbg/hprdbghv/code/interface/Export.c b/hyperdbg/hyperhv/code/interface/Export.c similarity index 63% rename from hyperdbg/hprdbghv/code/interface/Export.c rename to hyperdbg/hyperhv/code/interface/Export.c index 617cb85f..f959d642 100644 --- a/hyperdbg/hprdbghv/code/interface/Export.c +++ b/hyperdbg/hyperhv/code/interface/Export.c @@ -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; } /** @@ -115,25 +128,57 @@ VmFuncSetRflagTrapFlag(BOOLEAN Set) /** * @brief Set LOAD DEBUG CONTROLS on Vm-entry controls * + * @param CoreId target core id * @param Set Set or unset + * * @return VOID */ VOID -VmFuncSetLoadDebugControls(BOOLEAN Set) +VmFuncSetLoadDebugControls(UINT32 CoreId, BOOLEAN Set) { - HvSetLoadDebugControls(Set); + HvSetLoadDebugControls(&g_GuestState[CoreId], Set); +} + +/** + * @brief Set LOAD GUEST IA32_LBR_CTL on Vm-entry controls + * + * @param CoreId target core id + * @param Set Set or unset + * + * @return VOID + */ +VOID +VmFuncSetLoadGuestIa32LbrCtl(UINT32 CoreId, BOOLEAN Set) +{ + HvSetLoadGuestIa32LbrCtl(&g_GuestState[CoreId], Set); } /** * @brief Set SAVE DEBUG CONTROLS on Vm-exit controls * + * @param CoreId target core id * @param Set Set or unset + * * @return VOID */ VOID -VmFuncSetSaveDebugControls(BOOLEAN Set) +VmFuncSetSaveDebugControls(UINT32 CoreId, BOOLEAN Set) { - HvSetSaveDebugControls(Set); + HvSetSaveDebugControls(&g_GuestState[CoreId], Set); +} + +/** + * @brief Set CLEAR GUEST IA32_LBR_CTL on Vm-exit controls + * + * @param CoreId target core id + * @param Set Set or unset + * + * @return VOID + */ +VOID +VmFuncSetClearGuestIa32LbrCtl(UINT32 CoreId, BOOLEAN Set) +{ + HvSetClearGuestIa32LbrCtl(&g_GuestState[CoreId], Set); } /** @@ -389,6 +434,211 @@ VmFuncSetRip(UINT64 Rip) HvSetRip(Rip); } +/** + * @brief Get the guest state of IA32_DEBUGCTL + * + * @return UINT64 + */ +UINT64 +VmFuncGetDebugctl() +{ + return HvGetDebugctl(); +} + +/** + * @brief Get the guest state of IA32_DEBUGCTL on the target core from VMCS + * using VMCALL + * + * @return UINT64 + */ +UINT64 +VmFuncGetDebugctlVmcallOnTargetCore() +{ + return CrossVmcallGetDebugctlVmcallOnTargetCore(); +} + +/** + * @brief Get the guest state of IA32_LBR_CTL + * + * @return UINT64 + */ +UINT64 +VmFuncGetGuestIa32LbrCtl() +{ + return HvGetGuestIa32LbrCtl(); +} + +/** + * @brief Get the guest state of IA32_LBR_CTL on the target core from VMCS + * + * @return UINT64 + */ +UINT64 +VmFuncGetGuestIa32LbrCtlVmcallOnTargetCore() +{ + return CrossVmcallGetGuestIa32LbrCtlVmcallOnTargetCore(); +} + +/** + * @brief Check if CPU support save and load debug controls on exit and load entries + * + * @return BOOLEAN + */ +BOOLEAN +VmFuncCheckCpuSupportForSaveAndLoadDebugControls() +{ + return HvCheckCpuSupportForSaveAndLoadDebugControls(); +} + +/** + * @brief Check if CPU support load and clear guest IA32_LBR_CTL controls on VM-entry and VM-exit + * + * @return BOOLEAN + */ +BOOLEAN +VmFuncCheckCpuSupportForLoadAndClearGuestIa32LbrCtlControls() +{ + return HvCheckCpuSupportForLoadAndClearGuestIa32LbrCtlControls(); +} + +/** + * @brief Set the guest state of IA32_DEBUGCTL + * @param Value + * + * @return VOID + */ +VOID +VmFuncSetDebugctl(UINT64 Value) +{ + HvSetDebugctl(Value); +} + +/** + * @brief Set the guest state of IA32_DEBUGCTL on the target core from VMCS + * using VMCALL + * @param Value + * + * @return VOID + */ +VOID +VmFuncSetDebugctlVmcallOnTargetCore(UINT64 Value) +{ + CrossVmcallSetDebugctlVmcallOnTargetCore(Value); +} + +/** + * @brief Set the guest state of IA32_LBR_CTL + * @param Value + * + * @return VOID + */ +VOID +VmFuncSetGuestIa32LbrCtl(UINT64 Value) +{ + HvSetGuestIa32LbrCtl(Value); +} + +/** + * @brief Set the guest state of IA32_LBR_CTL on the target core from VMCS + * using VMCALL + * @param Value + * + * @return VOID + */ +VOID +VmFuncSetGuestIa32LbrCtlVmcallOnTargetCore(UINT64 Value) +{ + CrossVmcallSetGuestIa32LbrCtlVmcallOnTargetCore(Value); +} + +/** + * @brief Set the guest state of MSR_LEGACY_LBR_SELECT + * @param FilterOptions + * + * @return VOID + */ +VOID +VmFuncSetLbrSelect(UINT64 FilterOptions) +{ + HvSetLbrSelect(FilterOptions); +} + +/** + * @brief Set the guest state of MSR_LEGACY_LBR_SELECT on the target core from VMCS using VMCALL + * @param FilterOptions + * + * @return VOID + */ +VOID +VmFuncSetLbrSelectVmcallOnTargetCore(UINT64 FilterOptions) +{ + CrossVmcallSetLbrSelectVmcallOnTargetCore(FilterOptions); +} + +/** + * @brief Set LOAD DEBUG CONTROLS on VM-entry controls on the target core from VMCS using VMCALL + * + * @param Set Set or unset + * + * @return VOID + */ +VOID +VmFuncSetLoadDebugControlsVmcallOnTargetCore(BOOLEAN Set) +{ + CrossVmcallSetLoadDebugControlsVmcallOnTargetCore(Set); +} + +/** + * @brief Set LOAD GUEST IA32_LBR_CTL on VM-entry controls on the target core from VMCS using VMCALL + * + * @param Set Set or unset + * + * @return VOID + */ +VOID +VmFuncSetLoadGuestIa32LbrCtlVmcallOnTargetCore(BOOLEAN Set) +{ + CrossVmcallSetLoadGuestIa32LbrCtlVmcallOnTargetCore(Set); +} + +/** + * @brief Set SAVE DEBUG CONTROLS on VM-exit controls on the target core from VMCS using VMCALL + * + * @param Set Set or unset + * + * @return VOID + */ +VOID +VmFuncSetSaveDebugControlsVmcallOnTargetCore(BOOLEAN Set) +{ + CrossVmcallSetSaveDebugControlsVmcallOnTargetCore(Set); +} + +/** + * @brief Set CLEAR GUEST IA32_LBR_CTL on VM-exit controls on the target core from VMCS using VMCALL + * + * @param Set Set or unset + * + * @return VOID + */ +VOID +VmFuncSetClearGuestIa32LbrCtlVmcallOnTargetCore(BOOLEAN Set) +{ + CrossVmcallSetClearGuestIa32LbrCtlVmcallOnTargetCore(Set); +} + +/** + * @brief Set the guest state of DR7 + * @param Value + * + * @return VOID + */ +VOID +VmFuncSetDebugReg7(UINT64 Value) +{ + HvSetDebugReg7(Value); +} + /** * @brief Read guest's interruptibility state * @@ -589,6 +839,18 @@ VmFuncSetTriggerEventForCpuids(BOOLEAN Set) g_TriggerEventForCpuids = Set; } +/** + * @brief Set trigger event for XSETBVs + * + * @param Set Set or unset the trigger + * @return VOID + */ +VOID +VmFuncSetTriggerEventForXsetbvs(BOOLEAN Set) +{ + g_TriggerEventForXsetbvs = Set; +} + /** * @brief VMX-root compatible strlen * @param s A pointer to the string @@ -608,11 +870,23 @@ VmFuncVmxCompatibleStrlen(const CHAR * s) * @return UINT32 */ UINT32 -VmFuncVmxCompatibleWcslen(const wchar_t * s) +VmFuncVmxCompatibleWcslen(const WCHAR * s) { return VmxCompatibleWcslen(s); } +/** + * @brief VMX-root compatible micro sleep + * @param Us Delay in micro seconds + * + * @return VOID + */ +VOID +VmFuncVmxCompatibleMicroSleep(UINT64 Us) +{ + VmxCompatibleMicroSleep(Us); +} + /** * @brief Inject #PF and configure CR2 register * @@ -680,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); } @@ -731,7 +1005,21 @@ VmFuncEventInjectBreakpoint() INT32 VmFuncVmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2) { - return VmxCompatibleStrcmp(Address1, Address2); + return VmxCompatibleStrcmp(Address1, Address2, NULL_ZERO, FALSE); +} + +/** + * @brief VMX-root compatible strncmp + * @param Address1 + * @param Address2 + * @param Num + * + * @return INT32 + */ +INT32 +VmFuncVmxCompatibleStrncmp(const CHAR * Address1, const CHAR * Address2, SIZE_T Num) +{ + return VmxCompatibleStrcmp(Address1, Address2, Num, TRUE); } /** @@ -742,9 +1030,23 @@ VmFuncVmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2) * @return INT32 */ INT32 -VmFuncVmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2) +VmFuncVmxCompatibleWcscmp(const WCHAR * Address1, const WCHAR * Address2) { - return VmxCompatibleWcscmp(Address1, Address2); + return VmxCompatibleWcscmp(Address1, Address2, NULL_ZERO, FALSE); +} + +/** + * @brief VMX-root compatible wcsncmp + * @param Address1 + * @param Address2 + * @param Num + * + * @return INT32 + */ +INT32 +VmFuncVmxCompatibleWcsncmp(const WCHAR * Address1, const WCHAR * Address2, SIZE_T Num) +{ + return VmxCompatibleWcscmp(Address1, Address2, Num, TRUE); } /** @@ -756,14 +1058,14 @@ VmFuncVmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2) * @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 */ @@ -776,7 +1078,7 @@ VmFuncEnableMtfAndChangeExternalInterruptState(UINT32 CoreId) /** * @brief Checks to enable and reinject previous interrupts * - * @param UINT32 CoreId + * @param CoreId * * @return VOID */ @@ -785,3 +1087,58 @@ VmFuncEnableAndCheckForPreviousExternalInterrupts(UINT32 CoreId) { HvEnableAndCheckForPreviousExternalInterrupts(&g_GuestState[CoreId]); } + +/** + * @brief Store the details Local APIC in xapic or x2apic modes + * @param LocalApicBuffer + * @param IsUsingX2APIC + * + * @return BOOLEAN + */ +BOOLEAN +VmFuncApicStoreLocalApicFields(PLAPIC_PAGE LocalApicBuffer, PBOOLEAN IsUsingX2APIC) +{ + return ApicStoreLocalApicFields(LocalApicBuffer, IsUsingX2APIC); +} + +/** + * @brief Store the details of I/O APIC + * @param IoApicPackets + * + * @return BOOLEAN + */ +BOOLEAN +VmFuncApicStoreIoApicFields(IO_APIC_ENTRY_PACKETS * IoApicPackets) +{ + return ApicStoreIoApicFields(IoApicPackets); +} + +/** + * @brief Perform query for IDT entries + * + * @param IdtQueryRequest + * @param ReadFromVmxRoot + * + * @return VOID + */ +VOID +VmFuncIdtQueryEntries(PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtQueryRequest, + BOOLEAN ReadFromVmxRoot) +{ + IdtEmulationQueryIdtEntriesRequest(IdtQueryRequest, ReadFromVmxRoot); +} + +/** + * @brief Perform actions related to System Management Interrupts (SMIs) + * + * @param SmiOperationRequest + * @param ApplyFromVmxRootMode + * + * @return BOOLEAN + */ +BOOLEAN +VmFuncSmmPerformSmiOperation(SMI_OPERATION_PACKETS * SmiOperationRequest, + BOOLEAN ApplyFromVmxRootMode) +{ + return SmmPerformSmiOperation(SmiOperationRequest, ApplyFromVmxRootMode); +} diff --git a/hyperdbg/hyperhv/code/interface/HyperEvade.c b/hyperdbg/hyperhv/code/interface/HyperEvade.c new file mode 100644 index 00000000..2fb263c8 --- /dev/null +++ b/hyperdbg/hyperhv/code/interface/HyperEvade.c @@ -0,0 +1,159 @@ +/** + * @file HyperEvade.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @author jtaw5649 + * @brief Hyperevade function wrappers + * @details + * + * @version 0.14 + * @date 2025-06-07 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Wrapper for hiding debugger on transparent-mode (activate transparent-mode) + * + * @param HyperevadeCallbacks + * @param TransparentModeRequest + * + * @return BOOLEAN + */ +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 *** + // + + // + // Fill the callbacks for using hyperlog in hyperevade + // We use the callbacks directly to avoid two calls to the same function + // + HyperevadeCallbacks.LogCallbackPrepareAndSendMessageToQueueWrapper = g_Callbacks.LogCallbackPrepareAndSendMessageToQueueWrapper; + HyperevadeCallbacks.LogCallbackSendMessageToQueue = g_Callbacks.LogCallbackSendMessageToQueue; + HyperevadeCallbacks.LogCallbackSendBuffer = g_Callbacks.LogCallbackSendBuffer; + HyperevadeCallbacks.LogCallbackCheckIfBufferIsFull = g_Callbacks.LogCallbackCheckIfBufferIsFull; + + // + // HyperTrace callback(s) + // + HyperevadeCallbacks.HyperTraceLbrIsSupported = HyperTraceCallbackLbrIsSupported; + + // + // Memory callbacks + // + HyperevadeCallbacks.CheckAccessValidityAndSafety = CheckAccessValidityAndSafety; + HyperevadeCallbacks.MemoryMapperReadMemorySafeOnTargetProcess = MemoryMapperReadMemorySafeOnTargetProcess; + HyperevadeCallbacks.MemoryMapperWriteMemorySafeOnTargetProcess = MemoryMapperWriteMemorySafeOnTargetProcess; + + // + // Common callbacks + // + HyperevadeCallbacks.CommonGetProcessNameFromProcessControlBlock = CommonGetProcessNameFromProcessControlBlock; + + // + // System call callbacks + // + HyperevadeCallbacks.SyscallCallbackSetTrapFlagAfterSyscall = SyscallCallbackSetTrapFlagAfterSyscall; + + // + // VMX callbacks + // + HyperevadeCallbacks.HvHandleTrapFlag = HvHandleTrapFlag; + HyperevadeCallbacks.EventInjectGeneralProtection = EventInjectGeneralProtection; + + // + // 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 + // + g_CheckForFootprints = TRUE; + return TRUE; + } + else + { + // + // Status is set within the transparent mode (hyperevade) module + // + g_CheckForFootprints = FALSE; + return FALSE; + } +} + +/** + * @brief Deactivate transparent-mode + * @param TransparentModeRequest + * + * @return BOOLEAN + */ +BOOLEAN +TransparentUnhideDebuggerWrapper(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE * TransparentModeRequest) +{ + if (SyscallCallbackIsInitialized() && !SyscallCallbackUninitialize()) + { + if (TransparentModeRequest != NULL) + { + TransparentModeRequest->KernelStatus = DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER; + } + + return FALSE; + } + + if (TransparentUnhideDebugger()) + { + // + // Unset transparent mode for the VMM module + // + g_CheckForFootprints = FALSE; + + if (TransparentModeRequest != NULL) + { + TransparentModeRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + + return TRUE; + } + else + { + if (TransparentModeRequest != NULL) + { + TransparentModeRequest->KernelStatus = DEBUGGER_ERROR_DEBUGGER_ALREADY_UNHIDE; + } + return FALSE; + } +} diff --git a/hyperdbg/hprdbghv/code/memory/AddressCheck.c b/hyperdbg/hyperhv/code/memory/AddressCheck.c similarity index 86% rename from hyperdbg/hprdbghv/code/memory/AddressCheck.c rename to hyperdbg/hyperhv/code/memory/AddressCheck.c index 851b1f69..4513ce01 100644 --- a/hyperdbg/hprdbghv/code/memory/AddressCheck.c +++ b/hyperdbg/hyperhv/code/memory/AddressCheck.c @@ -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 @@ -112,7 +112,7 @@ CheckAddressCanonicality(UINT64 VAddr, PBOOLEAN IsKernelAddress) /** * @brief Checks if the physical address is correct or not based on physical address width * - * @param VAddr Physical address to check + * @param PAddr Physical address to check * * @return BOOLEAN */ @@ -130,7 +130,7 @@ CheckAddressPhysical(UINT64 PAddr) // // get max address for physical address // - MaxPA = ((UINT64)1ull << (AddrWidth - 1)) - 1; + MaxPA = ((UINT64)1ull << (AddrWidth)) - 1; // LogInfo("Max physical address: %llx", MaxPA); @@ -146,14 +146,15 @@ CheckAddressPhysical(UINT64 PAddr) } /** - * @brief Check the safety to access the memory + * @brief Check the safety to access the memory wrapper * @param TargetAddress * @param Size + * @param ProcessId NULL if the current process is used * * @return BOOLEAN */ BOOLEAN -CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size) +CheckAccessValidityAndSafetyWrapper(UINT64 TargetAddress, UINT32 Size, UINT32 ProcessId) { CR3_TYPE GuestCr3; UINT64 OriginalCr3; @@ -173,16 +174,26 @@ CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size) goto Return; } - // - // Find the current process cr3 - // - GuestCr3.Flags = LayoutGetCurrentProcessCr3().Flags; + if (ProcessId == NULL_ZERO) + { + // + // Find the current process cr3 + // + GuestCr3.Flags = LayoutGetCurrentProcessCr3().Flags; + } + else + { + // + // Find the target process cr3 + // + GuestCr3.Flags = LayoutGetCr3ByProcessId(ProcessId).Flags; + } // // Move to new cr3 // - OriginalCr3 = __readcr3(); - __writecr3(GuestCr3.Flags); + OriginalCr3 = CpuReadCr3(); + CpuWriteCr3(GuestCr3.Flags); // // We'll only check address with TSX if the address is a kernel-mode @@ -199,7 +210,7 @@ CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size) // 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)) @@ -290,14 +301,42 @@ RestoreCr3: // // Move back to original cr3 // - __writecr3(OriginalCr3); + CpuWriteCr3(OriginalCr3); Return: return Result; } /** - * @brief This function returns the maximum instruction length that can be read from this address + * @brief Check the safety to access the memory + * @param TargetAddress + * @param Size + * + * @return BOOLEAN + */ +BOOLEAN +CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size) +{ + return CheckAccessValidityAndSafetyWrapper(TargetAddress, Size, NULL_ZERO); +} + +/** + * @brief Check the safety to access the memory by process ID + * @param TargetAddress + * @param Size + * @param ProcessId + * + * @return BOOLEAN + */ +BOOLEAN +CheckAccessValidityAndSafetyByProcessId(UINT64 TargetAddress, UINT32 Size, UINT32 ProcessId) +{ + return CheckAccessValidityAndSafetyWrapper(TargetAddress, Size, ProcessId); +} + +/** + * @brief This function returns the maximum instruction length that + * can be read from this address * @param Address * * @return UINT32 diff --git a/hyperdbg/hprdbghv/code/memory/Conversion.c b/hyperdbg/hyperhv/code/memory/Conversion.c similarity index 100% rename from hyperdbg/hprdbghv/code/memory/Conversion.c rename to hyperdbg/hyperhv/code/memory/Conversion.c diff --git a/hyperdbg/hprdbghv/code/memory/Layout.c b/hyperdbg/hyperhv/code/memory/Layout.c similarity index 97% rename from hyperdbg/hprdbghv/code/memory/Layout.c rename to hyperdbg/hyperhv/code/memory/Layout.c index 9631f749..a7b69139 100644 --- a/hyperdbg/hprdbghv/code/memory/Layout.c +++ b/hyperdbg/hyperhv/code/memory/Layout.c @@ -76,7 +76,7 @@ LayoutGetExactGuestProcessCr3() { CR3_TYPE GuestCr3 = {0}; - __vmx_vmread(VMCS_GUEST_CR3, &GuestCr3.Flags); + VmxVmread64P(VMCS_GUEST_CR3, &GuestCr3.Flags); return GuestCr3; } diff --git a/hyperdbg/hprdbghv/code/memory/MemoryManager.c b/hyperdbg/hyperhv/code/memory/MemoryManager.c similarity index 56% rename from hyperdbg/hprdbghv/code/memory/MemoryManager.c rename to hyperdbg/hyperhv/code/memory/MemoryManager.c index 67e5ac4d..e9fd1c6a 100644 --- a/hyperdbg/hprdbghv/code/memory/MemoryManager.c +++ b/hyperdbg/hyperhv/code/memory/MemoryManager.c @@ -11,6 +11,63 @@ */ #include "pch.h" +/** + * @brief Read physical memory from the physical address (used in VMI mode) + * + * @param PhysicalAddress Physical Address + * @param Buffer Buffer to save the memory + * @param BufferSize Size of the buffer + * + * @return BOOLEAN + */ +BOOLEAN +ReadPhysicalMemoryUsingMapIoSpace(PVOID PhysicalAddress, PVOID Buffer, SIZE_T BufferSize) +{ + PHYSICAL_ADDRESS PhysicalAddressTemp = {0}; + PhysicalAddressTemp.QuadPart = (LONGLONG)PhysicalAddress; + + PVOID VirtualAddress = MmMapIoSpaceEx(PhysicalAddressTemp, BufferSize, PAGE_READWRITE | PAGE_NOCACHE); + + if (VirtualAddress == NULL) + { + return FALSE; + } + + RtlCopyMemory(Buffer, VirtualAddress, BufferSize); + + MmUnmapIoSpace(VirtualAddress, BufferSize); + + return TRUE; +} + +/** + * @brief Write physical memory to the physical address (used in VMI mode) + * + * @param PhysicalAddress Physical Address + * @param Buffer Buffer to write to the memory + * @param BufferSize Size of the buffer + * + * @return BOOLEAN + */ +BOOLEAN +WritePhysicalMemoryUsingMapIoSpace(PVOID PhysicalAddress, PVOID Buffer, SIZE_T BufferSize) +{ + PHYSICAL_ADDRESS PhysicalAddressTemp = {0}; + PhysicalAddressTemp.QuadPart = (LONGLONG)PhysicalAddress; + + PVOID VirtualAddress = MmMapIoSpaceEx(PhysicalAddressTemp, BufferSize, PAGE_READWRITE | PAGE_NOCACHE); + if (VirtualAddress == NULL) + { + return FALSE; + } + + RtlCopyMemory(VirtualAddress, Buffer, BufferSize); + + MmUnmapIoSpace(VirtualAddress, BufferSize); + + return TRUE; +} + /** * @brief Read process memory * @@ -113,7 +170,30 @@ MemoryManagerReadProcessMemoryNormal(HANDLE PID, } CopyAddress.PhysicalAddress.QuadPart = (LONGLONG)Address; - MmCopyMemory(UserBuffer, CopyAddress, Size, MM_COPY_MEMORY_PHYSICAL, ReturnSize); + + if (MmCopyMemory(UserBuffer, CopyAddress, Size, MM_COPY_MEMORY_PHYSICAL, ReturnSize) != STATUS_SUCCESS && *ReturnSize == 0) + { + // + // If the memory is not readable, it might be an MMIO address + // Try again with another method + // + + // LogInfo("reading using MMIO Map IO Space using VMCALL"); + + if (AsmVmxVmcall(VMCALL_READ_PHYSICAL_MEMORY, (UINT64)Address, (UINT64)UserBuffer, (UINT64)Size) == STATUS_SUCCESS) + { + *ReturnSize = Size; + return TRUE; + } + else + { + // + // unknown error + // + *ReturnSize = 0; + return FALSE; + } + } } else { @@ -136,3 +216,29 @@ MemoryManagerReadProcessMemoryNormal(HANDLE PID, } } } + +/** + * @brief Write process memory + * + * @details This function should not be called from vmx-root mode + * + * @param TargetAddress Target Address + * @param UserBuffer Buffer to write to the memory + * @param Size Size of the buffer + * + * @return BOOLEAN + */ +BOOLEAN +MemoryManagerWritePhysicalMemoryNormal(PVOID TargetAddress, + PVOID UserBuffer, + SIZE_T Size) +{ + if (AsmVmxVmcall(VMCALL_WRITE_PHYSICAL_MEMORY, (UINT64)TargetAddress, (UINT64)UserBuffer, (UINT64)Size) == STATUS_SUCCESS) + { + return TRUE; + } + else + { + return FALSE; + } +} diff --git a/hyperdbg/hprdbghv/code/memory/MemoryMapper.c b/hyperdbg/hyperhv/code/memory/MemoryMapper.c similarity index 91% rename from hyperdbg/hprdbghv/code/memory/MemoryMapper.c rename to hyperdbg/hyperhv/code/memory/MemoryMapper.c index 22c673dd..f95b1e13 100644 --- a/hyperdbg/hprdbghv/code/memory/MemoryMapper.c +++ b/hyperdbg/hyperhv/code/memory/MemoryMapper.c @@ -63,7 +63,7 @@ MemoryMapperGetPteVa(PVOID Va, PAGING_LEVEL Level) // // Read the current cr3 // - Cr3.Flags = __readcr3(); + Cr3.Flags = CpuReadCr3(); // // Call the wrapper @@ -287,7 +287,7 @@ MemoryMapperSetExecuteDisableToPteOnTargetProcess(PVOID Va, BOOLEAN Set) // // Invalidate the TLB // - __invlpg(Va); + CpuInvlpg(Va); // // Restore the original process @@ -680,12 +680,12 @@ MemoryMapperInitialize() // // Allocate the memory buffer structure // - g_MemoryMapper = CrsAllocateZeroedNonPagedPool(sizeof(MEMORY_MAPPER_ADDRESSES) * ProcessorsCount); + g_MemoryMapper = PlatformMemAllocateZeroedNonPagedPool(sizeof(MEMORY_MAPPER_ADDRESSES) * ProcessorsCount); // // 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 @@ -804,7 +804,7 @@ MemoryMapperReadMemorySafeByPte(PHYSICAL_ADDRESS PaAddressToRead, // because it will be automatically invalidated by the top hypervisor, however, // we should use invlpg in physical computers as it won't invalidate it automatically // - __invlpg(Va); + CpuInvlpg(Va); // // Also invalidate it from vpids if we're in vmx root @@ -888,7 +888,7 @@ MemoryMapperWriteMemorySafeByPte(PVOID SourceVA, // // Finally, invalidate the caches for the virtual address. // - __invlpg(Va); + CpuInvlpg(Va); // // Also invalidate it from vpids if we're in vmx root @@ -922,13 +922,16 @@ MemoryMapperWriteMemorySafeByPte(PVOID SourceVA, * * @param TypeOfRead Type of read * @param AddressToRead Physical Address to read + * @param TargetProcessId Target Process Id + * * @return UINT64 returns the target physical address and NULL if it fails */ _Use_decl_annotations_ UINT64 MemoryMapperReadMemorySafeByPhysicalAddressWrapperAddressMaker( MEMORY_MAPPER_WRAPPER_FOR_MEMORY_READ TypeOfRead, - UINT64 AddressToRead) + UINT64 AddressToRead, + UINT32 TargetProcessId) { PHYSICAL_ADDRESS PhysicalAddress = {0}; @@ -946,6 +949,19 @@ MemoryMapperReadMemorySafeByPhysicalAddressWrapperAddressMaker( break; + case MEMORY_MAPPER_WRAPPER_READ_VIRTUAL_MEMORY_UNSAFE: + + if (TargetProcessId == NULL_ZERO) + { + PhysicalAddress.QuadPart = VirtualAddressToPhysicalAddress((PVOID)AddressToRead); + } + else + { + PhysicalAddress.QuadPart = VirtualAddressToPhysicalAddressByProcessId((PVOID)AddressToRead, TargetProcessId); + } + + break; + default: return NULL64_ZERO; @@ -963,16 +979,19 @@ MemoryMapperReadMemorySafeByPhysicalAddressWrapperAddressMaker( * @param AddressToRead Address to read * @param BufferToSaveMemory Destination to save * @param SizeToRead Size + * @param TargetProcessId The process pid + * * @return BOOLEAN if it was successful the returns TRUE and if it was * unsuccessful then it returns FALSE */ _Use_decl_annotations_ BOOLEAN -MemoryMapperReadMemorySafeByPhysicalAddressWrapper( +MemoryMapperReadMemorySafeWrapper( MEMORY_MAPPER_WRAPPER_FOR_MEMORY_READ TypeOfRead, UINT64 AddressToRead, UINT64 BufferToSaveMemory, - SIZE_T SizeToRead) + SIZE_T SizeToRead, + UINT32 TargetProcessId) { ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL); UINT64 AddressToCheck; @@ -1022,7 +1041,8 @@ MemoryMapperReadMemorySafeByPhysicalAddressWrapper( // One access is enough (page+size won't pass from the PAGE_ALIGN boundary) // PhysicalAddress.QuadPart = MemoryMapperReadMemorySafeByPhysicalAddressWrapperAddressMaker(TypeOfRead, - AddressToRead); + AddressToRead, + TargetProcessId); if (!MemoryMapperReadMemorySafeByPte( PhysicalAddress, @@ -1051,7 +1071,8 @@ MemoryMapperReadMemorySafeByPhysicalAddressWrapper( // One access is enough (page+size won't pass from the PAGE_ALIGN boundary) // PhysicalAddress.QuadPart = MemoryMapperReadMemorySafeByPhysicalAddressWrapperAddressMaker(TypeOfRead, - AddressToRead); + AddressToRead, + TargetProcessId); return MemoryMapperReadMemorySafeByPte( PhysicalAddress, @@ -1081,10 +1102,11 @@ MemoryMapperReadMemorySafeByPhysicalAddress(UINT64 PaAddressToRead, // // Call the wrapper // - return MemoryMapperReadMemorySafeByPhysicalAddressWrapper(MEMORY_MAPPER_WRAPPER_READ_PHYSICAL_MEMORY, - PaAddressToRead, - BufferToSaveMemory, - SizeToRead); + return MemoryMapperReadMemorySafeWrapper(MEMORY_MAPPER_WRAPPER_READ_PHYSICAL_MEMORY, + PaAddressToRead, + BufferToSaveMemory, + SizeToRead, + NULL_ZERO); } /** @@ -1100,10 +1122,33 @@ _Use_decl_annotations_ BOOLEAN MemoryMapperReadMemorySafe(UINT64 VaAddressToRead, PVOID BufferToSaveMemory, SIZE_T SizeToRead) { - return MemoryMapperReadMemorySafeByPhysicalAddressWrapper(MEMORY_MAPPER_WRAPPER_READ_VIRTUAL_MEMORY, - VaAddressToRead, - (UINT64)BufferToSaveMemory, - SizeToRead); + return MemoryMapperReadMemorySafeWrapper(MEMORY_MAPPER_WRAPPER_READ_VIRTUAL_MEMORY, + VaAddressToRead, + (UINT64)BufferToSaveMemory, + SizeToRead, + NULL_ZERO); +} + +/** + * @brief Read memory unsafely by mapping the buffer (It's a wrapper) + * + * @param VaAddressToRead Virtual Address to read + * @param BufferToSaveMemory Destination to save + * @param SizeToRead Size + * @param TargetProcessId The process pid + * + * @return BOOLEAN if it was successful the returns TRUE and if it was + * unsuccessful then it returns FALSE + */ +_Use_decl_annotations_ +BOOLEAN +MemoryMapperReadMemoryUnsafe(UINT64 VaAddressToRead, PVOID BufferToSaveMemory, SIZE_T SizeToRead, UINT32 TargetProcessId) +{ + return MemoryMapperReadMemorySafeWrapper(MEMORY_MAPPER_WRAPPER_READ_VIRTUAL_MEMORY_UNSAFE, + VaAddressToRead, + (UINT64)BufferToSaveMemory, + SizeToRead, + TargetProcessId); } /** @@ -1135,8 +1180,8 @@ MemoryMapperReadMemorySafeOnTargetProcess(UINT64 VaAddressToRead, PVOID BufferTo // // Move to new cr3 // - OriginalCr3.Flags = __readcr3(); - __writecr3(GuestCr3.Flags); + OriginalCr3.Flags = CpuReadCr3(); + CpuWriteCr3(GuestCr3.Flags); // // Read target memory @@ -1146,7 +1191,7 @@ MemoryMapperReadMemorySafeOnTargetProcess(UINT64 VaAddressToRead, PVOID BufferTo // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return Result; } @@ -1180,8 +1225,8 @@ MemoryMapperWriteMemorySafeOnTargetProcess(UINT64 Destination, PVOID Source, SIZ // // Move to new cr3 // - OriginalCr3.Flags = __readcr3(); - __writecr3(GuestCr3.Flags); + OriginalCr3.Flags = CpuReadCr3(); + CpuWriteCr3(GuestCr3.Flags); // // Write target memory @@ -1191,7 +1236,7 @@ MemoryMapperWriteMemorySafeOnTargetProcess(UINT64 Destination, PVOID Source, SIZ // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return Result; } @@ -1675,7 +1720,7 @@ MemoryMapperMapPhysicalAddressToPte(PHYSICAL_ADDRESS PhysicalAddress, // because it will be automatically invalidated by the top hypervisor, however, // we should use invlpg in physical computers as it won't invalidate it automatically // - __invlpg(TargetProcessVirtualAddress); + CpuInvlpg(TargetProcessVirtualAddress); // // Restore the original process @@ -1719,3 +1764,51 @@ MemoryMapperSetSupervisorBitWithoutSwitchingByCr3(PVOID Va, BOOLEAN Set, PAGING_ return TRUE; } + +/** + * @brief Read physical memory safely from vmx non-root mode + * + * @param PaAddressToRead Physical Address to read + * @param BufferToSaveMemory Destination to save + * @param SizeToRead Size + * + * @return BOOLEAN whether was successful or not + */ +BOOLEAN +MemoryMapperReadMemorySafeFromVmxNonRootByPhysicalAddress(UINT64 PaAddressToRead, + PVOID BufferToSaveMemory, + SIZE_T SizeToRead) +{ + if (AsmVmxVmcall(VMCALL_READ_PHYSICAL_MEMORY, (UINT64)PaAddressToRead, (UINT64)BufferToSaveMemory, (UINT64)SizeToRead) == STATUS_SUCCESS) + { + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief Write physical memory safely from vmx non-root mode + * + * @param DestinationVa Destination Virtual Address + * @param Source Source Address + * @param SizeToWrite Size + * + * @return BOOLEAN whether was successful or not + */ +BOOLEAN +MemoryMapperWriteMemorySafeFromVmxNonRootyPhysicalAddress(UINT64 DestinationPa, + PVOID Source, + SIZE_T SizeToWrite) +{ + if (AsmVmxVmcall(VMCALL_WRITE_PHYSICAL_MEMORY, (UINT64)DestinationPa, (UINT64)Source, (UINT64)SizeToWrite) == STATUS_SUCCESS) + { + return TRUE; + } + else + { + return FALSE; + } +} diff --git a/hyperdbg/hyperhv/code/memory/Segmentation.c b/hyperdbg/hyperhv/code/memory/Segmentation.c new file mode 100644 index 00000000..26b2f4aa --- /dev/null +++ b/hyperdbg/hyperhv/code/memory/Segmentation.c @@ -0,0 +1,195 @@ +/** + * @file Segmentation.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Functions for handling memory segmentations + * + * @version 0.9 + * @date 2024-06-03 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Get Segment Descriptor + * + * @param SegmentSelector + * @param Selector + * @param GdtBase + * @return BOOLEAN + */ +_Use_decl_annotations_ +BOOLEAN +SegmentGetDescriptor(PUCHAR GdtBase, + UINT16 Selector, + PVMX_SEGMENT_SELECTOR SegmentSelector) +{ + SEGMENT_DESCRIPTOR_32 * DescriptorTable32; + SEGMENT_DESCRIPTOR_32 * Descriptor32; + SEGMENT_SELECTOR SegSelector = {.AsUInt = Selector}; + + if (!SegmentSelector) + return FALSE; + +#define SELECTOR_TABLE_LDT 0x1 +#define SELECTOR_TABLE_GDT 0x0 + + // + // Ignore LDT + // + if ((Selector == 0x0) || (SegSelector.Table != SELECTOR_TABLE_GDT)) + { + return FALSE; + } + + DescriptorTable32 = (SEGMENT_DESCRIPTOR_32 *)(GdtBase); + Descriptor32 = &DescriptorTable32[SegSelector.Index]; + + SegmentSelector->Selector = Selector; + SegmentSelector->Limit = CpuSegmentLimit(Selector); + SegmentSelector->Base = ((UINT64)Descriptor32->BaseAddressLow | (UINT64)Descriptor32->BaseAddressMiddle << 16 | (UINT64)Descriptor32->BaseAddressHigh << 24); + + SegmentSelector->Attributes.AsUInt = (AsmGetAccessRights(Selector) >> 8); + + if (SegSelector.Table == 0 && SegSelector.Index == 0) + { + SegmentSelector->Attributes.Unusable = TRUE; + } + + if ((Descriptor32->Type == SEGMENT_DESCRIPTOR_TYPE_TSS_BUSY) || (Descriptor32->Type == SEGMENT_DESCRIPTOR_TYPE_CALL_GATE)) + { + // + // this is a TSS or callgate etc, save the base high part + // + + UINT64 SegmentLimitHigh; + SegmentLimitHigh = (*(UINT64 *)((PUCHAR)Descriptor32 + 8)); + SegmentSelector->Base = (SegmentSelector->Base & 0xffffffff) | (SegmentLimitHigh << 32); + } + + if (SegmentSelector->Attributes.Granularity) + { + // + // 4096-bit granularity is enabled for this segment, scale the limit + // + SegmentSelector->Limit = (SegmentSelector->Limit << 12) + 0xfff; + } + + return TRUE; +} + +/** + * @brief Initialize the host GDT + * + * @param OsGdtBase + * @param OsGdtLimit + * @param TrSelector + * @param HostStack + * @param AllocatedHostGdt + * @param AllocatedHostTss + * + * @return VOID + */ +VOID +SegmentPrepareHostGdt( + SEGMENT_DESCRIPTOR_32 * OsGdtBase, + UINT16 OsGdtLimit, + UINT16 TrSelector, + UINT64 HostStack, + SEGMENT_DESCRIPTOR_32 * AllocatedHostGdt, + TASK_STATE_SEGMENT_64 * AllocatedHostTss) +{ + // + // Copy current OS GDT into host GDT + // Note that the limit is the maximum addressable byte offset within the segment, + // so the actual size of the GDT is limit + 1 + // + RtlCopyBytes(AllocatedHostGdt, OsGdtBase, OsGdtLimit + 1); + + // + // Make sure host TSS is empty + // + RtlZeroBytes(AllocatedHostTss, sizeof(TASK_STATE_SEGMENT_64)); + +#if USE_INTERRUPT_STACK_TABLE == TRUE + + UINT64 EndOfStack = 0; + + // + // Setup TSS memory for host (same host stack is used for all interrupts and privilege levels) + // + EndOfStack = ((UINT64)HostStack + HOST_INTERRUPT_STACK_SIZE - 1); + EndOfStack = ((UINT64)((ULONG_PTR)(EndOfStack) & ~(16 - 1))); + + LogDebugInfo("Host Interrupt Stack, from: %llx, to: %llx", HostStack, EndOfStack); + + AllocatedHostTss->Rsp0 = EndOfStack; + AllocatedHostTss->Rsp1 = EndOfStack; + AllocatedHostTss->Rsp2 = EndOfStack; + AllocatedHostTss->Ist1 = EndOfStack; + AllocatedHostTss->Ist2 = EndOfStack; + AllocatedHostTss->Ist3 = EndOfStack; + AllocatedHostTss->Ist4 = EndOfStack; + AllocatedHostTss->Ist5 = EndOfStack; + AllocatedHostTss->Ist6 = EndOfStack; + AllocatedHostTss->Ist7 = EndOfStack; + +#else + + UNREFERENCED_PARAMETER(HostStack); + +#endif // USE_INTERRUPT_STACK_TABLE == TRUE + + // + // Setup the TSS segment descriptor + // + SEGMENT_DESCRIPTOR_64 * GdtTssDesc = (SEGMENT_DESCRIPTOR_64 *)&AllocatedHostGdt[TrSelector]; + + // + // Point the TSS descriptor to our TSS + // + UINT64 Base = (UINT64)AllocatedHostTss; + GdtTssDesc->BaseAddressLow = (Base >> 00) & 0xFFFF; + GdtTssDesc->BaseAddressMiddle = (Base >> 16) & 0xFF; + GdtTssDesc->BaseAddressHigh = (Base >> 24) & 0xFF; + GdtTssDesc->BaseAddressUpper = (Base >> 32) & 0xFFFFFFFF; + + //////////////////////////////////////////////////////////////////// + + // SEGMENT_SELECTOR HostCsSelector = {0, 0, 1}; + // SEGMENT_SELECTOR HostTrSelector = {0, 0, 2}; + // + // // + // // Setup the CS segment descriptor + // // + // SEGMENT_DESCRIPTOR_32 CsDesc = AllocatedHostGdt[HostCsSelector.Index]; + // CsDesc.Type = SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ; + // CsDesc.DescriptorType = SEGMENT_DESCRIPTOR_TYPE_CODE_OR_DATA; + // CsDesc.DescriptorPrivilegeLevel = 0; + // CsDesc.Present = 1; + // CsDesc.LongMode = 1; + // CsDesc.DefaultBig = 0; + // CsDesc.Granularity = 0; + // + // // + // // Setup the TSS segment descriptor + // // + // SEGMENT_DESCRIPTOR_64 * TssDesc = (SEGMENT_DESCRIPTOR_64 *)&AllocatedHostGdt[HostTrSelector.Index]; + // TssDesc->Type = SEGMENT_DESCRIPTOR_TYPE_TSS_BUSY; + // TssDesc->DescriptorType = SEGMENT_DESCRIPTOR_TYPE_SYSTEM; + // TssDesc->DescriptorPrivilegeLevel = 0; + // TssDesc->Present = 1; + // TssDesc->Granularity = 0; + // TssDesc->SegmentLimitLow = 0x67; + // TssDesc->SegmentLimitHigh = 0; + // + // // + // // Point the TSS descriptor to our TSS + // // + // UINT64 Base = (UINT64)AllocatedHostTss; + // TssDesc->BaseAddressLow = (Base >> 00) & 0xFFFF; + // TssDesc->BaseAddressMiddle = (Base >> 16) & 0xFF; + // TssDesc->BaseAddressHigh = (Base >> 24) & 0xFF; + // TssDesc->BaseAddressUpper = (Base >> 32) & 0xFFFFFFFF; +} diff --git a/hyperdbg/hprdbghv/code/memory/SwitchLayout.c b/hyperdbg/hyperhv/code/memory/SwitchLayout.c similarity index 90% rename from hyperdbg/hprdbghv/code/memory/SwitchLayout.c rename to hyperdbg/hyperhv/code/memory/SwitchLayout.c index 6865fca4..b02ba8f2 100644 --- a/hyperdbg/hprdbghv/code/memory/SwitchLayout.c +++ b/hyperdbg/hyperhv/code/memory/SwitchLayout.c @@ -1,4 +1,4 @@ -/** +/** * @file SwitchLayout.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief Functions for switching memory layouts @@ -46,12 +46,12 @@ SwitchToProcessMemoryLayout(UINT32 ProcessId) // // Read the current cr3 // - CurrentProcessCr3.Flags = __readcr3(); + CurrentProcessCr3.Flags = CpuReadCr3(); // // Change to a new cr3 (of target process) // - __writecr3(GuestCr3); + CpuWriteCr3(GuestCr3); ObDereferenceObject(TargetEprocess); @@ -77,12 +77,12 @@ SwitchToCurrentProcessMemoryLayout() // // Read the current cr3 // - CurrentProcessCr3.Flags = __readcr3(); + CurrentProcessCr3.Flags = CpuReadCr3(); // // Change to a new cr3 (of target process) // - __writecr3(GuestCr3.Flags); + CpuWriteCr3(GuestCr3.Flags); return CurrentProcessCr3; } @@ -103,12 +103,12 @@ SwitchToProcessMemoryLayoutByCr3(CR3_TYPE TargetCr3) // // Read the current cr3 // - CurrentProcessCr3.Flags = __readcr3(); + CurrentProcessCr3.Flags = CpuReadCr3(); // // Change to a new cr3 (of target process) // - __writecr3(TargetCr3.Flags); + CpuWriteCr3(TargetCr3.Flags); return CurrentProcessCr3; } @@ -127,5 +127,5 @@ SwitchToPreviousProcess(CR3_TYPE PreviousProcess) // // Restore the original cr3 // - __writecr3(PreviousProcess.Flags); + CpuWriteCr3(PreviousProcess.Flags); } diff --git a/hyperdbg/hyperhv/code/mmio/MmioShadowing.c b/hyperdbg/hyperhv/code/mmio/MmioShadowing.c new file mode 100644 index 00000000..68f77ff5 --- /dev/null +++ b/hyperdbg/hyperhv/code/mmio/MmioShadowing.c @@ -0,0 +1,21 @@ +/** + * @file MmioShadowing.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Functions for MMIO shadowing + * + * @version 0.14 + * @date 2025-02-25 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +VOID +MmioShadowingInitialize( + PVOID MmioPhysicalAddress, + ULONG64 Size) +{ + UNREFERENCED_PARAMETER(MmioPhysicalAddress); + UNREFERENCED_PARAMETER(Size); +} diff --git a/hyperdbg/hyperhv/code/processor/Idt.c b/hyperdbg/hyperhv/code/processor/Idt.c new file mode 100644 index 00000000..989d3763 --- /dev/null +++ b/hyperdbg/hyperhv/code/processor/Idt.c @@ -0,0 +1,42 @@ +/** + * @file Idt.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Routines for Interrupt Descriptor Table + * @details + * + * @version 0.11 + * @date 2024-11-20 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Dump IDT Table based on current core + * + * @return VOID + */ +VOID +IdtDumpInterruptEntries() +{ + KDESCRIPTOR64 descr; + CpuSidt(&descr.Limit); + + ULONG n = (descr.Limit + 1) / sizeof(KIDTENTRY64); + + if (n > 0) + { + int i = 0; + KIDTENTRY64 * pidte = (KIDTENTRY64 *)descr.Base; + + do + { + ULONG_PTR addr = ((ULONG_PTR)pidte->OffsetHigh << 32) + + ((ULONG_PTR)pidte->OffsetMiddle << 16) + pidte->OffsetLow; + + LogInfo("Interrupt %u -> %p\n", i++, addr); + + } while (pidte++, --n); + } +} diff --git a/hyperdbg/hyperhv/code/processor/Smm.c b/hyperdbg/hyperhv/code/processor/Smm.c new file mode 100644 index 00000000..d025ab31 --- /dev/null +++ b/hyperdbg/hyperhv/code/processor/Smm.c @@ -0,0 +1,140 @@ +/** + * @file Smm.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Routines for operations related to System Management Mode (SMM) + * @details + * + * @version 0.15 + * @date 2025-08-02 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/* + * @brief Read the count of System Management Interrupts (SMIs) + * + * @return UINT64 + */ +UINT64 +SmmReadSmiCount() +{ + UINT64 SmiCount = 0; + + // + // Read the SMI count from MSR + // + SmiCount = (UINT64)CpuReadMsr(MSR_SMI_COUNT); + + return SmiCount; +} + +/* + * @brief Trigger a Power SMI + * + * @return BOOLEAN + */ +BOOLEAN +SmmTriggerPowerSmi() +{ + UINT8 SmmResponse = 0; + + // + // check the initial value received from 0xB3 port + // + SmmResponse = CpuIoInByte(0xb2); + + // + // write to 0xB2 port to cause SMI + // + CpuIoOutByte(0xb2, SMI_TRIGGER_POWER_VALUE); + + // + // Check the response in port 0xB3 + // + SmmResponse = CpuIoInByte(0xb2); + + if (SmmResponse == SMI_TRIGGER_POWER_VALUE) + { + // + // If the response is SMI_TRIGGER_POWER_VALUE, it means the SMI was triggered successfully + // + return TRUE; + } + else + { + // + // If the response is not SMI_TRIGGER_POWER_VALUE, it means the SMI was not triggered successfully + // + return FALSE; + } +} + +/** + * @brief Perform actions related to System Management Interrupts (SMIs) + * + * @param SmiOperationRequest + * @param ApplyFromVmxRootMode + * + * @return BOOLEAN + */ +BOOLEAN +SmmPerformSmiOperation(SMI_OPERATION_PACKETS * SmiOperationRequest, BOOLEAN ApplyFromVmxRootMode) +{ + BOOLEAN Status = FALSE; + + UNREFERENCED_PARAMETER(ApplyFromVmxRootMode); + + // + // Check the SMI operation type and perform the corresponding action + // + switch (SmiOperationRequest->SmiOperationType) + { + case SMI_OPERATION_REQUEST_TYPE_READ_COUNT: + + // + // Read the SMI count from the MSR + // + SmiOperationRequest->SmiCount = SmmReadSmiCount(); + + Status = TRUE; + break; + + case SMI_OPERATION_REQUEST_TYPE_TRIGGER_POWER_SMI: + + if (SmmTriggerPowerSmi()) + { + // + // If the SMI was triggered successfully + // + Status = TRUE; + } + else + { + // + // If the SMI was not triggered successfully, set error status + // + SmiOperationRequest->KernelStatus = DEBUGGER_ERROR_UNABLE_TO_TRIGGER_SMI; + } + + break; + + default: + + Status = FALSE; + SmiOperationRequest->KernelStatus = DEBUGGER_ERROR_INVALID_SMI_OPERATION_PARAMETERS; + + break; + } + + // + // Set the status of the SMI operation request + // + if (Status) + { + SmiOperationRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + + return Status; +} diff --git a/hyperdbg/hprdbghv/code/vmm/ept/Ept.c b/hyperdbg/hyperhv/code/vmm/ept/Ept.c similarity index 82% rename from hyperdbg/hprdbghv/code/vmm/ept/Ept.c rename to hyperdbg/hyperhv/code/vmm/ept/Ept.c index 2b5f1f99..4295aca0 100644 --- a/hyperdbg/hprdbghv/code/vmm/ept/Ept.c +++ b/hyperdbg/hyperhv/code/vmm/ept/Ept.c @@ -23,9 +23,9 @@ EptCheckFeatures(VOID) { IA32_VMX_EPT_VPID_CAP_REGISTER VpidRegister; IA32_MTRR_DEF_TYPE_REGISTER MTRRDefType; - - VpidRegister.AsUInt = __readmsr(IA32_VMX_EPT_VPID_CAP); - MTRRDefType.AsUInt = __readmsr(IA32_MTRR_DEF_TYPE); + g_IsVpidSupported = FALSE; + VpidRegister.AsUInt = CpuReadMsr(IA32_VMX_EPT_VPID_CAP); + MTRRDefType.AsUInt = CpuReadMsr(IA32_MTRR_DEF_TYPE); if (!VpidRegister.PageWalkLength4 || !VpidRegister.MemoryTypeWriteBack || !VpidRegister.Pde2MbPages) { @@ -37,6 +37,17 @@ EptCheckFeatures(VOID) LogDebugInfo("The processor doesn't report advanced VM-exit information for EPT violations"); } + if (VpidRegister.Invvpid && + VpidRegister.InvvpidAllContexts && + VpidRegister.InvvpidIndividualAddress && + VpidRegister.InvvpidSingleContext && + VpidRegister.InvvpidSingleContextRetainGlobals && + !g_IsTopLevelHypervisorHyperV) + { + g_IsVpidSupported = TRUE; + LogDebugInfo("The processor supports VPID"); + } + if (!VpidRegister.ExecuteOnlyPages) { g_CompatibilityCheck.ExecuteOnlySupport = FALSE; @@ -163,8 +174,8 @@ EptBuildMtrrMap(VOID) UINT32 CurrentRegister; UINT32 NumberOfBitsInMask; - MTRRCap.AsUInt = __readmsr(IA32_MTRR_CAPABILITIES); - MTRRDefType.AsUInt = __readmsr(IA32_MTRR_DEF_TYPE); + MTRRCap.AsUInt = CpuReadMsr(IA32_MTRR_CAPABILITIES); + MTRRDefType.AsUInt = CpuReadMsr(IA32_MTRR_DEF_TYPE); // // All MTRRs are disabled when clear, and the @@ -200,8 +211,8 @@ EptBuildMtrrMap(VOID) { const UINT32 K64Base = 0x0; const UINT32 K64Size = 0x10000; - IA32_MTRR_FIXED_RANGE_TYPE K64Types = {__readmsr(IA32_MTRR_FIX64K_00000)}; - for (unsigned int i = 0; i < 8; i++) + IA32_MTRR_FIXED_RANGE_TYPE K64Types = {CpuReadMsr(IA32_MTRR_FIX64K_00000)}; + for (UINT32 i = 0; i < 8; i++) { Descriptor = &g_EptState->MemoryRanges[g_EptState->NumberOfEnabledMemoryRanges++]; Descriptor->MemoryType = K64Types.s.Types[i]; @@ -212,10 +223,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 = {__readmsr(IA32_MTRR_FIX16K_80000 + i)}; - for (unsigned int j = 0; j < 8; j++) + IA32_MTRR_FIXED_RANGE_TYPE K16Types = {CpuReadMsr(IA32_MTRR_FIX16K_80000 + i)}; + for (UINT32 j = 0; j < 8; j++) { Descriptor = &g_EptState->MemoryRanges[g_EptState->NumberOfEnabledMemoryRanges++]; Descriptor->MemoryType = K16Types.s.Types[j]; @@ -227,11 +238,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 = {__readmsr(IA32_MTRR_FIX4K_C0000 + 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]; @@ -247,8 +258,8 @@ EptBuildMtrrMap(VOID) // // For each dynamic register pair // - CurrentPhysBase.AsUInt = __readmsr(IA32_MTRR_PHYSBASE0 + (CurrentRegister * 2)); - CurrentPhysMask.AsUInt = __readmsr(IA32_MTRR_PHYSMASK0 + (CurrentRegister * 2)); + CurrentPhysBase.AsUInt = CpuReadMsr(IA32_MTRR_PHYSBASE0 + (CurrentRegister * 2)); + CurrentPhysMask.AsUInt = CpuReadMsr(IA32_MTRR_PHYSMASK0 + (CurrentRegister * 2)); // // Is the range enabled? @@ -270,7 +281,7 @@ EptBuildMtrrMap(VOID) // Calculate the total size of the range // The lowest bit of the mask that is set to 1 specifies the size of the range // - _BitScanForward64((ULONG *)&NumberOfBitsInMask, CurrentPhysMask.PageFrameNumber * PAGE_SIZE); + CpuBitScanForward64((ULONG *)&NumberOfBitsInMask, CurrentPhysMask.PageFrameNumber * PAGE_SIZE); // // Size of the range in bytes + Base Address @@ -293,6 +304,28 @@ EptBuildMtrrMap(VOID) return TRUE; } +/** + * @brief Resolve the split PML1 VA that belongs to a given PML2 entry + * + * @param EptPageTable The EPT page table + * @param TargetEntry The target PML2 entry + * @return PEPT_PML1_ENTRY Returns base VA of PML1 page, or NULL if not tracked + */ +_Must_inspect_result_ +static PEPT_PML1_ENTRY +EptGetSplitPml1VaByPml2Entry(_In_ PVMM_EPT_PAGE_TABLE EptPageTable, _In_ PEPT_PML2_ENTRY TargetEntry) +{ + LIST_FOR_EACH_LINK(EptPageTable->DynamicSplitList, VMM_EPT_DYNAMIC_SPLIT, DynamicSplitList, CurrentSplit) + { + if (CurrentSplit->Fields.Entry == TargetEntry) + { + return &CurrentSplit->PML1[0]; + } + } + + return NULL; +} + /** * @brief Get the PML1 entry for this physical address if the page is split * @@ -303,10 +336,9 @@ EptBuildMtrrMap(VOID) PEPT_PML1_ENTRY EptGetPml1Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress) { - SIZE_T Directory, DirectoryPointer, PML4Entry; - PEPT_PML2_ENTRY PML2; - PEPT_PML1_ENTRY PML1; - PEPT_PML2_POINTER PML2Pointer; + SIZE_T Directory, DirectoryPointer, PML4Entry; + PEPT_PML2_ENTRY PML2; + PEPT_PML1_ENTRY PML1; Directory = ADDRMASK_EPT_PML2_INDEX(PhysicalAddress); DirectoryPointer = ADDRMASK_EPT_PML3_INDEX(PhysicalAddress); @@ -331,15 +363,9 @@ EptGetPml1Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress) } // - // Conversion to get the right PageFrameNumber. - // These pointers occupy the same place in the table and are directly convertible. + // Resolve the split PML1 VA that was recorded during EptSplitLargePage // - PML2Pointer = (PEPT_PML2_POINTER)PML2; - - // - // If it is, translate to the PML1 pointer - // - PML1 = (PEPT_PML1_ENTRY)PhysicalAddressToVirtualAddress(PML2Pointer->PageFrameNumber * PAGE_SIZE); + PML1 = EptGetSplitPml1VaByPml2Entry(EptPageTable, PML2); if (!PML1) { @@ -367,10 +393,9 @@ EptGetPml1Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress) PVOID EptGetPml1OrPml2Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress, BOOLEAN * IsLargePage) { - SIZE_T Directory, DirectoryPointer, PML4Entry; - PEPT_PML2_ENTRY PML2; - PEPT_PML1_ENTRY PML1; - PEPT_PML2_POINTER PML2Pointer; + SIZE_T Directory, DirectoryPointer, PML4Entry; + PEPT_PML2_ENTRY PML2; + PEPT_PML1_ENTRY PML1; Directory = ADDRMASK_EPT_PML2_INDEX(PhysicalAddress); DirectoryPointer = ADDRMASK_EPT_PML3_INDEX(PhysicalAddress); @@ -396,15 +421,9 @@ EptGetPml1OrPml2Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress, } // - // Conversion to get the right PageFrameNumber. - // These pointers occupy the same place in the table and are directly convertible. + // Resolve the split PML1 VA that was recorded during EptSplitLargePage // - PML2Pointer = (PEPT_PML2_POINTER)PML2; - - // - // If it is, translate to the PML1 pointer - // - PML1 = (PEPT_PML1_ENTRY)PhysicalAddressToVirtualAddress(PML2Pointer->PageFrameNumber * PAGE_SIZE); + PML1 = EptGetSplitPml1VaByPml2Entry(EptPageTable, PML2); if (!PML1) { @@ -450,17 +469,17 @@ EptGetPml2Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress) } /** - * @brief Split 2MB (LargePage) into 4kb pages + * @brief Convert large pages to 4KB pages * * @param EptPageTable The EPT Page Table - * @param PreAllocatedBuffer The address of pre-allocated buffer + * @param UsePreAllocatedBuffer Whether allocate a memory or use pre-allocated buffer * @param PhysicalAddress Physical address of where we want to split * * @return BOOLEAN Returns true if it was successful or false if there was an error */ BOOLEAN EptSplitLargePage(PVMM_EPT_PAGE_TABLE EptPageTable, - PVOID PreAllocatedBuffer, + BOOLEAN UsePreAllocatedBuffer, SIZE_T PhysicalAddress) { PVMM_EPT_DYNAMIC_SPLIT NewSplit; @@ -486,19 +505,21 @@ EptSplitLargePage(PVMM_EPT_PAGE_TABLE EptPageTable, // if (!TargetEntry->LargePage) { - // - // As it's a large page and we request a pool for it, we need to - // free the pool because it's not used anymore - // - PoolManagerFreePool((UINT64)PreAllocatedBuffer); - return TRUE; } // // Allocate the PML1 entries // - NewSplit = (PVMM_EPT_DYNAMIC_SPLIT)PreAllocatedBuffer; + if (UsePreAllocatedBuffer) + { + NewSplit = (PVMM_EPT_DYNAMIC_SPLIT)PoolManagerCallbackRequestPool(SPLIT_2MB_PAGING_TO_4KB_PAGE, TRUE, sizeof(VMM_EPT_DYNAMIC_SPLIT)); + } + else + { + NewSplit = (PVMM_EPT_DYNAMIC_SPLIT)PlatformMemAllocateNonPagedPool(sizeof(VMM_EPT_DYNAMIC_SPLIT)); + } + if (!NewSplit) { LogError("Err, failed to allocate dynamic split memory"); @@ -510,7 +531,7 @@ EptSplitLargePage(PVMM_EPT_PAGE_TABLE EptPageTable, // Point back to the entry in the dynamic split for easy reference for which entry that // dynamic split is for // - NewSplit->u.Entry = TargetEntry; + NewSplit->Fields.Entry = TargetEntry; // // Make a template for RWX @@ -520,6 +541,18 @@ EptSplitLargePage(PVMM_EPT_PAGE_TABLE EptPageTable, EntryTemplate.WriteAccess = 1; EntryTemplate.ExecuteAccess = 1; + // + // Set the UserModeExecute bit based on the global state of MBEC + // + if (g_ModeBasedExecutionControlState) + { + EntryTemplate.UserModeExecute = 1; + } + else + { + EntryTemplate.UserModeExecute = 0; + } + // // copy other bits from target entry // @@ -530,7 +563,7 @@ EptSplitLargePage(PVMM_EPT_PAGE_TABLE EptPageTable, // // Copy the template into all the PML1 entries // - __stosq((SIZE_T *)&NewSplit->PML1[0], EntryTemplate.AsUInt, VMM_EPT_PML1E_COUNT); + CpuStosQ((SIZE_T *)&NewSplit->PML1[0], EntryTemplate.AsUInt, VMM_EPT_PML1E_COUNT); // // Set the page frame numbers for identity mapping @@ -547,10 +580,23 @@ EptSplitLargePage(PVMM_EPT_PAGE_TABLE EptPageTable, // // Allocate a new pointer which will replace the 2MB entry with a pointer to 512 4096 byte entries // - NewPointer.AsUInt = 0; - NewPointer.WriteAccess = 1; - NewPointer.ReadAccess = 1; - NewPointer.ExecuteAccess = 1; + NewPointer.AsUInt = 0; + NewPointer.WriteAccess = 1; + NewPointer.ReadAccess = 1; + NewPointer.ExecuteAccess = 1; + + // + // Set the UserModeExecute bit based on the global state of MBEC + // + if (g_ModeBasedExecutionControlState) + { + NewPointer.UserModeExecute = 1; + } + else + { + NewPointer.UserModeExecute = 0; + } + NewPointer.PageFrameNumber = (SIZE_T)VirtualAddressToPhysicalAddress(&NewSplit->PML1[0]) / PAGE_SIZE; // @@ -558,6 +604,12 @@ EptSplitLargePage(PVMM_EPT_PAGE_TABLE EptPageTable, // RtlCopyMemory(TargetEntry, &NewPointer, sizeof(NewPointer)); + // + // Track the split so we can directly resolve PML1 VA from PML2 entry + // without any PA->VA reverse translation + // + InsertHeadList(&EptPageTable->DynamicSplitList, &(NewSplit->DynamicSplitList)); + return TRUE; } @@ -602,8 +654,6 @@ EptIsValidForLargePage(SIZE_T PageFrameNumber) BOOLEAN EptSetupPML2Entry(PVMM_EPT_PAGE_TABLE EptPageTable, PEPT_PML2_ENTRY NewEntry, SIZE_T PageFrameNumber) { - PVOID TargetBuffer; - // // Each of the 512 collections of 512 PML2 entries is setup here // This will, in total, identity map every physical address from 0x0 @@ -621,15 +671,10 @@ EptSetupPML2Entry(PVMM_EPT_PAGE_TABLE EptPageTable, PEPT_PML2_ENTRY NewEntry, SI } else { - TargetBuffer = (PVOID)CrsAllocateNonPagedPool(sizeof(VMM_EPT_DYNAMIC_SPLIT)); - - if (!TargetBuffer) - { - LogError("Err, cannot allocate page for splitting edge large pages"); - return FALSE; - } - - return EptSplitLargePage(EptPageTable, TargetBuffer, PageFrameNumber * SIZE_2_MB); + // + // Here we won't need to use pre-allocated buffers + // + return EptSplitLargePage(EptPageTable, FALSE, PageFrameNumber * SIZE_2_MB); } } @@ -642,7 +687,8 @@ PVMM_EPT_PAGE_TABLE EptAllocateAndCreateIdentityPageTable(VOID) { PVMM_EPT_PAGE_TABLE PageTable; - EPT_PML3_POINTER RWXTemplate; + EPT_PML3_POINTER PML3Template; + EPT_PML3_ENTRY PML3TemplateLarge; EPT_PML2_ENTRY PML2EntryTemplate; SIZE_T EntryGroupIndex; SIZE_T EntryIndex; @@ -655,7 +701,7 @@ EptAllocateAndCreateIdentityPageTable(VOID) // Allocate address anywhere in the OS's memory space and // zero out all entries to ensure all unused entries are marked Not Present // - PageTable = CrsAllocateContiguousZeroedMemory(sizeof(VMM_EPT_PAGE_TABLE)); + PageTable = PlatformMemAllocateContiguousZeroedMemory(sizeof(VMM_EPT_PAGE_TABLE)); if (PageTable == NULL) { @@ -664,13 +710,37 @@ EptAllocateAndCreateIdentityPageTable(VOID) } // - // Mark the first 512GB PML4 entry as present, which allows us to manage up - // to 512GB of discrete paging structures. + // Keep track of dynamic 2MB->4KB split metadata for this EPT table. // - PageTable->PML4[0].PageFrameNumber = (SIZE_T)VirtualAddressToPhysicalAddress(&PageTable->PML3[0]) / PAGE_SIZE; - PageTable->PML4[0].ReadAccess = 1; - PageTable->PML4[0].WriteAccess = 1; - PageTable->PML4[0].ExecuteAccess = 1; + InitializeListHead(&PageTable->DynamicSplitList); + + // + // Create the template for the first entry in the PML4 + // + PageTable->PML4[0].ReadAccess = 1; + PageTable->PML4[0].WriteAccess = 1; + PageTable->PML4[0].ExecuteAccess = 1; + + // + // Copy the template into each of the 512 PML4 entry slots + // + CpuStosQ((SIZE_T *)&PageTable->PML4[1], PageTable->PML4[0].AsUInt, VMM_EPT_PML4E_COUNT - 1); + + for (int i = 0; i < VMM_EPT_PML4E_COUNT; i++) + { + if (i == 0) + { + // + // Mark the first 512GB PML4 entry as present, which allows us to manage up + // to 512GB of discrete paging structures and also set other reserved bits + // + PageTable->PML4[0].PageFrameNumber = (SIZE_T)VirtualAddressToPhysicalAddress(&PageTable->PML3[0]) / PAGE_SIZE; + } + else + { + PageTable->PML4[i].PageFrameNumber = (SIZE_T)VirtualAddressToPhysicalAddress(&PageTable->PML3_RSVD[i - 1][0]) / PAGE_SIZE; + } + } // // Now mark each 1GB PML3 entry as RWX and map each to their PML2 entry @@ -679,20 +749,35 @@ EptAllocateAndCreateIdentityPageTable(VOID) // // Ensure stack memory is cleared // - RWXTemplate.AsUInt = 0; + PML3Template.AsUInt = 0; + PML3TemplateLarge.AsUInt = 0; // // Set up one 'template' RWX PML3 entry and copy it into each of the 512 PML3 entries - // Using the same method as SimpleVisor for copying each entry using intrinsics. + // Using the same method as SimpleVisor for copying each entry using intrinsics // - RWXTemplate.ReadAccess = 1; - RWXTemplate.WriteAccess = 1; - RWXTemplate.ExecuteAccess = 1; + PML3Template.ReadAccess = 1; + PML3Template.WriteAccess = 1; + PML3Template.ExecuteAccess = 1; + + PML3TemplateLarge.LargePage = 1; + PML3TemplateLarge.ReadAccess = 1; + PML3TemplateLarge.WriteAccess = 1; + PML3TemplateLarge.ExecuteAccess = 1; + PML3TemplateLarge.MemoryType = MEMORY_TYPE_UNCACHEABLE; // - // Copy the template into each of the 512 PML3 entry slots + // Copy the template into each of the 512 PML3 entry slots for the original entries // - __stosq((SIZE_T *)&PageTable->PML3[0], RWXTemplate.AsUInt, VMM_EPT_PML3E_COUNT); + CpuStosQ((SIZE_T *)&PageTable->PML3[0], PML3Template.AsUInt, VMM_EPT_PML3E_COUNT); + + // + // 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++) + { + CpuStosQ((SIZE_T *)&PageTable->PML3_RSVD[i][0], PML3TemplateLarge.AsUInt, VMM_EPT_PML3E_COUNT); + } // // For each of the 512 PML3 entries @@ -700,12 +785,33 @@ EptAllocateAndCreateIdentityPageTable(VOID) for (EntryIndex = 0; EntryIndex < VMM_EPT_PML3E_COUNT; EntryIndex++) { // - // Map the 1GB PML3 entry to 512 PML2 (2MB) entries to describe each large page. - // NOTE: We do *not* manage any PML1 (4096 byte) entries and do not allocate them. + // Map the 1GB PML3 entry to 512 PML2 (2MB) entries to describe each large page + // NOTE: We do *not* manage any PML1 (4096 byte) entries and do not allocate them // PageTable->PML3[EntryIndex].PageFrameNumber = (SIZE_T)VirtualAddressToPhysicalAddress(&PageTable->PML2[EntryIndex][0]) / PAGE_SIZE; } + // + // 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 j = 0; j < VMM_EPT_PML3E_COUNT; j++) + { + // + // Map the 1GB PML3 reserved entry to 512 PML3 (1GB) entries to describe each large page + // NOTE: We do *not* manage them since they are reserved for out of 512 GB MMIO ranges + // The first 512GB is used for the main system memory and the rest is reserved for MMIO + // + PageTable->PML3_RSVD[i][j].PageFrameNumber = (SIZE_512_GB + // First 512GB is used for system memory + (i * SIZE_512_GB) + (j * SIZE_1_GB)) >> // MMIO ranges + 30; // Convert to page frame number + } + } + + // + // Now we will set up the PML2 entries, which are 2MB large pages + // PML2EntryTemplate.AsUInt = 0; // @@ -725,9 +831,9 @@ EptAllocateAndCreateIdentityPageTable(VOID) // mark it RWX using the same template above. // This marks the entries as "Present" regardless of if the actual system has memory at // this region or not. We will cause a fault in our EPT handler if the guest access a page - // outside a usable range, despite the EPT frame being present here. + // outside a usable range, despite the EPT frame being present here // - __stosq((SIZE_T *)&PageTable->PML2[0], PML2EntryTemplate.AsUInt, VMM_EPT_PML3E_COUNT * VMM_EPT_PML2E_COUNT); + CpuStosQ((SIZE_T *)&PageTable->PML2[0], PML2EntryTemplate.AsUInt, VMM_EPT_PML3E_COUNT * VMM_EPT_PML2E_COUNT); // // For each of the 512 collections of 512 2MB PML2 entries @@ -767,7 +873,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 @@ -779,7 +885,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) { @@ -1007,19 +1113,19 @@ EptHandleEptViolation(VIRTUAL_MACHINE_STATE * VCpu) // // Reading guest physical address // - __vmx_vmread(VMCS_GUEST_PHYSICAL_ADDRESS, &GuestPhysicalAddr); + VmxVmread64P(VMCS_GUEST_PHYSICAL_ADDRESS, &GuestPhysicalAddr); - if (ExecTrapHandleEptViolationVmexit(VCpu, &ViolationQualification)) - { - return TRUE; - } - else if (EptHandlePageHookExit(VCpu, ViolationQualification, GuestPhysicalAddr)) + if (EptHandlePageHookExit(VCpu, ViolationQualification, GuestPhysicalAddr)) { // // Handled by page hook code // return TRUE; } + else if (ExecTrapHandleEptViolationVmexit(VCpu, &ViolationQualification)) + { + return TRUE; + } else if (VmmCallbackUnhandledEptViolation(VCpu->CoreId, (UINT64)ViolationQualification.AsUInt, GuestPhysicalAddr)) { // @@ -1047,7 +1153,7 @@ EptHandleMisconfiguration(VOID) { UINT64 GuestPhysicalAddr = 0; - __vmx_vmread(VMCS_GUEST_PHYSICAL_ADDRESS, &GuestPhysicalAddr); + VmxVmread64P(VMCS_GUEST_PHYSICAL_ADDRESS, &GuestPhysicalAddr); LogInfo("EPT Misconfiguration!"); @@ -1130,7 +1236,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) { @@ -1216,7 +1322,7 @@ EptCheckAndHandleBreakpoint(VIRTUAL_MACHINE_STATE * VCpu) // // Reading guest's RIP // - __vmx_vmread(VMCS_GUEST_RIP, &GuestRip); + VmxVmread64P(VMCS_GUEST_RIP, &GuestRip); // // Don't increment rip by default diff --git a/hyperdbg/hprdbghv/code/vmm/ept/Invept.c b/hyperdbg/hyperhv/code/vmm/ept/Invept.c similarity index 100% rename from hyperdbg/hprdbghv/code/vmm/ept/Invept.c rename to hyperdbg/hyperhv/code/vmm/ept/Invept.c diff --git a/hyperdbg/hprdbghv/code/vmm/ept/Vpid.c b/hyperdbg/hyperhv/code/vmm/ept/Vpid.c similarity index 93% rename from hyperdbg/hprdbghv/code/vmm/ept/Vpid.c rename to hyperdbg/hyperhv/code/vmm/ept/Vpid.c index a4874c4d..cd587b57 100644 --- a/hyperdbg/hprdbghv/code/vmm/ept/Vpid.c +++ b/hyperdbg/hyperhv/code/vmm/ept/Vpid.c @@ -25,6 +25,12 @@ VpidInvvpid(INVVPID_TYPE Type, INVVPID_DESCRIPTOR * Descriptor) INVVPID_DESCRIPTOR * TargetDescriptor = NULL; INVVPID_DESCRIPTOR ZeroDescriptor = {0}; + // No need to do anything if VPID is not supported. + if (!g_IsVpidSupported) + { + return; + } + if (!Descriptor) { TargetDescriptor = &ZeroDescriptor; diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/Counters.c b/hyperdbg/hyperhv/code/vmm/vmx/Counters.c similarity index 95% rename from hyperdbg/hprdbghv/code/vmm/vmx/Counters.c rename to hyperdbg/hyperhv/code/vmm/vmx/Counters.c index 9506dc6c..d1493c49 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/Counters.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/Counters.c @@ -1,4 +1,4 @@ -/** +/** * @file Counters.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief The functions for emulating counters @@ -26,7 +26,7 @@ CounterEmulateRdtsc(VIRTUAL_MACHINE_STATE * VCpu) // to solve it, in the future we solve it using tsc offsetting // or tsc scalling (The reason is because of that fucking patchguard :( ) // - UINT64 Tsc = __rdtsc(); + UINT64 Tsc = CpuReadTsc(); PGUEST_REGS GuestRegs = VCpu->Regs; GuestRegs->rax = 0x00000000ffffffff & Tsc; @@ -43,7 +43,7 @@ VOID CounterEmulateRdtscp(VIRTUAL_MACHINE_STATE * VCpu) { UINT32 Aux = 0; - UINT64 Tsc = __rdtscp(&Aux); + UINT64 Tsc = CpuReadTscp(&Aux); PGUEST_REGS GuestRegs = VCpu->Regs; GuestRegs->rax = 0x00000000ffffffff & Tsc; diff --git a/hyperdbg/hyperhv/code/vmm/vmx/CrossVmcalls.c b/hyperdbg/hyperhv/code/vmm/vmx/CrossVmcalls.c new file mode 100644 index 00000000..b64fb169 --- /dev/null +++ b/hyperdbg/hyperhv/code/vmm/vmx/CrossVmcalls.c @@ -0,0 +1,155 @@ +/** + * @file CrossVmcalls.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Routines relating to cross (standalone) VMCALLs + * @details + * @version 0.19 + * @date 2026-04-14 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Get the guest state of IA32_DEBUGCTL on the target core from VMCS + * using VMCALL + * + * @return UINT64 + */ +UINT64 +CrossVmcallGetDebugctlVmcallOnTargetCore() +{ + UINT64 DebugctlValue; + AsmVmxVmcall(VMCALL_GET_VMCS_DEBUGCTL, (UINT64)&DebugctlValue, NULL64_ZERO, NULL64_ZERO); + return DebugctlValue; +} + +/** + * @brief Get the guest state of IA32_LBR_CTL on the target core from VMCS using VMCALL + * + * @return UINT64 + */ +UINT64 +CrossVmcallGetGuestIa32LbrCtlVmcallOnTargetCore() +{ + UINT64 GuestIa32LbrCtlValue; + AsmVmxVmcall(VMCALL_GET_GUEST_IA32_LBR_CTL, (UINT64)&GuestIa32LbrCtlValue, NULL64_ZERO, NULL64_ZERO); + return GuestIa32LbrCtlValue; +} + +/** + * @brief Set the guest state of IA32_DEBUGCTL on the target core from VMCS using VMCALL + * @param Value + * + * @return VOID + */ +VOID +CrossVmcallSetDebugctlVmcallOnTargetCore(UINT64 Value) +{ + AsmVmxVmcall(VMCALL_SET_VMCS_DEBUGCTL, Value, NULL64_ZERO, NULL64_ZERO); +} + +/** + * @brief Set the guest state of IA32_LBR_CTL on the target core from VMCS using VMCALL + * @param Value + * + * @return VOID + */ +VOID +CrossVmcallSetGuestIa32LbrCtlVmcallOnTargetCore(UINT64 Value) +{ + AsmVmxVmcall(VMCALL_SET_GUEST_IA32_LBR_CTL, Value, NULL64_ZERO, NULL64_ZERO); +} + +/** + * @brief Set the guest state of MSR_LEGACY_LBR_SELECT on the target core from VMCS using VMCALL + * @param FilterOptions + * + * @return VOID + */ +VOID +CrossVmcallSetLbrSelectVmcallOnTargetCore(UINT64 FilterOptions) +{ + AsmVmxVmcall(VMCALL_SET_MSR_LBR_SELECT, FilterOptions, NULL64_ZERO, NULL64_ZERO); +} + +/** + * @brief Set LOAD DEBUG CONTROLS on Vm-entry controls on the target core from VMCS using VMCALL + * + * @param Set Set or unset + * + * @return VOID + */ +VOID +CrossVmcallSetLoadDebugControlsVmcallOnTargetCore(BOOLEAN Set) +{ + if (Set) + { + AsmVmxVmcall(VMCALL_SET_VM_ENTRY_LOAD_DEBUG_CONTROLS, NULL64_ZERO, NULL64_ZERO, NULL64_ZERO); + } + else + { + AsmVmxVmcall(VMCALL_UNSET_VM_ENTRY_LOAD_DEBUG_CONTROLS, NULL64_ZERO, NULL64_ZERO, NULL64_ZERO); + } +} + +/** + * @brief Set CLEAR GUEST IA32_LBR_CTL on Vm-entry controls on the target core from VMCS using VMCALL + * + * @param Set Set or unset + * + * @return VOID + */ +VOID +CrossVmcallSetLoadGuestIa32LbrCtlVmcallOnTargetCore(BOOLEAN Set) +{ + if (Set) + { + AsmVmxVmcall(VMCALL_SET_VM_ENTRY_LOAD_GUEST_IA32_LBR_CTL, NULL64_ZERO, NULL64_ZERO, NULL64_ZERO); + } + else + { + AsmVmxVmcall(VMCALL_UNSET_VM_ENTRY_LOAD_GUEST_IA32_LBR_CTL, NULL64_ZERO, NULL64_ZERO, NULL64_ZERO); + } +} + +/** + * @brief Set SAVE DEBUG CONTROLS on Vm-exit controls on the target core from VMCS using VMCALL + * + * @param Set Set or unset + * + * @return VOID + */ +VOID +CrossVmcallSetSaveDebugControlsVmcallOnTargetCore(BOOLEAN Set) +{ + if (Set) + { + AsmVmxVmcall(VMCALL_SET_VM_EXIT_SAVE_DEBUG_CONTROLS, NULL64_ZERO, NULL64_ZERO, NULL64_ZERO); + } + else + { + AsmVmxVmcall(VMCALL_UNSET_VM_EXIT_SAVE_DEBUG_CONTROLS, NULL64_ZERO, NULL64_ZERO, NULL64_ZERO); + } +} + +/** + * @brief Set CLEAR GUEST IA32_LBR_CTL on Vm-exit controls on the target core from VMCS using VMCALL + * + * @param Set Set or unset + * + * @return VOID + */ +VOID +CrossVmcallSetClearGuestIa32LbrCtlVmcallOnTargetCore(BOOLEAN Set) +{ + if (Set) + { + AsmVmxVmcall(VMCALL_SET_CLEAR_GUEST_IA32_LBR_CTL, NULL64_ZERO, NULL64_ZERO, NULL64_ZERO); + } + else + { + AsmVmxVmcall(VMCALL_UNSET_CLEAR_GUEST_IA32_LBR_CTL, NULL64_ZERO, NULL64_ZERO, NULL64_ZERO); + } +} diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/CrossVmexits.c b/hyperdbg/hyperhv/code/vmm/vmx/CrossVmexits.c similarity index 61% rename from hyperdbg/hprdbghv/code/vmm/vmx/CrossVmexits.c rename to hyperdbg/hyperhv/code/vmm/vmx/CrossVmexits.c index 2be2e500..aa24a0c0 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/CrossVmexits.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/CrossVmexits.c @@ -20,7 +20,27 @@ VOID VmxHandleXsetbv(VIRTUAL_MACHINE_STATE * VCpu) { - _xsetbv(VCpu->Regs->rcx & 0xffffffff, VCpu->Regs->rdx << 32 | VCpu->Regs->rax); + CPUID_EAX_01 CpuidInfo; + VMX_SEGMENT_SELECTOR GuestCs = GetGuestCs(); + UINT32 XCrIndex = VCpu->Regs->rcx & 0xffffffff; + XCR0 XCr0 = {.AsUInt = VCpu->Regs->rdx << 32 | VCpu->Regs->rax}; + CR4 GuestCr4 = {.AsUInt = GetGuestCr4()}; + + if (XCrIndex != 0 || GuestCs.Attributes.DescriptorPrivilegeLevel != 0 || !CommonIsXCr0Valid(XCr0)) + { + EventInjectGeneralProtection(); + return; + } + + CommonCpuidInstruction(CPUID_VERSION_INFORMATION, 0, (INT32 *)&CpuidInfo); + + if (CpuidInfo.CpuidFeatureInformationEcx.XsaveXrstorInstruction == 0 || GuestCr4.OsXsave == 0) + { + EventInjectUndefinedOpcode(VCpu); + return; + } + + _xsetbv(XCrIndex, XCr0.AsUInt); } /** diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/Events.c b/hyperdbg/hyperhv/code/vmm/vmx/Events.c similarity index 95% rename from hyperdbg/hprdbghv/code/vmm/vmx/Events.c rename to hyperdbg/hyperhv/code/vmm/vmx/Events.c index ae20e937..34bee0dc 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/Events.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/Events.c @@ -1,4 +1,4 @@ -/** +/** * @file Events.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief Functions relating to Exception Bitmap and Event (Interrupt and Exception) Injection @@ -86,6 +86,23 @@ EventInjectUndefinedOpcode(VIRTUAL_MACHINE_STATE * VCpu) HvSuppressRipIncrement(VCpu); } +/** + * @brief Inject NMI to the guest (Event Injection) + * @param VCpu The virtual processor's state + * + * @return VOID + */ +VOID +EventInjectNmi(VIRTUAL_MACHINE_STATE * VCpu) +{ + EventInjectInterruption(INTERRUPT_TYPE_NMI, EXCEPTION_VECTOR_NMI, FALSE, 0); + + // + // Suppress RIP increment + // + HvSuppressRipIncrement(VCpu); +} + /** * @brief Inject Debug Breakpoint Exception * @@ -111,7 +128,7 @@ EventInjectPageFaultWithoutErrorCode(UINT64 PageFaultAddress) // // Write the page-fault address // - __writecr2(PageFaultAddress); + CpuWriteCr2(PageFaultAddress); // // Make the error code @@ -184,7 +201,7 @@ EventInjectPageFaults(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, // // Cr2 is used as the page-fault address // - __writecr2(PageFaultAddress); + CpuWriteCr2(PageFaultAddress); HvSuppressRipIncrement(VCpu); diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/Hv.c b/hyperdbg/hyperhv/code/vmm/vmx/Hv.c similarity index 72% rename from hyperdbg/hprdbghv/code/vmm/vmx/Hv.c rename to hyperdbg/hyperhv/code/vmm/vmx/Hv.c index b40a3f9c..155ced78 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/Hv.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/Hv.c @@ -24,7 +24,7 @@ HvAdjustControls(UINT32 Ctl, UINT32 Msr) { MSR MsrValue = {0}; - MsrValue.Flags = __readmsr(Msr); + MsrValue.Flags = CpuReadMsr(Msr); Ctl &= MsrValue.Fields.High; /* bit == 0 in high word ==> must be zero */ Ctl |= MsrValue.Fields.Low; /* bit == 1 in low word ==> must be one */ return Ctl; @@ -42,7 +42,7 @@ BOOLEAN HvSetGuestSelector(PVOID GdtBase, UINT32 SegmentRegister, UINT16 Selector) { VMX_SEGMENT_SELECTOR SegmentSelector = {0}; - VmxGetSegmentDescriptor(GdtBase, Selector, &SegmentSelector); + SegmentGetDescriptor(GdtBase, Selector, &SegmentSelector); if (Selector == 0x0) { @@ -73,14 +73,14 @@ HvHandleCpuid(VIRTUAL_MACHINE_STATE * VCpu) // Otherwise, issue the CPUID to the logical processor based on the indexes // on the VP's GPRs. // - __cpuidex(CpuInfo, (INT32)Regs->rax, (INT32)Regs->rcx); + CpuCpuIdEx(CpuInfo, (INT32)Regs->rax, (INT32)Regs->rcx); // // check whether we are in transparent mode or not // if we are in transparent mode then ignore the // cpuid modifications e.g. hyperviosr name or bit // - if (!g_TransparentMode) + if (!g_CheckForFootprints) { // // Check if this was CPUID 1h, which is the features request @@ -116,6 +116,10 @@ HvHandleCpuid(VIRTUAL_MACHINE_STATE * VCpu) CpuInfo[1] = CpuInfo[2] = CpuInfo[3] = 0; } } + else + { + TransparentCheckAndModifyCpuid(Regs, CpuInfo); + } // // Copy the values from the logical processor registers into the VP GPRs @@ -154,7 +158,7 @@ HvHandleControlRegisterAccess(VIRTUAL_MACHINE_STATE * VCpu, /* if (CrExitQualification->Fields.Register == 4) { - __vmx_vmread(VMCS_GUEST_RSP, &GuestRsp); + VmxVmread64P(VMCS_GUEST_RSP, &GuestRsp); *RegPtr = GuestRsp; } */ @@ -194,14 +198,6 @@ HvHandleControlRegisterAccess(VIRTUAL_MACHINE_STATE * VCpu, // InterceptionCallbackTriggerCr3ProcessChange(VCpu->CoreId); - // - // Call user debugger handler of thread intercepting mechanism - // - if (g_CheckPageFaultsAndMov2Cr3VmexitsWithUserDebugger) - { - InterceptionCallbackCr3VmexitsForThreadInterception(VCpu->CoreId, NewCr3Reg); - } - // // Call handler of the reversing machine // @@ -233,19 +229,19 @@ HvHandleControlRegisterAccess(VIRTUAL_MACHINE_STATE * VCpu, { case VMX_EXIT_QUALIFICATION_REGISTER_CR0: - __vmx_vmread(VMCS_GUEST_CR0, RegPtr); + VmxVmread64P(VMCS_GUEST_CR0, RegPtr); break; case VMX_EXIT_QUALIFICATION_REGISTER_CR3: - __vmx_vmread(VMCS_GUEST_CR3, RegPtr); + VmxVmread64P(VMCS_GUEST_CR3, RegPtr); break; case VMX_EXIT_QUALIFICATION_REGISTER_CR4: - __vmx_vmread(VMCS_GUEST_CR4, RegPtr); + VmxVmread64P(VMCS_GUEST_CR4, RegPtr); break; @@ -277,7 +273,7 @@ HvFillGuestSelectorData(PVOID GdtBase, UINT32 SegmentRegister, UINT16 Selector) { VMX_SEGMENT_SELECTOR SegmentSelector = {0}; - VmxGetSegmentDescriptor(GdtBase, Selector, &SegmentSelector); + SegmentGetDescriptor(GdtBase, Selector, &SegmentSelector); if (Selector == 0x0) { @@ -303,10 +299,10 @@ HvResumeToNextInstruction() { UINT64 ResumeRIP = NULL64_ZERO; UINT64 CurrentRIP = NULL64_ZERO; - size_t ExitInstructionLength = 0; + SIZE_T ExitInstructionLength = 0; - __vmx_vmread(VMCS_GUEST_RIP, &CurrentRIP); - __vmx_vmread(VMCS_VMEXIT_INSTRUCTION_LENGTH, &ExitInstructionLength); + VmxVmread64P(VMCS_GUEST_RIP, &CurrentRIP); + VmxVmread64P(VMCS_VMEXIT_INSTRUCTION_LENGTH, &ExitInstructionLength); ResumeRIP = CurrentRIP + ExitInstructionLength; @@ -357,11 +353,11 @@ HvSetMonitorTrapFlag(BOOLEAN Set) if (Set) { - CpuBasedVmExecControls |= CPU_BASED_MONITOR_TRAP_FLAG; + CpuBasedVmExecControls |= IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_FLAG; } else { - CpuBasedVmExecControls &= ~CPU_BASED_MONITOR_TRAP_FLAG; + CpuBasedVmExecControls &= ~IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_FLAG; } // @@ -395,12 +391,28 @@ HvSetRflagTrapFlag(BOOLEAN Set) /** * @brief Set LOAD DEBUG CONTROLS on Vm-entry controls * + * @param VCpu * @param Set Set or unset * @return VOID */ VOID -HvSetLoadDebugControls(BOOLEAN Set) +HvSetLoadDebugControls(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set) { + ProtectedHvSetLoadDebugControls(VCpu, Set); +} + +/** + * @brief Set LOAD GUEST IA32_LBR_CTL on Vm-entry controls + * + * @param VCpu + * @param Set Set or unset + * @return VOID + */ +VOID +HvSetLoadGuestIa32LbrCtl(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set) +{ + UNREFERENCED_PARAMETER(VCpu); + UINT32 VmentryControls = 0; // @@ -410,28 +422,44 @@ HvSetLoadDebugControls(BOOLEAN Set) if (Set) { - VmentryControls |= VM_ENTRY_LOAD_DEBUG_CONTROLS; + VmentryControls |= IA32_VMX_ENTRY_CTLS_LOAD_IA32_LBR_CTL_FLAG; } else { - VmentryControls &= ~VM_ENTRY_LOAD_DEBUG_CONTROLS; + VmentryControls &= ~IA32_VMX_ENTRY_CTLS_LOAD_IA32_LBR_CTL_FLAG; } // // Set the new value // - VmxVmwrite64(VMCS_CTRL_VMENTRY_CONTROLS, VmentryControls); + VmxVmwrite32(VMCS_CTRL_VMENTRY_CONTROLS, VmentryControls); } /** * @brief Set SAVE DEBUG CONTROLS on Vm-exit controls * + * @param VCpu * @param Set Set or unset * @return VOID */ VOID -HvSetSaveDebugControls(BOOLEAN Set) +HvSetSaveDebugControls(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set) { + ProtectedHvSetSaveDebugControls(VCpu, Set); +} + +/** + * @brief Set SAVE GUEST IA32_LBR_CTL on Vm-exit controls + * + * @param VCpu + * @param Set Set or unset + * @return VOID + */ +VOID +HvSetClearGuestIa32LbrCtl(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set) +{ + UNREFERENCED_PARAMETER(VCpu); + UINT32 VmexitControls = 0; // @@ -441,17 +469,17 @@ HvSetSaveDebugControls(BOOLEAN Set) if (Set) { - VmexitControls |= VM_EXIT_SAVE_DEBUG_CONTROLS; + VmexitControls |= IA32_VMX_EXIT_CTLS_CLEAR_IA32_LBR_CTL_FLAG; } else { - VmexitControls &= ~VM_EXIT_SAVE_DEBUG_CONTROLS; + VmexitControls &= ~IA32_VMX_EXIT_CTLS_CLEAR_IA32_LBR_CTL_FLAG; } // // Set the new value // - VmxVmwrite64(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, VmexitControls); + VmxVmwrite32(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, VmexitControls); } /** @@ -468,34 +496,50 @@ HvRestoreRegisters() UINT64 GdtrLimit; UINT64 IdtrBase; UINT64 IdtrLimit; + UINT16 DsSelector; + UINT16 EsSelector; + UINT16 SsSelector; + UINT16 FsSelector; // // Restore FS Base // - __vmx_vmread(VMCS_GUEST_FS_BASE, &FsBase); - __writemsr(IA32_FS_BASE, FsBase); + VmxVmread64P(VMCS_GUEST_FS_BASE, &FsBase); + CpuWriteMsr(IA32_FS_BASE, FsBase); // // Restore Gs Base // - __vmx_vmread(VMCS_GUEST_GS_BASE, &GsBase); - __writemsr(IA32_GS_BASE, GsBase); + VmxVmread64P(VMCS_GUEST_GS_BASE, &GsBase); + CpuWriteMsr(IA32_GS_BASE, GsBase); // // Restore GDTR // - __vmx_vmread(VMCS_GUEST_GDTR_BASE, &GdtrBase); - __vmx_vmread(VMCS_GUEST_GDTR_LIMIT, &GdtrLimit); + 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 + // + VmxVmread16P(VMCS_GUEST_DS_SELECTOR, &DsSelector); + AsmSetDs(DsSelector); + VmxVmread16P(VMCS_GUEST_ES_SELECTOR, &EsSelector); + AsmSetEs(EsSelector); + VmxVmread16P(VMCS_GUEST_SS_SELECTOR, &SsSelector); + AsmSetSs(SsSelector); + VmxVmread16P(VMCS_GUEST_FS_SELECTOR, &FsSelector); + AsmSetFs(FsSelector); // // Restore IDTR // - __vmx_vmread(VMCS_GUEST_IDTR_BASE, &IdtrBase); - __vmx_vmread(VMCS_GUEST_IDTR_LIMIT, &IdtrLimit); + VmxVmread64P(VMCS_GUEST_IDTR_BASE, &IdtrBase); + VmxVmread64P(VMCS_GUEST_IDTR_LIMIT, &IdtrLimit); - AsmReloadIdtr((void *)IdtrBase, (unsigned long)IdtrLimit); + AsmReloadIdtr((PVOID)IdtrBase, (ULONG)IdtrLimit); } /** @@ -517,11 +561,11 @@ HvSetPmcVmexit(BOOLEAN Set) if (Set) { - CpuBasedVmExecControls |= CPU_BASED_RDPMC_EXITING; + CpuBasedVmExecControls |= IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_FLAG; } else { - CpuBasedVmExecControls &= ~CPU_BASED_RDPMC_EXITING; + CpuBasedVmExecControls &= ~IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_FLAG; } // @@ -617,11 +661,11 @@ HvSetInterruptWindowExiting(BOOLEAN Set) // if (Set) { - CpuBasedVmExecControls |= CPU_BASED_VIRTUAL_INTR_PENDING; + CpuBasedVmExecControls |= IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_FLAG; } else { - CpuBasedVmExecControls &= ~CPU_BASED_VIRTUAL_INTR_PENDING; + CpuBasedVmExecControls &= ~IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_FLAG; } // @@ -725,11 +769,11 @@ HvSetNmiWindowExiting(BOOLEAN Set) // if (Set) { - CpuBasedVmExecControls |= CPU_BASED_VIRTUAL_NMI_PENDING; + CpuBasedVmExecControls |= IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_FLAG; } else { - CpuBasedVmExecControls &= ~CPU_BASED_VIRTUAL_NMI_PENDING; + CpuBasedVmExecControls &= ~IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_FLAG; } // @@ -848,11 +892,11 @@ HvHandleMovDebugRegister(VIRTUAL_MACHINE_STATE * VCpu) if (Dr7.GeneralDetect) { DR6 Dr6 = { - .AsUInt = __readdr(6), + .AsUInt = CpuReadDr(6), .BreakpointCondition = 0, .DebugRegisterAccessDetected = TRUE}; - __writedr(6, Dr6.AsUInt); + CpuWriteDr(6, Dr6.AsUInt); Dr7.GeneralDetect = FALSE; @@ -874,7 +918,10 @@ HvHandleMovDebugRegister(VIRTUAL_MACHINE_STATE * VCpu) // 32 bits results in a #GP(0) exception. // (ref: Vol3B[17.2.6(Debug Registers and Intel 64 Processors)]) // - if (ExitQualification.DirectionOfAccess == VMX_EXIT_QUALIFICATION_DIRECTION_MOV_TO_DR && (ExitQualification.DebugRegister == VMX_EXIT_QUALIFICATION_REGISTER_DR6 || ExitQualification.DebugRegister == VMX_EXIT_QUALIFICATION_REGISTER_DR7) && (GpRegister >> 32) != 0) + if (ExitQualification.DirectionOfAccess == VMX_EXIT_QUALIFICATION_DIRECTION_MOV_TO_DR && + (ExitQualification.DebugRegister == VMX_EXIT_QUALIFICATION_REGISTER_DR6 || + ExitQualification.DebugRegister == VMX_EXIT_QUALIFICATION_REGISTER_DR7) && + (GpRegister >> 32) != 0) { EventInjectGeneralProtection(); @@ -891,22 +938,22 @@ HvHandleMovDebugRegister(VIRTUAL_MACHINE_STATE * VCpu) switch (ExitQualification.DebugRegister) { case VMX_EXIT_QUALIFICATION_REGISTER_DR0: - __writedr(VMX_EXIT_QUALIFICATION_REGISTER_DR0, GpRegister); + CpuWriteDr(VMX_EXIT_QUALIFICATION_REGISTER_DR0, GpRegister); break; case VMX_EXIT_QUALIFICATION_REGISTER_DR1: - __writedr(VMX_EXIT_QUALIFICATION_REGISTER_DR1, GpRegister); + CpuWriteDr(VMX_EXIT_QUALIFICATION_REGISTER_DR1, GpRegister); break; case VMX_EXIT_QUALIFICATION_REGISTER_DR2: - __writedr(VMX_EXIT_QUALIFICATION_REGISTER_DR2, GpRegister); + CpuWriteDr(VMX_EXIT_QUALIFICATION_REGISTER_DR2, GpRegister); break; case VMX_EXIT_QUALIFICATION_REGISTER_DR3: - __writedr(VMX_EXIT_QUALIFICATION_REGISTER_DR3, GpRegister); + CpuWriteDr(VMX_EXIT_QUALIFICATION_REGISTER_DR3, GpRegister); break; case VMX_EXIT_QUALIFICATION_REGISTER_DR6: - __writedr(VMX_EXIT_QUALIFICATION_REGISTER_DR6, GpRegister); + CpuWriteDr(VMX_EXIT_QUALIFICATION_REGISTER_DR6, GpRegister); break; case VMX_EXIT_QUALIFICATION_REGISTER_DR7: - __writedr(VMX_EXIT_QUALIFICATION_REGISTER_DR7, GpRegister); + CpuWriteDr(VMX_EXIT_QUALIFICATION_REGISTER_DR7, GpRegister); break; default: break; @@ -917,22 +964,22 @@ HvHandleMovDebugRegister(VIRTUAL_MACHINE_STATE * VCpu) switch (ExitQualification.DebugRegister) { case VMX_EXIT_QUALIFICATION_REGISTER_DR0: - GpRegister = __readdr(VMX_EXIT_QUALIFICATION_REGISTER_DR0); + GpRegister = CpuReadDr(VMX_EXIT_QUALIFICATION_REGISTER_DR0); break; case VMX_EXIT_QUALIFICATION_REGISTER_DR1: - GpRegister = __readdr(VMX_EXIT_QUALIFICATION_REGISTER_DR1); + GpRegister = CpuReadDr(VMX_EXIT_QUALIFICATION_REGISTER_DR1); break; case VMX_EXIT_QUALIFICATION_REGISTER_DR2: - GpRegister = __readdr(VMX_EXIT_QUALIFICATION_REGISTER_DR2); + GpRegister = CpuReadDr(VMX_EXIT_QUALIFICATION_REGISTER_DR2); break; case VMX_EXIT_QUALIFICATION_REGISTER_DR3: - GpRegister = __readdr(VMX_EXIT_QUALIFICATION_REGISTER_DR3); + GpRegister = CpuReadDr(VMX_EXIT_QUALIFICATION_REGISTER_DR3); break; case VMX_EXIT_QUALIFICATION_REGISTER_DR6: - GpRegister = __readdr(VMX_EXIT_QUALIFICATION_REGISTER_DR6); + GpRegister = CpuReadDr(VMX_EXIT_QUALIFICATION_REGISTER_DR6); break; case VMX_EXIT_QUALIFICATION_REGISTER_DR7: - GpRegister = __readdr(VMX_EXIT_QUALIFICATION_REGISTER_DR7); + GpRegister = CpuReadDr(VMX_EXIT_QUALIFICATION_REGISTER_DR7); break; default: break; @@ -963,13 +1010,13 @@ HvSetNmiExiting(BOOLEAN Set) if (Set) { - PinBasedControls |= PIN_BASED_VM_EXECUTION_CONTROLS_NMI_EXITING; - VmExitControls |= VM_EXIT_ACK_INTR_ON_EXIT; + PinBasedControls |= IA32_VMX_PINBASED_CTLS_NMI_EXITING_FLAG; + VmExitControls |= IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_FLAG; } else { - PinBasedControls &= ~PIN_BASED_VM_EXECUTION_CONTROLS_NMI_EXITING; - VmExitControls &= ~VM_EXIT_ACK_INTR_ON_EXIT; + PinBasedControls &= ~IA32_VMX_PINBASED_CTLS_NMI_EXITING_FLAG; + VmExitControls &= ~IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_FLAG; } // @@ -997,11 +1044,11 @@ HvSetVmxPreemptionTimerExiting(BOOLEAN Set) if (Set) { - PinBasedControls |= PIN_BASED_VM_EXECUTION_CONTROLS_ACTIVE_VMX_TIMER; + PinBasedControls |= IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_FLAG; } else { - PinBasedControls &= ~PIN_BASED_VM_EXECUTION_CONTROLS_ACTIVE_VMX_TIMER; + PinBasedControls &= ~IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_FLAG; } // @@ -1064,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 */ @@ -1137,7 +1183,7 @@ HvGetCsSelector() // UINT64 CsSel = NULL64_ZERO; - __vmx_vmread(VMCS_GUEST_CS_SELECTOR, &CsSel); + VmxVmread64P(VMCS_GUEST_CS_SELECTOR, &CsSel); return CsSel & 0xffff; } @@ -1152,7 +1198,7 @@ HvGetRflags() { UINT64 Rflags = NULL64_ZERO; - __vmx_vmread(VMCS_GUEST_RFLAGS, &Rflags); + VmxVmread64P(VMCS_GUEST_RFLAGS, &Rflags); return Rflags; } @@ -1179,7 +1225,7 @@ HvGetRip() { UINT64 Rip = NULL64_ZERO; - __vmx_vmread(VMCS_GUEST_RIP, &Rip); + VmxVmread64P(VMCS_GUEST_RIP, &Rip); return Rip; } @@ -1206,7 +1252,7 @@ HvGetInterruptibilityState() { UINT64 InterruptibilityState = NULL64_ZERO; - __vmx_vmread(VMCS_GUEST_INTERRUPTIBILITY_STATE, &InterruptibilityState); + VmxVmread64P(VMCS_GUEST_INTERRUPTIBILITY_STATE, &InterruptibilityState); return InterruptibilityState; } @@ -1366,7 +1412,10 @@ HvInitVmm(VMM_CALLBACKS * VmmCallbacks) // // Make sure that transparent-mode is disabled // - g_TransparentMode = FALSE; + if (g_CheckForFootprints) + { + TransparentUnhideDebuggerWrapper(NULL); + } // // Not waiting for the interrupt-window to inject page-faults @@ -1441,3 +1490,294 @@ HvPreventExternalInterrupts(VIRTUAL_MACHINE_STATE * VCpu) // VCpu->EnableExternalInterruptsOnContinueMtf = TRUE; } + +/** + * @brief Get the guest state of pending debug exceptions + * + * @return UINT64 + */ +UINT64 +HvGetPendingDebugExceptions() +{ + UINT64 Value; + VmxVmread64P(VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, &Value); + + return Value; +} + +/** + * @brief Set the guest state of pending debug exceptions + * @param Value The new state + * + * @return VOID + */ +VOID +HvSetPendingDebugExceptions(UINT64 Value) +{ + VmxVmwrite64(VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, Value); +} + +/** + * @brief Get the guest state of IA32_DEBUGCTL + * + * @return UINT64 + */ +UINT64 +HvGetDebugctl() +{ + UINT32 LowPart; + UINT32 HighPart; + + VmxVmread32P(VMCS_GUEST_DEBUGCTL, &LowPart); + VmxVmread32P(VMCS_GUEST_DEBUGCTL_HIGH, &HighPart); + + return (UINT64)HighPart << 32 | LowPart; +} + +/** + * @brief Get the guest state of IA32_LBR_CTL + * + * @return UINT64 + */ +UINT64 +HvGetGuestIa32LbrCtl() +{ + UINT64 GuestIa32LbrCtl; + + VmxVmread64P(VMCS_GUEST_LBR_CTL, &GuestIa32LbrCtl); + + return GuestIa32LbrCtl; +} + +/** + * @brief Get and store the guest state of IA32_DEBUGCTL + * @details mainly used from the VMCALL handler + * + * @param StoreDebugctl + * + * @return VOID + */ +VOID +HvGetAndStoreDebugctl(UINT64 * StoreDebugctl) +{ + UINT64 DebugctlValue; + + // + // Read DEBUGCTL from VMCS + // + DebugctlValue = HvGetDebugctl(); + + // + // Store the DEBUGCTL + // + *StoreDebugctl = DebugctlValue; +} + +/** + * @brief Get and store the guest state of IA32_LBR_CTL + * @details mainly used from the VMCALL handler + * + * @param StoreGuestIa32Lbr + * + * @return VOID + */ +VOID +HvGetAndStoreGuestIa32LbrCtl(UINT64 * StoreGuestIa32Lbr) +{ + UINT64 GuestIa32LbrCtl; + + // + // Read IA32_LBR_CTL from VMCS + // + GuestIa32LbrCtl = HvGetGuestIa32LbrCtl(); + + // + // Store the IA32_LBR_CTL + // + *StoreGuestIa32Lbr = GuestIa32LbrCtl; +} + +/** + * @brief Set the guest state of IA32_DEBUGCTL + * @param Value The new state + * + * @return VOID + */ +VOID +HvSetDebugctl(UINT64 Value) +{ + VmxVmwrite32(VMCS_GUEST_DEBUGCTL, Value & 0xFFFFFFFF); + VmxVmwrite32(VMCS_GUEST_DEBUGCTL_HIGH, Value >> 32); +} + +/** + * @brief Set the guest state of IA32_LBR_CTL + * @param Value The new state + * + * @return VOID + */ +VOID +HvSetGuestIa32LbrCtl(UINT64 Value) +{ + VmxVmwrite64(VMCS_GUEST_LBR_CTL, Value); +} + +/** + * @brief Set LBR selector + * @details If VMM is active, this should be done in vmx-root, otherwise, it doesn't work + * @param FilterOptions The value to write on MSR_LEGACY_LBR_SELECT + * + * @return VOID + */ +VOID +HvSetLbrSelect(UINT64 FilterOptions) +{ + CpuWriteMsr(MSR_LEGACY_LBR_SELECT, FilterOptions); +} + +/** + * @brief Check if CPU support save and load debug controls on exit and load entries + * + * @return BOOLEAN + */ +BOOLEAN +HvCheckCpuSupportForSaveAndLoadDebugControls() +{ + IA32_VMX_BASIC_REGISTER VmxBasicMsr = {0}; + + // + // Reading IA32_VMX_BASIC_MSR + // + VmxBasicMsr.AsUInt = CpuReadMsr(IA32_VMX_BASIC); + + // + // Read 1-settings of save debug controls (exit controls) + // + UINT32 ExitCtls = HvAdjustControls( + IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_FLAG, + VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS); + + // + // Read 1-settings of load debug controls (entry controls) + // + UINT32 EntryCtls = HvAdjustControls( + IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_FLAG, + VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS); + + // + // Check if entry and exit controls are supported on this system + // + if (ExitCtls != NULL_ZERO && EntryCtls != NULL_ZERO) + { + // + // Supported + // + return TRUE; + } + else + { + // + // Not supported + // + return FALSE; + } +} + +/** + * @brief Check if CPU support load and clear guest IA32_LBR_CTL controls on entry and exit + * + * @return BOOLEAN + */ +BOOLEAN +HvCheckCpuSupportForLoadAndClearGuestIa32LbrCtlControls() +{ + IA32_VMX_BASIC_REGISTER VmxBasicMsr = {0}; + + // + // Reading IA32_VMX_BASIC_MSR + // + VmxBasicMsr.AsUInt = CpuReadMsr(IA32_VMX_BASIC); + + // + // Read 1-settings of save debug controls (exit controls) + // + UINT32 ExitCtls = HvAdjustControls( + IA32_VMX_EXIT_CTLS_CLEAR_IA32_LBR_CTL_FLAG, + VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS); + + // + // Read 1-settings of load debug controls (entry controls) + // + UINT32 EntryCtls = HvAdjustControls( + IA32_VMX_ENTRY_CTLS_LOAD_IA32_LBR_CTL_FLAG, + VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS); + + // + // Check if entry and exit controls are supported on this system + // + if (ExitCtls != NULL_ZERO && EntryCtls != NULL_ZERO) + { + // + // Supported + // + return TRUE; + } + else + { + // + // Not supported + // + return FALSE; + } +} + +/** + * @brief Set the guest state of DR7 + * @param Value The new value for DR7 + * + * @return VOID + */ +VOID +HvSetDebugReg7(UINT64 Value) +{ + VmxVmwrite64(VMCS_GUEST_DR7, Value); +} + +/** + * @brief Handle the case when the trap flag is set, and + * we need to inject the single-step exception right + * after vm-entry + * + * @return VOID + */ +VOID +HvHandleTrapFlag() +{ + IA32_DEBUGCTL_REGISTER Debugctl = {.AsUInt = HvGetDebugctl()}; + RFLAGS GuestRFlags = {.AsUInt = GetGuestRFlags()}; + VMX_PENDING_DEBUG_EXCEPTIONS PendingDebugExceptions; + VMX_INTERRUPTIBILITY_STATE InterruptibilityState; + + // + // The btf flag means that the trap flag generates the single-step exception + // only for branch instructions + // + if (GuestRFlags.TrapFlag && !Debugctl.Btf) + { + PendingDebugExceptions.AsUInt = HvGetPendingDebugExceptions(); + PendingDebugExceptions.Bs = 1; + HvSetPendingDebugExceptions(PendingDebugExceptions.AsUInt); + + InterruptibilityState.AsUInt = (UINT32)HvGetInterruptibilityState(); + + // + // We also must clear this flag in case of instruction emulation to achieve + // correctness of the single-step exception + // + if (InterruptibilityState.BlockingByMovSs) + { + InterruptibilityState.BlockingByMovSs = 0; + HvSetInterruptibilityState(InterruptibilityState.AsUInt); + } + } +} diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/IdtEmulation.c b/hyperdbg/hyperhv/code/vmm/vmx/IdtEmulation.c similarity index 51% rename from hyperdbg/hprdbghv/code/vmm/vmx/IdtEmulation.c rename to hyperdbg/hyperhv/code/vmm/vmx/IdtEmulation.c index 0019ebfb..09226007 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/IdtEmulation.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/IdtEmulation.c @@ -11,6 +11,279 @@ */ #include "pch.h" +/** + * @brief Perform query for IDT entries + * + * @param IdtQueryRequest + * @param ReadFromVmxRoot + * + * @return VOID + */ +VOID +IdtEmulationQueryIdtEntriesRequest(PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtQueryRequest, + BOOLEAN ReadFromVmxRoot) +{ + SIDT_ENTRY IdtrReg; + KIDT_ENTRY * IdtEntries; + + // + // Read IDTR register + // + + if (!ReadFromVmxRoot) + { + // + // Since it's not in VMX Root, we can directly read the IDTR register + // + CpuSidt(&IdtrReg); + + // + // Get the IDT base address + // + IdtEntries = (KIDT_ENTRY *)IdtrReg.IdtBase; + } + else + { + // + // Since it's in VMX Root, we need to read the IDTR register from the VMCS + // + IdtEntries = (KIDT_ENTRY *)GetGuestIdtr(); + } + + // + // Gather a list of IDT entries + // + for (UINT32 i = 0; i < MAX_NUMBER_OF_IDT_ENTRIES; i++) + { + IdtQueryRequest->IdtEntry[i] = (UINT64)((UINT64)IdtEntries[i].HighestPart << 32) | + ((UINT64)IdtEntries[i].HighPart << 16) | + (UINT64)IdtEntries[i].LowPart; + } +} + +/** + * @brief Create an interrupt gate that points to the supplied interrupt handler + * + * @param VCpu The virtual processor's state + * @param Entry + * + * @return VOID + */ +VOID +IdtEmulationCreateInterruptGate(PVOID Handler, SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64 * Entry) +{ + // SEGMENT_SELECTOR HostCsSelector = {0, 0, 1}; + // + // Entry->InterruptStackTable = 0; + // Entry->SegmentSelector = HostCsSelector.AsUInt; + // Entry->MustBeZero0 = 0; + // Entry->Type = SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE; + // Entry->MustBeZero1 = 0; + // Entry->DescriptorPrivilegeLevel = 0; + // Entry->Present = 1; + // Entry->Reserved = 0; + + UINT64 Offset = (UINT64)Handler; + Entry->OffsetLow = (Offset >> 0) & 0xFFFF; + Entry->OffsetMiddle = (Offset >> 16) & 0xFFFF; + Entry->OffsetHigh = (Offset >> 32) & 0xFFFFFFFF; + +#if USE_INTERRUPT_STACK_TABLE == TRUE + + // + // Use first index (IST1) + // + Entry->InterruptStackTable = 1; + +#else + + // + // Make sure to unset IST since we didn't use a separate stack pointer + // on TSS entry at GDT + // + Entry->InterruptStackTable = 0; + +#endif // USE_INTERRUPT_STACK_TABLE == TRUE +} + +/** + * @brief Prepare Host IDT + * + * @param VCpu The virtual processor's state + * + * @return VOID + */ +VOID +IdtEmulationPrepareHostIdt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) +{ + SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64 * VmxHostIdt = (SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64 *)VCpu->HostIdt; + SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64 * WindowsIdt = (SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64 *)AsmGetIdtBase(); + + // + // Zero the memory + // + RtlZeroMemory(VmxHostIdt, HOST_IDT_DESCRIPTOR_COUNT * sizeof(SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64)); + + // + // Copy OS interrupt (IDT) entries + // + RtlCopyBytes(VmxHostIdt, + WindowsIdt, + HOST_IDT_DESCRIPTOR_COUNT * sizeof(SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64)); + + /* + for (SIZE_T i = 0; i < HOST_IDT_DESCRIPTOR_COUNT; i++) + { + SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64 CurrentEntry = WindowsIdt[i]; + + UINT64 Offset = 0; + Offset |= ((UINT64)CurrentEntry.OffsetLow) << 0; + Offset |= ((UINT64)CurrentEntry.OffsetMiddle) << 16; + Offset |= ((UINT64)CurrentEntry.OffsetHigh) << 32; + + // LogInfo("IDT Entry [%d] at: %llx", i, Offset); + + IdtEmulationCreateInterruptGate((PVOID)Offset, &VmxHostIdt[i]); + } + */ + + // + // Function related to handling host IDT are a modified version of the following project: + // https://github.com/jonomango/hv/blob/main/hv + // + + // + // Add customize interrupt handlers + // + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler0, &VmxHostIdt[EXCEPTION_VECTOR_DIVIDE_ERROR]); + // IdtEmulationCreateInterruptGate((PVOID)InterruptHandler1, &VmxHostIdt[EXCEPTION_VECTOR_DEBUG_BREAKPOINT]); // #DB + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler2, &VmxHostIdt[EXCEPTION_VECTOR_NMI]); + // IdtEmulationCreateInterruptGate((PVOID)InterruptHandler3, &VmxHostIdt[EXCEPTION_VECTOR_BREAKPOINT]); // #BP + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler4, &VmxHostIdt[EXCEPTION_VECTOR_OVERFLOW]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler5, &VmxHostIdt[EXCEPTION_VECTOR_BOUND_RANGE_EXCEEDED]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler6, &VmxHostIdt[EXCEPTION_VECTOR_UNDEFINED_OPCODE]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler7, &VmxHostIdt[EXCEPTION_VECTOR_NO_MATH_COPROCESSOR]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler8, &VmxHostIdt[EXCEPTION_VECTOR_DOUBLE_FAULT]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler10, &VmxHostIdt[EXCEPTION_VECTOR_INVALID_TASK_SEGMENT_SELECTOR]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler11, &VmxHostIdt[EXCEPTION_VECTOR_SEGMENT_NOT_PRESENT]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler12, &VmxHostIdt[EXCEPTION_VECTOR_STACK_SEGMENT_FAULT]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler13, &VmxHostIdt[EXCEPTION_VECTOR_GENERAL_PROTECTION_FAULT]); + // IdtEmulationCreateInterruptGate((PVOID)InterruptHandler14, &VmxHostIdt[EXCEPTION_VECTOR_PAGE_FAULT]); // #PF + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler16, &VmxHostIdt[EXCEPTION_VECTOR_MATH_FAULT]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler17, &VmxHostIdt[EXCEPTION_VECTOR_ALIGNMENT_CHECK]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler18, &VmxHostIdt[EXCEPTION_VECTOR_MACHINE_CHECK]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler19, &VmxHostIdt[EXCEPTION_VECTOR_SIMD_FLOATING_POINT_NUMERIC_ERROR]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler20, &VmxHostIdt[EXCEPTION_VECTOR_VIRTUAL_EXCEPTION]); + IdtEmulationCreateInterruptGate((PVOID)InterruptHandler30, &VmxHostIdt[EXCEPTION_VECTOR_RESERVED11]); +} + +/** + * @brief Handle Page-fault exception bitmap VM-exits + * + * @param VCpu The virtual processor's state + * @param InterruptExit interrupt exit information + * + * @return VOID + */ +VOID +IdtEmulationhandleHostInterrupt(_Inout_ INTERRUPT_TRAP_FRAME * IntrTrapFrame) +{ + UINT64 PageFaultCr2; + ULONG CurrentCore; + BOOLEAN Interruptible; + VMX_INTERRUPTIBILITY_STATE InterruptibilityState = {0}; + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + VIRTUAL_MACHINE_STATE * VCpu = &g_GuestState[CurrentCore]; + + // + // Store the latest exception vector + // + VCpu->LastExceptionOccurredInHost = IntrTrapFrame->vector; + + switch (IntrTrapFrame->vector) + { + case EXCEPTION_VECTOR_NMI: + + // + // host NMIs + // + // LogInfo("NMI received!"); + + // + // Check if NMI needs to be injected back to the guest or not + // Trap frame is sent because as this function unreference this + // parameter, NULL cannot be sent + // + if (!VmxBroadcastHandleNmiCallback((PVOID)IntrTrapFrame, FALSE)) + { + // + // We cannot just use the NMI Window Exiting here because + // in certain scenarios, VMRESUME with Error 0x7 will happen + // Which means that the layout of the VMCS is wrong + // + // For the future reference, I think using NMI Windows Exiting + // here is also not useful but in theory it should serve as a + // backup plan if the system is not ready to receive NMIs, then + // we could inject it when the NMI Window is open but in reality + // it will corrupt the VMCS layout (VMRESUME 0x7 error) + // + + // + // Check if interruptibility state allows NMIs or not + // + VmxVmread32P(VMCS_GUEST_INTERRUPTIBILITY_STATE, &InterruptibilityState.AsUInt); + + Interruptible = !InterruptibilityState.BlockingByNmi; + + if (Interruptible) + { + // + // Re-inject the NMI + // + EventInjectNmi(VCpu); + } + else + { + // + // Inject NMI when the NMI Window opened + // + HvSetNmiWindowExiting(TRUE); + } + } + + break; + + case EXCEPTION_VECTOR_PAGE_FAULT: + + // + // host page-fault + // + PageFaultCr2 = CpuReadCr2(); + + LogInfo("Page-fault received, rip: %llx, rsp: %llx, error: %llx, CR2: %llx", + IntrTrapFrame->rip, + IntrTrapFrame->rsp, + IntrTrapFrame->error, + PageFaultCr2); + + break; + + default: + + // + // host exceptions + // + LogInfo("Host exception, rip: %llx, rsp: %llx, error: %llx, vector: %x", + IntrTrapFrame->rip, + IntrTrapFrame->rsp, + IntrTrapFrame->error, + IntrTrapFrame->vector); + DbgBreakPoint(); + + break; + } +} + /** * @brief Handle Page-fault exception bitmap VM-exits * @@ -36,7 +309,7 @@ IdtEmulationHandlePageFaults(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, // // Read the page-fault address // - __vmx_vmread(VMCS_EXIT_QUALIFICATION, &PageFaultAddress); + VmxVmread64P(VMCS_EXIT_QUALIFICATION, &PageFaultAddress); // LogInfo("#PF Fault = %016llx, Page Fault Code = 0x%x | %s%s%s%s", // PageFaultAddress, @@ -46,18 +319,10 @@ IdtEmulationHandlePageFaults(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, // PageFaultErrorCode.UserModeAccess ? "u" : "", // PageFaultErrorCode.Execute ? "f" : ""); - // Handle page-faults - // Check page-fault with user-debugger - // The page-fault is handled through the user debugger, no need further action - // NOTE: THE ADDRESS SHOULD BE NULL HERE // - if (!DebuggingCallbackConditionalPageFaultException(VCpu->CoreId, PageFaultAddress, PageFaultErrorCode.AsUInt)) - { - // - // The #pf is not related to the debugger, re-inject it - // - EventInjectPageFaults(VCpu, InterruptExit, PageFaultAddress, PageFaultErrorCode); - } + // Handle page-faults + // + EventInjectPageFaults(VCpu, InterruptExit, PageFaultAddress, PageFaultErrorCode); } /** @@ -91,8 +356,10 @@ IdtEmulationHandleExceptionAndNmi(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, UINT64 GuestRip = NULL64_ZERO; BYTE TargetMem = NULL_ZERO; - __vmx_vmread(VMCS_GUEST_RIP, &GuestRip); + VmxVmread64P(VMCS_GUEST_RIP, &GuestRip); + MemoryMapperReadMemorySafe(GuestRip, &TargetMem, sizeof(BYTE)); + if (!EptCheckAndHandleBreakpoint(VCpu) || TargetMem == 0xcc) { if (!DebuggingCallbackHandleBreakpointException(VCpu->CoreId)) @@ -138,7 +405,23 @@ IdtEmulationHandleExceptionAndNmi(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, case EXCEPTION_VECTOR_DEBUG_BREAKPOINT: - if (!DebuggingCallbackHandleDebugBreakpointException(VCpu->CoreId)) + // + // Check if syscall callback is enabled and if so, then we need to + // check whether the this trap flag is set because of intercepting + // the result of a system-call or not + // + if (g_SyscallCallbackStatus && + SyscallCallbackCheckAndHandleAfterSyscallTrapFlags(VCpu, + HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId()))) + { + // + // Being here means that this #DB was caused by a trap flag of + // the system-call in the syscall callback, so no need to further handle + // it (nothing to do) + // + } + else if (!DebuggingCallbackHandleDebugBreakpointException(VCpu->CoreId)) { // // It's not because of thread change detection, so re-inject it @@ -152,7 +435,7 @@ IdtEmulationHandleExceptionAndNmi(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, if (VCpu->EnableExternalInterruptsOnContinue || VCpu->EnableExternalInterruptsOnContinueMtf || - VCpu->RegisterBreakOnMtf) + VCpu->InstrumentationStepInMtf) { // // Ignore the nmi @@ -198,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 @@ -235,11 +518,11 @@ IdtEmulationHandleExternalInterrupt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, // // In order to enable External Interrupt Exiting we have to set - // PIN_BASED_VM_EXECUTION_CONTROLS_EXTERNAL_INTERRUPT in vmx + // IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_FLAG in vmx // pin-based controls (PIN_BASED_VM_EXEC_CONTROL) and also - // we should enable VM_EXIT_ACK_INTR_ON_EXIT on vmx vm-exit - // controls (VMCS_CTRL_VMEXIT_CONTROLS), also this function might not - // always be successful if the guest is not in the interruptible + // we should enable IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_FLAG + // on vmx vm-exit controls (VMCS_CTRL_VMEXIT_CONTROLS), also this function + // might not always be successful if the guest is not in the interruptible // state so it wait for and interrupt-window exiting to re-inject // the interrupt into the guest // @@ -321,9 +604,15 @@ IdtEmulationHandleExternalInterrupt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, VOID IdtEmulationHandleNmiWindowExiting(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) { - UNREFERENCED_PARAMETER(VCpu); + // + // Inject the NMI into the guest + // + EventInjectNmi(VCpu); - LogError("Why NMI-window exiting happens?"); + // + // Disable NMI-window exiting since we have no more NMIs to inject + // + HvSetNmiWindowExiting(FALSE); } /** @@ -388,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 diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/IoHandler.c b/hyperdbg/hyperhv/code/vmm/vmx/IoHandler.c similarity index 91% rename from hyperdbg/hprdbghv/code/vmm/vmx/IoHandler.c rename to hyperdbg/hyperhv/code/vmm/vmx/IoHandler.c index b506b337..77daa753 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/IoHandler.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/IoHandler.c @@ -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); } diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/ManageRegs.c b/hyperdbg/hyperhv/code/vmm/vmx/ManageRegs.c similarity index 87% rename from hyperdbg/hprdbghv/code/vmm/vmx/ManageRegs.c rename to hyperdbg/hyperhv/code/vmm/vmx/ManageRegs.c index 6127d337..ad816203 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/ManageRegs.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/ManageRegs.c @@ -1,4 +1,4 @@ -/** +/** * @file ManageRegs.c * @author Sina Karvandi (sina@hyperdbg.org) * @author Alee Amini (alee@hyperdbg.org) @@ -21,7 +21,7 @@ VOID SetGuestCsSel(PVMX_SEGMENT_SELECTOR Cs) { - __vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, Cs->Selector); + VmxVmwrite16(VMCS_GUEST_CS_SELECTOR, Cs->Selector); } /** @@ -34,10 +34,10 @@ SetGuestCsSel(PVMX_SEGMENT_SELECTOR Cs) VOID SetGuestCs(PVMX_SEGMENT_SELECTOR Cs) { - __vmx_vmwrite(VMCS_GUEST_CS_BASE, Cs->Base); - __vmx_vmwrite(VMCS_GUEST_CS_LIMIT, Cs->Limit); - __vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, Cs->Attributes.AsUInt); - __vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, Cs->Selector); + VmxVmwrite64(VMCS_GUEST_CS_BASE, Cs->Base); + VmxVmwrite32(VMCS_GUEST_CS_LIMIT, Cs->Limit); + VmxVmwrite32(VMCS_GUEST_CS_ACCESS_RIGHTS, Cs->Attributes.AsUInt); + VmxVmwrite16(VMCS_GUEST_CS_SELECTOR, Cs->Selector); } /** @@ -50,7 +50,7 @@ GetGuestCs() { VMX_SEGMENT_SELECTOR Cs; - __vmx_vmread(VMCS_GUEST_CS_BASE, &Cs.Base); + VmxVmread64P(VMCS_GUEST_CS_BASE, &Cs.Base); VmxVmread32P(VMCS_GUEST_CS_LIMIT, &Cs.Limit); VmxVmread32P(VMCS_GUEST_CS_ACCESS_RIGHTS, &Cs.Attributes.AsUInt); VmxVmread16P(VMCS_GUEST_CS_SELECTOR, &Cs.Selector); @@ -67,7 +67,7 @@ GetGuestCs() VOID SetGuestSsSel(PVMX_SEGMENT_SELECTOR Ss) { - __vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, Ss->Selector); + VmxVmwrite16(VMCS_GUEST_SS_SELECTOR, Ss->Selector); } /** @@ -95,7 +95,7 @@ GetGuestSs() { VMX_SEGMENT_SELECTOR Ss; - __vmx_vmread(VMCS_GUEST_SS_BASE, &Ss.Base); + VmxVmread64P(VMCS_GUEST_SS_BASE, &Ss.Base); VmxVmread32P(VMCS_GUEST_SS_LIMIT, &Ss.Limit); VmxVmread32P(VMCS_GUEST_SS_ACCESS_RIGHTS, &Ss.Attributes.AsUInt); VmxVmread16P(VMCS_GUEST_SS_SELECTOR, &Ss.Selector); @@ -140,7 +140,7 @@ GetGuestDs() { VMX_SEGMENT_SELECTOR Ds; - __vmx_vmread(VMCS_GUEST_DS_BASE, &Ds.Base); + VmxVmread64P(VMCS_GUEST_DS_BASE, &Ds.Base); VmxVmread32P(VMCS_GUEST_DS_LIMIT, &Ds.Limit); VmxVmread32P(VMCS_GUEST_DS_ACCESS_RIGHTS, &Ds.Attributes.AsUInt); VmxVmread16P(VMCS_GUEST_DS_SELECTOR, &Ds.Selector); @@ -185,7 +185,7 @@ GetGuestFs() { VMX_SEGMENT_SELECTOR Fs; - __vmx_vmread(VMCS_GUEST_FS_BASE, &Fs.Base); + VmxVmread64P(VMCS_GUEST_FS_BASE, &Fs.Base); VmxVmread32P(VMCS_GUEST_FS_LIMIT, &Fs.Limit); VmxVmread32P(VMCS_GUEST_FS_ACCESS_RIGHTS, &Fs.Attributes.AsUInt); VmxVmread16P(VMCS_GUEST_FS_SELECTOR, &Fs.Selector); @@ -230,7 +230,7 @@ GetGuestGs() { VMX_SEGMENT_SELECTOR Gs; - __vmx_vmread(VMCS_GUEST_GS_BASE, &Gs.Base); + VmxVmread64P(VMCS_GUEST_GS_BASE, &Gs.Base); VmxVmread32P(VMCS_GUEST_GS_LIMIT, &Gs.Limit); VmxVmread32P(VMCS_GUEST_GS_ACCESS_RIGHTS, &Gs.Attributes.AsUInt); VmxVmread16P(VMCS_GUEST_GS_SELECTOR, &Gs.Selector); @@ -275,7 +275,7 @@ GetGuestEs() { VMX_SEGMENT_SELECTOR Es; - __vmx_vmread(VMCS_GUEST_ES_BASE, &Es.Base); + VmxVmread64P(VMCS_GUEST_ES_BASE, &Es.Base); VmxVmread32P(VMCS_GUEST_ES_LIMIT, &Es.Limit); VmxVmread32P(VMCS_GUEST_ES_ACCESS_RIGHTS, &Es.Attributes.AsUInt); VmxVmread16P(VMCS_GUEST_ES_SELECTOR, &Es.Selector); @@ -305,7 +305,7 @@ GetGuestIdtr() { UINT64 Idtr; - __vmx_vmread(VMCS_GUEST_IDTR_BASE, &Idtr); + VmxVmread64P(VMCS_GUEST_IDTR_BASE, &Idtr); return Idtr; } @@ -332,7 +332,7 @@ GetGuestLdtr() { UINT64 Ldtr; - __vmx_vmread(VMCS_GUEST_LDTR_BASE, &Ldtr); + VmxVmread64P(VMCS_GUEST_LDTR_BASE, &Ldtr); return Ldtr; } @@ -359,7 +359,7 @@ GetGuestGdtr() { UINT64 Gdtr; - __vmx_vmread(VMCS_GUEST_GDTR_BASE, &Gdtr); + VmxVmread64P(VMCS_GUEST_GDTR_BASE, &Gdtr); return Gdtr; } @@ -384,7 +384,7 @@ GetGuestTr() { UINT64 Tr; - __vmx_vmread(VMCS_GUEST_TR_BASE, &Tr); + VmxVmread64P(VMCS_GUEST_TR_BASE, &Tr); return Tr; } @@ -409,7 +409,9 @@ UINT64 GetGuestRFlags() { UINT64 RFlags; - __vmx_vmread(VMCS_GUEST_RFLAGS, &RFlags); + + VmxVmread64P(VMCS_GUEST_RFLAGS, &RFlags); + return RFlags; } @@ -447,7 +449,8 @@ GetGuestRIP() { UINT64 RIP; - __vmx_vmread(VMCS_GUEST_RIP, &RIP); + VmxVmread64P(VMCS_GUEST_RIP, &RIP); + return RIP; } @@ -461,7 +464,8 @@ GetGuestCr0() { UINT64 Cr0; - __vmx_vmread(VMCS_GUEST_CR0, &Cr0); + VmxVmread64P(VMCS_GUEST_CR0, &Cr0); + return Cr0; } @@ -475,7 +479,7 @@ GetGuestCr2() { UINT64 Cr2; - Cr2 = __readcr2(); + Cr2 = CpuReadCr2(); return Cr2; } @@ -489,7 +493,8 @@ GetGuestCr3() { UINT64 Cr3; - __vmx_vmread(VMCS_GUEST_CR3, &Cr3); + VmxVmread64P(VMCS_GUEST_CR3, &Cr3); + return Cr3; } @@ -503,7 +508,8 @@ GetGuestCr4() { UINT64 Cr4; - __vmx_vmread(VMCS_GUEST_CR4, &Cr4); + VmxVmread64P(VMCS_GUEST_CR4, &Cr4); + return Cr4; } @@ -517,7 +523,7 @@ GetGuestCr8() { UINT64 Cr8; - Cr8 = __readcr8(); + Cr8 = CpuReadCr8(); return Cr8; } @@ -542,7 +548,7 @@ SetGuestCr0(UINT64 Cr0) VOID SetGuestCr2(UINT64 Cr2) { - __writecr2(Cr2); + CpuWriteCr2(Cr2); } /** @@ -578,7 +584,7 @@ SetGuestCr4(UINT64 Cr4) VOID SetGuestCr8(UINT64 Cr8) { - __writecr8(Cr8); + CpuWriteCr8(Cr8); } /** @@ -590,7 +596,7 @@ SetGuestCr8(UINT64 Cr8) VOID SetGuestDr0(UINT64 value) { - __writedr(0, value); + CpuWriteDr(0, value); } /** @@ -602,7 +608,7 @@ SetGuestDr0(UINT64 value) VOID SetGuestDr1(UINT64 value) { - __writedr(1, value); + CpuWriteDr(1, value); } /** @@ -614,7 +620,7 @@ SetGuestDr1(UINT64 value) VOID SetGuestDr2(UINT64 value) { - __writedr(2, value); + CpuWriteDr(2, value); } /** @@ -626,7 +632,7 @@ SetGuestDr2(UINT64 value) VOID SetGuestDr3(UINT64 value) { - __writedr(3, value); + CpuWriteDr(3, value); } /** @@ -638,7 +644,7 @@ SetGuestDr3(UINT64 value) VOID SetGuestDr6(UINT64 value) { - __writedr(6, value); + CpuWriteDr(6, value); } /** @@ -650,7 +656,7 @@ SetGuestDr6(UINT64 value) VOID SetGuestDr7(UINT64 value) { - __writedr(7, value); + CpuWriteDr(7, value); } /** @@ -662,7 +668,7 @@ UINT64 GetGuestDr0() { UINT64 Dr0 = 0; - Dr0 = __readdr(0); + Dr0 = CpuReadDr(0); return Dr0; } @@ -675,7 +681,7 @@ UINT64 GetGuestDr1() { UINT64 Dr1 = 0; - Dr1 = __readdr(1); + Dr1 = CpuReadDr(1); return Dr1; } @@ -688,7 +694,7 @@ UINT64 GetGuestDr2() { UINT64 Dr2 = 0; - Dr2 = __readdr(2); + Dr2 = CpuReadDr(2); return Dr2; } @@ -701,7 +707,7 @@ UINT64 GetGuestDr3() { UINT64 Dr3 = 0; - Dr3 = __readdr(3); + Dr3 = CpuReadDr(3); return Dr3; } @@ -714,7 +720,7 @@ UINT64 GetGuestDr6() { UINT64 Dr6 = 0; - Dr6 = __readdr(6); + Dr6 = CpuReadDr(6); return Dr6; } @@ -727,6 +733,6 @@ UINT64 GetGuestDr7() { UINT64 Dr7 = 0; - Dr7 = __readdr(7); + Dr7 = CpuReadDr(7); return Dr7; } diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/MsrHandlers.c b/hyperdbg/hyperhv/code/vmm/vmx/MsrHandlers.c similarity index 70% rename from hyperdbg/hprdbghv/code/vmm/vmx/MsrHandlers.c rename to hyperdbg/hyperhv/code/vmm/vmx/MsrHandlers.c index 70f5a0e7..2600002a 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/MsrHandlers.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/MsrHandlers.c @@ -11,17 +11,62 @@ */ #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 * - * @param GuestRegs Guest's gp registers + * @param VCpu The virtual processor's state + * * @return VOID */ VOID -MsrHandleRdmsrVmexit(PGUEST_REGS GuestRegs) +MsrHandleRdmsrVmexit(VIRTUAL_MACHINE_STATE * VCpu) { - MSR Msr = {0}; - UINT32 TargetMsr; + UINT32 TargetMsr; + MSR Msr = {0}; + PGUEST_REGS GuestRegs = VCpu->Regs; // // RDMSR. The RDMSR instruction causes a VM exit if any of the following are true: @@ -48,6 +93,23 @@ MsrHandleRdmsrVmexit(PGUEST_REGS GuestRegs) // results. // + // LogInfo("MSR read (RDMSR) VM-exit, MSR: %x, from: %llx", + // TargetMsr, + // VCpu->LastVmexitRip); + + // + // Checking whether it is a synthetic MSR for Hyper-V + // + if (g_IsTopLevelHypervisorHyperV && 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 // @@ -108,7 +170,7 @@ MsrHandleRdmsrVmexit(PGUEST_REGS GuestRegs) // // 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 @@ -117,10 +179,18 @@ MsrHandleRdmsrVmexit(PGUEST_REGS GuestRegs) return; } + // + // Check for the footprints of the RDMSR in the transparent mode + // + if (g_CheckForFootprints && TransparentCheckAndModifyMsrRead(VCpu->Regs, TargetMsr)) + { + return; + } + // // Msr is valid // - Msr.Flags = __readmsr(TargetMsr); + Msr.Flags = CpuReadMsr(TargetMsr); // // Check if it's EFER MSR then we show a false SCE state @@ -155,15 +225,17 @@ MsrHandleRdmsrVmexit(PGUEST_REGS GuestRegs) /** * @brief Handles in the cases when RDMSR causes a vm-exit * - * @param GuestRegs Guest's gp registers + * @param VCpu The virtual processor's state + * * @return VOID */ VOID -MsrHandleWrmsrVmexit(PGUEST_REGS GuestRegs) +MsrHandleWrmsrVmexit(VIRTUAL_MACHINE_STATE * VCpu) { - MSR Msr = {0}; - UINT32 TargetMsr; - BOOLEAN UnusedIsKernel; + UINT32 TargetMsr; + BOOLEAN UnusedIsKernel; + MSR Msr = {0}; + PGUEST_REGS GuestRegs = VCpu->Regs; // // Execute WRMSR or RDMSR on behalf of the guest. Important that this @@ -182,6 +254,21 @@ MsrHandleWrmsrVmexit(PGUEST_REGS GuestRegs) Msr.Fields.Low = (ULONG)GuestRegs->rax; Msr.Fields.High = (ULONG)GuestRegs->rdx; + // LogInfo("MSR write (WRMSR) VM-exit, MSR: %x, rax: %llx, rdx: %llx, from: %llx", + // TargetMsr, + // GuestRegs->rax, + // GuestRegs->rdx, + // VCpu->LastVmexitRip); + + // + // Checking whether it is a synthetic MSR for Hyper-V + // + if (g_IsTopLevelHypervisorHyperV && 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 // @@ -245,10 +332,19 @@ MsrHandleWrmsrVmexit(PGUEST_REGS GuestRegs) default: + // + // Check for the footprints of the WRMSR in the transparent mode + // + if (g_CheckForFootprints && TransparentCheckAndModifyMsrWrite(VCpu->Regs, TargetMsr)) + { + return; + } + // // Perform the WRMSR // - __writemsr((unsigned long)GuestRegs->rcx, Msr.Flags); + CpuWriteMsr((ULONG)GuestRegs->rcx, Msr.Flags); + break; } } @@ -286,22 +382,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 @@ -335,22 +431,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 @@ -373,13 +469,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); } /** @@ -395,19 +491,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)); } /** @@ -426,7 +522,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 @@ -455,7 +551,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 @@ -473,7 +569,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 @@ -502,5 +598,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); } diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/Mtf.c b/hyperdbg/hyperhv/code/vmm/vmx/Mtf.c similarity index 53% rename from hyperdbg/hprdbghv/code/vmm/vmx/Mtf.c rename to hyperdbg/hyperhv/code/vmm/vmx/Mtf.c index bbd66d46..c8a004d0 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/Mtf.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/Mtf.c @@ -33,12 +33,9 @@ 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)) { // // MTF is handled @@ -67,53 +64,11 @@ MtfHandleVmexit(VIRTUAL_MACHINE_STATE * VCpu) VCpu->MtfEptHookRestorePoint = NULL; // - // Check for reenabling external interrupts + // Check for re-enabling external interrupts // 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 // diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/ProtectedHv.c b/hyperdbg/hyperhv/code/vmm/vmx/ProtectedHv.c similarity index 77% rename from hyperdbg/hprdbghv/code/vmm/vmx/ProtectedHv.c rename to hyperdbg/hyperhv/code/vmm/vmx/ProtectedHv.c index 7b937b04..171e30e2 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/ProtectedHv.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/ProtectedHv.c @@ -1,4 +1,4 @@ -/** +/** * @file ProtectedHv.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief File for protected hypervisor resources @@ -42,11 +42,12 @@ ProtectedHvChangeExceptionBitmapWithIntegrityCheck(VIRTUAL_MACHINE_STATE * VCpu, } // - // Check for #PF by thread interception mechanism in user debugger + // Check for syscall callback (masking #DBs and #BPs) // - if (g_CheckPageFaultsAndMov2Cr3VmexitsWithUserDebugger) + if (g_SyscallCallbackStatus) { - CurrentMask |= 1 << EXCEPTION_VECTOR_PAGE_FAULT; + CurrentMask |= 1 << EXCEPTION_VECTOR_DEBUG_BREAKPOINT; + CurrentMask |= 1 << EXCEPTION_VECTOR_BREAKPOINT; } // @@ -214,11 +215,11 @@ ProtectedHvApplySetExternalInterruptExiting(VIRTUAL_MACHINE_STATE * VCpu, BOOLEA // // In order to enable External Interrupt Exiting we have to set - // PIN_BASED_VM_EXECUTION_CONTROLS_EXTERNAL_INTERRUPT in vmx + // IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_FLAG in vmx // pin-based controls (PIN_BASED_VM_EXEC_CONTROL) and also - // we should enable VM_EXIT_ACK_INTR_ON_EXIT on vmx vm-exit - // controls (VMCS_CTRL_VMEXIT_CONTROLS), also this function might not - // always be successful if the guest is not in the interruptible + // we should enable IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_FLAG + // on vmx vm-exit controls (VMCS_CTRL_VMEXIT_CONTROLS), also this function + // might not always be successful if the guest is not in the interruptible // state so it wait for and interrupt-window exiting to re-inject // the interrupt into the guest // @@ -231,13 +232,13 @@ ProtectedHvApplySetExternalInterruptExiting(VIRTUAL_MACHINE_STATE * VCpu, BOOLEA if (Set) { - PinBasedControls |= PIN_BASED_VM_EXECUTION_CONTROLS_EXTERNAL_INTERRUPT; - VmExitControls |= VM_EXIT_ACK_INTR_ON_EXIT; + PinBasedControls |= IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_FLAG; + VmExitControls |= IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_FLAG; } else { - PinBasedControls &= ~PIN_BASED_VM_EXECUTION_CONTROLS_EXTERNAL_INTERRUPT; - VmExitControls &= ~VM_EXIT_ACK_INTR_ON_EXIT; + PinBasedControls &= ~IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_FLAG; + VmExitControls &= ~IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_FLAG; } // @@ -304,17 +305,6 @@ ProtectedHvSetTscVmexit(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set, PROTECTED_HV_ { return; } - - // - // Check if transparent mode is enabled - // - if (g_TransparentMode) - { - // - // We should ignore it as we want this bit on transparent mode - // - return; - } } // @@ -324,11 +314,11 @@ ProtectedHvSetTscVmexit(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set, PROTECTED_HV_ if (Set) { - CpuBasedVmExecControls |= CPU_BASED_RDTSC_EXITING; + CpuBasedVmExecControls |= IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_FLAG; } else { - CpuBasedVmExecControls &= ~CPU_BASED_RDTSC_EXITING; + CpuBasedVmExecControls &= ~IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_FLAG; } // // Set the new value @@ -378,11 +368,11 @@ ProtectedHvSetMovDebugRegsVmexit(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set, PROT if (Set) { - CpuBasedVmExecControls |= CPU_BASED_MOV_DR_EXITING; + CpuBasedVmExecControls |= IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_FLAG; } else { - CpuBasedVmExecControls &= ~CPU_BASED_MOV_DR_EXITING; + CpuBasedVmExecControls &= ~IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_FLAG; } // @@ -409,7 +399,7 @@ ProtectedHvSetMovToCrVmexit(BOOLEAN Set, UINT64 ControlRegister, UINT64 MaskRegi if (Set) { VmxVmwrite64(VMCS_CTRL_CR0_GUEST_HOST_MASK, MaskRegister); - VmxVmwrite64(VMCS_CTRL_CR0_READ_SHADOW, __readcr0()); + VmxVmwrite64(VMCS_CTRL_CR0_READ_SHADOW, CpuReadCr0()); } else { @@ -422,7 +412,7 @@ ProtectedHvSetMovToCrVmexit(BOOLEAN Set, UINT64 ControlRegister, UINT64 MaskRegi if (Set) { VmxVmwrite64(VMCS_CTRL_CR4_GUEST_HOST_MASK, MaskRegister); - VmxVmwrite64(VMCS_CTRL_CR4_READ_SHADOW, __readcr0()); + VmxVmwrite64(VMCS_CTRL_CR4_READ_SHADOW, CpuReadCr0()); } else { @@ -503,17 +493,6 @@ ProtectedHvSetMovToCr3Vmexit(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set, PROTECTE return; } - // - // Check if use debugger is in intercepting phase for threads or not - // - if (g_CheckPageFaultsAndMov2Cr3VmexitsWithUserDebugger) - { - // - // The user debugger needs mov2cr3s - // - return; - } - // // Check if the trap execution is enabled or not, and whether the // uninitialization phase started or not @@ -534,11 +513,11 @@ ProtectedHvSetMovToCr3Vmexit(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set, PROTECTE if (Set) { - CpuBasedVmExecControls |= CPU_BASED_CR3_LOAD_EXITING; + CpuBasedVmExecControls |= IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_FLAG; } else { - CpuBasedVmExecControls &= ~CPU_BASED_CR3_LOAD_EXITING; + CpuBasedVmExecControls &= ~IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_FLAG; } // @@ -547,6 +526,140 @@ ProtectedHvSetMovToCr3Vmexit(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set, PROTECTE VmxVmwrite64(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, CpuBasedVmExecControls); } +/** + * @brief Set LOAD DEBUG CONTROLS on Vm-entry controls + * + * @param VCpu + * @param Set Set or unset + * @param PassOver + * + * @return VOID + */ +VOID +ProtectedHvSetLoadDebugControlsIntegrityCheck(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set, PROTECTED_HV_RESOURCES_PASSING_OVERS PassOver) +{ + UINT32 VmentryControls = 0; + + // + // The protected checks are only performed if the "Set" is "FALSE", + // because if sb wants to set it to "TRUE" then we're no need to + // worry about it as it remains enabled + // + if (Set == FALSE) + { + // + // Check the top-level driver's state + // + if (VmmCallbackQueryTerminateProtectedResource(VCpu->CoreId, + PROTECTED_HV_RESOURCES_SAVE_AND_LOAD_DEBUG_CONTROLS, + NULL, + PassOver)) + { + return; + } + } + + // + // Read the previous flags + // + VmxVmread32P(VMCS_CTRL_VMENTRY_CONTROLS, &VmentryControls); + + if (Set) + { + VmentryControls |= IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_FLAG; + } + else + { + VmentryControls &= ~IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_FLAG; + } + + // + // Set the new value + // + VmxVmwrite32(VMCS_CTRL_VMENTRY_CONTROLS, VmentryControls); +} + +/** + * @brief Set SAVE DEBUG CONTROLS on Vm-exit controls + * + * @param VCpu + * @param Set Set or unset + * @param PassOver + * + * @return VOID + */ +VOID +ProtectedHvSetSaveDebugControlsIntegrityCheck(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set, PROTECTED_HV_RESOURCES_PASSING_OVERS PassOver) +{ + UINT32 VmexitControls = 0; + + // + // The protected checks are only performed if the "Set" is "FALSE", + // because if sb wants to set it to "TRUE" then we're no need to + // worry about it as it remains enabled + // + if (Set == FALSE) + { + // + // Check the top-level driver's state + // + if (VmmCallbackQueryTerminateProtectedResource(VCpu->CoreId, + PROTECTED_HV_RESOURCES_SAVE_AND_LOAD_DEBUG_CONTROLS, + NULL, + PassOver)) + { + return; + } + } + + // + // Read the previous flags + // + VmxVmread32P(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, &VmexitControls); + + if (Set) + { + VmexitControls |= IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_FLAG; + } + else + { + VmexitControls &= ~IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_FLAG; + } + + // + // Set the new value + // + VmxVmwrite32(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, VmexitControls); +} + +/** + * @brief Set LOAD DEBUG CONTROLS on VM-entry controls + * + * @param VCpu + * @param Set Set or unset + * + * @return VOID + */ +VOID +ProtectedHvSetSaveDebugControls(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set) +{ + ProtectedHvSetSaveDebugControlsIntegrityCheck(VCpu, Set, PASSING_OVER_NONE); +} + +/** + * @brief Set SAVE DEBUG CONTROLS on VM-exit controls + * + * @param VCpu + * @param Set Set or unset + * + * @return VOID + */ +VOID +ProtectedHvSetLoadDebugControls(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set) +{ + ProtectedHvSetLoadDebugControlsIntegrityCheck(VCpu, Set, PASSING_OVER_NONE); +} + /** * @brief Set the RDTSC/P Exiting * diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/Vmcall.c b/hyperdbg/hyperhv/code/vmm/vmx/Vmcall.c similarity index 76% rename from hyperdbg/hprdbghv/code/vmm/vmx/Vmcall.c rename to hyperdbg/hyperhv/code/vmm/vmx/Vmcall.c index c897528a..88f6d560 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/Vmcall.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/Vmcall.c @@ -164,7 +164,7 @@ VmxVmcallHandler(VIRTUAL_MACHINE_STATE * VCpu, } case VMCALL_VMXOFF: { - VmxVmxoff(VCpu); + VmxPerformVmxoff(VCpu); VmcallStatus = STATUS_SUCCESS; break; @@ -365,25 +365,25 @@ VmxVmcallHandler(VIRTUAL_MACHINE_STATE * VCpu, } case VMCALL_SET_VM_ENTRY_LOAD_DEBUG_CONTROLS: { - HvSetLoadDebugControls(TRUE); + HvSetLoadDebugControls(VCpu, TRUE); VmcallStatus = STATUS_SUCCESS; break; } case VMCALL_UNSET_VM_ENTRY_LOAD_DEBUG_CONTROLS: { - HvSetLoadDebugControls(FALSE); + HvSetLoadDebugControls(VCpu, FALSE); VmcallStatus = STATUS_SUCCESS; break; } case VMCALL_SET_VM_EXIT_SAVE_DEBUG_CONTROLS: { - HvSetSaveDebugControls(TRUE); + HvSetSaveDebugControls(VCpu, TRUE); VmcallStatus = STATUS_SUCCESS; break; } case VMCALL_UNSET_VM_EXIT_SAVE_DEBUG_CONTROLS: { - HvSetSaveDebugControls(FALSE); + HvSetSaveDebugControls(VCpu, FALSE); VmcallStatus = STATUS_SUCCESS; break; } @@ -458,9 +458,159 @@ VmxVmcallHandler(VIRTUAL_MACHINE_STATE * VCpu, VmcallStatus = STATUS_SUCCESS; break; } + case VMCALL_READ_PHYSICAL_MEM_BYPASS_CACHING_POLICIES: + { + if (ReadPhysicalMemoryUsingMapIoSpace((PVOID)OptionalParam1, (PVOID)OptionalParam2, (SIZE_T)OptionalParam3)) + { + VmcallStatus = STATUS_SUCCESS; + } + else + { + VmcallStatus = STATUS_UNSUCCESSFUL; + } + + break; + } + case VMCALL_WRITE_PHYSICAL_MEM_BYPASS_CACHING_POLICIES: + { + if (WritePhysicalMemoryUsingMapIoSpace((PVOID)OptionalParam1, (PVOID)OptionalParam2, (SIZE_T)OptionalParam3)) + { + VmcallStatus = STATUS_SUCCESS; + } + else + { + VmcallStatus = STATUS_UNSUCCESSFUL; + } + + break; + } + case VMCALL_READ_PHYSICAL_MEMORY: + { + // + // Check whether the physical memory is valid or not + // + if (!CheckAddressPhysical(OptionalParam1)) + { + VmcallStatus = STATUS_SUCCESS; + break; + } + + // + // Perform the read operation + // + if (MemoryMapperReadMemorySafeByPhysicalAddress((UINT64)OptionalParam1, (UINT64)OptionalParam2, (SIZE_T)OptionalParam3)) + { + VmcallStatus = STATUS_SUCCESS; + } + else + { + VmcallStatus = STATUS_UNSUCCESSFUL; + } + + break; + } + case VMCALL_WRITE_PHYSICAL_MEMORY: + { + // + // Check whether the physical memory is valid or not + // + if (!CheckAddressPhysical(OptionalParam1)) + { + VmcallStatus = STATUS_SUCCESS; + break; + } + + // + // Perform the write operation + // + if (MemoryMapperWriteMemorySafeByPhysicalAddress((UINT64)OptionalParam1, (UINT64)OptionalParam2, (SIZE_T)OptionalParam3)) + { + VmcallStatus = STATUS_SUCCESS; + } + else + { + VmcallStatus = STATUS_UNSUCCESSFUL; + } + + break; + } + case VMCALL_GET_VMCS_DEBUGCTL: + { + // + // Perform getting DEBUGCTL from VMCS + // + HvGetAndStoreDebugctl((UINT64 *)OptionalParam1); + + VmcallStatus = STATUS_SUCCESS; + break; + } + case VMCALL_SET_VMCS_DEBUGCTL: + { + // + // Perform setting DEBUGCTL from VMCS + // + HvSetDebugctl(OptionalParam1); + + VmcallStatus = STATUS_SUCCESS; + + break; + } + case VMCALL_SET_MSR_LBR_SELECT: + { + // + // Perform setting MSR_LEGACY_LBR_SELECT + // + HvSetLbrSelect(OptionalParam1); + VmcallStatus = STATUS_SUCCESS; + break; + } + case VMCALL_GET_GUEST_IA32_LBR_CTL: + { + // + // Perform getting guest IA32_LBR_CTL from VMCS + // + HvGetAndStoreGuestIa32LbrCtl((UINT64 *)OptionalParam1); + + VmcallStatus = STATUS_SUCCESS; + break; + } + case VMCALL_SET_GUEST_IA32_LBR_CTL: + { + // + // Perform setting guest IA32_LBR_CTL on VMCS + // + HvSetGuestIa32LbrCtl(OptionalParam1); + + VmcallStatus = STATUS_SUCCESS; + break; + } + case VMCALL_SET_VM_ENTRY_LOAD_GUEST_IA32_LBR_CTL: + { + HvSetLoadGuestIa32LbrCtl(VCpu, TRUE); + VmcallStatus = STATUS_SUCCESS; + break; + } + case VMCALL_UNSET_VM_ENTRY_LOAD_GUEST_IA32_LBR_CTL: + { + HvSetLoadGuestIa32LbrCtl(VCpu, FALSE); + VmcallStatus = STATUS_SUCCESS; + break; + } + case VMCALL_SET_CLEAR_GUEST_IA32_LBR_CTL: + { + HvSetClearGuestIa32LbrCtl(VCpu, TRUE); + VmcallStatus = STATUS_SUCCESS; + break; + } + case VMCALL_UNSET_CLEAR_GUEST_IA32_LBR_CTL: + { + HvSetClearGuestIa32LbrCtl(VCpu, FALSE); + VmcallStatus = STATUS_SUCCESS; + break; + } default: { - LogError("Err, unsupported VMCALL"); + LogError("Err, unsupported VMCALL (%llx)", VmcallNumber); VmcallStatus = STATUS_UNSUCCESSFUL; break; } diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/Vmexit.c b/hyperdbg/hyperhv/code/vmm/vmx/Vmexit.c similarity index 81% rename from hyperdbg/hprdbghv/code/vmm/vmx/Vmexit.c rename to hyperdbg/hyperhv/code/vmm/vmx/Vmexit.c index 95bf9c8d..54c5511d 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/Vmexit.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/Vmexit.c @@ -21,10 +21,9 @@ BOOLEAN VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) { - UINT32 ExitReason = 0; - BOOLEAN Result = FALSE; - BOOLEAN ShouldEmulateRdtscp = TRUE; - VIRTUAL_MACHINE_STATE * VCpu = NULL; + UINT32 ExitReason = 0; + BOOLEAN Result = FALSE; + VIRTUAL_MACHINE_STATE * VCpu = NULL; // // *********** SEND MESSAGE AFTER WE SET THE STATE *********** @@ -32,9 +31,10 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) VCpu = &g_GuestState[KeGetCurrentProcessorNumberEx(NULL)]; // - // Set the registers + // Set the registers (general-purpose and XMM) // - VCpu->Regs = GuestRegs; + VCpu->Regs = GuestRegs; + VCpu->XmmRegs = (GUEST_XMM_REGS *)(((CHAR *)GuestRegs) + sizeof(GUEST_REGS)); // // Indicates we are in Vmx root mode in this logical core @@ -48,13 +48,9 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) ExitReason &= 0xffff; // - // Check if we're operating in transparent-mode or not - // If yes then we start operating in transparent-mode + // Save the exit reason // - if (g_TransparentMode) - { - ShouldEmulateRdtscp = TransparentModeStart(VCpu, ExitReason); - } + VCpu->ExitReason = ExitReason; // // Increase the RIP by default @@ -64,12 +60,12 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) // // Save the current rip // - __vmx_vmread(VMCS_GUEST_RIP, &VCpu->LastVmexitRip); + VmxVmread64P(VMCS_GUEST_RIP, &VCpu->LastVmexitRip); // // Set the rsp in general purpose registers structure // - __vmx_vmread(VMCS_GUEST_RSP, &VCpu->Regs->rsp); + VmxVmread64P(VMCS_GUEST_RSP, &VCpu->Regs->rsp); // // Read the exit qualification @@ -82,6 +78,7 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) // LogInfo("VM_EXIT_REASON : 0x%x", ExitReason); // LogInfo("VMCS_EXIT_QUALIFICATION : 0x%llx", VCpu->ExitQualification); // + switch (ExitReason) { case VMX_EXIT_REASON_TRIPLE_FAULT: @@ -111,7 +108,7 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) // cf=1 indicate vm instructions fail // // UINT64 Rflags = 0; - // __vmx_vmread(VMCS_GUEST_RFLAGS, &Rflags); + // VmxVmread64P(VMCS_GUEST_RFLAGS, &Rflags); // VmxVmwrite64(VMCS_GUEST_RFLAGS, Rflags | 0x1); // @@ -145,7 +142,7 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) case VMX_EXIT_REASON_EXECUTE_RDMSR: { // - // Handle vm-exit, events, dispatches and perform changes + // Handle vm-exit, events, dispatches and perform MSR read // DispatchEventRdmsr(VCpu); @@ -160,8 +157,21 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) break; } + case VMX_EXIT_REASON_IO_SMI: + case VMX_EXIT_REASON_SMI: + { + // + // Handle SMI and IO-SMI (should never happen in normal cases) + // + LogInfo("VM-exit reason SMM %llx | qual: %llx", ExitReason, VCpu->ExitQualification); + + break; + } case VMX_EXIT_REASON_EXECUTE_CPUID: { + // + // Dispatch and trigger the CPUID instruction events + // DispatchEventCpuid(VCpu); break; @@ -178,6 +188,9 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) } case VMX_EXIT_REASON_EPT_VIOLATION: { + // + // Handle EPT violation + // if (EptHandleEptViolation(VCpu) == FALSE) { LogError("Err, there were errors in handling EPT violation"); @@ -187,6 +200,9 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) } case VMX_EXIT_REASON_EPT_MISCONFIGURATION: { + // + // Handle EPT misconfiguration (should never happen) + // EptHandleMisconfiguration(); break; @@ -264,12 +280,8 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) // // Check whether we are allowed to change the registers // and emulate rdtsc or not - // Note : Using !tsc command in transparent-mode is not allowed // - if (ShouldEmulateRdtscp) - { - DispatchEventTsc(VCpu, ExitReason == VMX_EXIT_REASON_EXECUTE_RDTSCP ? TRUE : FALSE); - } + DispatchEventTsc(VCpu, ExitReason == VMX_EXIT_REASON_EXECUTE_RDTSCP ? TRUE : FALSE); break; } @@ -294,9 +306,9 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) case VMX_EXIT_REASON_EXECUTE_XSETBV: { // - // Handle xsetbv (unconditional vm-exit) + // Dispatch and trigger the XSETBV instruction events // - VmxHandleXsetbv(VCpu); + DispatchEventXsetbv(VCpu); break; } @@ -320,6 +332,9 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) } default: { + // + // Not handled vm-exit + // LogError("Err, unknown vmexit, reason : 0x%llx", ExitReason); break; @@ -332,6 +347,16 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) // if (!VCpu->VmxoffState.IsVmxoffExecuted && VCpu->IncrementRip) { + // + // If we are in transparent-mode, then we need to handle the trap flag as the result + // of an anti-hypervisor technique of using the trap flag after a VM-exit + // to detect the hypervisor + // + if (g_CheckForFootprints) + { + TransparentCheckAndTrapFlagAfterVmexit(); + } + HvResumeToNextInstruction(); } @@ -343,21 +368,6 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs) Result = TRUE; } - // - // Restore the previous time - // - if (g_TransparentMode) - { - if (ExitReason != VMX_EXIT_REASON_EXECUTE_RDTSC && ExitReason != VMX_EXIT_REASON_EXECUTE_RDTSCP && ExitReason != VMX_EXIT_REASON_EXECUTE_CPUID) - { - // - // We not wanna change the global timer while RDTSC and RDTSCP - // was the reason of vm-exit - // - __writemsr(MSR_IA32_TIME_STAMP_COUNTER, VCpu->TransparencyState.PreviousTimeStampCounter); - } - } - // // Set indicator of Vmx non root mode to false // diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/Vmx.c b/hyperdbg/hyperhv/code/vmm/vmx/Vmx.c similarity index 70% rename from hyperdbg/hprdbghv/code/vmm/vmx/Vmx.c rename to hyperdbg/hyperhv/code/vmm/vmx/Vmx.c index 44857e55..1de5c030 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/Vmx.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/Vmx.c @@ -11,152 +11,6 @@ */ #include "pch.h" -/** - * @brief VMX VMREAD instruction (64-bit) - * @param Field - * @param FieldValue - * - * @return UCHAR - */ -inline UCHAR -VmxVmread64(size_t Field, - UINT64 FieldValue) -{ - return __vmx_vmread((size_t)Field, (size_t *)FieldValue); -} - -/** - * @brief VMX VMREAD instruction (32-bit) - * @param Field - * @param FieldValue - * - * @return UCHAR - */ -inline UCHAR -VmxVmread32(size_t Field, - UINT32 FieldValue) -{ - UINT64 TargetField = 0ull; - - TargetField = FieldValue; - - return __vmx_vmread((size_t)Field, (size_t *)TargetField); -} - -/** - * @brief VMX VMREAD instruction (16-bit) - * @param Field - * @param FieldValue - * - * @return UCHAR - */ -inline UCHAR -VmxVmread16(size_t Field, - UINT16 FieldValue) -{ - UINT64 TargetField = 0ull; - - TargetField = FieldValue; - - return __vmx_vmread((size_t)Field, (size_t *)TargetField); -} - -/** - * @brief VMX VMREAD instruction (64-bit) - * @param Field - * @param FieldValue - * - * @return UCHAR - */ -inline UCHAR -VmxVmread64P(size_t Field, - UINT64 * FieldValue) -{ - return __vmx_vmread((size_t)Field, (size_t *)FieldValue); -} - -/** - * @brief VMX VMREAD instruction (32-bit) - * @param Field - * @param FieldValue - * - * @return UCHAR - */ -inline UCHAR -VmxVmread32P(size_t Field, - UINT32 * FieldValue) -{ - UINT64 TargetField = 0ull; - - TargetField = (UINT64)FieldValue; - - return __vmx_vmread((size_t)Field, (size_t *)TargetField); -} - -/** - * @brief VMX VMREAD instruction (16-bit) - * @param Field - * @param FieldValue - * - * @return UCHAR - */ -inline UCHAR -VmxVmread16P(size_t Field, - UINT16 * FieldValue) -{ - UINT64 TargetField = 0ull; - - TargetField = (UINT64)FieldValue; - - return __vmx_vmread((size_t)Field, (size_t *)TargetField); -} - -/** - * @brief VMX VMWRITE instruction (64-bit) - * @param Field - * @param FieldValue - * - * @return UCHAR - */ -inline UCHAR -VmxVmwrite64(size_t Field, - UINT64 FieldValue) -{ - return __vmx_vmwrite((size_t)Field, (size_t)FieldValue); -} - -/** - * @brief VMX VMWRITE instruction (32-bit) - * @param Field - * @param FieldValue - * - * @return UCHAR - */ -inline UCHAR -VmxVmwrite32(size_t Field, - UINT32 FieldValue) -{ - UINT64 TargetValue = NULL64_ZERO; - TargetValue = (UINT64)FieldValue; - return __vmx_vmwrite((size_t)Field, (size_t)TargetValue); -} - -/** - * @brief VMX VMWRITE instruction (16-bit) - * @param Field - * @param FieldValue - * - * @return UCHAR - */ -inline UCHAR -VmxVmwrite16(size_t Field, - UINT16 FieldValue) -{ - UINT64 TargetValue = NULL64_ZERO; - TargetValue = (UINT64)FieldValue; - return __vmx_vmwrite((size_t)Field, (size_t)TargetValue); -} - /** * @brief Check whether VMX Feature is supported or not * @@ -171,7 +25,7 @@ VmxCheckVmxSupport() // // Gets Processor Info and Feature Bits // - __cpuid((int *)&Data, 1); + CpuCpuId((INT *)&Data, 1); // // Check For VMX Bit CPUID.ECX[5] @@ -184,7 +38,7 @@ VmxCheckVmxSupport() return FALSE; } - FeatureControlMsr.AsUInt = __readmsr(IA32_FEATURE_CONTROL); + FeatureControlMsr.AsUInt = CpuReadMsr(IA32_FEATURE_CONTROL); // // Commented because of https://stackoverflow.com/questions/34900224/ @@ -201,7 +55,7 @@ VmxCheckVmxSupport() // { // FeatureControlMsr.Fields.Lock = TRUE; // FeatureControlMsr.Fields.EnableVmxon = TRUE; - // __writemsr(IA32_FEATURE_CONTROL, FeatureControlMsr.Flags); + // CpuWriteMsr(IA32_FEATURE_CONTROL, FeatureControlMsr.Flags); // } if (FeatureControlMsr.EnableVmxOutsideSmx == FALSE) @@ -278,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) *** @@ -318,6 +172,61 @@ VmxInitialize() // return FALSE; } + +#if USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE + + // + // Allocating Host IDT + // + if (!VmxAllocateHostIdt(GuestState)) + { + // + // Some error in allocating Host IDT + // + return FALSE; + } +#endif // USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE + +#if USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE + + // + // Allocating Host GDT + // + if (!VmxAllocateHostGdt(GuestState)) + { + // + // Some error in allocating Host GDT + // + return FALSE; + } + + // + // Allocating Host TSS + // + if (!VmxAllocateHostTss(GuestState)) + { + // + // Some error in allocating Host TSS + // + return FALSE; + } + +#endif // USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE + +#if USE_INTERRUPT_STACK_TABLE == TRUE + + // + // Allocating Host Interrupt Stack + // + if (!VmxAllocateHostInterruptStack(GuestState)) + { + // + // Some error in allocating Interrupt Stack + // + return FALSE; + } + +#endif // USE_INTERRUPT_STACK_TABLE == TRUE } // @@ -365,10 +274,27 @@ VmxPerformVirtualizationOnAllCores() return FALSE; } + // + // Check if the top level hypervisor is Hyper-V or not + // + if (VmxIsTopLevelHypervisorHyperV()) + { + // + // The top-level hypervisor is hyper-v + // + g_IsTopLevelHypervisorHyperV = TRUE; + + LogDebugInfo(" Hyper-V is detected as the top-level hypervisor"); + } + else + { + LogDebugInfo(" Hyper-V is not detected as the top-level hypervisor"); + } + // // Allocate global variable to hold Ept State // - g_EptState = CrsAllocateZeroedNonPagedPool(sizeof(EPT_STATE)); + g_EptState = PlatformMemAllocateZeroedNonPagedPool(sizeof(EPT_STATE)); if (!g_EptState) { @@ -408,15 +334,6 @@ VmxPerformVirtualizationOnAllCores() LogDebugInfo("MTRR memory map built successfully"); } - // - // Initialize Pool Manager - // - if (!PoolManagerInitialize()) - { - LogError("Err, could not initialize pool manager"); - return FALSE; - } - if (!EptLogicalProcessorInitialize()) { // @@ -492,22 +409,22 @@ VmxFixCr4AndCr0Bits() // // Fix Cr0 // - CrFixed.Flags = __readmsr(IA32_VMX_CR0_FIXED0); - Cr0.AsUInt = __readcr0(); + CrFixed.Flags = CpuReadMsr(IA32_VMX_CR0_FIXED0); + Cr0.AsUInt = CpuReadCr0(); Cr0.AsUInt |= CrFixed.Fields.Low; - CrFixed.Flags = __readmsr(IA32_VMX_CR0_FIXED1); + CrFixed.Flags = CpuReadMsr(IA32_VMX_CR0_FIXED1); Cr0.AsUInt &= CrFixed.Fields.Low; - __writecr0(Cr0.AsUInt); + CpuWriteCr0(Cr0.AsUInt); // // Fix Cr4 // - CrFixed.Flags = __readmsr(IA32_VMX_CR4_FIXED0); - Cr4.AsUInt = __readcr4(); + CrFixed.Flags = CpuReadMsr(IA32_VMX_CR4_FIXED0); + Cr4.AsUInt = CpuReadCr4(); Cr4.AsUInt |= CrFixed.Fields.Low; - CrFixed.Flags = __readmsr(IA32_VMX_CR4_FIXED1); + CrFixed.Flags = CpuReadMsr(IA32_VMX_CR4_FIXED1); Cr4.AsUInt &= CrFixed.Fields.Low; - __writecr4(Cr4.AsUInt); + CpuWriteCr4(Cr4.AsUInt); } /** @@ -524,7 +441,7 @@ VmxCheckIsOnVmxRoot() __try { - if (!__vmx_vmread(VMCS_GUEST_VMCS_LINK_POINTER, &VmcsLink)) + if (!VmxVmread64P(VMCS_GUEST_VMCS_LINK_POINTER, &VmcsLink)) { if (VmcsLink != 0) { @@ -555,6 +472,28 @@ VmxVirtualizeCurrentSystem(PVOID GuestStack) LogDebugInfo("Virtualizing current system (logical core : 0x%x)", CurrentCore); +#if USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE + + // + // Prepare Host IDT + // + IdtEmulationPrepareHostIdt(VCpu); +#endif // USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE + +#if USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE + + // + // Prepare Host GDT and TSS + // + SegmentPrepareHostGdt((SEGMENT_DESCRIPTOR_32 *)AsmGetGdtBase(), + AsmGetGdtLimit(), + AsmGetTr(), + VCpu->HostInterruptStack, + (SEGMENT_DESCRIPTOR_32 *)VCpu->HostGdt, + (TASK_STATE_SEGMENT_64 *)VCpu->HostTss); + +#endif // USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE + // // Clear the VMCS State // @@ -585,7 +524,7 @@ VmxVirtualizeCurrentSystem(PVOID GuestStack) VCpu->HasLaunched = TRUE; - __vmx_vmlaunch(); + VmxVmlaunch(); // // ******** if Vmlaunch succeed will never be here ! ******** @@ -599,14 +538,14 @@ VmxVirtualizeCurrentSystem(PVOID GuestStack) // // Read error code firstly // - __vmx_vmread(VMCS_VM_INSTRUCTION_ERROR, &ErrorCode); + VmxVmread64P(VMCS_VM_INSTRUCTION_ERROR, &ErrorCode); LogError("Err, unable to execute VMLAUNCH, status : 0x%llx", ErrorCode); // // Then Execute Vmxoff // - __vmx_off(); + VmxVmxoff(); LogError("Err, VMXOFF Executed Successfully but it was because of an error"); return FALSE; @@ -639,10 +578,22 @@ VmxTerminate() // MmFreeContiguousMemory((PVOID)VCpu->VmxonRegionVirtualAddress); MmFreeContiguousMemory((PVOID)VCpu->VmcsRegionVirtualAddress); - CrsFreePool((PVOID)VCpu->VmmStack); - CrsFreePool((PVOID)VCpu->MsrBitmapVirtualAddress); - CrsFreePool((PVOID)VCpu->IoBitmapVirtualAddressA); - CrsFreePool((PVOID)VCpu->IoBitmapVirtualAddressB); + PlatformMemFreePool((PVOID)VCpu->VmmStack); + PlatformMemFreePool((PVOID)VCpu->MsrBitmapVirtualAddress); + PlatformMemFreePool((PVOID)VCpu->IoBitmapVirtualAddressA); + PlatformMemFreePool((PVOID)VCpu->IoBitmapVirtualAddressB); +#if USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE + PlatformMemFreePool((PVOID)VCpu->HostIdt); +#endif // USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE + +#if USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE + PlatformMemFreePool((PVOID)VCpu->HostGdt); + PlatformMemFreePool((PVOID)VCpu->HostTss); +#endif // USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE + +#if USE_INTERRUPT_STACK_TABLE == TRUE + PlatformMemFreePool((PVOID)VCpu->HostInterruptStack); +#endif // USE_INTERRUPT_STACK_TABLE == FALSE return TRUE; } @@ -656,11 +607,11 @@ VmxTerminate() * @return VOID */ VOID -VmxVmptrst() +VmxPerformVmptrst() { PHYSICAL_ADDRESS VmcsPhysicalAddr; VmcsPhysicalAddr.QuadPart = 0; - __vmx_vmptrst((unsigned __int64 *)&VmcsPhysicalAddr); + VmxVmptrst((UINT64 *)&VmcsPhysicalAddr); LogDebugInfo("VMPTRST result : %llx", VmcsPhysicalAddr); } @@ -681,7 +632,7 @@ VmxClearVmcsState(VIRTUAL_MACHINE_STATE * VCpu) // // Clear the state of the VMCS to inactive // - VmclearStatus = __vmx_vmclear(&VCpu->VmcsRegionPhysicalAddress); + VmclearStatus = VmxVmclear(&VCpu->VmcsRegionPhysicalAddress); LogDebugInfo("VMCS VMCLEAR status : 0x%x", VmclearStatus); @@ -691,7 +642,8 @@ VmxClearVmcsState(VIRTUAL_MACHINE_STATE * VCpu) // Otherwise terminate the VMX // LogDebugInfo("VMCS failed to clear, status : 0x%x", VmclearStatus); - __vmx_off(); + VmxVmxoff(); + return FALSE; } return TRUE; @@ -710,7 +662,8 @@ VmxLoadVmcs(VIRTUAL_MACHINE_STATE * VCpu) { int VmptrldStatus; - VmptrldStatus = __vmx_vmptrld(&VCpu->VmcsRegionPhysicalAddress); + VmptrldStatus = VmxVmptrld(&VCpu->VmcsRegionPhysicalAddress); + if (VmptrldStatus) { LogDebugInfo("VMCS failed to load, status : 0x%x", VmptrldStatus); @@ -734,13 +687,13 @@ VmxSetupVmcs(VIRTUAL_MACHINE_STATE * VCpu, PVOID GuestStack) UINT32 SecondaryProcBasedVmExecControls; PVOID HostRsp; UINT64 GdtBase = 0; - VMX_SEGMENT_SELECTOR SegmentSelector = {0}; IA32_VMX_BASIC_REGISTER VmxBasicMsr = {0}; + VMX_SEGMENT_SELECTOR SegmentSelector = {0}; // // Reading IA32_VMX_BASIC_MSR // - VmxBasicMsr.AsUInt = __readmsr(IA32_VMX_BASIC); + VmxBasicMsr.AsUInt = CpuReadMsr(IA32_VMX_BASIC); VmxVmwrite64(VMCS_HOST_ES_SELECTOR, AsmGetEs() & 0xF8); VmxVmwrite64(VMCS_HOST_CS_SELECTOR, AsmGetCs() & 0xF8); @@ -755,8 +708,8 @@ VmxSetupVmcs(VIRTUAL_MACHINE_STATE * VCpu, PVOID GuestStack) // VmxVmwrite64(VMCS_GUEST_VMCS_LINK_POINTER, ~0ULL); - VmxVmwrite64(VMCS_GUEST_DEBUGCTL, __readmsr(IA32_DEBUGCTL) & 0xFFFFFFFF); - VmxVmwrite64(VMCS_GUEST_DEBUGCTL_HIGH, __readmsr(IA32_DEBUGCTL) >> 32); + VmxVmwrite64(VMCS_GUEST_DEBUGCTL, CpuReadMsr(IA32_DEBUGCTL) & 0xFFFFFFFF); + VmxVmwrite64(VMCS_GUEST_DEBUGCTL_HIGH, CpuReadMsr(IA32_DEBUGCTL) >> 32); // // ******* Time-stamp counter offset ******* @@ -783,30 +736,52 @@ VmxSetupVmcs(VIRTUAL_MACHINE_STATE * VCpu, PVOID GuestStack) HvFillGuestSelectorData((PVOID)GdtBase, LDTR, AsmGetLdtr()); HvFillGuestSelectorData((PVOID)GdtBase, TR, AsmGetTr()); - VmxVmwrite64(VMCS_GUEST_FS_BASE, __readmsr(IA32_FS_BASE)); - VmxVmwrite64(VMCS_GUEST_GS_BASE, __readmsr(IA32_GS_BASE)); + VmxVmwrite64(VMCS_GUEST_FS_BASE, CpuReadMsr(IA32_FS_BASE)); + VmxVmwrite64(VMCS_GUEST_GS_BASE, CpuReadMsr(IA32_GS_BASE)); - CpuBasedVmExecControls = HvAdjustControls(CPU_BASED_ACTIVATE_IO_BITMAP | CPU_BASED_ACTIVATE_MSR_BITMAP | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, - VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_PROCBASED_CTLS : IA32_VMX_PROCBASED_CTLS); + CpuBasedVmExecControls = HvAdjustControls( + IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS_FLAG | + IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS_FLAG | + IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS_FLAG, + VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_PROCBASED_CTLS : IA32_VMX_PROCBASED_CTLS); VmxVmwrite64(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, CpuBasedVmExecControls); LogDebugInfo("CPU Based VM Exec Controls (Based on %s) : 0x%x", VmxBasicMsr.VmxControls ? "IA32_VMX_TRUE_PROCBASED_CTLS" : "IA32_VMX_PROCBASED_CTLS", CpuBasedVmExecControls); + UINT32 SecondaryProcBasedVmExecControlsFlags = IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP_FLAG | + IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT_FLAG | + IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID_FLAG | + IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES_FLAG | + IA32_VMX_PROCBASED_CTLS2_ENABLE_USER_WAIT_PAUSE_FLAG; - SecondaryProcBasedVmExecControls = HvAdjustControls(CPU_BASED_CTL2_RDTSCP | CPU_BASED_CTL2_ENABLE_EPT | CPU_BASED_CTL2_ENABLE_INVPCID | CPU_BASED_CTL2_ENABLE_XSAVE_XRSTORS | CPU_BASED_CTL2_ENABLE_VPID, - IA32_VMX_PROCBASED_CTLS2); + if (g_IsVpidSupported) + { + SecondaryProcBasedVmExecControlsFlags |= IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID_FLAG; + } + SecondaryProcBasedVmExecControls = HvAdjustControls(SecondaryProcBasedVmExecControlsFlags, IA32_VMX_PROCBASED_CTLS2); VmxVmwrite64(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, SecondaryProcBasedVmExecControls); LogDebugInfo("Secondary Proc Based VM Exec Controls (IA32_VMX_PROCBASED_CTLS2) : 0x%x", SecondaryProcBasedVmExecControls); - VmxVmwrite64(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, HvAdjustControls(0, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_PINBASED_CTLS : IA32_VMX_PINBASED_CTLS)); + VmxVmwrite64(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, + HvAdjustControls( + 0, + VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_PINBASED_CTLS : IA32_VMX_PINBASED_CTLS)); - VmxVmwrite64(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, HvAdjustControls(VM_EXIT_HOST_ADDR_SPACE_SIZE, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS)); + VmxVmwrite64(VMCS_CTRL_PRIMARY_VMEXIT_CONTROLS, + HvAdjustControls( + IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_FLAG | + IA32_VMX_EXIT_CTLS_LOAD_IA32_CET_STATE_FLAG, + VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_EXIT_CTLS : IA32_VMX_EXIT_CTLS)); - VmxVmwrite64(VMCS_CTRL_VMENTRY_CONTROLS, HvAdjustControls(VM_ENTRY_IA32E_MODE, VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS)); + VmxVmwrite64(VMCS_CTRL_VMENTRY_CONTROLS, + HvAdjustControls( + IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_FLAG | + IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_FLAG, + VmxBasicMsr.VmxControls ? IA32_VMX_TRUE_ENTRY_CTLS : IA32_VMX_ENTRY_CTLS)); VmxVmwrite64(VMCS_CTRL_CR0_GUEST_HOST_MASK, 0); VmxVmwrite64(VMCS_CTRL_CR4_GUEST_HOST_MASK, 0); @@ -814,14 +789,14 @@ VmxSetupVmcs(VIRTUAL_MACHINE_STATE * VCpu, PVOID GuestStack) VmxVmwrite64(VMCS_CTRL_CR0_READ_SHADOW, 0); VmxVmwrite64(VMCS_CTRL_CR4_READ_SHADOW, 0); - VmxVmwrite64(VMCS_GUEST_CR0, __readcr0()); - VmxVmwrite64(VMCS_GUEST_CR3, __readcr3()); - VmxVmwrite64(VMCS_GUEST_CR4, __readcr4()); + VmxVmwrite64(VMCS_GUEST_CR0, CpuReadCr0()); + VmxVmwrite64(VMCS_GUEST_CR3, CpuReadCr3()); + VmxVmwrite64(VMCS_GUEST_CR4, CpuReadCr4()); VmxVmwrite64(VMCS_GUEST_DR7, 0x400); - VmxVmwrite64(VMCS_HOST_CR0, __readcr0()); - VmxVmwrite64(VMCS_HOST_CR4, __readcr4()); + VmxVmwrite64(VMCS_HOST_CR0, CpuReadCr0()); + VmxVmwrite64(VMCS_HOST_CR4, CpuReadCr4()); // // Because we may be executing in an arbitrary user-mode, process as part @@ -838,22 +813,42 @@ VmxSetupVmcs(VIRTUAL_MACHINE_STATE * VCpu, PVOID GuestStack) VmxVmwrite64(VMCS_GUEST_RFLAGS, AsmGetRflags()); - VmxVmwrite64(VMCS_GUEST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS)); - VmxVmwrite64(VMCS_GUEST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP)); - VmxVmwrite64(VMCS_GUEST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP)); + VmxVmwrite64(VMCS_GUEST_SYSENTER_CS, CpuReadMsr(IA32_SYSENTER_CS)); + VmxVmwrite64(VMCS_GUEST_SYSENTER_EIP, CpuReadMsr(IA32_SYSENTER_EIP)); + VmxVmwrite64(VMCS_GUEST_SYSENTER_ESP, CpuReadMsr(IA32_SYSENTER_ESP)); + +#if USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE + + SegmentGetDescriptor((PUCHAR)VCpu->HostGdt, AsmGetTr(), &SegmentSelector); - VmxGetSegmentDescriptor((PUCHAR)AsmGetGdtBase(), AsmGetTr(), &SegmentSelector); VmxVmwrite64(VMCS_HOST_TR_BASE, SegmentSelector.Base); + VmxVmwrite64(VMCS_HOST_GDTR_BASE, VCpu->HostGdt); - VmxVmwrite64(VMCS_HOST_FS_BASE, __readmsr(IA32_FS_BASE)); - VmxVmwrite64(VMCS_HOST_GS_BASE, __readmsr(IA32_GS_BASE)); +#else + SegmentGetDescriptor((PUCHAR)AsmGetGdtBase(), AsmGetTr(), &SegmentSelector); + + VmxVmwrite64(VMCS_HOST_TR_BASE, SegmentSelector.Base); VmxVmwrite64(VMCS_HOST_GDTR_BASE, AsmGetGdtBase()); + +#endif // USE_DEFAULT_OS_GDT_AS_HOST_GDT == FALSE + + VmxVmwrite64(VMCS_HOST_FS_BASE, CpuReadMsr(IA32_FS_BASE)); + VmxVmwrite64(VMCS_HOST_GS_BASE, CpuReadMsr(IA32_GS_BASE)); + +#if USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE + + VmxVmwrite64(VMCS_HOST_IDTR_BASE, VCpu->HostIdt); + +#else + VmxVmwrite64(VMCS_HOST_IDTR_BASE, AsmGetIdtBase()); - VmxVmwrite64(VMCS_HOST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS)); - VmxVmwrite64(VMCS_HOST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP)); - VmxVmwrite64(VMCS_HOST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP)); +#endif // USE_DEFAULT_OS_IDT_AS_HOST_IDT == FALSE + + VmxVmwrite64(VMCS_HOST_SYSENTER_CS, CpuReadMsr(IA32_SYSENTER_CS)); + VmxVmwrite64(VMCS_HOST_SYSENTER_EIP, CpuReadMsr(IA32_SYSENTER_EIP)); + VmxVmwrite64(VMCS_HOST_SYSENTER_ESP, CpuReadMsr(IA32_SYSENTER_ESP)); // // Set MSR Bitmaps @@ -903,29 +898,33 @@ VmxSetupVmcs(VIRTUAL_MACHINE_STATE * VCpu, PVOID GuestStack) } /** - * @brief Resume VM using VMRESUME instruction + * @brief Resume VM using the VMRESUME instruction * * @return VOID */ VOID -VmxVmresume() +VmxPerformVmresume() { - UINT64 ErrorCode = 0; + UINT32 ErrorCode = 0; - __vmx_vmresume(); + VmxVmresume(); // // if VMRESUME succeed will never be here ! // - __vmx_vmread(VMCS_VM_INSTRUCTION_ERROR, &ErrorCode); - __vmx_off(); + VmxVmread32P(VMCS_VM_INSTRUCTION_ERROR, &ErrorCode); + + VmxVmxoff(); // // It's such a bad error because we don't where to go ! // prefer to break // - LogError("Err, in executing VMRESUME , status : 0x%llx", ErrorCode); + + LogError("Err, in executing VMRESUME, status : 0x%llx, last VM-exit reason: 0x%x", + ErrorCode, + g_GuestState[KeGetCurrentProcessorNumberEx(NULL)].ExitReason); } /** @@ -989,7 +988,7 @@ VmxVmfunc(UINT32 EptpIndex, UINT32 Function) * @return VOID */ VOID -VmxVmxoff(VIRTUAL_MACHINE_STATE * VCpu) +VmxPerformVmxoff(VIRTUAL_MACHINE_STATE * VCpu) { UINT64 GuestRSP = 0; // Save a pointer to guest rsp for times that we want to return to previous guest stateS UINT64 GuestRIP = 0; // Save a pointer to guest rip for times that we want to return to previous guest state @@ -1007,19 +1006,19 @@ VmxVmxoff(VIRTUAL_MACHINE_STATE * VCpu) // process continues to run with its expected address space mappings. // - __vmx_vmread(VMCS_GUEST_CR3, &GuestCr3); - __writecr3(GuestCr3); + VmxVmread64P(VMCS_GUEST_CR3, &GuestCr3); + CpuWriteCr3(GuestCr3); // // Read guest rsp and rip // - __vmx_vmread(VMCS_GUEST_RIP, &GuestRIP); - __vmx_vmread(VMCS_GUEST_RSP, &GuestRSP); + VmxVmread64P(VMCS_GUEST_RIP, &GuestRIP); + VmxVmread64P(VMCS_GUEST_RSP, &GuestRSP); // // Read instruction length // - __vmx_vmread(VMCS_VMEXIT_INSTRUCTION_LENGTH, &ExitInstructionLength); + VmxVmread64P(VMCS_VMEXIT_INSTRUCTION_LENGTH, &ExitInstructionLength); GuestRIP += ExitInstructionLength; // @@ -1038,6 +1037,15 @@ VmxVmxoff(VIRTUAL_MACHINE_STATE * VCpu) // HvRestoreRegisters(); + // + // Restore XMM registers + // We restore XMM registers here because we are going to execute vmxoff instruction + // which enables interrupts and we don't want to lose the XMM registers + // since immediately after vmxoff, an interrupt might occur and context switch + // might change the XMM registers + // + 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. // See sections 24.1 and 24.11 of the SDM. @@ -1047,7 +1055,12 @@ VmxVmxoff(VIRTUAL_MACHINE_STATE * VCpu) // // Execute Vmxoff // - __vmx_off(); + VmxVmxoff(); + + // + // *** Note: After executing VMXOFF, XMM registers should not be used anymore + // Since we already restored them *** + // // // Indicate the current core is not currently virtualized @@ -1057,7 +1070,7 @@ VmxVmxoff(VIRTUAL_MACHINE_STATE * VCpu) // // Now that VMX is OFF, we have to unset vmx-enable bit on cr4 // - __writecr4(__readcr4() & (~X86_CR4_VMXE)); + CpuWriteCr4(CpuReadCr4() & (~REG_CR4_VMXE)); } /** @@ -1106,7 +1119,10 @@ VmxPerformTermination() // // Unhide (disable and de-allocate) transparent-mode // - TransparentUnhideDebugger(); + if (g_CheckForFootprints) + { + TransparentUnhideDebuggerWrapper(NULL); + } // // Remove All the hooks if any @@ -1130,13 +1146,13 @@ VmxPerformTermination() // // Free the buffer related to MSRs that cause #GP // - CrsFreePool(g_MsrBitmapInvalidMsrs); + PlatformMemFreePool(g_MsrBitmapInvalidMsrs); g_MsrBitmapInvalidMsrs = NULL; // // 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) { @@ -1149,14 +1165,9 @@ VmxPerformTermination() // // Free EptState // - CrsFreePool(g_EptState); + PlatformMemFreePool(g_EptState); g_EptState = NULL; - // - // Free the Pool manager - // - PoolManagerUninitialize(); - // // Uninitialize memory mapper // @@ -1196,8 +1207,8 @@ VmxCompatibleStrlen(const CHAR * S) // // Move to new cr3 // - OriginalCr3.Flags = __readcr3(); - __writecr3(GuestCr3.Flags); + OriginalCr3.Flags = CpuReadCr3(); + CpuWriteCr3(GuestCr3.Flags); // // First check @@ -1211,7 +1222,7 @@ VmxCompatibleStrlen(const CHAR * S) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0; } @@ -1232,7 +1243,7 @@ VmxCompatibleStrlen(const CHAR * S) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return Count; } @@ -1247,7 +1258,7 @@ VmxCompatibleStrlen(const CHAR * S) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0; } } @@ -1256,7 +1267,7 @@ VmxCompatibleStrlen(const CHAR * S) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); } /** @@ -1267,9 +1278,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; @@ -1285,15 +1296,15 @@ VmxCompatibleWcslen(const wchar_t * S) // // Move to new cr3 // - OriginalCr3.Flags = __readcr3(); - __writecr3(GuestCr3.Flags); + OriginalCr3.Flags = CpuReadCr3(); + CpuWriteCr3(GuestCr3.Flags); AlignedAddress = (UINT64)PAGE_ALIGN((UINT64)S); // // First check // - if (!CheckAccessValidityAndSafety(AlignedAddress, sizeof(wchar_t))) + if (!CheckAccessValidityAndSafety(AlignedAddress, sizeof(WCHAR))) { // // Error @@ -1302,7 +1313,7 @@ VmxCompatibleWcslen(const wchar_t * S) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0; } @@ -1311,7 +1322,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') { @@ -1323,13 +1334,13 @@ VmxCompatibleWcslen(const wchar_t * S) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return Count; } if (!((UINT64)S & (PAGE_SIZE - 1))) { - if (!CheckAccessValidityAndSafety((UINT64)S, sizeof(wchar_t))) + if (!CheckAccessValidityAndSafety((UINT64)S, sizeof(WCHAR))) { // // Error @@ -1338,7 +1349,7 @@ VmxCompatibleWcslen(const wchar_t * S) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0; } } @@ -1347,87 +1358,51 @@ VmxCompatibleWcslen(const wchar_t * S) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); } /** - * @brief Get Segment Descriptor + * @brief VMX-root compatible micro sleep + * @param Us Delay in micro seconds * - * @param SegmentSelector - * @param Selector - * @param GdtBase - * @return BOOLEAN + * @return VOID */ -_Use_decl_annotations_ -BOOLEAN -VmxGetSegmentDescriptor(PUCHAR GdtBase, UINT16 Selector, PVMX_SEGMENT_SELECTOR SegmentSelector) +VOID +VmxCompatibleMicroSleep(UINT64 Us) { - SEGMENT_DESCRIPTOR_32 * DescriptorTable32; - SEGMENT_DESCRIPTOR_32 * Descriptor32; - SEGMENT_SELECTOR SegSelector = {.AsUInt = Selector}; + LARGE_INTEGER Start, End, Frequency; + KeQueryPerformanceCounter(&Frequency); - if (!SegmentSelector) - return FALSE; + LONGLONG Ticks = (Frequency.QuadPart / 1000000) * Us; -#define SELECTOR_TABLE_LDT 0x1 -#define SELECTOR_TABLE_GDT 0x0 + Start = KeQueryPerformanceCounter(NULL); - // - // Ignore LDT - // - if ((Selector == 0x0) || (SegSelector.Table != SELECTOR_TABLE_GDT)) + while (TRUE) { - return FALSE; + End = KeQueryPerformanceCounter(NULL); + if (End.QuadPart - Start.QuadPart > Ticks) + break; } - - DescriptorTable32 = (SEGMENT_DESCRIPTOR_32 *)(GdtBase); - Descriptor32 = &DescriptorTable32[SegSelector.Index]; - - SegmentSelector->Selector = Selector; - SegmentSelector->Limit = __segmentlimit(Selector); - SegmentSelector->Base = ((UINT64)Descriptor32->BaseAddressLow | (UINT64)Descriptor32->BaseAddressMiddle << 16 | (UINT64)Descriptor32->BaseAddressHigh << 24); - - SegmentSelector->Attributes.AsUInt = (AsmGetAccessRights(Selector) >> 8); - - if (SegSelector.Table == 0 && SegSelector.Index == 0) - { - SegmentSelector->Attributes.Unusable = TRUE; - } - - if ((Descriptor32->Type == SEGMENT_DESCRIPTOR_TYPE_TSS_BUSY) || (Descriptor32->Type == SEGMENT_DESCRIPTOR_TYPE_CALL_GATE)) - { - // - // this is a TSS or callgate etc, save the base high part - // - - UINT64 SegmentLimitHigh; - SegmentLimitHigh = (*(UINT64 *)((PUCHAR)Descriptor32 + 8)); - SegmentSelector->Base = (SegmentSelector->Base & 0xffffffff) | (SegmentLimitHigh << 32); - } - - if (SegmentSelector->Attributes.Granularity) - { - // - // 4096-bit granularity is enabled for this segment, scale the limit - // - SegmentSelector->Limit = (SegmentSelector->Limit << 12) + 0xfff; - } - - return TRUE; } /** - * @brief implementation of vmx-root mode compatible strcmp + * @brief implementation of vmx-root mode compatible strcmp and strncmp * @param Address1 * @param Address2 + * @param Num + * param IsStrncmp * * @return INT32 0x2 indicates error, otherwise the same result as strcmp in string.h */ INT32 -VmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2) +VmxCompatibleStrcmp(const CHAR * Address1, + const CHAR * Address2, + SIZE_T Num, + BOOLEAN IsStrncmp) { CHAR C1 = NULL_ZERO, C2 = NULL_ZERO; INT32 Result = 0; + UINT32 Count = 0; UINT64 AlignedAddress1, AlignedAddress2; CR3_TYPE GuestCr3; CR3_TYPE OriginalCr3; @@ -1443,8 +1418,8 @@ VmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2) // // Move to new cr3 // - OriginalCr3.Flags = __readcr3(); - __writecr3(GuestCr3.Flags); + OriginalCr3.Flags = CpuReadCr3(); + CpuWriteCr3(GuestCr3.Flags); // // First check @@ -1458,12 +1433,33 @@ VmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0x2; } do { + // + // Check to see if we have byte number constraints + // + if (IsStrncmp) + { + if (Count == Num) + { + // + // Maximum number of bytes reached + // + break; + } + else + { + // + // Maximum number of bytes not reached + // + Count++; + } + } + /* C1 = *Address1; */ @@ -1488,7 +1484,7 @@ VmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0x2; } } @@ -1504,7 +1500,7 @@ VmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0x2; } } @@ -1523,22 +1519,28 @@ VmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return Result; } /** - * @brief implementation of vmx-root mode compatible wcscmp + * @brief implementation of vmx-root mode compatible wcscmp and wcsncmp * @param Address1 * @param Address2 + * @param Num + * @param IsWcsncmp * * @return INT32 0x2 indicates error, otherwise the same result as wcscmp in string.h */ INT32 -VmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2) +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; CR3_TYPE GuestCr3; CR3_TYPE OriginalCr3; @@ -1554,13 +1556,13 @@ VmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2) // // Move to new cr3 // - OriginalCr3.Flags = __readcr3(); - __writecr3(GuestCr3.Flags); + OriginalCr3.Flags = CpuReadCr3(); + CpuWriteCr3(GuestCr3.Flags); // // First check // - if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(wchar_t)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(wchar_t))) + if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(WCHAR)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(WCHAR))) { // // Error @@ -1569,28 +1571,49 @@ VmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0x2; } do { + // + // Check to see if we have byte number constraints + // + if (IsWcsncmp) + { + if (Count == Num) + { + // + // Maximum number of bytes reached + // + break; + } + else + { + // + // Maximum number of bytes not reached + // + Count++; + } + } + /* 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 @@ -1599,14 +1622,14 @@ VmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0x2; } } if (!((UINT64)AlignedAddress2 & (PAGE_SIZE - 1))) { - if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(wchar_t))) + if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(WCHAR))) { // // Error @@ -1615,7 +1638,7 @@ VmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0x2; } } @@ -1635,7 +1658,7 @@ VmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return Result; } @@ -1648,7 +1671,7 @@ VmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2) * @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; @@ -1667,13 +1690,13 @@ VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count) // // Move to new cr3 // - OriginalCr3.Flags = __readcr3(); - __writecr3(GuestCr3.Flags); + OriginalCr3.Flags = CpuReadCr3(); + CpuWriteCr3(GuestCr3.Flags); // // First check // - if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(wchar_t)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(wchar_t))) + if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(WCHAR)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(WCHAR))) { // // Error @@ -1682,7 +1705,7 @@ VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0x2; } @@ -1703,7 +1726,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 @@ -1712,14 +1735,14 @@ VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0x2; } } if (!((UINT64)AlignedAddress2 & (PAGE_SIZE - 1))) { - if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(wchar_t))) + if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(WCHAR))) { // // Error @@ -1728,7 +1751,7 @@ VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return 0x2; } } @@ -1748,6 +1771,31 @@ VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count) // // Move back to original cr3 // - __writecr3(OriginalCr3.Flags); + CpuWriteCr3(OriginalCr3.Flags); return Result; } + +/** + * @brief checks if the current top level hypervisor is Hyper-V + * + * + * @return BOOLEAN TRUE indicates that the current top level hypervisor is Hyper-V, FALSE otherwise. + */ +BOOLEAN +VmxIsTopLevelHypervisorHyperV() +{ + INT32 ProcessorFeatures[4] = {0}; + CpuCpuIdEx(ProcessorFeatures, CPUID_PROCESSOR_AND_PROCESSOR_FEATURE_IDENTIFIERS, 0); + + if (!((ULONG)(ProcessorFeatures[2]) & HYPERV_HYPERVISOR_PRESENT_BIT)) + { + return FALSE; + } + + INT32 HypervisorVendor[4] = {0}; + CpuCpuIdEx(HypervisorVendor, HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, 0); + + return (ULONG)(HypervisorVendor[1]) == HYPERV_CPUID_VENDOR_MICROSOFT_EBX && + (ULONG)(HypervisorVendor[2]) == HYPERV_CPUID_VENDOR_MICROSOFT_ECX && + (ULONG)(HypervisorVendor[3]) == HYPERV_CPUID_VENDOR_MICROSOFT_EDX; +} diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/VmxBroadcast.c b/hyperdbg/hyperhv/code/vmm/vmx/VmxBroadcast.c similarity index 96% rename from hyperdbg/hprdbghv/code/vmm/vmx/VmxBroadcast.c rename to hyperdbg/hyperhv/code/vmm/vmx/VmxBroadcast.c index 0e4cf03b..6b23c7fa 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/VmxBroadcast.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/VmxBroadcast.c @@ -28,11 +28,15 @@ VmxBroadcastInitialize() // ApicInitialize(); +#if USE_DEFAULT_OS_IDT_AS_HOST_IDT == TRUE + // // Register NMI handler for vmx-root // g_NmiHandlerForKeDeregisterNmiCallback = KeRegisterNmiCallback(&VmxBroadcastHandleNmiCallback, NULL); +#endif // USE_DEFAULT_OS_IDT_AS_HOST_IDT == TRUE + // // Broadcast on all core to cause exit for NMIs // @@ -57,11 +61,15 @@ VmxBroadcastUninitialize() // g_NmiBroadcastingInitialized = FALSE; +#if USE_DEFAULT_OS_IDT_AS_HOST_IDT == TRUE + // // De-register NMI handler // KeDeregisterNmiCallback(g_NmiHandlerForKeDeregisterNmiCallback); +#endif // USE_DEFAULT_OS_IDT_AS_HOST_IDT == TRUE + // // Broadcast on all core to cause not to exit for NMIs // @@ -149,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) { diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/VmxMechanisms.c b/hyperdbg/hyperhv/code/vmm/vmx/VmxMechanisms.c similarity index 100% rename from hyperdbg/hprdbghv/code/vmm/vmx/VmxMechanisms.c rename to hyperdbg/hyperhv/code/vmm/vmx/VmxMechanisms.c diff --git a/hyperdbg/hprdbghv/code/vmm/vmx/VmxRegions.c b/hyperdbg/hyperhv/code/vmm/vmx/VmxRegions.c similarity index 66% rename from hyperdbg/hprdbghv/code/vmm/vmx/VmxRegions.c rename to hyperdbg/hyperhv/code/vmm/vmx/VmxRegions.c index e4386f09..5d008d3f 100644 --- a/hyperdbg/hprdbghv/code/vmm/vmx/VmxRegions.c +++ b/hyperdbg/hyperhv/code/vmm/vmx/VmxRegions.c @@ -30,19 +30,19 @@ VmxAllocateVmxonRegion(VIRTUAL_MACHINE_STATE * VCpu) UINT64 AlignedVmxonRegion; UINT64 AlignedVmxonRegionPhysicalAddr; -#ifdef ENV_WINDOWS +#ifdef HYPERDBG_ENV_WINDOWS // // at IRQL > DISPATCH_LEVEL memory allocation routines don't work // if (KeGetCurrentIrql() > DISPATCH_LEVEL) KeRaiseIrqlToDpcLevel(); -#endif // ENV_WINDOWS +#endif // HYPERDBG_ENV_WINDOWS // // Allocating a 4-KByte Contiguous Memory region // VmxonSize = 2 * VMXON_SIZE; - VmxonRegion = CrsAllocateContiguousZeroedMemory(VmxonSize + ALIGNMENT_PAGE_SIZE); + VmxonRegion = PlatformMemAllocateContiguousZeroedMemory(VmxonSize + ALIGNMENT_PAGE_SIZE); if (VmxonRegion == NULL) { LogError("Err, couldn't allocate buffer for VMXON region"); @@ -63,7 +63,7 @@ VmxAllocateVmxonRegion(VIRTUAL_MACHINE_STATE * VCpu) // // get IA32_VMX_BASIC_MSR RevisionId // - VmxBasicMsr.AsUInt = __readmsr(IA32_VMX_BASIC); + VmxBasicMsr.AsUInt = CpuReadMsr(IA32_VMX_BASIC); LogDebugInfo("Revision Identifier (IA32_VMX_BASIC - MSR 0x480) : 0x%x", VmxBasicMsr.VmcsRevisionId); // @@ -74,7 +74,8 @@ VmxAllocateVmxonRegion(VIRTUAL_MACHINE_STATE * VCpu) // // Execute Vmxon instruction // - VmxonStatus = __vmx_on(&AlignedVmxonRegionPhysicalAddr); + VmxonStatus = VmxVmxon(&AlignedVmxonRegionPhysicalAddr); + if (VmxonStatus) { LogError("Err, executing vmxon instruction failed with status : %d", VmxonStatus); @@ -109,19 +110,19 @@ VmxAllocateVmcsRegion(VIRTUAL_MACHINE_STATE * VCpu) UINT64 AlignedVmcsRegion; UINT64 AlignedVmcsRegionPhysicalAddr; -#ifdef ENV_WINDOWS +#ifdef HYPERDBG_ENV_WINDOWS // // at IRQL > DISPATCH_LEVEL memory allocation routines don't work // if (KeGetCurrentIrql() > DISPATCH_LEVEL) KeRaiseIrqlToDpcLevel(); -#endif // ENV_WINDOWS +#endif // HYPERDBG_ENV_WINDOWS // // Allocating a 4-KByte Contiguous Memory region // VmcsSize = 2 * VMCS_SIZE; - VmcsRegion = CrsAllocateContiguousZeroedMemory(VmcsSize + ALIGNMENT_PAGE_SIZE); + VmcsRegion = PlatformMemAllocateContiguousZeroedMemory(VmcsSize + ALIGNMENT_PAGE_SIZE); if (VmcsRegion == NULL) { LogError("Err, couldn't allocate Buffer for VMCS region"); @@ -139,7 +140,7 @@ VmxAllocateVmcsRegion(VIRTUAL_MACHINE_STATE * VCpu) // // get IA32_VMX_BASIC_MSR RevisionId // - VmxBasicMsr.AsUInt = __readmsr(IA32_VMX_BASIC); + VmxBasicMsr.AsUInt = CpuReadMsr(IA32_VMX_BASIC); LogDebugInfo("Revision Identifier (IA32_VMX_BASIC - MSR 0x480) : 0x%x", VmxBasicMsr.VmcsRevisionId); // @@ -169,7 +170,7 @@ VmxAllocateVmmStack(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) // // Allocate stack for the VM Exit Handler // - VCpu->VmmStack = (UINT64)CrsAllocateZeroedNonPagedPool(VMM_STACK_SIZE); + VCpu->VmmStack = (UINT64)PlatformMemAllocateZeroedNonPagedPool(VMM_STACK_SIZE); if (VCpu->VmmStack == NULL64_ZERO) { @@ -195,7 +196,7 @@ VmxAllocateMsrBitmap(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) // Allocate memory for MSR Bitmap // Should be aligned // - VCpu->MsrBitmapVirtualAddress = (UINT64)CrsAllocateZeroedNonPagedPool(PAGE_SIZE); + VCpu->MsrBitmapVirtualAddress = (UINT64)PlatformMemAllocateZeroedNonPagedPool(PAGE_SIZE); if (VCpu->MsrBitmapVirtualAddress == NULL64_ZERO) { @@ -214,7 +215,7 @@ VmxAllocateMsrBitmap(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) /** * @brief Allocate a buffer for I/O Bitmap * - * @param ProcessorID + * @param VCpu * @return BOOLEAN Returns true if allocation was successful otherwise returns false */ BOOLEAN @@ -223,7 +224,7 @@ VmxAllocateIoBitmaps(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) // // Allocate memory for I/O Bitmap (A) // - VCpu->IoBitmapVirtualAddressA = (UINT64)CrsAllocateZeroedNonPagedPool(PAGE_SIZE); // should be aligned + VCpu->IoBitmapVirtualAddressA = (UINT64)PlatformMemAllocateZeroedNonPagedPool(PAGE_SIZE); // should be aligned if (VCpu->IoBitmapVirtualAddressA == NULL64_ZERO) { @@ -239,7 +240,7 @@ VmxAllocateIoBitmaps(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) // // Allocate memory for I/O Bitmap (B) // - VCpu->IoBitmapVirtualAddressB = (UINT64)CrsAllocateZeroedNonPagedPool(PAGE_SIZE); // should be aligned + VCpu->IoBitmapVirtualAddressB = (UINT64)PlatformMemAllocateZeroedNonPagedPool(PAGE_SIZE); // should be aligned if (VCpu->IoBitmapVirtualAddressB == NULL64_ZERO) { @@ -265,7 +266,7 @@ VmxAllocateInvalidMsrBimap() { UINT64 * InvalidMsrBitmap; - InvalidMsrBitmap = CrsAllocateZeroedNonPagedPool(0x1000 / 0x8); + InvalidMsrBitmap = PlatformMemAllocateZeroedNonPagedPool(0x1000 / 0x8); if (InvalidMsrBitmap == NULL) { @@ -276,13 +277,132 @@ VmxAllocateInvalidMsrBimap() { __try { - __readmsr(i); + CpuReadMsr(i); } __except (EXCEPTION_EXECUTE_HANDLER) { - SetBit(i, (unsigned long *)InvalidMsrBitmap); + SetBit(i, (ULONG *)InvalidMsrBitmap); } } return InvalidMsrBitmap; } + +/** + * @brief Allocate a buffer for host IDT + * + * @param VCpu + * @return BOOLEAN Returns true if allocation was successful otherwise returns false + */ +BOOLEAN +VmxAllocateHostIdt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) +{ + UINT32 IdtSize = HOST_IDT_DESCRIPTOR_COUNT * sizeof(SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64); + + // + // Make sure the memory is aligned + // + if (PAGE_SIZE > IdtSize) + { + IdtSize = PAGE_SIZE; + } + + // + // Allocate aligned memory for host IDT + // + VCpu->HostIdt = (UINT64)PlatformMemAllocateZeroedNonPagedPool(IdtSize); // should be aligned + + if (VCpu->HostIdt == NULL64_ZERO) + { + LogError("Err, insufficient memory in allocating host IDT"); + return FALSE; + } + + LogDebugInfo("Host IDT virtual address : 0x%llx", VCpu->HostIdt); + + return TRUE; +} + +/** + * @brief Allocate a buffer for host GDT + * + * @param VCpu + * @return BOOLEAN Returns true if allocation was successful otherwise returns false + */ +BOOLEAN +VmxAllocateHostGdt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) +{ + UINT32 GdtSize = HOST_GDT_DESCRIPTOR_COUNT * sizeof(SEGMENT_DESCRIPTOR_64); + + // + // Make sure the memory is aligned + // + if (PAGE_SIZE > GdtSize) + { + GdtSize = PAGE_SIZE; + } + + // + // Allocate aligned memory for host GDT + // + VCpu->HostGdt = (UINT64)PlatformMemAllocateZeroedNonPagedPool(GdtSize); // should be aligned + + if (VCpu->HostGdt == NULL64_ZERO) + { + LogError("Err, insufficient memory in allocating host GDT"); + return FALSE; + } + + LogDebugInfo("Host GDT virtual address : 0x%llx", VCpu->HostGdt); + + return TRUE; +} + +/** + * @brief Allocate a buffer for host TSS + * + * @param VCpu + * @return BOOLEAN Returns true if allocation was successful otherwise returns false + */ +BOOLEAN +VmxAllocateHostTss(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) +{ + UINT32 TssSize = PAGE_SIZE; // Make sure the memory is aligned + + // + // Allocate aligned memory for host TSS + // + VCpu->HostTss = (UINT64)PlatformMemAllocateZeroedNonPagedPool(TssSize); // should be aligned + + if (VCpu->HostTss == NULL64_ZERO) + { + LogError("Err, insufficient memory in allocating host TSS"); + return FALSE; + } + + LogDebugInfo("Host TSS virtual address : 0x%llx", VCpu->HostTss); + + return TRUE; +} + +/** + * @brief Allocate a buffer for host interrupt stack + * + * @param VCpu + * @return BOOLEAN Returns true if allocation was successful otherwise returns false + */ +BOOLEAN +VmxAllocateHostInterruptStack(_Inout_ VIRTUAL_MACHINE_STATE * VCpu) +{ + VCpu->HostInterruptStack = (UINT64)PlatformMemAllocateZeroedNonPagedPool(HOST_INTERRUPT_STACK_SIZE); + + if (VCpu->HostInterruptStack == NULL64_ZERO) + { + LogError("Err, insufficient memory in allocating host interrupt stack"); + return FALSE; + } + + LogDebugInfo("Host interrupt stack virtual address : 0x%llx", VCpu->HostInterruptStack); + + return TRUE; +} diff --git a/hyperdbg/hyperhv/header/assembly/InlineAsm.h b/hyperdbg/hyperhv/header/assembly/InlineAsm.h new file mode 100644 index 00000000..8bc23ba7 --- /dev/null +++ b/hyperdbg/hyperhv/header/assembly/InlineAsm.h @@ -0,0 +1,546 @@ +/** + * @file InlineAsm.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief The definition of functions written in Assembly + * @details + * @version 0.1 + * @date 2020-04-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +// +// ==================== Vmx Operations ==================== +// File : AsmVmxOperation.asm +// + +/** + * @brief Enable VMX Operation + * + */ +extern VOID inline AsmEnableVmxOperation(); + +/** + * @brief Restore in vmxoff state + * + */ +extern VOID inline AsmRestoreToVmxOffState(); + +/** + * @brief Request Vmcall + * + * @param VmcallNumber + * @param OptionalParam1 + * @param OptionalParam2 + * @param OptionalParam3 + * @return NTSTATUS + */ +extern NTSTATUS inline AsmVmxVmcall(UINT64 VmcallNumber, + UINT64 OptionalParam1, + UINT64 OptionalParam2, + UINT64 OptionalParam3); + +/** + * @brief Hyper-v vmcall handler + * + * @param GuestRegisters + * @return VOID + */ +extern VOID inline AsmHypervVmcall(UINT64 GuestRegisters); + +/** + * @brief VMFUNC instruction + * + * @param EptpIndex + * @param Function + * + * @return UINT64 I'm not sure what it returns + */ +extern UINT64 inline AsmVmfunc(ULONG EptpIndex, ULONG Function); + +// +// ==================== Vmx Context State Operations ==================== +// File : AsmVmxContextState.asm +// + +/** + * @brief Save state on vmx + * + */ +extern VOID +AsmVmxSaveState(); + +/** + * @brief Restore state on vmx + * + */ +extern VOID +AsmVmxRestoreState(); + +// +// ==================== Vmx VM-Exit Handler ==================== +// File : AsmVmexitHandler.asm +// + +/** + * @brief Vm-exit handler + * + */ +extern VOID +AsmVmexitHandler(); + +/** + * @brief Save vmxoff state + * + */ +extern VOID inline AsmSaveVmxOffState(); + +/** + * @brief Restore XMM registers + * + */ +extern VOID inline AsmVmxoffRestoreXmmRegs(UINT64 XmmRegs); + +// +// ==================== Extended Page Tables ==================== +// File : AsmEpt.asm +// + +/** + * @brief INVEPT wrapper + * + * @param Type + * @param Descriptors + * @return UCHAR + */ +extern UCHAR inline AsmInvept(ULONG Type, PVOID Descriptors); + +/** + * @brief INVVPID wrapper + * + * @param Type + * @param Descriptors + * @return UCHAR + */ +extern UCHAR inline AsmInvvpid(ULONG Type, PVOID Descriptors); + +// +// ==================== Get segment registers ==================== +// File : AsmSegmentRegs.asm +// + +/* ********* Segment registers ********* */ + +/** + * @brief Get CS Register + * + * @return UINT16 + */ +extern UINT16 +AsmGetCs(); + +/** + * @brief Get DS Register + * + * @return UINT16 + */ +extern UINT16 +AsmGetDs(); + +extern VOID +AsmSetDs(UINT16 DsSelector); + +/** + * @brief Get ES Register + * + * @return UINT16 + */ +extern UINT16 +AsmGetEs(); + +extern VOID +AsmSetEs(UINT16 EsSelector); + +/** + * @brief Get SS Register + * + * @return UINT16 + */ +extern UINT16 +AsmGetSs(); + +extern VOID +AsmSetSs(UINT16 SsSelector); + +/** + * @brief Get FS Register + * + * @return UINT16 + */ +extern UINT16 +AsmGetFs(); + +extern VOID +AsmSetFs(UINT16 FsSelector); + +/** + * @brief Get GS Register + * + * @return UINT16 + */ +extern UINT16 +AsmGetGs(); + +/** + * @brief Get LDTR Register + * + * @return UINT16 + */ +extern UINT16 +AsmGetLdtr(); + +/** + * @brief Get TR Register + * + * @return UINT16 + */ +extern UINT16 +AsmGetTr(); + +/* ******* Gdt related functions ******* */ + +/** + * @brief get GDT base + * + * @return UINT64 + */ +extern UINT64 inline AsmGetGdtBase(); + +/** + * @brief Get GDT Limit + * + * @return UINT16 + */ +extern UINT16 +AsmGetGdtLimit(); + +/* ******* Idt related functions ******* */ + +/** + * @brief Get IDT base + * + * @return UINT64 + */ +extern UINT64 inline AsmGetIdtBase(); + +/** + * @brief Get IDT limit + * + * @return UINT16 + */ +extern UINT16 +AsmGetIdtLimit(); + +extern UINT32 +AsmGetAccessRights(UINT16 Selector); +// +// ==================== Common Functions ==================== +// File : AsmCommon.asm +// + +/** + * @brief Get R/EFLAGS + * + * @return UINT16 + */ +extern UINT16 +AsmGetRflags(); + +/** + * @brief Run CLI Instruction + * + */ +extern VOID inline AsmCliInstruction(); + +/** + * @brief Run STI Instruction + * + */ +extern VOID inline AsmStiInstruction(); + +/** + * @brief Reload new GDTR + * + * @param GdtBase + * @param GdtLimit + */ +extern VOID +AsmReloadGdtr(PVOID GdtBase, ULONG GdtLimit); + +/** + * @brief Reload new IDTR + * + * @param IdtrBase + * @param IdtrLimit + */ +extern VOID +AsmReloadIdtr(PVOID IdtrBase, ULONG IdtrLimit); + +/** + * @brief Read SSP + * + * @return UINT64 + */ +extern UINT64 +AsmReadSsp(); + +// +// ==================== Hook Functions ==================== +// File : AsmHooks.asm +// + +/** + * @brief Detour hook handler + * + */ +extern VOID + AsmGeneralDetourHook(VOID); + +// +// ==================== Kernel Test Functions ==================== +// File : AsmKernelSideTests.asm +// + +/** + * @brief Tests with test tags wrapper + * + */ +extern UINT64 +AsmTestWrapperWithTestTags(UINT64 Param1, + UINT64 Param2, + UINT64 Param3, + UINT64 Param4); + +// +// ==================== Interrupt Handler Functions ==================== +// File : Interrupt Handlers.asm.asm +// + +/** + * @brief The 0th entry in IDT + * + */ +extern VOID +InterruptHandler0(); + +/** + * @brief The 1st entry in IDT + * + */ +extern VOID +InterruptHandler1(); + +/** + * @brief The 2nd entry in IDT + * + */ +extern VOID +InterruptHandler2(); + +/** + * @brief The 3rd entry in IDT + * + */ +extern VOID +InterruptHandler3(); + +/** + * @brief The 4th entry in IDT + * + */ +extern VOID +InterruptHandler4(); + +/** + * @brief The 5th entry in IDT + * + */ +extern VOID +InterruptHandler5(); + +/** + * @brief The 6th entry in IDT + * + */ +extern VOID +InterruptHandler6(); + +/** + * @brief The 7th entry in IDT + * + */ +extern VOID +InterruptHandler7(); + +/** + * @brief The 8th entry in IDT + * + */ +extern VOID +InterruptHandler8(); + +/** + * @brief The 9th entry in IDT + * + */ +extern VOID +InterruptHandler9(); + +/** + * @brief The 10th entry in IDT + * + */ +extern VOID +InterruptHandler10(); + +/** + * @brief The 11th entry in IDT + * + */ +extern VOID +InterruptHandler11(); + +/** + * @brief The 12th entry in IDT + * + */ +extern VOID +InterruptHandler12(); + +/** + * @brief The 13th entry in IDT + * + */ +extern VOID +InterruptHandler13(); + +/** + * @brief The 14th entry in IDT + * + */ +extern VOID +InterruptHandler14(); + +/** + * @brief The 15th entry in IDT + * + */ +extern VOID +InterruptHandler15(); + +/** + * @brief The 16th entry in IDT + * + */ +extern VOID +InterruptHandler16(); + +/** + * @brief The 17th entry in IDT + * + */ +extern VOID +InterruptHandler17(); + +/** + * @brief The 18th entry in IDT + * + */ +extern VOID +InterruptHandler18(); + +/** + * @brief The 19th entry in IDT + * + */ +extern VOID +InterruptHandler19(); + +/** + * @brief The 20th entry in IDT + * + */ +extern VOID +InterruptHandler20(); + +/** + * @brief The 21st entry in IDT + * + */ +extern VOID +InterruptHandler21(); + +/** + * @brief The 22nd entry in IDT + * + */ +extern VOID +InterruptHandler22(); + +/** + * @brief The 23rd entry in IDT + * + */ +extern VOID +InterruptHandler23(); + +/** + * @brief The 24th entry in IDT + * + */ +extern VOID +InterruptHandler24(); + +/** + * @brief The 25th entry in IDT + * + */ +extern VOID +InterruptHandler25(); + +/** + * @brief The 26th entry in IDT + * + */ +extern VOID +InterruptHandler26(); + +/** + * @brief The 27th entry in IDT + * + */ +extern VOID +InterruptHandler27(); + +/** + * @brief The 28th entry in IDT + * + */ +extern VOID +InterruptHandler28(); + +/** + * @brief The 29th entry in IDT + * + */ +extern VOID +InterruptHandler29(); + +/** + * @brief The 30th entry in IDT + * + */ +extern VOID +InterruptHandler30(); diff --git a/hyperdbg/hprdbghv/header/broadcast/Broadcast.h b/hyperdbg/hyperhv/header/broadcast/Broadcast.h similarity index 100% rename from hyperdbg/hprdbghv/header/broadcast/Broadcast.h rename to hyperdbg/hyperhv/header/broadcast/Broadcast.h diff --git a/hyperdbg/hprdbghv/header/broadcast/DpcRoutines.h b/hyperdbg/hyperhv/header/broadcast/DpcRoutines.h similarity index 100% rename from hyperdbg/hprdbghv/header/broadcast/DpcRoutines.h rename to hyperdbg/hyperhv/header/broadcast/DpcRoutines.h diff --git a/hyperdbg/hprdbghv/header/common/Bitwise.h b/hyperdbg/hyperhv/header/common/Bitwise.h similarity index 71% rename from hyperdbg/hprdbghv/header/common/Bitwise.h rename to hyperdbg/hyperhv/header/common/Bitwise.h index 5e5e674a..13601671 100644 --- a/hyperdbg/hprdbghv/header/common/Bitwise.h +++ b/hyperdbg/hyperhv/header/common/Bitwise.h @@ -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); diff --git a/hyperdbg/hyperhv/header/common/Common.h b/hyperdbg/hyperhv/header/common/Common.h new file mode 100644 index 00000000..317e841c --- /dev/null +++ b/hyperdbg/hyperhv/header/common/Common.h @@ -0,0 +1,171 @@ +/** + * @file Common.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Header files for common functions + * @details + * @version 0.1 + * @date 2020-04-10 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +/** + * @brief Core Id + * + */ +#define __CPU_INDEX__ KeGetCurrentProcessorNumberEx(NULL) + +/** + * @brief Alignment Size + * + */ +#define ALIGNMENT_PAGE_SIZE 4096 + +/** + * @brief Maximum x64 Address + * + */ +#define MAXIMUM_ADDRESS 0xffffffffffffffff + +/** + * @brief System and User ring definitions + * + */ +#define DPL_USER 3 +#define DPL_SYSTEM 0 + +/** + * @brief RPL Mask + * + */ +#define RPL_MASK 3 + +#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) + +/** + * @brief Offset from a page's 4096 bytes + * + */ +#define PAGE_OFFSET(Va) ((PVOID)((ULONG_PTR)(Va) & (PAGE_SIZE - 1))) + +/** + * @brief Intel TSX Constants + * + */ +#define _XBEGIN_STARTED (~0u) +#define _XABORT_EXPLICIT (1 << 0) +#define _XABORT_RETRY (1 << 1) +#define _XABORT_CONFLICT (1 << 2) +#define _XABORT_CAPACITY (1 << 3) +#define _XABORT_DEBUG (1 << 4) +#define _XABORT_NESTED (1 << 5) + +#ifndef _XABORT_CODE +# define _XABORT_CODE(x) (((x) >> 24) & 0xFF) +#endif // !_XABORT_CODE + +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +typedef SEGMENT_DESCRIPTOR_32 * PSEGMENT_DESCRIPTOR; + +/** + * @brief CPUID Registers + * + */ +typedef struct _CPUID +{ + INT eax; + INT ebx; + INT ecx; + INT edx; +} CPUID, *PCPUID; + +typedef union _CR_FIXED +{ + UINT64 Flags; + + struct + { + ULONG Low; + LONG High; + + } Fields; + +} CR_FIXED, *PCR_FIXED; + +////////////////////////////////////////////////// +// Windows-specific structures // +////////////////////////////////////////////////// + +/** + * @brief KPROCESS Brief structure + * + */ +typedef struct _NT_KPROCESS +{ + DISPATCHER_HEADER Header; + LIST_ENTRY ProfileListHead; + ULONG_PTR DirectoryTableBase; + UCHAR Data[1]; +} NT_KPROCESS, *PNT_KPROCESS; + +////////////////////////////////////////////////// +// Function Types // +////////////////////////////////////////////////// + +/** + * @brief Prototype to run a function on a logical core + * + */ +typedef VOID (*RunOnLogicalCoreFunc)(ULONG ProcessorId); + +////////////////////////////////////////////////// +// External Functions // +////////////////////////////////////////////////// + +UCHAR * +PsGetProcessImageFileName(IN PEPROCESS Process); + +////////////////////////////////////////////////// +// Function Definitions // +////////////////////////////////////////////////// + +// ---------------------------------------------------------------------------- +// Private Interfaces +// + +static NTSTATUS +CommonGetHandleFromProcess(_In_ UINT32 ProcessId, _Out_ PHANDLE Handle); + +// ---------------------------------------------------------------------------- +// Public Interfaces +// + +BOOLEAN +CommonAffinityBroadcastToProcessors(_In_ ULONG ProcessorNumber, _In_ RunOnLogicalCoreFunc Routine); + +BOOLEAN +CommonIsStringStartsWith(const CHAR * pre, const CHAR * str); + +BOOLEAN +CommonIsGuestOnUsermode32Bit(); + +PCHAR +CommonGetProcessNameFromProcessControlBlock(PEPROCESS eprocess); + +VOID +CommonCpuidInstruction(UINT32 Func, UINT32 SubFunc, INT * CpuInfo); + +VOID +CommonWriteDebugInformation(VIRTUAL_MACHINE_STATE * VCpu); + +BOOLEAN +CommonIsXCr0Valid(XCR0 XCr0); diff --git a/hyperdbg/hprdbghv/header/common/Msr.h b/hyperdbg/hyperhv/header/common/Msr.h similarity index 59% rename from hyperdbg/hprdbghv/header/common/Msr.h rename to hyperdbg/hyperhv/header/common/Msr.h index 2665c691..eab90724 100644 --- a/hyperdbg/hprdbghv/header/common/Msr.h +++ b/hyperdbg/hyperhv/header/common/Msr.h @@ -11,6 +11,18 @@ */ #pragma once +////////////////////////////////////////////////// +// MSR Numbers // +////////////////////////////////////////////////// + +/** + * @brief MSR for System Management Interrupt (SMI) count + * + * @details This MSR is used to read the count of System Management Interrupts (SMIs) + * that have occurred since the last reset + */ +#define MSR_SMI_COUNT 0x00000034 + ////////////////////////////////////////////////// // Structures // ////////////////////////////////////////////////// diff --git a/hyperdbg/hprdbghv/header/common/State.h b/hyperdbg/hyperhv/header/common/State.h similarity index 55% rename from hyperdbg/hprdbghv/header/common/State.h rename to hyperdbg/hyperhv/header/common/State.h index c6cdec74..8ea8a312 100644 --- a/hyperdbg/hprdbghv/header/common/State.h +++ b/hyperdbg/hyperhv/header/common/State.h @@ -15,11 +15,12 @@ // typedefs // ////////////////////////////////////////////////// -typedef EPT_PML4E EPT_PML4_POINTER, *PEPT_PML4_POINTER; -typedef EPT_PDPTE EPT_PML3_POINTER, *PEPT_PML3_POINTER; -typedef EPT_PDE_2MB EPT_PML2_ENTRY, *PEPT_PML2_ENTRY; -typedef EPT_PDE EPT_PML2_POINTER, *PEPT_PML2_POINTER; -typedef EPT_PTE EPT_PML1_ENTRY, *PEPT_PML1_ENTRY; +typedef EPT_PML4E EPT_PML4_POINTER, *PEPT_PML4_POINTER; +typedef EPT_PDPTE EPT_PML3_POINTER, *PEPT_PML3_POINTER; +typedef EPT_PDPTE_1GB EPT_PML3_ENTRY, *PEPT_PML3_ENTRY; +typedef EPT_PDE_2MB EPT_PML2_ENTRY, *PEPT_PML2_ENTRY; +typedef EPT_PDE EPT_PML2_POINTER, *PEPT_PML2_POINTER; +typedef EPT_PTE EPT_PML1_ENTRY, *PEPT_PML1_ENTRY; ////////////////////////////////////////////////// // Constants // @@ -109,6 +110,14 @@ typedef struct _VMM_EPT_PAGE_TABLE DECLSPEC_ALIGN(PAGE_SIZE) EPT_PML4_POINTER PML4[VMM_EPT_PML4E_COUNT]; + /** + * @brief Describes exactly 512 contiguous 1GB memory regions within a our singular 512GB PML4 region + * (This entry is used to support the entire address space). + * @details The reason why there is a minus one here is that the original PML3 is described in the next field. + */ + DECLSPEC_ALIGN(PAGE_SIZE) + EPT_PML3_ENTRY PML3_RSVD[VMM_EPT_PML4E_COUNT - 1][VMM_EPT_PML3E_COUNT]; + /** * @brief Describes exactly 512 contiguous 1GB memory regions within a our singular 512GB PML4 region. */ @@ -123,6 +132,13 @@ typedef struct _VMM_EPT_PAGE_TABLE DECLSPEC_ALIGN(PAGE_SIZE) EPT_PML2_ENTRY PML2[VMM_EPT_PML3E_COUNT][VMM_EPT_PML2E_COUNT]; + /** + * @brief Tracks dynamic 2MB->4KB splits for this EPT table. + * NOTE: Each item stores a direct VA to the split PML1 page and the corresponding PML2 entry it services. + * + */ + LIST_ENTRY DynamicSplitList; + } VMM_EPT_PAGE_TABLE, *PVMM_EPT_PAGE_TABLE; ////////////////////////////////////////////////// @@ -234,6 +250,11 @@ typedef struct _EPT_HOOKED_PAGE_DETAIL */ BOOLEAN IsHiddenBreakpoint; + /** + * @brief This field shows whether the hook is for MMIO shadowing or not + */ + BOOLEAN IsMmioShadowing; + /** * @brief Temporary context for the post event monitors * It shows the context of the last address that triggered the hook @@ -288,46 +309,53 @@ typedef struct _NMI_BROADCASTING_STATE */ typedef struct _VIRTUAL_MACHINE_STATE { - BOOLEAN IsOnVmxRootMode; // Detects whether the current logical core is on Executing on VMX Root Mode - BOOLEAN IncrementRip; // Checks whether it has to redo the previous instruction or not (it used mainly in Ept routines) - BOOLEAN HasLaunched; // Indicate whether the core is virtualized or not - BOOLEAN IgnoreMtfUnset; // Indicate whether the core should ignore unsetting the MTF or not - 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 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 - PUINT64 PmlBufferAddress; // Address of buffer used for dirty logging - BOOLEAN Test; // Used for test purposes - UINT64 TestNumber; // Used for test purposes (Number) - GUEST_REGS * Regs; // The virtual processor's general-purpose registers - UINT32 CoreId; // The core's unique identifier - UINT32 ExitReason; // The core's exit reason - UINT32 ExitQualification; // The core's exit qualification - UINT64 LastVmexitRip; // RIP in the current VM-exit - UINT64 VmxonRegionPhysicalAddress; // Vmxon region physical address - UINT64 VmxonRegionVirtualAddress; // VMXON region virtual address - UINT64 VmcsRegionPhysicalAddress; // VMCS region physical address - UINT64 VmcsRegionVirtualAddress; // VMCS region virtual address - UINT64 VmmStack; // Stack for VMM in VM-Exit State - UINT64 MsrBitmapVirtualAddress; // Msr Bitmap Virtual Address - UINT64 MsrBitmapPhysicalAddress; // Msr Bitmap Physical Address - UINT64 IoBitmapVirtualAddressA; // I/O Bitmap Virtual Address (A) - UINT64 IoBitmapPhysicalAddressA; // I/O Bitmap Physical Address (A) - UINT64 IoBitmapVirtualAddressB; // I/O Bitmap Virtual Address (B) - UINT64 IoBitmapPhysicalAddressB; // I/O Bitmap Physical Address (B) - UINT32 PendingExternalInterrupts[PENDING_INTERRUPTS_BUFFER_CAPACITY]; // This list holds a buffer for external-interrupts that are in pending state due to the external-interrupt - // blocking and waits for interrupt-window exiting - // From hvpp : - // Pending interrupt queue (FIFO). - // Make storage for up-to 64 pending interrupts. - // In practice I haven't seen more than 2 pending interrupts. - VMX_VMXOFF_STATE VmxoffState; // Shows the vmxoff state of the guest - NMI_BROADCASTING_STATE NmiBroadcastingState; // Shows the state of NMI broadcasting - VM_EXIT_TRANSPARENCY TransparencyState; // The state of the debugger in transparent-mode - PEPT_HOOKED_PAGE_DETAIL MtfEptHookRestorePoint; // It shows the detail of the hooked paged that should be restore in MTF vm-exit + BOOLEAN IsOnVmxRootMode; // Detects whether the current logical core is on Executing on VMX Root Mode + BOOLEAN IncrementRip; // Checks whether it has to redo the previous instruction or not (it used mainly in Ept routines) + BOOLEAN HasLaunched; // Indicate whether the core is virtualized or not + BOOLEAN IgnoreMtfUnset; // Indicate whether the core should ignore unsetting the MTF or not + 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 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 + PUINT64 PmlBufferAddress; // Address of buffer used for dirty logging + BOOLEAN Test; // Used for test purposes + UINT64 TestNumber; // Used for test purposes (Number) + GUEST_REGS * Regs; // The virtual processor's general-purpose registers + GUEST_XMM_REGS * XmmRegs; // The virtual processor's XMM registers + UINT32 CoreId; // The core's unique identifier + UINT32 ExitReason; // The core's exit reason + UINT32 ExitQualification; // The core's exit qualification + UINT64 LastVmexitRip; // RIP in the current VM-exit + UINT64 VmxonRegionPhysicalAddress; // Vmxon region physical address + UINT64 VmxonRegionVirtualAddress; // VMXON region virtual address + UINT64 VmcsRegionPhysicalAddress; // VMCS region physical address + UINT64 VmcsRegionVirtualAddress; // VMCS region virtual address + UINT64 VmmStack; // Stack for VMM in VM-Exit State + UINT64 MsrBitmapVirtualAddress; // Msr Bitmap Virtual Address + UINT64 MsrBitmapPhysicalAddress; // Msr Bitmap Physical Address + UINT64 IoBitmapVirtualAddressA; // I/O Bitmap Virtual Address (A) + UINT64 IoBitmapPhysicalAddressA; // I/O Bitmap Physical Address (A) + UINT64 IoBitmapVirtualAddressB; // I/O Bitmap Virtual Address (B) + UINT64 IoBitmapPhysicalAddressB; // I/O Bitmap Physical Address (B) + UINT32 QueuedNmi; // Queued NMIs + UINT32 PendingExternalInterrupts[PENDING_INTERRUPTS_BUFFER_CAPACITY]; // This list holds a buffer for external-interrupts that are in pending state due to the external-interrupt + // blocking and waits for interrupt-window exiting + // From hvpp : + // Pending interrupt queue (FIFO). + // Make storage for up-to 64 pending interrupts. + // In practice I haven't seen more than 2 pending interrupts. + VMX_VMXOFF_STATE VmxoffState; // Shows the vmxoff state of the guest + NMI_BROADCASTING_STATE NmiBroadcastingState; // Shows the state of NMI broadcasting + VM_EXIT_TRANSPARENCY TransparencyState; // The state of the debugger in transparent-mode + PEPT_HOOKED_PAGE_DETAIL MtfEptHookRestorePoint; // It shows the detail of the hooked paged that should be restore in MTF vm-exit + UINT8 LastExceptionOccurredInHost; // The vector of last exception occurred in host + UINT64 HostIdt; // host Interrupt Descriptor Table (actual type is SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64*) + UINT64 HostGdt; // host Global Descriptor Table (actual type is SEGMENT_DESCRIPTOR_32* or SEGMENT_DESCRIPTOR_64*) + UINT64 HostTss; // host Task State Segment (actual type is TASK_STATE_SEGMENT_64*) + UINT64 HostInterruptStack; // host interrupt RSP // // EPT Descriptors diff --git a/hyperdbg/hprdbghv/header/common/Trace.h b/hyperdbg/hyperhv/header/common/Trace.h similarity index 100% rename from hyperdbg/hprdbghv/header/common/Trace.h rename to hyperdbg/hyperhv/header/common/Trace.h diff --git a/hyperdbg/hprdbghv/header/common/UnloadDll.h b/hyperdbg/hyperhv/header/common/UnloadDll.h similarity index 75% rename from hyperdbg/hprdbghv/header/common/UnloadDll.h rename to hyperdbg/hyperhv/header/common/UnloadDll.h index c6388ac7..2dc53a57 100644 --- a/hyperdbg/hprdbghv/header/common/UnloadDll.h +++ b/hyperdbg/hyperhv/header/common/UnloadDll.h @@ -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); diff --git a/hyperdbg/hprdbghv/header/devices/Apic.h b/hyperdbg/hyperhv/header/devices/Apic.h similarity index 75% rename from hyperdbg/hprdbghv/header/devices/Apic.h rename to hyperdbg/hyperhv/header/devices/Apic.h index 341d2b96..a33598ea 100644 --- a/hyperdbg/hprdbghv/header/devices/Apic.h +++ b/hyperdbg/hyperhv/header/devices/Apic.h @@ -26,7 +26,7 @@ #define APIC_LVR 0x30 #define APIC_LVR_MASK 0xFF00FF -#define GET_APIC_VERSION(x) ((x)&0xFFu) +#define GET_APIC_VERSION(x) ((x) & 0xFFu) #define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFFu) #define APIC_INTEGRATED(x) (1) @@ -142,6 +142,65 @@ #define APIC_EILVT3 0x530 #define APIC_BASE_MSR 0x800 +#define APIC_BASE_MSR 0x800 + +////////////////////////////////////////////////// +// I/O APIC // +////////////////////////////////////////////////// + +typedef struct _IO_APIC_ENT +{ + UINT32 Reg; + UINT32 Pad[3]; + UINT32 Data; + +} IO_APIC_ENT, *PIO_APIC_ENT; + +#define IO_APIC_DEFAULT_BASE_ADDR 0xFEC00000 // Default physical address of IO APIC + +#define IOAPIC_APPEND_QWORD(hi, lo) (((UINT64)(hi) << 32) | (UINT64)(lo)) +#define IOAPIC_LOW_DWORD(x) ((UINT32)(x)) +#define IOAPIC_HIGH_DWORD(x) ((UINT32)((x) >> 32)) + +#define IOAPIC_REDTBL(x) (0x10 + (x) * 2) +#define IOAPIC_REDTBL_MAX (24) + +#define LU_SIZE 0x400 + +#define LU_ID_REGISTER 0x00000020 +#define LU_VERS_REGISTER 0x00000030 +#define LU_TPR 0x00000080 +#define LU_APR 0x00000090 +#define LU_PPR 0x000000A0 +#define LU_EOI 0x000000B0 +#define LU_REMOTE_REGISTER 0x000000C0 + +#define LU_DEST 0x000000D0 +#define LU_DEST_FORMAT 0x000000E0 + +#define LU_SPURIOUS_VECTOR 0x000000F0 +#define LU_FAULT_VECTOR 0x00000370 + +#define LU_ISR_0 0x00000100 +#define LU_TMR_0 0x00000180 +#define LU_IRR_0 0x00000200 +#define LU_ERROR_STATUS 0x00000280 +#define LU_INT_CMD_LOW 0x00000300 +#define LU_INT_CMD_HIGH 0x00000310 +#define LU_TIMER_VECTOR 0x00000320 +#define LU_INT_VECTOR_0 0x00000350 +#define LU_INT_VECTOR_1 0x00000360 +#define LU_INITIAL_COUNT 0x00000380 +#define LU_CURRENT_COUNT 0x00000390 +#define LU_DIVIDER_CONFIG 0x000003E0 + +#define IO_REGISTER_SELECT 0x00000000 +#define IO_REGISTER_WINDOW 0x00000010 + +#define IO_ID_REGISTER 0x00000000 +#define IO_VERS_REGISTER 0x00000001 +#define IO_ARB_ID_REGISTER 0x00000002 +#define IO_REDIR_BASE 0x00000010 ////////////////////////////////////////////////// // Functions // @@ -153,6 +212,12 @@ ApicInitialize(); VOID ApicUninitialize(); +BOOLEAN +ApicStoreLocalApicFields(PLAPIC_PAGE LApicBuffer, PBOOLEAN IsUsingX2APIC); + +BOOLEAN +ApicStoreIoApicFields(IO_APIC_ENTRY_PACKETS * IoApicPackets); + VOID ApicSelfIpi(UINT32 Vector); diff --git a/hyperdbg/hyperhv/header/devices/Pci.h b/hyperdbg/hyperhv/header/devices/Pci.h new file mode 100644 index 00000000..a14a658d --- /dev/null +++ b/hyperdbg/hyperhv/header/devices/Pci.h @@ -0,0 +1,29 @@ +/** + * @file Pci.c + * @author Bjrn Ruytenberg (bjorn@bjornweb.nl) + * @brief Headers related to interacting with PCI(e) fabric + * @details + * @version 0.10.3 + * @date 2024-11-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once +#include "pch.h" + +////////////////////////////////////////////////// +// Definition // +////////////////////////////////////////////////// + +#define CFGADR 0xCF8 +#define CFGDAT 0xCFC + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +QWORD +PciReadCam(WORD Bus, WORD Device, WORD Function, BYTE Offset, UINT8 Width); +BOOLEAN +PciWriteCam(WORD Bus, WORD Device, WORD Function, BYTE Offset, UINT8 Width, QWORD Value); diff --git a/hyperdbg/hprdbghv/header/disassembler/Disassembler.h b/hyperdbg/hyperhv/header/disassembler/Disassembler.h similarity index 100% rename from hyperdbg/hprdbghv/header/disassembler/Disassembler.h rename to hyperdbg/hyperhv/header/disassembler/Disassembler.h diff --git a/hyperdbg/hprdbghv/header/features/CompatibilityChecks.h b/hyperdbg/hyperhv/header/features/CompatibilityChecks.h similarity index 86% rename from hyperdbg/hprdbghv/header/features/CompatibilityChecks.h rename to hyperdbg/hyperhv/header/features/CompatibilityChecks.h index 52bf74e2..a7b4baa1 100644 --- a/hyperdbg/hprdbghv/header/features/CompatibilityChecks.h +++ b/hyperdbg/hyperhv/header/features/CompatibilityChecks.h @@ -27,6 +27,8 @@ typedef struct _COMPATIBILITY_CHECKS_STATUS BOOLEAN PmlSupport; // check Page Modification Logging (PML) support BOOLEAN ModeBasedExecutionSupport; // check for mode based execution support (processors after Kaby Lake release will support this feature) BOOLEAN ExecuteOnlySupport; // Support for execute-only pages (indicating that data accesses are not allowed while instruction fetches are allowed) + BOOLEAN CetIbtSupport; // CET IBT support (indicating that indirect branch tracking is supported) + BOOLEAN CetShadowStackSupport; // CET shadow stack support (indicating that shadow stacks are supported) UINT32 VirtualAddressWidth; // Virtual address width for x86 processors UINT32 PhysicalAddressWidth; // Physical address width for x86 processors diff --git a/hyperdbg/hprdbghv/header/features/DirtyLogging.h b/hyperdbg/hyperhv/header/features/DirtyLogging.h similarity index 100% rename from hyperdbg/hprdbghv/header/features/DirtyLogging.h rename to hyperdbg/hyperhv/header/features/DirtyLogging.h diff --git a/hyperdbg/hprdbghv/header/globals/GlobalVariableManagement.h b/hyperdbg/hyperhv/header/globals/GlobalVariableManagement.h similarity index 100% rename from hyperdbg/hprdbghv/header/globals/GlobalVariableManagement.h rename to hyperdbg/hyperhv/header/globals/GlobalVariableManagement.h diff --git a/hyperdbg/hprdbghv/header/globals/GlobalVariables.h b/hyperdbg/hyperhv/header/globals/GlobalVariables.h similarity index 81% rename from hyperdbg/hprdbghv/header/globals/GlobalVariables.h rename to hyperdbg/hyperhv/header/globals/GlobalVariables.h index 85c720fd..b0b71f10 100644 --- a/hyperdbg/hprdbghv/header/globals/GlobalVariables.h +++ b/hyperdbg/hyperhv/header/globals/GlobalVariables.h @@ -49,12 +49,6 @@ MEMORY_MAPPER_ADDRESSES * g_MemoryMapper; */ EPT_STATE * g_EptState; -/** - * @brief holds the measurements from the user-mode and kernel-mode - * - */ -TRANSPARENCY_MEASUREMENTS * g_TransparentModeMeasurements; - /** * @brief List header of hidden hooks detour * @@ -68,18 +62,17 @@ LIST_ENTRY g_EptHook2sDetourListHead; BOOLEAN g_IsEptHook2sDetourListInitialized; /** - * @brief Shows whether the debugger transparent mode - * is enabled (true) or not (false) - * - */ -BOOLEAN g_TransparentMode; - -/** - * @brief APIC Base + * @brief Local APIC Base * */ VOID * g_ApicBase; +/** + * @brief I/O APIC Base + * + */ +VOID * g_IoApicBase; + /** * @brief check for broadcasting NMI mechanism support and its * initialization @@ -106,19 +99,37 @@ BOOLEAN g_IsUnsafeSyscallOrSysretHandling; */ UINT64 * g_MsrBitmapInvalidMsrs; -/** - * @brief Whether the page-fault and cr3 vm-exits in vmx-root should check - * the #PFs or the PML4.Supervisor with user debugger or not - * - */ -BOOLEAN g_CheckPageFaultsAndMov2Cr3VmexitsWithUserDebugger; - /** * @brief Enable interception of Cr3 for Mode-based Execution detection * */ BOOLEAN g_ModeBasedExecutionControlState; +/** + * @brief State of syscall callback trap flags + * + */ +SYSCALL_CALLBACK_TRAP_FLAG_STATE * g_SyscallCallbackTrapFlagState; + +/** + * @brief Shows whether the syscall callback is enabled or not + * + */ +BOOLEAN g_SyscallCallbackStatus; + +/** + * @brief Target hook address for the system call handler + * + */ +PVOID g_SystemCallHookAddress; + +/** + * @brief Shows whether the footprints (anti-debugging and + * anti-hypervisor) should be checked or not + * + */ +BOOLEAN g_CheckForFootprints; + ////////////////////////////////////////////////// // Global Variable (debugger-related) // ////////////////////////////////////////////////// @@ -137,6 +148,8 @@ BOOLEAN g_TriggerEventForVmcalls; */ BOOLEAN g_TriggerEventForCpuids; +BOOLEAN g_TriggerEventForXsetbvs; + ////////////////////////////////////////////////// // Global Variable (Execution Trap) // ////////////////////////////////////////////////// @@ -172,7 +185,7 @@ BOOLEAN g_IsInterceptingInstructions; ////////////////////////////////////////////////// /** - * @brief Shows whether the the VMM is waiting to inject a page-fault + * @brief Shows whether the VMM is waiting to inject a page-fault * or not * */ @@ -195,3 +208,13 @@ UINT64 g_PageFaultInjectionAddressTo; * */ UINT32 g_PageFaultInjectionErrorCode; + +/** + * @brief Whether VPID is supported or not + */ +BOOLEAN g_IsVpidSupported; + +/** + * @brief Whether the top level hypervisor is Hyper-V or not + */ +BOOLEAN g_IsTopLevelHypervisorHyperV; diff --git a/hyperdbg/hprdbghv/header/hooks/ExecTrap.h b/hyperdbg/hyperhv/header/hooks/ExecTrap.h similarity index 84% rename from hyperdbg/hprdbghv/header/hooks/ExecTrap.h rename to hyperdbg/hyperhv/header/hooks/ExecTrap.h index 64803eb4..43f4a96a 100644 --- a/hyperdbg/hprdbghv/header/hooks/ExecTrap.h +++ b/hyperdbg/hyperhv/header/hooks/ExecTrap.h @@ -22,6 +22,16 @@ */ #define MAXIMUM_NUMBER_OF_PROCESSES_FOR_USER_KERNEL_EXEC_THREAD 100 +////////////////////////////////////////////////// +// Locks // +////////////////////////////////////////////////// + +/** + * @brief The lock for modifying the list of processes for user-mode, kernel-mode execution traps + * + */ +volatile LONG ExecTrapProcessListLock; + ////////////////////////////////////////////////// // Structures // ////////////////////////////////////////////////// @@ -62,6 +72,9 @@ ExecTrapUninitialize(); BOOLEAN ExecTrapInitialize(); +VOID +ExecTrapApplyMbecConfiguratinFromKernelSide(VIRTUAL_MACHINE_STATE * VCpu); + BOOLEAN ExecTrapHandleEptViolationVmexit(VIRTUAL_MACHINE_STATE * VCpu, VMX_EXIT_QUALIFICATION_EPT_VIOLATION * ViolationQualification); diff --git a/hyperdbg/hprdbghv/header/hooks/Hooks.h b/hyperdbg/hyperhv/header/hooks/Hooks.h similarity index 85% rename from hyperdbg/hprdbghv/header/hooks/Hooks.h rename to hyperdbg/hyperhv/header/hooks/Hooks.h index 152a8964..aad7adcb 100644 --- a/hyperdbg/hprdbghv/header/hooks/Hooks.h +++ b/hyperdbg/hyperhv/header/hooks/Hooks.h @@ -11,6 +11,22 @@ */ #pragma once +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +/** + * @brief Details of detours style EPT hooks + * + */ +typedef struct _HIDDEN_HOOKS_DETOUR_DETAILS +{ + LIST_ENTRY OtherHooksList; + PVOID HookedFunctionAddress; + PVOID ReturnAddress; + +} HIDDEN_HOOKS_DETOUR_DETAILS, *PHIDDEN_HOOKS_DETOUR_DETAILS; + ////////////////////////////////////////////////// // Syscall Hook // ////////////////////////////////////////////////// @@ -46,105 +62,10 @@ #define IMAGE_VXD_SIGNATURE 0x454C // LE #define IMAGE_NT_SIGNATURE 0x00004550 // PE00 -////////////////////////////////////////////////// -// Structure // -////////////////////////////////////////////////// - -/** - * @brief SSDT structure - * - */ -typedef struct _SSDTStruct -{ - LONG * pServiceTable; - PVOID pCounterTable; -#ifdef _WIN64 - UINT64 NumberOfServices; -#else - ULONG NumberOfServices; -#endif - PCHAR pArgumentTable; -} SSDTStruct, *PSSDTStruct; - -/** - * @brief Details of detours style EPT hooks - * - */ -typedef struct _HIDDEN_HOOKS_DETOUR_DETAILS -{ - LIST_ENTRY OtherHooksList; - PVOID HookedFunctionAddress; - PVOID ReturnAddress; - -} HIDDEN_HOOKS_DETOUR_DETAILS, *PHIDDEN_HOOKS_DETOUR_DETAILS; - -/** - * @brief Module entry - * - */ -typedef struct _SYSTEM_MODULE_ENTRY -{ - HANDLE Section; - PVOID MappedBase; - PVOID ImageBase; - ULONG ImageSize; - ULONG Flags; - UINT16 LoadOrderIndex; - UINT16 InitOrderIndex; - UINT16 LoadCount; - UINT16 OffsetToFileName; - UCHAR FullPathName[256]; -} SYSTEM_MODULE_ENTRY, *PSYSTEM_MODULE_ENTRY; - -/** - * @brief System Information for modules - * - */ -typedef struct _SYSTEM_MODULE_INFORMATION -{ - ULONG Count; - SYSTEM_MODULE_ENTRY Module; - -} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; - -/** - * @brief System information class - * - */ -typedef enum _SYSTEM_INFORMATION_CLASS -{ - SystemModuleInformation = 11, - SystemKernelDebuggerInformation = 35 -} SYSTEM_INFORMATION_CLASS, - *PSYSTEM_INFORMATION_CLASS; - -typedef NTSTATUS(NTAPI * ZWQUERYSYSTEMINFORMATION)( - IN SYSTEM_INFORMATION_CLASS SystemInformationClass, - OUT PVOID SystemInformation, - IN ULONG SystemInformationLength, - OUT PULONG ReturnLength OPTIONAL); - -NTSTATUS(*NtCreateFileOrig) -( - PHANDLE FileHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - PIO_STATUS_BLOCK IoStatusBlock, - PLARGE_INTEGER AllocationSize, - ULONG FileAttributes, - ULONG ShareAccess, - ULONG CreateDisposition, - ULONG CreateOptions, - PVOID EaBuffer, - ULONG EaLength); - ////////////////////////////////////////////////// // Syscall Hooks Functions // ////////////////////////////////////////////////// -VOID -SyscallHookTest(); - VOID SyscallHookConfigureEFER(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN EnableEFERSyscallHook); @@ -334,6 +255,16 @@ EptHookRestoreAllHooksToOriginalEntry(VIRTUAL_MACHINE_STATE * VCpu); VOID EptHookUnHookAll(); +/** + * @brief Remove all hooks from the hooked pages by the given hooking tag + * @details Should be called from Vmx Non-root + * + * @param HookingTag The hooking tag to unhook + * @return BOOLEAN If unhook was successful it returns true or if it was not successful returns false + */ +BOOLEAN +EptHookUnHookAllByHookingTag(UINT64 HookingTag); + /** * @brief Remove single hook from the hooked pages list and invalidate TLB * From VMX non-root mode @@ -348,6 +279,17 @@ EptHookUnHookSingleAddress(UINT64 VirtualAddress, UINT64 PhysAddress, UINT32 ProcessId); +/** + * @brief Remove single hook from the hooked pages by the given hooking tag + * @details Should be called from Vmx root-mode + * + * @param HookingTag The hooking tag to unhook + * @return BOOLEAN If unhook was successful it returns true or if it was not successful returns false + */ +BOOLEAN +EptHookUnHookSingleHookByHookingTagFromVmxRoot(UINT64 HookingTag, + EPT_SINGLE_HOOK_UNHOOKING_DETAILS * TargetUnhookingDetails); + /** * @brief Remove single hook from the hooked pages list and invalidate TLB * From VMX root-mode diff --git a/hyperdbg/hprdbghv/header/hooks/ModeBasedExecHook.h b/hyperdbg/hyperhv/header/hooks/ModeBasedExecHook.h similarity index 100% rename from hyperdbg/hprdbghv/header/hooks/ModeBasedExecHook.h rename to hyperdbg/hyperhv/header/hooks/ModeBasedExecHook.h diff --git a/hyperdbg/hyperhv/header/hooks/SyscallCallback.h b/hyperdbg/hyperhv/header/hooks/SyscallCallback.h new file mode 100644 index 00000000..efbac8bc --- /dev/null +++ b/hyperdbg/hyperhv/header/hooks/SyscallCallback.h @@ -0,0 +1,101 @@ +/** + * @file SyscallHook.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @author jtaw5649 + * @brief Header for syscall hook callbacks + * @details + * + * @version 0.14 + * @date 2025-06-07 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +////////////////////////////////////////////////// +// Locks // +////////////////////////////////////////////////// + +/** + * @brief The lock for modifying list of process/thread for syscall callback trap flags + * + */ +volatile LONG SyscallCallbackModeTrapListLock; + +////////////////////////////////////////////////// +// Definitions // +////////////////////////////////////////////////// + +/** + * @brief maximum number of thread/process ids to be allocated for keeping track of + * of the trap flag + * + */ +#define MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_SYSCALL_CALLBACK_TRAPS 500 + +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +/** + * @brief The thread/process information + * + */ +typedef struct _SYSCALL_CALLBACK_PROCESS_THREAD_INFORMATION +{ + union + { + UINT64 asUInt; + + struct + { + UINT32 ProcessId; + UINT32 ThreadId; + } Fields; + }; + +} SYSCALL_CALLBACK_PROCESS_THREAD_INFORMATION, *PSYSCALL_CALLBACK_PROCESS_THREAD_INFORMATION; + +/** + * @brief The threads that we expect to get the trap flag + * + * @details Used for keeping track of the threads that we expect to get the trap flag + * + */ +typedef struct _SYSCALL_CALLBACK_TRAP_FLAG_STATE +{ + UINT32 NumberOfItems; + SYSCALL_CALLBACK_PROCESS_THREAD_INFORMATION ThreadInformation[MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_SYSCALL_CALLBACK_TRAPS]; + UINT64 Context[MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_SYSCALL_CALLBACK_TRAPS]; + SYSCALL_CALLBACK_CONTEXT_PARAMS Params[MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_SYSCALL_CALLBACK_TRAPS]; + +} SYSCALL_CALLBACK_TRAP_FLAG_STATE, *PSYSCALL_CALLBACK_TRAP_FLAG_STATE; + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +SyscallCallbackInitialize(); + +BOOLEAN +SyscallCallbackIsInitialized(); + +BOOLEAN +SyscallCallbackUninitialize(); + +BOOLEAN +SyscallCallbackSetTrapFlagAfterSyscall(GUEST_REGS * Regs, + UINT32 ProcessId, + UINT32 ThreadId, + UINT64 Context, + SYSCALL_CALLBACK_CONTEXT_PARAMS * Params); + +BOOLEAN +SyscallCallbackCheckAndHandleAfterSyscallTrapFlags(VIRTUAL_MACHINE_STATE * VCpu, + UINT32 ProcessId, + UINT32 ThreadId); + +VOID +SyscallCallbackHandleSystemCallHook(VIRTUAL_MACHINE_STATE * VCpu); diff --git a/hyperdbg/hprdbghv/header/interface/Callback.h b/hyperdbg/hyperhv/header/interface/Callback.h similarity index 60% rename from hyperdbg/hprdbghv/header/interface/Callback.h rename to hyperdbg/hyperhv/header/interface/Callback.h index d5754a21..294cb22a 100644 --- a/hyperdbg/hprdbghv/header/interface/Callback.h +++ b/hyperdbg/hyperhv/header/interface/Callback.h @@ -12,34 +12,6 @@ */ #pragma once -// -// Log Callbacks -// - -BOOLEAN -LogCallbackPrepareAndSendMessageToQueue(UINT32 OperationCode, - BOOLEAN IsImmediateMessage, - BOOLEAN ShowCurrentSystemTime, - BOOLEAN Priority, - const char * Fmt, - ...); - -BOOLEAN -LogCallbackSendMessageToQueue(UINT32 OperationCode, - BOOLEAN IsImmediateMessage, - CHAR * LogMessage, - UINT32 BufferLen, - BOOLEAN Priority); - -BOOLEAN -LogCallbackCheckIfBufferIsFull(BOOLEAN Priority); - -BOOLEAN -LogCallbackSendBuffer(_In_ UINT32 OperationCode, - _In_reads_bytes_(BufferLength) PVOID Buffer, - _In_ UINT32 BufferLength, - _In_ BOOLEAN Priority); - // // VMM Callbacks // @@ -72,15 +44,21 @@ VmmCallbackUnhandledEptViolation(UINT32 CoreId, UINT64 ViolationQualification, UINT64 GuestPhysicalAddr); +BOOLEAN +VmmCallbackHandleMtfCallback(UINT32 CoreId); + VOID VmmCallbackSetLastError(UINT32 LastError); -VOID -VmmCallbackRegisteredMtfHandler(UINT32 CoreId); - VOID VmmCallbackNmiBroadcastRequestHandler(UINT32 CoreId, BOOLEAN IsOnVmxNmiHandler); +// +// HyperTrace Callbacks +// +BOOLEAN +HyperTraceCallbackLbrIsSupported(UINT32 * Capacity, BOOLEAN * IsArchLbr); + // // Debugging Callbacks // @@ -92,9 +70,26 @@ BOOLEAN DebuggingCallbackHandleDebugBreakpointException(UINT32 CoreId); BOOLEAN -DebuggingCallbackConditionalPageFaultException(UINT32 CoreId, - UINT64 Address, - UINT32 PageFaultErrorCode); +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 @@ -102,6 +97,3 @@ DebuggingCallbackConditionalPageFaultException(UINT32 CoreId, VOID InterceptionCallbackTriggerCr3ProcessChange(UINT32 CoreId); - -VOID -InterceptionCallbackCr3VmexitsForThreadInterception(UINT32 CoreId, CR3_TYPE NewCr3); diff --git a/hyperdbg/hprdbghv/header/interface/DirectVmcall.h b/hyperdbg/hyperhv/header/interface/DirectVmcall.h similarity index 100% rename from hyperdbg/hprdbghv/header/interface/DirectVmcall.h rename to hyperdbg/hyperhv/header/interface/DirectVmcall.h diff --git a/hyperdbg/hprdbghv/header/interface/Dispatch.h b/hyperdbg/hyperhv/header/interface/Dispatch.h similarity index 96% rename from hyperdbg/hprdbghv/header/interface/Dispatch.h rename to hyperdbg/hyperhv/header/interface/Dispatch.h index 7ec91d77..f35ed6ef 100644 --- a/hyperdbg/hprdbghv/header/interface/Dispatch.h +++ b/hyperdbg/hyperhv/header/interface/Dispatch.h @@ -25,6 +25,9 @@ DispatchEventEferSyscall(VIRTUAL_MACHINE_STATE * VCpu); VOID DispatchEventCpuid(VIRTUAL_MACHINE_STATE * VCpu); +VOID +DispatchEventXsetbv(VIRTUAL_MACHINE_STATE * VCpu); + VOID DispatchEventTsc(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN IsRdtscp); @@ -32,7 +35,7 @@ VOID DispatchEventVmcall(VIRTUAL_MACHINE_STATE * VCpu); VOID -DispatchEventMode(VIRTUAL_MACHINE_STATE * VCpu, DEBUGGER_EVENT_MODE_TYPE TargetMode, BOOLEAN HandleState); +DispatchEventMode(VIRTUAL_MACHINE_STATE * VCpu, DEBUGGER_EVENT_MODE_TYPE TargetMode); VOID DispatchEventMovToCr3(VIRTUAL_MACHINE_STATE * VCpu); diff --git a/hyperdbg/hprdbghv/header/memory/AddressCheck.h b/hyperdbg/hyperhv/header/memory/AddressCheck.h similarity index 100% rename from hyperdbg/hprdbghv/header/memory/AddressCheck.h rename to hyperdbg/hyperhv/header/memory/AddressCheck.h diff --git a/hyperdbg/hprdbghv/header/memory/Conversion.h b/hyperdbg/hyperhv/header/memory/Conversion.h similarity index 100% rename from hyperdbg/hprdbghv/header/memory/Conversion.h rename to hyperdbg/hyperhv/header/memory/Conversion.h diff --git a/hyperdbg/hprdbghv/header/memory/Layout.h b/hyperdbg/hyperhv/header/memory/Layout.h similarity index 88% rename from hyperdbg/hprdbghv/header/memory/Layout.h rename to hyperdbg/hyperhv/header/memory/Layout.h index f1106df9..7fa322a4 100644 --- a/hyperdbg/hprdbghv/header/memory/Layout.h +++ b/hyperdbg/hyperhv/header/memory/Layout.h @@ -15,8 +15,9 @@ // Functions // ////////////////////////////////////////////////// -CR3_TYPE -LayoutGetCr3ByProcessId(_In_ UINT32 ProcessId); +// +// Some functions are exported on VMM exports +// UINT64 LayoutGetSystemDirectoryTableBase(); diff --git a/hyperdbg/hprdbghv/header/memory/MemoryMapper.h b/hyperdbg/hyperhv/header/memory/MemoryMapper.h similarity index 94% rename from hyperdbg/hprdbghv/header/memory/MemoryMapper.h rename to hyperdbg/hyperhv/header/memory/MemoryMapper.h index 63a43ebb..decf89d6 100644 --- a/hyperdbg/hprdbghv/header/memory/MemoryMapper.h +++ b/hyperdbg/hyperhv/header/memory/MemoryMapper.h @@ -35,6 +35,8 @@ typedef enum _MEMORY_MAPPER_WRAPPER_FOR_MEMORY_READ { MEMORY_MAPPER_WRAPPER_READ_PHYSICAL_MEMORY, MEMORY_MAPPER_WRAPPER_READ_VIRTUAL_MEMORY, + MEMORY_MAPPER_WRAPPER_READ_VIRTUAL_MEMORY_UNSAFE + } MEMORY_MAPPER_WRAPPER_FOR_MEMORY_READ; /** @@ -45,7 +47,7 @@ typedef enum _MEMORY_MAPPER_WRAPPER_FOR_MEMORY_WRITE { MEMORY_MAPPER_WRAPPER_WRITE_PHYSICAL_MEMORY, MEMORY_MAPPER_WRAPPER_WRITE_VIRTUAL_MEMORY_SAFE, - MEMORY_MAPPER_WRAPPER_WRITE_VIRTUAL_MEMORY_UNSAFE, + MEMORY_MAPPER_WRAPPER_WRITE_VIRTUAL_MEMORY_UNSAFE } MEMORY_MAPPER_WRAPPER_FOR_MEMORY_WRITE; @@ -163,14 +165,16 @@ MemoryMapperWriteMemorySafeByPte(_In_ PVOID SourceVA, static UINT64 MemoryMapperReadMemorySafeByPhysicalAddressWrapperAddressMaker( _In_ MEMORY_MAPPER_WRAPPER_FOR_MEMORY_READ TypeOfRead, - _In_ UINT64 AddressToRead); + _In_ UINT64 AddressToRead, + _In_ UINT32 TargetProcessId); static BOOLEAN -MemoryMapperReadMemorySafeByPhysicalAddressWrapper( +MemoryMapperReadMemorySafeWrapper( _In_ MEMORY_MAPPER_WRAPPER_FOR_MEMORY_READ TypeOfRead, _In_ UINT64 AddressToRead, _Inout_ UINT64 BufferToSaveMemory, - _In_ SIZE_T SizeToRead); + _In_ SIZE_T SizeToRead, + _In_ UINT32 TargetProcessId); static UINT64 MemoryMapperWriteMemorySafeWrapperAddressMaker(_In_ MEMORY_MAPPER_WRAPPER_FOR_MEMORY_WRITE TypeOfWrite, diff --git a/hyperdbg/hyperhv/header/memory/Segmentation.h b/hyperdbg/hyperhv/header/memory/Segmentation.h new file mode 100644 index 00000000..78987058 --- /dev/null +++ b/hyperdbg/hyperhv/header/memory/Segmentation.h @@ -0,0 +1,60 @@ +/** + * @file Segmentation.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Functions for handling memory segmentations + * @details + * @version 0.9 + * @date 2024-06-03 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Constants // +////////////////////////////////////////////////// + +/** + * @brief Whether the hypervisor should use the default OS's + * GDT as the host GDT in VMCS or not + * + */ +#define USE_DEFAULT_OS_GDT_AS_HOST_GDT FALSE + +/** + * @brief Maximum number of entries in GDT + * + */ +#define HOST_GDT_DESCRIPTOR_COUNT 10 // approximately + +/** + * @brief Size of host interrupt stack + * + */ +#define HOST_INTERRUPT_STACK_SIZE 4 * PAGE_SIZE + +/** + * @brief Use Interrupt Stack Table (IST1..IST7) + * + */ +#define USE_INTERRUPT_STACK_TABLE FALSE + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +_Success_(return) +BOOLEAN +SegmentGetDescriptor(_In_ PUCHAR GdtBase, + _In_ UINT16 Selector, + _Out_ PVMX_SEGMENT_SELECTOR SegmentSelector); + +VOID +SegmentPrepareHostGdt( + SEGMENT_DESCRIPTOR_32 * OsGdtBase, + UINT16 OsGdtLimit, + UINT16 TrSelector, + UINT64 HostStack, + SEGMENT_DESCRIPTOR_32 * AllocatedHostGdt, + TASK_STATE_SEGMENT_64 * AllocatedHostTss); diff --git a/hyperdbg/hprdbghv/header/memory/SwitchLayout.h b/hyperdbg/hyperhv/header/memory/SwitchLayout.h similarity index 100% rename from hyperdbg/hprdbghv/header/memory/SwitchLayout.h rename to hyperdbg/hyperhv/header/memory/SwitchLayout.h diff --git a/hyperdbg/hyperhv/header/mmio/MmioShadowing.h b/hyperdbg/hyperhv/header/mmio/MmioShadowing.h new file mode 100644 index 00000000..3aee98dd --- /dev/null +++ b/hyperdbg/hyperhv/header/mmio/MmioShadowing.h @@ -0,0 +1,16 @@ +/** + * @file MmioShadowing.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Header files for MMIO shadowing + * @details + * @version 0.14 + * @date 2025-02-24 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// diff --git a/hyperdbg/hyperhv/header/processor/Idt.h b/hyperdbg/hyperhv/header/processor/Idt.h new file mode 100644 index 00000000..996d8f84 --- /dev/null +++ b/hyperdbg/hyperhv/header/processor/Idt.h @@ -0,0 +1,49 @@ +/** + * @file Idt.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers relating to Interrupt Descriptor Table + * @details + * + * @version 0.11 + * @date 2024-11-20 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Definition // +////////////////////////////////////////////////// + +typedef union _KIDTENTRY64 +{ + struct + { + USHORT OffsetLow; + USHORT Selector; + USHORT IstIndex : 3; + USHORT Reserved0 : 5; + USHORT Type : 5; + USHORT Dpl : 2; + USHORT Present : 1; + USHORT OffsetMiddle; + ULONG OffsetHigh; + ULONG Reserved1; + }; + UINT64 Alignment; +} KIDTENTRY64, *PKIDTENTRY64; + +typedef struct _KDESCRIPTOR64 +{ + USHORT Pad[3]; + USHORT Limit; + PVOID Base; +} KDESCRIPTOR64, *PKDESCRIPTOR64; + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +IdtDumpInterruptEntries(); diff --git a/hyperdbg/hyperhv/header/processor/Smm.h b/hyperdbg/hyperhv/header/processor/Smm.h new file mode 100644 index 00000000..05946608 --- /dev/null +++ b/hyperdbg/hyperhv/header/processor/Smm.h @@ -0,0 +1,30 @@ +/** + * @file Smm.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers relating to operations related to System Management Mode (SMM) + * @details + * + * @version 0.15 + * @date 2025-08-02 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Constants // +////////////////////////////////////////////////// + +/** + * @brief SMI trigger port value + * + */ +#define SMI_TRIGGER_POWER_VALUE 0x80 + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +SmmPerformSmiOperation(SMI_OPERATION_PACKETS * SmiOperationRequest, BOOLEAN ApplyFromVmxRootMode); diff --git a/hyperdbg/hprdbghv/header/vmm/ept/Ept.h b/hyperdbg/hyperhv/header/vmm/ept/Ept.h similarity index 83% rename from hyperdbg/hprdbghv/header/vmm/ept/Ept.h rename to hyperdbg/hyperhv/header/vmm/ept/Ept.h index 333e89f4..b8a69750 100644 --- a/hyperdbg/hprdbghv/header/vmm/ept/Ept.h +++ b/hyperdbg/hyperhv/header/vmm/ept/Ept.h @@ -30,6 +30,18 @@ */ #define SIZE_2_MB ((SIZE_T)(512 * PAGE_SIZE)) +/** + * @brief Integer 1GB + * + */ +#define SIZE_1_GB ((SIZE_T)(512 * SIZE_2_MB)) + +/** + * @brief Integer 512GB + * + */ +#define SIZE_512_GB ((SIZE_T)(512 * SIZE_1_GB)) + /** * @brief Offset into the 1st paging structure (4096 byte) * @@ -115,15 +127,9 @@ typedef union _IA32_MTRR_FIXED_RANGE_TYPE */ typedef struct _EPT_STATE { - LIST_ENTRY HookedPagesList; // A list of the details about hooked pages - MTRR_RANGE_DESCRIPTOR MemoryRanges[NUM_MTRR_ENTRIES]; // Physical memory ranges described by the BIOS in the MTRRs. Used to build the EPT identity mapping. - UINT32 NumberOfEnabledMemoryRanges; // Number of memory ranges specified in MemoryRanges - PVMM_EPT_PAGE_TABLE EptPageTable; // Page table entries for EPT operation - PVMM_EPT_PAGE_TABLE ModeBasedUserDisabledEptPageTable; // Page table entries for hooks based on user-mode disabled mode-based execution control bits - PVMM_EPT_PAGE_TABLE ModeBasedKernelDisabledEptPageTable; // Page table entries for hooks based on kernel-mode disabled mode-based execution control bits - EPT_POINTER ModeBasedUserDisabledEptPointer; // Extended-Page-Table Pointer for user-disabled mode-based execution - EPT_POINTER ModeBasedKernelDisabledEptPointer; // Extended-Page-Table Pointer for kernel-disabled mode-based execution - EPT_POINTER ExecuteOnlyEptPointer; // Extended-Page-Table Pointer for execute-only execution + LIST_ENTRY HookedPagesList; // A list of the details about hooked pages + MTRR_RANGE_DESCRIPTOR MemoryRanges[NUM_MTRR_ENTRIES]; // Physical memory ranges described by the BIOS in the MTRRs. Used to build the EPT identity mapping. + UINT32 NumberOfEnabledMemoryRanges; // Number of memory ranges specified in MemoryRanges UINT8 DefaultMemoryType; } EPT_STATE, *PEPT_STATE; @@ -141,14 +147,14 @@ typedef struct _VMM_EPT_DYNAMIC_SPLIT EPT_PML1_ENTRY PML1[VMM_EPT_PML1E_COUNT]; /** - * @brief The pointer to the 2MB entry in the page table which this split is servicing. + * @brief The pointer to the 2MB entry in the page table which this split is servicing * */ union { PEPT_PML2_ENTRY Entry; PEPT_PML2_POINTER Pointer; - } u; + } Fields; /** * @brief Linked list entries for each dynamic split @@ -203,16 +209,16 @@ PVMM_EPT_PAGE_TABLE EptAllocateAndCreateIdentityPageTable(VOID); /** - * @brief Convert 2MB pages to 4KB pages + * @brief Convert large pages to 4KB pages * * @param EptPageTable - * @param PreAllocatedBuffer + * @param UsePreAllocatedBuffer * @param PhysicalAddress * @return BOOLEAN */ BOOLEAN EptSplitLargePage(PVMM_EPT_PAGE_TABLE EptPageTable, - PVOID PreAllocatedBuffer, + BOOLEAN UsePreAllocatedBuffer, SIZE_T PhysicalAddress); /** @@ -274,7 +280,7 @@ EptGetPml1OrPml2Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress, * @return VOID */ VOID -EptHandleMisconfiguration(VOID); + EptHandleMisconfiguration(VOID); /** * @brief This function set the specific PML1 entry in a spinlock protected area then diff --git a/hyperdbg/hprdbghv/header/vmm/ept/Invept.h b/hyperdbg/hyperhv/header/vmm/ept/Invept.h similarity index 93% rename from hyperdbg/hprdbghv/header/vmm/ept/Invept.h rename to hyperdbg/hyperhv/header/vmm/ept/Invept.h index 501b2262..a76bc8c5 100644 --- a/hyperdbg/hprdbghv/header/vmm/ept/Invept.h +++ b/hyperdbg/hyperhv/header/vmm/ept/Invept.h @@ -26,4 +26,4 @@ UCHAR EptInveptAllContexts(); UCHAR -EptInveptSingleContext(_In_ UINT64 EptPonter); +EptInveptSingleContext(_In_ UINT64 EptPointer); diff --git a/hyperdbg/hprdbghv/header/vmm/ept/Vpid.h b/hyperdbg/hyperhv/header/vmm/ept/Vpid.h similarity index 100% rename from hyperdbg/hprdbghv/header/vmm/ept/Vpid.h rename to hyperdbg/hyperhv/header/vmm/ept/Vpid.h diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/Counters.h b/hyperdbg/hyperhv/header/vmm/vmx/Counters.h similarity index 100% rename from hyperdbg/hprdbghv/header/vmm/vmx/Counters.h rename to hyperdbg/hyperhv/header/vmm/vmx/Counters.h diff --git a/hyperdbg/hyperhv/header/vmm/vmx/CrossVmcalls.h b/hyperdbg/hyperhv/header/vmm/vmx/CrossVmcalls.h new file mode 100644 index 00000000..a973f57d --- /dev/null +++ b/hyperdbg/hyperhv/header/vmm/vmx/CrossVmcalls.h @@ -0,0 +1,43 @@ +/** + * @file CrossVmcalls.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers relating to cross (standalone) VMCALLs + * @details + * @version 0.19 + * @date 2026-04-14 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +UINT64 +CrossVmcallGetDebugctlVmcallOnTargetCore(); + +UINT64 +CrossVmcallGetGuestIa32LbrCtlVmcallOnTargetCore(); + +VOID +CrossVmcallSetDebugctlVmcallOnTargetCore(UINT64 Value); + +VOID +CrossVmcallSetGuestIa32LbrCtlVmcallOnTargetCore(UINT64 Value); + +VOID +CrossVmcallSetLbrSelectVmcallOnTargetCore(UINT64 FilterOptions); + +VOID +CrossVmcallSetLoadDebugControlsVmcallOnTargetCore(BOOLEAN Set); + +VOID +CrossVmcallSetLoadGuestIa32LbrCtlVmcallOnTargetCore(BOOLEAN Set); + +VOID +CrossVmcallSetSaveDebugControlsVmcallOnTargetCore(BOOLEAN Set); + +VOID +CrossVmcallSetClearGuestIa32LbrCtlVmcallOnTargetCore(BOOLEAN Set); diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/Events.h b/hyperdbg/hyperhv/header/vmm/vmx/Events.h similarity index 98% rename from hyperdbg/hprdbghv/header/vmm/vmx/Events.h rename to hyperdbg/hyperhv/header/vmm/vmx/Events.h index 21234310..9f49e9c1 100644 --- a/hyperdbg/hprdbghv/header/vmm/vmx/Events.h +++ b/hyperdbg/hyperhv/header/vmm/vmx/Events.h @@ -119,6 +119,9 @@ EventInjectGeneralProtection(); VOID EventInjectUndefinedOpcode(VIRTUAL_MACHINE_STATE * VCpu); +VOID +EventInjectNmi(VIRTUAL_MACHINE_STATE * VCpu); + VOID EventInjectPageFaultWithoutErrorCode(UINT64 PageFaultAddress); diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/Hv.h b/hyperdbg/hyperhv/header/vmm/vmx/Hv.h similarity index 73% rename from hyperdbg/hprdbghv/header/vmm/vmx/Hv.h rename to hyperdbg/hyperhv/header/vmm/vmx/Hv.h index fa9fbe18..2aa85bea 100644 --- a/hyperdbg/hprdbghv/header/vmm/vmx/Hv.h +++ b/hyperdbg/hyperhv/header/vmm/vmx/Hv.h @@ -118,20 +118,42 @@ HvSetRflagTrapFlag(BOOLEAN Set); /** * @brief Set LOAD DEBUG CONTROLS on Vm-entry controls * + * @param VCpu * @param Set Set or unset * @return VOID */ VOID -HvSetLoadDebugControls(BOOLEAN Set); +HvSetLoadDebugControls(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set); + +/** + * @brief Set LOAD GUEST IA32_LBR_CTL on Vm-entry controls + * + * @param VCpu + * @param Set Set or unset + * @return VOID + */ +VOID +HvSetLoadGuestIa32LbrCtl(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set); /** * @brief Set SAVE DEBUG CONTROLS on Vm-exit controls * + * @param VCpu * @param Set Set or unset * @return VOID */ VOID -HvSetSaveDebugControls(BOOLEAN Set); +HvSetSaveDebugControls(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set); + +/** + * @brief Set SAVE GUEST IA32_LBR_CTL on Vm-exit controls + * + * @param VCpu + * @param Set Set or unset + * @return VOID + */ +VOID +HvSetClearGuestIa32LbrCtl(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set); /** * @brief Reset GDTR/IDTR and other old when you do vmxoff as the patchguard @@ -430,3 +452,121 @@ HvEnableMtfAndChangeExternalInterruptState(VIRTUAL_MACHINE_STATE * VCpu); */ VOID HvPreventExternalInterrupts(VIRTUAL_MACHINE_STATE * VCpu); + +/** + * @brief Get the guest state of pending debug exceptions + * + * @return UINT64 + */ +UINT64 +HvGetPendingDebugExceptions(); + +/** + * @brief Set the guest state of pending debug exceptions + * @param Value The new state + * + * @return VOID + */ +VOID +HvSetPendingDebugExceptions(UINT64 Value); + +/** + * @brief Get the guest state of IA32_DEBUGCTL + * + * @return UINT64 + */ +UINT64 +HvGetDebugctl(); + +/** + * @brief Get the guest state of IA32_LBR_CTL + * + * @return UINT64 + */ +UINT64 +HvGetGuestIa32LbrCtl(); + +/** + * @brief Get and store the guest state of IA32_DEBUGCTL + * @details mainly used from the VMCALL handler + * + * @param StoreDebugctl + * + * @return VOID + */ +VOID +HvGetAndStoreDebugctl(UINT64 * StoreDebugctl); + +/** + * @brief Get and store the guest state of IA32_LBR_CTL + * @details mainly used from the VMCALL handler + * + * @param StoreGuestIa32Lbr + * + * @return VOID + */ +VOID +HvGetAndStoreGuestIa32LbrCtl(UINT64 * StoreGuestIa32Lbr); + +/** + * @brief Set the guest state of IA32_DEBUGCTL + * @param Value The new state + * + * @return VOID + */ +VOID +HvSetDebugctl(UINT64 Value); + +/** + * @brief Set the guest state of IA32_LBR_CTL + * @param Value The new state + * + * @return VOID + */ +VOID +HvSetGuestIa32LbrCtl(UINT64 Value); + +/** + * @brief Set LBR selector + * @details If VMM is active, this should be done in vmx-root, otherwise, it doesn't work + * @param FilterOptions The value to write on MSR_LEGACY_LBR_SELECT + * + * @return VOID + */ +VOID +HvSetLbrSelect(UINT64 FilterOptions); + +/** + * @brief Check if CPU support save and load debug controls on exit and load entries + * + * @return BOOLEAN + */ +BOOLEAN +HvCheckCpuSupportForSaveAndLoadDebugControls(); + +/** + * @brief Check if CPU support load and clear guest IA32_LBR_CTL controls on VM-entry and VM-exit + * + * @return BOOLEAN + */ +BOOLEAN +HvCheckCpuSupportForLoadAndClearGuestIa32LbrCtlControls(); + +/** + * @brief Set the guest state of DR7 + * @param Value The new value for DR7 + * + * @return VOID + */ +VOID +HvSetDebugReg7(UINT64 Value); + +/** + * @brief Handle the case when the trap flag is set, and + * we need to inject the single-step exception right + * after vm-entry + * + * @return VOID + */ +VOID +HvHandleTrapFlag(); diff --git a/hyperdbg/hyperhv/header/vmm/vmx/IdtEmulation.h b/hyperdbg/hyperhv/header/vmm/vmx/IdtEmulation.h new file mode 100644 index 00000000..1c0d49b8 --- /dev/null +++ b/hyperdbg/hyperhv/header/vmm/vmx/IdtEmulation.h @@ -0,0 +1,240 @@ +/** + * @file IdtEmulation.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Header for Handlers of Guest's IDT Emulator + * @details + * @version 0.1 + * @date 2020-06-10 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Constants // +////////////////////////////////////////////////// + +/** + * @brief Whether the hypervisor should use the default OS's + * IDT as the host IDT in VMCS or not + * + */ +#define USE_DEFAULT_OS_IDT_AS_HOST_IDT FALSE + +/** + * @brief Maximum number of interrupt entries in IDT + * + */ +#define HOST_IDT_DESCRIPTOR_COUNT 256 + +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +#pragma pack(push, 1) + +typedef struct _SIDT_ENTRY +{ + USHORT IdtLimit; + ULONG_PTR IdtBase; +} SIDT_ENTRY, *PSIDT_ENTRY; + +typedef struct _KIDT_ENTRY +{ + ULONG LowPart : 16; + ULONG SegmentSelector : 16; + ULONG Reserved1 : 5; + ULONG Reserved2 : 3; + ULONG Type : 3; + ULONG Size : 1; + ULONG Reserved3 : 1; + ULONG Dpl : 2; + ULONG Present : 1; + ULONG HighPart : 16; +#if defined _M_AMD64 + ULONG HighestPart; + ULONG Reserved; +#endif +} KIDT_ENTRY, *PKIDT_ENTRY; + +#pragma pack(pop) + +/** + * @brief Trap frame for interrupts + * + */ +typedef struct _INTERRUPT_TRAP_FRAME +{ + // + // general-purpose registers + // + union + { + UINT64 rax; + UINT32 eax; + UINT16 ax; + UINT8 al; + }; + union + { + UINT64 rcx; + UINT32 ecx; + UINT16 cx; + UINT8 cl; + }; + union + { + UINT64 rdx; + UINT32 edx; + UINT16 dx; + UINT8 dl; + }; + union + { + UINT64 rbx; + UINT32 ebx; + UINT16 bx; + UINT8 bl; + }; + union + { + UINT64 rbp; + UINT32 ebp; + UINT16 bp; + UINT8 bpl; + }; + union + { + UINT64 rsi; + UINT32 esi; + UINT16 si; + UINT8 sil; + }; + union + { + UINT64 rdi; + UINT32 edi; + UINT16 di; + UINT8 dil; + }; + union + { + UINT64 r8; + UINT32 r8d; + UINT16 r8w; + UINT8 r8b; + }; + union + { + UINT64 r9; + UINT32 r9d; + UINT16 r9w; + UINT8 r9b; + }; + union + { + UINT64 r10; + UINT32 r10d; + UINT16 r10w; + UINT8 r10b; + }; + union + { + UINT64 r11; + UINT32 r11d; + UINT16 r11w; + UINT8 r11b; + }; + union + { + UINT64 r12; + UINT32 r12d; + UINT16 r12w; + UINT8 r12b; + }; + union + { + UINT64 r13; + UINT32 r13d; + UINT16 r13w; + UINT8 r13b; + }; + union + { + UINT64 r14; + UINT32 r14d; + UINT16 r14w; + UINT8 r14b; + }; + union + { + UINT64 r15; + UINT32 r15d; + UINT16 r15w; + UINT8 r15b; + }; + + // interrupt vector + UINT8 vector; + + // _MACHINE_FRAME + UINT64 error; + UINT64 rip; + UINT64 cs; + UINT64 rflags; + UINT64 rsp; + UINT64 ss; +} INTERRUPT_TRAP_FRAME, *PINTERRUPT_TRAP_FRAME; + +// +// remember to update this value in AsmInterruptHandlers.asm +// +static_assert(sizeof(INTERRUPT_TRAP_FRAME) == (0x78 + 0x38), "Size of INTERRUPT_TRAP_FRAME is not as expected"); + +/** + * @brief Filled out when a host exception occurs + * + */ +typedef struct _HOST_EXCEPTION_INFO +{ + // + // whether an exception occurred or not + // + BOOLEAN ExceptionOccurred; + + // + // interrupt vector + // + UINT64 Vector; + + // + // error code + // + UINT64 Error; +} HOST_EXCEPTION_INFO, *PHOST_EXCEPTION_INFO; + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +IdtEmulationPrepareHostIdt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); + +VOID +IdtEmulationHandleExceptionAndNmi(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, + _In_ VMEXIT_INTERRUPT_INFORMATION InterruptExit); + +VOID +IdtEmulationHandleExternalInterrupt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu, + _In_ VMEXIT_INTERRUPT_INFORMATION InterruptExit); + +VOID +IdtEmulationHandleNmiWindowExiting(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); + +VOID +IdtEmulationHandleInterruptWindowExiting(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); + +VOID +IdtEmulationQueryIdtEntriesRequest(PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtQueryRequest, + BOOLEAN ReadFromVmxRoot); diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/IoHandler.h b/hyperdbg/hyperhv/header/vmm/vmx/IoHandler.h similarity index 53% rename from hyperdbg/hprdbghv/header/vmm/vmx/IoHandler.h rename to hyperdbg/hyperhv/header/vmm/vmx/IoHandler.h index 15767148..20b698f6 100644 --- a/hyperdbg/hprdbghv/header/vmm/vmx/IoHandler.h +++ b/hyperdbg/hyperhv/header/vmm/vmx/IoHandler.h @@ -39,124 +39,76 @@ typedef enum _IO_OP_ENCODING // I/O Instructions Functions // ////////////////////////////////////////////////// -unsigned char -__inbyte(unsigned short); -#pragma intrinsic(__inbyte) - inline UINT8 IoInByte(UINT16 port) { - return __inbyte(port); + return CpuIoInByte(port); } -unsigned short -__inword(unsigned short); -#pragma intrinsic(__inword) - inline UINT16 IoInWord(UINT16 port) { - return __inword(port); + return CpuIoInWord(port); } -unsigned long -__indword(unsigned short); -#pragma intrinsic(__indword) - inline UINT32 IoInDword(UINT16 port) { - return __indword(port); + return CpuIoInDword(port); } -void -__inbytestring(unsigned short, unsigned char *, unsigned long); -#pragma intrinsic(__inbytestring) - -inline void +inline VOID IoInByteString(UINT16 port, UINT8 * data, UINT32 size) { - __inbytestring(port, data, size); + CpuIoInByteString(port, data, size); } -void -__inwordstring(unsigned short, unsigned short *, unsigned long); -#pragma intrinsic(__inwordstring) - -inline void +inline VOID IoInWordString(UINT16 port, UINT16 * data, UINT32 size) { - __inwordstring(port, data, size); + CpuIoInWordString(port, data, size); } -void -__indwordstring(unsigned short, unsigned long *, unsigned long); -#pragma intrinsic(__indwordstring) - -inline void +inline VOID IoInDwordString(UINT16 port, UINT32 * data, UINT32 size) { - __indwordstring(port, (unsigned long *)data, size); + CpuIoInDwordString(port, data, size); } -void -__outbyte(unsigned short, unsigned char); -#pragma intrinsic(__outbyte) - -inline void +inline VOID IoOutByte(UINT16 port, UINT8 value) { - __outbyte(port, value); + CpuIoOutByte(port, value); } -void -__outword(unsigned short, unsigned short); -#pragma intrinsic(__outword) - -inline void +inline VOID IoOutWord(UINT16 port, UINT16 value) { - __outword(port, value); + CpuIoOutWord(port, value); } -void -__outdword(unsigned short, unsigned long); -#pragma intrinsic(__outdword) - -inline void +inline VOID IoOutDword(UINT16 port, UINT32 value) { - __outdword(port, value); + CpuIoOutDword(port, value); } -void -__outbytestring(unsigned short, unsigned char *, unsigned long); -#pragma intrinsic(__outbytestring) - -inline void +inline VOID IoOutByteString(UINT16 port, UINT8 * data, UINT32 count) { - __outbytestring(port, data, count); + CpuIoOutByteString(port, data, count); } -void -__outwordstring(unsigned short, unsigned short *, unsigned long); -#pragma intrinsic(__outwordstring) - -inline void +inline VOID IoOutWordString(UINT16 port, UINT16 * data, UINT32 count) { - __outwordstring(port, data, count); + CpuIoOutWordString(port, data, count); } -void -__outdwordstring(unsigned short, unsigned long *, unsigned long); -#pragma intrinsic(__outdwordstring) - -inline void +inline VOID IoOutDwordString(UINT16 port, UINT32 * data, UINT32 count) { - __outdwordstring(port, (unsigned long *)data, count); + CpuIoOutDwordString(port, data, count); } ////////////////////////////////////////////////// diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/MsrHandlers.h b/hyperdbg/hyperhv/header/vmm/vmx/MsrHandlers.h similarity index 85% rename from hyperdbg/hprdbghv/header/vmm/vmx/MsrHandlers.h rename to hyperdbg/hyperhv/header/vmm/vmx/MsrHandlers.h index 4d3a6b9a..3114949d 100644 --- a/hyperdbg/hprdbghv/header/vmm/vmx/MsrHandlers.h +++ b/hyperdbg/hyperhv/header/vmm/vmx/MsrHandlers.h @@ -15,11 +15,14 @@ // Functions // ////////////////////////////////////////////////// -VOID -MsrHandleRdmsrVmexit(PGUEST_REGS GuestRegs); +BOOLEAN +MsrHandleIsHypervSyntheticMsr(_In_ UINT32 TargetMsr); VOID -MsrHandleWrmsrVmexit(PGUEST_REGS GuestRegs); +MsrHandleRdmsrVmexit(VIRTUAL_MACHINE_STATE * VCpu); + +VOID +MsrHandleWrmsrVmexit(VIRTUAL_MACHINE_STATE * VCpu); BOOLEAN MsrHandleSetMsrBitmap(VIRTUAL_MACHINE_STATE * VCpu, UINT32 Msr, BOOLEAN ReadDetection, BOOLEAN WriteDetection); diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/Mtf.h b/hyperdbg/hyperhv/header/vmm/vmx/Mtf.h similarity index 100% rename from hyperdbg/hprdbghv/header/vmm/vmx/Mtf.h rename to hyperdbg/hyperhv/header/vmm/vmx/Mtf.h diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/ProtectedHv.h b/hyperdbg/hyperhv/header/vmm/vmx/ProtectedHv.h similarity index 90% rename from hyperdbg/hprdbghv/header/vmm/vmx/ProtectedHv.h rename to hyperdbg/hyperhv/header/vmm/vmx/ProtectedHv.h index aeb1f8f0..9f8d669f 100644 --- a/hyperdbg/hprdbghv/header/vmm/vmx/ProtectedHv.h +++ b/hyperdbg/hyperhv/header/vmm/vmx/ProtectedHv.h @@ -84,3 +84,13 @@ ProtectedHvSetMov2CrExiting(BOOLEAN Set, UINT64 ControlRegister, UINT64 MaskRegi VOID ProtectedHvSetMov2Cr3Exiting(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set); + +// +// Save and load state on vm-exit and vm-entry +// + +VOID +ProtectedHvSetSaveDebugControls(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set); + +VOID +ProtectedHvSetLoadDebugControls(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set); diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/Vmcall.h b/hyperdbg/hyperhv/header/vmm/vmx/Vmcall.h similarity index 82% rename from hyperdbg/hprdbghv/header/vmm/vmx/Vmcall.h rename to hyperdbg/hyperhv/header/vmm/vmx/Vmcall.h index 9eb06fab..33001dc2 100644 --- a/hyperdbg/hprdbghv/header/vmm/vmx/Vmcall.h +++ b/hyperdbg/hyperhv/header/vmm/vmx/Vmcall.h @@ -161,8 +161,7 @@ /** * @brief VMCALL to reset exception bitmap on VMCS - * @details THIS VMCALL SHOULD BE USED ONLY IN - * RESETTING (CLEARING) EXCEPTION EVENTS + * @details THIS VMCALL SHOULD BE USED ONLY IN RESETTING (CLEARING) EXCEPTION EVENTS * */ #define VMCALL_RESET_EXCEPTION_BITMAP_ONLY_ON_CLEARING_EXCEPTION_EVENTS 0x00000019 @@ -297,6 +296,84 @@ */ #define VMCALL_DISABLE_OR_ENABLE_MBEC 0x0000002d +/** + * @brief VMCALL to bypass caching policies to read MMIO + * + */ +#define VMCALL_READ_PHYSICAL_MEM_BYPASS_CACHING_POLICIES 0x0000002e // not used + +/** + * @brief VMCALL to bypass caching policies to write MMIO + * + */ +#define VMCALL_WRITE_PHYSICAL_MEM_BYPASS_CACHING_POLICIES 0x0000002f // not used + +/** + * @brief VMCALL to read physical memory + * + */ +#define VMCALL_READ_PHYSICAL_MEMORY 0x00000030 + +/** + * @brief VMCALL to write physical memory + * + */ +#define VMCALL_WRITE_PHYSICAL_MEMORY 0x00000031 + +/** + * @brief VMCALL to get IA32_DEBUGCTL on VMCS + * + */ +#define VMCALL_GET_VMCS_DEBUGCTL 0x00000032 + +/** + * @brief VMCALL to set IA32_DEBUGCTL on VMCS + * + */ +#define VMCALL_SET_VMCS_DEBUGCTL 0x00000033 + +/** + * @brief VMCALL to set MSR_LEGACY_LBR_SELECT using WRMSR + * + */ +#define VMCALL_SET_MSR_LBR_SELECT 0x00000034 + +/** + * @brief VMCALL to get the guest state of IA32_LBR_CTL on VMCS + * + */ +#define VMCALL_GET_GUEST_IA32_LBR_CTL 0x00000035 + +/** + * @brief VMCALL to set the guest state of IA32_LBR_CTL on VMCS + * + */ +#define VMCALL_SET_GUEST_IA32_LBR_CTL 0x00000036 + +/** + * @brief VMCALL to set LOAD GUEST IA32_LBR_CTL on VM-entry controls + * + */ +#define VMCALL_SET_VM_ENTRY_LOAD_GUEST_IA32_LBR_CTL 0x00000037 + +/** + * @brief VMCALL to unset LOAD GUEST IA32_LBR_CTL on VM-entry controls + * + */ +#define VMCALL_UNSET_VM_ENTRY_LOAD_GUEST_IA32_LBR_CTL 0x00000038 + +/** + * @brief VMCALL to set CLEAR GUEST IA32_LBR_CTL on VM-exit controls + * + */ +#define VMCALL_SET_CLEAR_GUEST_IA32_LBR_CTL 0x00000039 + +/** + * @brief VMCALL to unset CLEAR GUEST IA32_LBR_CTL on VM-exit controls + * + */ +#define VMCALL_UNSET_CLEAR_GUEST_IA32_LBR_CTL 0x0000003A + ////////////////////////////////////////////////// // Functions // ////////////////////////////////////////////////// diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/Vmx.h b/hyperdbg/hyperhv/header/vmm/vmx/Vmx.h similarity index 64% rename from hyperdbg/hprdbghv/header/vmm/vmx/Vmx.h rename to hyperdbg/hyperhv/header/vmm/vmx/Vmx.h index 6fd11bec..2cb7b05d 100644 --- a/hyperdbg/hprdbghv/header/vmm/vmx/Vmx.h +++ b/hyperdbg/hyperhv/header/vmm/vmx/Vmx.h @@ -27,81 +27,6 @@ */ #define VMXON_SIZE 4096 -/** - * @brief PIN-Based Execution - * - */ -#define PIN_BASED_VM_EXECUTION_CONTROLS_EXTERNAL_INTERRUPT 0x00000001 -#define PIN_BASED_VM_EXECUTION_CONTROLS_NMI_EXITING 0x00000008 -#define PIN_BASED_VM_EXECUTION_CONTROLS_VIRTUAL_NMI 0x00000020 -#define PIN_BASED_VM_EXECUTION_CONTROLS_ACTIVE_VMX_TIMER 0x00000040 -#define PIN_BASED_VM_EXECUTION_CONTROLS_PROCESS_POSTED_INTERRUPTS 0x00000080 - -/** - * @brief CPU-Based Controls - * - */ -#define CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004 -#define CPU_BASED_USE_TSC_OFFSETTING 0x00000008 -#define CPU_BASED_HLT_EXITING 0x00000080 -#define CPU_BASED_INVLPG_EXITING 0x00000200 -#define CPU_BASED_MWAIT_EXITING 0x00000400 -#define CPU_BASED_RDPMC_EXITING 0x00000800 -#define CPU_BASED_RDTSC_EXITING 0x00001000 -#define CPU_BASED_CR3_LOAD_EXITING 0x00008000 -#define CPU_BASED_CR3_STORE_EXITING 0x00010000 -#define CPU_BASED_CR8_LOAD_EXITING 0x00080000 -#define CPU_BASED_CR8_STORE_EXITING 0x00100000 -#define CPU_BASED_TPR_SHADOW 0x00200000 -#define CPU_BASED_VIRTUAL_NMI_PENDING 0x00400000 -#define CPU_BASED_MOV_DR_EXITING 0x00800000 -#define CPU_BASED_UNCOND_IO_EXITING 0x01000000 -#define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000 -#define CPU_BASED_MONITOR_TRAP_FLAG 0x08000000 -#define CPU_BASED_ACTIVATE_MSR_BITMAP 0x10000000 -#define CPU_BASED_MONITOR_EXITING 0x20000000 -#define CPU_BASED_PAUSE_EXITING 0x40000000 -#define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS 0x80000000 - -/** - * @brief Secondary CPU-Based Controls - * - */ -#define CPU_BASED_CTL2_ENABLE_EPT 0x2 -#define CPU_BASED_CTL2_RDTSCP 0x8 -#define CPU_BASED_CTL2_ENABLE_VPID 0x20 -#define CPU_BASED_CTL2_UNRESTRICTED_GUEST 0x80 -#define CPU_BASED_CTL2_VIRTUAL_INTERRUPT_DELIVERY 0x200 -#define CPU_BASED_CTL2_ENABLE_INVPCID 0x1000 -#define CPU_BASED_CTL2_ENABLE_VMFUNC 0x2000 -#define CPU_BASED_CTL2_ENABLE_XSAVE_XRSTORS 0x100000 - -/** - * @brief VM-exit Control Bits - * - */ -#define VM_EXIT_SAVE_DEBUG_CONTROLS 0x00000004 -#define VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200 -#define VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL 0x00001000 -#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 -#define VM_EXIT_SAVE_IA32_PAT 0x00040000 -#define VM_EXIT_LOAD_IA32_PAT 0x00080000 -#define VM_EXIT_SAVE_IA32_EFER 0x00100000 -#define VM_EXIT_LOAD_IA32_EFER 0x00200000 -#define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER 0x00400000 - -/** - * @brief VM-entry Control Bits - * - */ -#define VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000004 -#define VM_ENTRY_IA32E_MODE 0x00000200 -#define VM_ENTRY_SMM 0x00000400 -#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 -#define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL 0x00002000 -#define VM_ENTRY_LOAD_IA32_PAT 0x00004000 -#define VM_ENTRY_LOAD_IA32_EFER 0x00008000 - /** * @brief CPUID RCX(s) - Based on Hyper-V * @@ -280,6 +205,12 @@ enum HYPERCALL_CODE HvCallFlushGuestPhysicalAddressList = 0x00B0 }; +/** @brief Hyper-V CPUID leaves +*/ +#define HYPERV_CPUID_VENDOR_MICROSOFT_EBX 0x7263694d // "Micr" +#define HYPERV_CPUID_VENDOR_MICROSOFT_ECX 0x666f736f // "osof" +#define HYPERV_CPUID_VENDOR_MICROSOFT_EDX 0x76482074 // "t Hv" + ////////////////////////////////////////////////// // Enums // ////////////////////////////////////////////////// @@ -300,50 +231,13 @@ typedef enum _MOV_TO_DEBUG_REG AccessFromDebugRegister = 1, } MOV_TO_DEBUG_REG; -////////////////////////////////////////////////// -// VMX Instructions // -////////////////////////////////////////////////// - -extern inline UCHAR -VmxVmread64(size_t Field, UINT64 FieldValue); - -extern inline UCHAR -VmxVmread32(size_t Field, UINT32 FieldValue); - -extern inline UCHAR -VmxVmread16(size_t Field, UINT16 FieldValue); - -extern inline UCHAR -VmxVmread64P(size_t Field, UINT64 * FieldValue); - -extern inline UCHAR -VmxVmread32P(size_t Field, UINT32 * FieldValue); - -extern inline UCHAR -VmxVmread16P(size_t Field, UINT16 * FieldValue); - -extern inline UCHAR -VmxVmwrite64(size_t Field, UINT64 FieldValue); - -extern inline UCHAR -VmxVmwrite32(size_t Field, UINT32 FieldValue); - -extern inline UCHAR -VmxVmwrite16(size_t Field, UINT16 FieldValue); - -VOID -VmxVmptrst(); - -VOID -VmxVmresume(); - -VOID -VmxVmxoff(VIRTUAL_MACHINE_STATE * VCpu); - ////////////////////////////////////////////////// // Functions // ////////////////////////////////////////////////// +BOOLEAN +VmxIsTopLevelHypervisorHyperV(); + BOOLEAN VmxCheckVmxSupport(); @@ -356,44 +250,9 @@ VmxPerformVirtualizationOnAllCores(); BOOLEAN VmxTerminate(); -VOID -VmxPerformTermination(); - -_Success_(return != FALSE) -BOOLEAN -VmxAllocateVmxonRegion(_Out_ VIRTUAL_MACHINE_STATE * VCpu); - -_Success_(return != FALSE) -BOOLEAN -VmxAllocateVmcsRegion(_Out_ VIRTUAL_MACHINE_STATE * VCpu); - -BOOLEAN -VmxAllocateVmmStack(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); - -BOOLEAN -VmxAllocateMsrBitmap(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); - -BOOLEAN -VmxAllocateIoBitmaps(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); - -UINT64 * -VmxAllocateInvalidMsrBimap(); - -VOID -VmxHandleXsetbv(VIRTUAL_MACHINE_STATE * VCpu); - -VOID -VmxHandleVmxPreemptionTimerVmexit(VIRTUAL_MACHINE_STATE * VCpu); - -VOID -VmxHandleTripleFaults(VIRTUAL_MACHINE_STATE * VCpu); - BOOLEAN VmxPerformVirtualizationOnSpecificCore(); -VOID -VmxFixCr4AndCr0Bits(); - BOOLEAN VmxLoadVmcs(_In_ VIRTUAL_MACHINE_STATE * VCpu); @@ -409,6 +268,33 @@ VmxVirtualizeCurrentSystem(PVOID GuestStack); BOOLEAN VmxSetupVmcs(_In_ VIRTUAL_MACHINE_STATE * VCpu, _In_ PVOID GuestStack); +VOID +VmxPerformVmptrst(); + +VOID +VmxPerformVmresume(); + +VOID +VmxPerformVmxoff(VIRTUAL_MACHINE_STATE * VCpu); + +VOID +VmxPerformTermination(); + +VOID +VmxHandleXsetbv(VIRTUAL_MACHINE_STATE * VCpu); + +VOID +VmxHandleVmxPreemptionTimerVmexit(VIRTUAL_MACHINE_STATE * VCpu); + +VOID +VmxHandleTripleFaults(VIRTUAL_MACHINE_STATE * VCpu); + +VOID +VmxFixCr4AndCr0Bits(); + +VOID +VmxCompatibleMicroSleep(UINT64 ns); + UINT64 VmxReturnStackPointerForVmxoff(); @@ -421,21 +307,25 @@ VmxGetCurrentExecutionMode(); BOOLEAN VmxGetCurrentLaunchState(); -_Success_(return) -BOOLEAN -VmxGetSegmentDescriptor(_In_ PUCHAR GdtBase, _In_ UINT16 Selector, _Out_ PVMX_SEGMENT_SELECTOR SegmentSelector); - UINT32 VmxCompatibleStrlen(const CHAR * S); UINT32 -VmxCompatibleWcslen(const wchar_t * S); +VmxCompatibleWcslen(const WCHAR * S); INT32 -VmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2); +VmxCompatibleStrcmp(const CHAR * Address1, + const CHAR * Address2, + SIZE_T Num, + BOOLEAN IsStrncmp); INT32 -VmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2); +VmxCompatibleWcscmp(const WCHAR * Address1, + const WCHAR * Address2, + SIZE_T Num, + BOOLEAN IsWcsncmp); INT32 -VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count); +VmxCompatibleMemcmp(const CHAR * Address1, + const CHAR * Address2, + SIZE_T Count); diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/VmxBroadcast.h b/hyperdbg/hyperhv/header/vmm/vmx/VmxBroadcast.h similarity index 100% rename from hyperdbg/hprdbghv/header/vmm/vmx/VmxBroadcast.h rename to hyperdbg/hyperhv/header/vmm/vmx/VmxBroadcast.h diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/VmxMechanisms.h b/hyperdbg/hyperhv/header/vmm/vmx/VmxMechanisms.h similarity index 100% rename from hyperdbg/hprdbghv/header/vmm/vmx/VmxMechanisms.h rename to hyperdbg/hyperhv/header/vmm/vmx/VmxMechanisms.h diff --git a/hyperdbg/hyperhv/header/vmm/vmx/VmxRegions.h b/hyperdbg/hyperhv/header/vmm/vmx/VmxRegions.h new file mode 100644 index 00000000..e9c8b175 --- /dev/null +++ b/hyperdbg/hyperhv/header/vmm/vmx/VmxRegions.h @@ -0,0 +1,48 @@ +/** + * @file VmxRegions.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for implement allocations for VMX Regions (VMXON Region, VMCS, MSR Bitmap and etc.) + * @details + * @version 0.9 + * @date 2024-06-03 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +_Success_(return != FALSE) +BOOLEAN +VmxAllocateVmxonRegion(_Out_ VIRTUAL_MACHINE_STATE * VCpu); + +_Success_(return != FALSE) +BOOLEAN +VmxAllocateVmcsRegion(_Out_ VIRTUAL_MACHINE_STATE * VCpu); + +BOOLEAN +VmxAllocateVmmStack(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); + +BOOLEAN +VmxAllocateMsrBitmap(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); + +BOOLEAN +VmxAllocateIoBitmaps(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); + +UINT64 * +VmxAllocateInvalidMsrBimap(); + +BOOLEAN +VmxAllocateHostIdt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); + +BOOLEAN +VmxAllocateHostGdt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); + +BOOLEAN +VmxAllocateHostTss(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); + +BOOLEAN +VmxAllocateHostInterruptStack(_Inout_ VIRTUAL_MACHINE_STATE * VCpu); diff --git a/hyperdbg/hyperhv/hyperhv.def b/hyperdbg/hyperhv/hyperhv.def new file mode 100644 index 00000000..c0ec4aff --- /dev/null +++ b/hyperdbg/hyperhv/hyperhv.def @@ -0,0 +1,6 @@ +LIBRARY hyperhv + +EXPORTS + + DllInitialize PRIVATE + DllUnload PRIVATE \ No newline at end of file diff --git a/hyperdbg/hprdbghv/hprdbghv.vcxproj b/hyperdbg/hyperhv/hyperhv.vcxproj similarity index 74% rename from hyperdbg/hprdbghv/hprdbghv.vcxproj rename to hyperdbg/hyperhv/hyperhv.vcxproj index 9004260e..53c55a14 100644 --- a/hyperdbg/hprdbghv/hprdbghv.vcxproj +++ b/hyperdbg/hyperhv/hyperhv.vcxproj @@ -1,5 +1,8 @@  + + + debug @@ -17,9 +20,9 @@ 12.0 Debug Win32 - hprdbghv + hyperhv $(LatestTargetPlatformVersion) - hprdbghv + hyperhv @@ -28,7 +31,7 @@ WindowsKernelModeDriver10.0 DynamicLibrary KMDF - Universal + Desktop false false @@ -38,7 +41,7 @@ WindowsKernelModeDriver10.0 DynamicLibrary KMDF - Universal + Desktop false false @@ -53,13 +56,16 @@ DbgengKernelDebugger - true + + $(SolutionDir)build\bin\$(Configuration)\ $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + false DbgengKernelDebugger - true + + $(SolutionDir)build\bin\$(Configuration)\ false $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ @@ -75,15 +81,16 @@ $(IntDir)$(TargetName).pch Level4 ZYDIS_STATIC_BUILD;ZYCORE_STATIC_BUILD;ZYAN_NO_LIBC;ZYDIS_NO_LIBC;%(PreprocessorDefinitions) + stdcpp20 true %(AdditionalDependencies) - %(AdditionalDependencies);;$(SolutionDir)libraries\zydis\kernel\Zycore.lib;$(SolutionDir)libraries\zydis\kernel\Zydis.lib + %(AdditionalDependencies);$(SolutionDir)libraries\zydis\kernel\Zycore.lib;$(SolutionDir)libraries\zydis\kernel\Zydis.lib;$(SolutionDir)build\bin\$(Configuration)\hyperevade.lib true - hprdbghv.def + hyperhv.def SHA256 @@ -97,9 +104,9 @@ true - %(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfLdr.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfDriverEntry.lib;$(SolutionDir)libraries\zydis\kernel\Zycore.lib;$(SolutionDir)libraries\zydis\kernel\Zydis.lib + %(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfLdr.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfDriverEntry.lib;$(SolutionDir)libraries\zydis\kernel\Zycore.lib;$(SolutionDir)libraries\zydis\kernel\Zydis.lib;$(SolutionDir)build\bin\$(Configuration)\hyperevade.lib true - hprdbghv.def + hyperhv.def true @@ -110,8 +117,9 @@ pch.h $(IntDir)$(TargetName).pch Neither - Disabled + Full ZYDIS_STATIC_BUILD;ZYCORE_STATIC_BUILD;ZYAN_NO_LIBC;ZYDIS_NO_LIBC;%(PreprocessorDefinitions) + stdcpp20 SHA256 @@ -124,11 +132,16 @@ + + + + + @@ -136,6 +149,7 @@ + @@ -145,25 +159,28 @@ - + + - + - - + + + + @@ -188,6 +205,7 @@ + @@ -221,23 +239,28 @@ + + + + + - + @@ -246,6 +269,7 @@ + @@ -253,15 +277,16 @@ - + - - - + + + + @@ -274,10 +299,24 @@ + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/hyperdbg/hprdbghv/hprdbghv.vcxproj.filters b/hyperdbg/hyperhv/hyperhv.vcxproj.filters similarity index 86% rename from hyperdbg/hprdbghv/hprdbghv.vcxproj.filters rename to hyperdbg/hyperhv/hyperhv.vcxproj.filters index 0ee1ae4a..fbbe5e33 100644 --- a/hyperdbg/hprdbghv/hprdbghv.vcxproj.filters +++ b/hyperdbg/hyperhv/hyperhv.vcxproj.filters @@ -63,12 +63,6 @@ {20741da2-52c0-4c6c-ab4f-d8a29bae81e7} - - {33ddc8db-b65a-4ebd-a214-1b8060bf6ab0} - - - {3646ca74-c21f-4d7d-8e93-51ec5fae9d0f} - {bd4cf053-c1f6-40df-984d-37f9f50b85ac} @@ -135,6 +129,24 @@ {0c6f7e8d-4829-4a45-b09d-4c40cfcc5cf7} + + {36f1d8ba-6527-4c1b-8016-ae66d1bd41e7} + + + {8efcd014-6f76-436f-bca7-33f1cf2bd980} + + + {6136b867-021b-4f61-aa79-c1b6ccafe670} + + + {c310c4a9-c337-454d-94ca-4c6b1216cf41} + + + {20e523af-8b6d-4293-bd6d-ce6087f2d4a2} + + + {58bb81a8-dd12-4e47-b6c8-7d61981fef62} + @@ -191,9 +203,6 @@ code\memory - - code\memory - code\components\registers @@ -212,9 +221,6 @@ code\vmm\vmx - - code\platform - code\globals @@ -224,18 +230,12 @@ code\interface - - code\transparency - code\hooks\ept-hook code\hooks\syscall-hook - - code\hooks\syscall-hook - code\broadcast @@ -302,6 +302,45 @@ code\interface + + code\platform + + + code\memory + + + code\devices + + + code\processor + + + code\mmio + + + code\hooks\syscall-hook + + + code\interface + + + code\processor + + + code\vmm\vmx + + + code\platform + + + code\platform + + + code\platform + + + code\components\callback + @@ -310,9 +349,6 @@ header\common - - header\common - header\common @@ -355,9 +391,6 @@ header\memory - - header\memory - header\vmm\vmx @@ -373,12 +406,6 @@ header\vmm\vmx - - header\platform - - - header\platform - header\globals @@ -391,9 +418,6 @@ header\common - - header\transparency - header\interface @@ -559,6 +583,45 @@ header\interface + + header\platform + + + header\memory + + + header\vmm\vmx + + + header\devices + + + header\processor + + + header\mmio + + + header\hooks + + + header\processor + + + header\vmm\vmx + + + header\platform + + + header\platform + + + header\platform + + + header\components\callback + @@ -582,5 +645,11 @@ code\assembly + + code\assembly + + + + \ No newline at end of file diff --git a/hyperdbg/hyperhv/packages.config b/hyperdbg/hyperhv/packages.config new file mode 100644 index 00000000..eb276766 --- /dev/null +++ b/hyperdbg/hyperhv/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/hyperdbg/hprdbghv/pch.c b/hyperdbg/hyperhv/pch.c similarity index 100% rename from hyperdbg/hprdbghv/pch.c rename to hyperdbg/hyperhv/pch.c diff --git a/hyperdbg/hprdbghv/pch.h b/hyperdbg/hyperhv/pch.h similarity index 68% rename from hyperdbg/hprdbghv/pch.h rename to hyperdbg/hyperhv/pch.h index 6f7f8fab..43398529 100644 --- a/hyperdbg/hprdbghv/pch.h +++ b/hyperdbg/hyperhv/pch.h @@ -17,17 +17,6 @@ #pragma warning(disable : 4201) // Suppress nameless struct/union warning -// -// Windows defined functions -// -#include -#include -#include -#include -#include -#include -#include - // // Scope definitions // @@ -35,6 +24,23 @@ #define HYPERDBG_KERNEL_MODE #define HYPERDBG_VMM +// +// Environment headers +// +#include "platform/general/header/Environment.h" + +#ifdef HYPERDBG_ENV_WINDOWS + +// +// General WDK headers +// +# include +# include +# include +# include + +#endif // HYPERDBG_ENV_WINDOWS + // // Definition of Intel primitives (External header) // @@ -48,15 +54,21 @@ // // HyperDbg Kernel-mode headers // -#include "Configuration.h" +#include "config/Configuration.h" #include "macros/MetaMacros.h" -#include "platform/CrossApi.h" -#include "platform/Environment.h" + +// +// Platform independent headers +// +#include "platform/kernel/header/PlatformMem.h" +#include "platform/kernel/header/PlatformIntrinsics.h" +#include "platform/kernel/header/PlatformBroadcast.h" +#include "platform/kernel/header/PlatformIntrinsicsVmx.h" // // VMM Callbacks // -#include "SDK/Modules/VMM.h" +#include "SDK/modules/VMM.h" // // The core's state @@ -67,20 +79,22 @@ // VMX and EPT Types // #include "vmm/vmx/Vmx.h" +#include "vmm/vmx/VmxRegions.h" #include "vmm/ept/Ept.h" -#include "SDK/Imports/HyperDbgVmmImports.h" +#include "SDK/imports/kernel/HyperDbgVmmImports.h" + +// +// Hyper-V TLFS +// +#include "hyper-v/HypervTlfs.h" // // VMX and Capabilities // -#include "transparency/Transparency.h" #include "vmm/vmx/VmxBroadcast.h" #include "memory/MemoryMapper.h" #include "interface/Dispatch.h" -#include "common/Dpc.h" -#include "vmm/vmx/HypervTlfs.h" #include "common/Msr.h" -#include "memory/PoolManager.h" #include "common/Trace.h" #include "assembly/InlineAsm.h" #include "vmm/ept/Vpid.h" @@ -88,17 +102,21 @@ #include "memory/Layout.h" #include "memory/SwitchLayout.h" #include "memory/AddressCheck.h" +#include "memory/Segmentation.h" #include "common/Bitwise.h" #include "common/Common.h" -#include "components/spinlock/header/Spinlock.h" #include "vmm/vmx/Events.h" #include "devices/Apic.h" +#include "devices/Pci.h" +#include "processor/Smm.h" +#include "processor/Idt.h" #include "vmm/vmx/Mtf.h" #include "vmm/vmx/Counters.h" #include "vmm/vmx/IdtEmulation.h" #include "vmm/ept/Invept.h" #include "vmm/vmx/Vmcall.h" #include "interface/DirectVmcall.h" +#include "vmm/vmx/CrossVmcalls.h" #include "vmm/vmx/Hv.h" #include "vmm/vmx/MsrHandlers.h" #include "vmm/vmx/ProtectedHv.h" @@ -106,9 +124,11 @@ #include "vmm/vmx/VmxMechanisms.h" #include "hooks/Hooks.h" #include "hooks/ModeBasedExecHook.h" +#include "hooks/SyscallCallback.h" #include "interface/Callback.h" #include "features/DirtyLogging.h" #include "features/CompatibilityChecks.h" +#include "mmio/MmioShadowing.h" // // Disassembler Header @@ -139,6 +159,11 @@ #include "components/optimizations/header/BinarySearch.h" #include "components/optimizations/header/InsertionSort.h" +// +// Spinlocks +// +#include "components/spinlock/header/Spinlock.h" + // // Global Variables should be the last header to include // @@ -148,5 +173,12 @@ // // HyperLog Module // -#include "SDK/Modules/HyperLog.h" -#include "SDK/Imports/HyperDbgHyperLogIntrinsics.h" +#include "SDK/modules/HyperLog.h" +#include "SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h" +#include "components/callback/header/HyperLogCallback.h" + +// +// Transparent-mode (hyperevade) headers +// +#include "SDK/modules/HyperEvade.h" +#include "SDK/imports/kernel/HyperDbgHyperEvade.h" diff --git a/hyperdbg/hyperkd/CMakeLists.txt b/hyperdbg/hyperkd/CMakeLists.txt new file mode 100644 index 00000000..2dc81aaf --- /dev/null +++ b/hyperdbg/hyperkd/CMakeLists.txt @@ -0,0 +1,102 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "../include/components/optimizations/code/AvlTree.c" + "../include/components/optimizations/code/BinarySearch.c" + "../include/components/optimizations/code/InsertionSort.c" + "../include/components/optimizations/code/OptimizationsExamples.c" + "../include/components/spinlock/code/Spinlock.c" + "../include/platform/kernel/code/PlatformMem.c" + "../script-eval/code/Functions.c" + "../script-eval/code/Keywords.c" + "../script-eval/code/PseudoRegisters.c" + "../script-eval/code/Regs.c" + "../script-eval/code/ScriptEngineEval.c" + "code/common/Common.c" + "code/debugger/broadcast/DpcRoutines.c" + "code/debugger/broadcast/HaltedBroadcast.c" + "code/debugger/broadcast/HaltedRoutines.c" + "code/debugger/commands/BreakpointCommands.c" + "code/debugger/commands/Callstack.c" + "code/debugger/commands/DebuggerCommands.c" + "code/debugger/commands/ExtensionCommands.c" + "code/debugger/communication/SerialConnection.c" + "code/debugger/core/Debugger.c" + "code/debugger/core/DebuggerVmcalls.c" + "code/debugger/core/HaltedCore.c" + "code/debugger/events/ApplyEvents.c" + "code/debugger/events/DebuggerEvents.c" + "code/debugger/events/Termination.c" + "code/debugger/events/ValidateEvents.c" + "code/debugger/kernel-level/Kd.c" + "code/debugger/memory/Allocations.c" + "code/debugger/meta-events/MetaDispatch.c" + "code/debugger/meta-events/Tracing.c" + "code/debugger/objects/Process.c" + "code/debugger/objects/Thread.c" + "code/debugger/script-engine/ScriptEngine.c" + "code/debugger/tests/KernelTests.c" + "code/debugger/user-level/Attaching.c" + "code/debugger/user-level/ThreadHolder.c" + "code/debugger/user-level/Ud.c" + "code/debugger/user-level/UserAccess.c" + "code/driver/Driver.c" + "code/driver/Ioctl.c" + "code/driver/Loader.c" + "../include/components/optimizations/header/AvlTree.h" + "../include/components/optimizations/header/BinarySearch.h" + "../include/components/optimizations/header/InsertionSort.h" + "../include/components/optimizations/header/OptimizationsExamples.h" + "../include/components/spinlock/header/Spinlock.h" + "../include/macros/MetaMacros.h" + "../include/platform/kernel/header/Environment.h" + "../include/platform/kernel/header/PlatformMem.h" + "header/assembly/Assembly.h" + "header/common/Common.h" + "header/common/Dpc.h" + "header/debugger/broadcast/DpcRoutines.h" + "header/debugger/broadcast/HaltedBroadcast.h" + "header/debugger/broadcast/HaltedRoutines.h" + "header/debugger/commands/BreakpointCommands.h" + "header/debugger/commands/Callstack.h" + "header/debugger/commands/DebuggerCommands.h" + "header/debugger/commands/ExtensionCommands.h" + "header/debugger/communication/SerialConnection.h" + "header/debugger/core/Debugger.h" + "header/debugger/core/DebuggerVmcalls.h" + "header/debugger/core/HaltedCore.h" + "header/debugger/core/State.h" + "header/debugger/events/ApplyEvents.h" + "header/debugger/events/DebuggerEvents.h" + "header/debugger/events/Termination.h" + "header/debugger/events/ValidateEvents.h" + "header/debugger/kernel-level/Kd.h" + "header/debugger/memory/Allocations.h" + "header/debugger/memory/Memory.h" + "header/debugger/meta-events/MetaDispatch.h" + "header/debugger/meta-events/Tracing.h" + "header/debugger/objects/Process.h" + "header/debugger/objects/Thread.h" + "header/debugger/script-engine/ScriptEngine.h" + "header/debugger/tests/KernelTests.h" + "header/debugger/user-level/Attaching.h" + "header/debugger/user-level/ThreadHolder.h" + "header/debugger/user-level/Ud.h" + "header/debugger/user-level/UserAccess.h" + "header/driver/Driver.h" + "header/driver/Loader.h" + "header/globals/Global.h" + "header/pch.h" + "code/assembly/AsmDebugger.asm" +) +include_directories( + "../include" + "header" + "code" + "." + "../dependencies" + "../script-eval" +) +wdk_add_driver(hyperkd + KMDF 1.15 + ${SourceFiles} +) diff --git a/hyperdbg/hprdbgkd/code/assembly/AsmDebugger.asm b/hyperdbg/hyperkd/code/assembly/AsmDebugger.asm similarity index 97% rename from hyperdbg/hprdbgkd/code/assembly/AsmDebugger.asm rename to hyperdbg/hyperkd/code/assembly/AsmDebugger.asm index 7899226c..0c35173c 100644 --- a/hyperdbg/hprdbgkd/code/assembly/AsmDebugger.asm +++ b/hyperdbg/hyperkd/code/assembly/AsmDebugger.asm @@ -57,7 +57,7 @@ SaveTheRegisters: push R15 ; The function will be called as DebuggerCheckForCondition(PGUEST_REGS Regs, PVOID Context); - call R8 ; Because R8 contains the 4th argument and a pointer to the function of target condition code + call R8 ; Because R8 contains the 3th argument and a pointer to the function of target condition code RestoreTheRegisters: pop R15 diff --git a/hyperdbg/hprdbgkd/code/common/Common.c b/hyperdbg/hyperkd/code/common/Common.c similarity index 100% rename from hyperdbg/hprdbgkd/code/common/Common.c rename to hyperdbg/hyperkd/code/common/Common.c diff --git a/hyperdbg/hyperkd/code/common/Synchronization.c b/hyperdbg/hyperkd/code/common/Synchronization.c new file mode 100644 index 00000000..a35b753e --- /dev/null +++ b/hyperdbg/hyperkd/code/common/Synchronization.c @@ -0,0 +1,61 @@ +/** + * @file Synchronization.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Routines synchronization objects + * @details + * @version 0.16 + * @date 2025-08-30 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Initialize a waiting event + * + * @param Event + * @return VOID + */ +VOID +SynchronizationInitializeEvent(PRKEVENT Event) +{ + // + // Initialize an event + // + KeInitializeEvent(Event, SynchronizationEvent, FALSE); +} + +/** + * @brief Set (signal) a waiting event + * + * @param Event + * @return VOID + */ +VOID +SynchronizationSetEvent(PRKEVENT Event) +{ + // + // Set (signal) an event + // + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); +} + +/** + * @brief Wait for a waiting event + * + * @param Event + * @return VOID + */ +VOID +SynchronizationWaitForEvent(PRKEVENT Event) +{ + // + // Wait for an event + // + KeWaitForSingleObject(Event, + Executive, + KernelMode, + FALSE, + NULL); +} diff --git a/hyperdbg/hprdbgkd/code/debugger/broadcast/DpcRoutines.c b/hyperdbg/hyperkd/code/debugger/broadcast/DpcRoutines.c similarity index 76% rename from hyperdbg/hprdbgkd/code/debugger/broadcast/DpcRoutines.c rename to hyperdbg/hyperkd/code/debugger/broadcast/DpcRoutines.c index 643b8834..9296f576 100644 --- a/hyperdbg/hprdbgkd/code/debugger/broadcast/DpcRoutines.c +++ b/hyperdbg/hyperkd/code/debugger/broadcast/DpcRoutines.c @@ -1,4 +1,4 @@ -/** +/** * @file DpcRoutines.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief All the dpc routines which relates to executing on a single core @@ -50,7 +50,7 @@ DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredCo // // Allocate Memory for DPC // - Dpc = CrsAllocateZeroedNonPagedPool(sizeof(KDPC)); + Dpc = PlatformMemAllocateZeroedNonPagedPool(sizeof(KDPC)); if (!Dpc) { @@ -91,7 +91,7 @@ DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredCo // // We can't get the lock, probably sth goes wrong ! // - CrsFreePool(Dpc); + PlatformMemFreePool(Dpc); return STATUS_UNSUCCESSFUL; } @@ -110,7 +110,7 @@ DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredCo // // Now it's safe to deallocate the bugger // - CrsFreePool(Dpc); + PlatformMemFreePool(Dpc); return STATUS_SUCCESS; } @@ -138,7 +138,7 @@ DpcRoutinePerformWriteMsr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgumen // // write on MSR // - __writemsr(CurrentDebuggingState->MsrState.Msr, CurrentDebuggingState->MsrState.Value); + CpuWriteMsr((ULONG)CurrentDebuggingState->MsrState.Msr, CurrentDebuggingState->MsrState.Value); // // As this function is designed for a single, @@ -170,7 +170,7 @@ DpcRoutinePerformReadMsr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument // // read on MSR // - CurrentDebuggingState->MsrState.Value = __readmsr(CurrentDebuggingState->MsrState.Msr); + CurrentDebuggingState->MsrState.Value = CpuReadMsr((ULONG)CurrentDebuggingState->MsrState.Msr); // // As this function is designed for a single, @@ -200,17 +200,12 @@ DpcRoutineWriteMsrToAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgu // // write on MSR // - __writemsr(CurrentDebuggingState->MsrState.Msr, CurrentDebuggingState->MsrState.Value); + CpuWriteMsr((ULONG)CurrentDebuggingState->MsrState.Msr, CurrentDebuggingState->MsrState.Value); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -234,17 +229,12 @@ DpcRoutineReadMsrToAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgum // // read msr // - CurrentDebuggingState->MsrState.Value = __readmsr(CurrentDebuggingState->MsrState.Msr); + CurrentDebuggingState->MsrState.Value = CpuReadMsr((ULONG)CurrentDebuggingState->MsrState.Msr); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); - - // - // Mark the DPC as being complete - // - KeSignalCallDpcDone(SystemArgument1); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); } /** @@ -267,13 +257,36 @@ DpcRoutineVmExitAndHaltSystemAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID S // VmFuncVmxVmcall(DEBUGGER_VMCALL_VM_EXIT_HALT_SYSTEM, 0, 0, 0); + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller // - // Wait for all DPCs to synchronize at this point - // - KeSignalCallDpcSynchronize(SystemArgument2); + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); +} + +/** + * @brief Broadcast applying hardware debug register + * + * @param Dpc + * @param DeferredContext + * @param SystemArgument1 + * @param SystemArgument2 + * @return BOOLEAN + */ +BOOLEAN +DpcRoutineSetHardwareDebugRegisters(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); // - // Mark the DPC as being complete + // Apply hardware debug registers // - KeSignalCallDpcDone(SystemArgument1); + UdApplyHardwareDebugRegister(DeferredContext); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; } diff --git a/hyperdbg/hprdbgkd/code/debugger/broadcast/HaltedBroadcast.c b/hyperdbg/hyperkd/code/debugger/broadcast/HaltedBroadcast.c similarity index 100% rename from hyperdbg/hprdbgkd/code/debugger/broadcast/HaltedBroadcast.c rename to hyperdbg/hyperkd/code/debugger/broadcast/HaltedBroadcast.c diff --git a/hyperdbg/hprdbgkd/code/debugger/broadcast/HaltedRoutines.c b/hyperdbg/hyperkd/code/debugger/broadcast/HaltedRoutines.c similarity index 100% rename from hyperdbg/hprdbgkd/code/debugger/broadcast/HaltedRoutines.c rename to hyperdbg/hyperkd/code/debugger/broadcast/HaltedRoutines.c diff --git a/hyperdbg/hprdbgkd/code/debugger/commands/BreakpointCommands.c b/hyperdbg/hyperkd/code/debugger/commands/BreakpointCommands.c similarity index 79% rename from hyperdbg/hprdbgkd/code/debugger/commands/BreakpointCommands.c rename to hyperdbg/hyperkd/code/debugger/commands/BreakpointCommands.c index 5e500c31..496e600b 100644 --- a/hyperdbg/hprdbgkd/code/debugger/commands/BreakpointCommands.c +++ b/hyperdbg/hyperkd/code/debugger/commands/BreakpointCommands.c @@ -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) { @@ -214,7 +214,8 @@ BreakpointRestoreTheTrapFlagOnceTriggered(UINT32 ProcessId, UINT32 ThreadId) SuccessfullyStored = InsertionSortInsertItem((UINT64 *)&g_TrapFlagState.ThreadInformation[0], &g_TrapFlagState.NumberOfItems, MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_TRAPS, - ProcThrdInfo.asUInt); + &Index, // not used + ProcThrdInfo.AsUInt); goto Return; } @@ -289,9 +290,8 @@ BreakpointCheckAndHandleDebugBreakpoint(UINT32 CoreId) // KdHandleDebugEventsWhenKernelDebuggerIsAttached(DbgState, TrapSetByDebugger); } - else if (UdCheckAndHandleBreakpointsAndDebugBreaks(DbgState, - DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_DEBUG_BREAK, - NULL)) + else if (g_UserDebuggerState == TRUE && + UdHandleDebugEventsWhenUserDebuggerIsAttached(DbgState, TrapSetByDebugger)) { // // if the above function returns true, no need for further action @@ -337,9 +337,8 @@ BreakpointCheckAndHandleDebugBreakpoint(UINT32 CoreId) // KdHandleDebugEventsWhenKernelDebuggerIsAttached(DbgState, TrapSetByDebugger); } - else if (UdCheckAndHandleBreakpointsAndDebugBreaks(DbgState, - DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_DEBUG_BREAK, - NULL)) + else if (g_UserDebuggerState == TRUE && + UdHandleDebugEventsWhenUserDebuggerIsAttached(DbgState, TrapSetByDebugger)) { // // if the above function returns true, no need for further action @@ -433,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) { @@ -460,22 +458,6 @@ BreakpointCheckAndHandleReApplyingBreakpoint(UINT32 CoreId) (UINT64)&BreakpointByte, sizeof(BYTE)); - // - // Check if we should re-enabled IF bit of RFLAGS or not - // - if (DbgState->SoftwareBreakpointState->SetRflagsIFBitOnMtf) - { - RFLAGS Rflags = {0}; - - Rflags.AsUInt = VmFuncGetRflags(); - - Rflags.InterruptEnableFlag = TRUE; - - VmFuncSetRflags(Rflags.AsUInt); - - DbgState->SoftwareBreakpointState->SetRflagsIFBitOnMtf = FALSE; - } - DbgState->SoftwareBreakpointState = NULL; } @@ -503,7 +485,6 @@ BreakpointCheckAndHandleDebuggerDefinedBreakpoints(PROCESSOR_DEBUGGING_STATE * D PLIST_ENTRY TempList = 0; UINT64 GuestRipPhysical = (UINT64)NULL; DEBUGGER_TRIGGERED_EVENT_DETAILS TargetContext = {0}; - RFLAGS Rflags = {0}; BOOLEAN AvoidUnsetMtf = FALSE; BOOLEAN IgnoreUserHandling = FALSE; @@ -601,9 +582,20 @@ BreakpointCheckAndHandleDebuggerDefinedBreakpoints(PROCESSOR_DEBUGGING_STATE * D // *** It's not safe to access CurrentBreakpointDesc anymore as the // breakpoint might be removed *** // - KdHandleBreakpointAndDebugBreakpoints(DbgState, - Reason, - &TargetContext); + if (g_KernelDebuggerState) + { + KdHandleBreakpointAndDebugBreakpoints(DbgState, + Reason, + &TargetContext); + } + else if (g_UserDebuggerState) + { + UdHandleInstantBreak(DbgState, Reason, NULL); + } + else + { + LogInfo("Err, no debugger is attached to handle the breakpoint"); + } } } @@ -623,34 +615,20 @@ BreakpointCheckAndHandleDebuggerDefinedBreakpoints(PROCESSOR_DEBUGGING_STATE * D // DbgState->SoftwareBreakpointState = CurrentBreakpointDesc; - // - // Fire and MTF - // - VmFuncSetMonitorTrapFlag(TRUE); - AvoidUnsetMtf = TRUE; - // // As we want to continue debuggee, the MTF might arrive when the // host finish executing it's time slice; thus, a clock interrupt // or an IPI might be arrived and the next instruction is not what - // we expect, because of that we check if the IF (Interrupt enable) - // flag of RFLAGS is enabled or not, if enabled then we remove it - // to avoid any clock-interrupt or IPI to arrive and the next - // instruction is our next instruction in the current execution - // context + // we expect. The following codes are added because we realized if the execution takes long then + // the execution might be switched to another routines, thus, MTF might conclude on + // another routine and we might (and will) trigger the same instruction soon // - Rflags.AsUInt = VmFuncGetRflags(); + VmFuncEnableMtfAndChangeExternalInterruptState(DbgState->CoreId); - if (Rflags.InterruptEnableFlag) - { - Rflags.InterruptEnableFlag = FALSE; - VmFuncSetRflags(Rflags.AsUInt); - - // - // An indicator to restore RFLAGS if to enabled state - // - DbgState->SoftwareBreakpointState->SetRflagsIFBitOnMtf = TRUE; - } + // + // Avoid unsetting MTF + // + AvoidUnsetMtf = TRUE; } // @@ -687,66 +665,106 @@ BreakpointHandleBreakpoints(UINT32 CoreId) UINT64 GuestRip = 0; PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId]; + GuestRip = VmFuncGetRip(); + + // + // A breakpoint triggered and two things might be happened, + // first, a breakpoint is triggered randomly in the computer and + // we shouldn't do anything on it (won't change the instruction) + // second, the breakpoint is because of the 'bp' command, we should + // replace it with exact byte + // + + // + // Check if the breakpoint is handled by the debugger routines + // + if (BreakpointCheckAndHandleDebuggerDefinedBreakpoints(DbgState, + GuestRip, + DEBUGGEE_PAUSING_REASON_DEBUGGEE_SOFTWARE_BREAKPOINT_HIT, + FALSE)) + { + // + // The breakpoint is handled by the debugger routines + // so, we don't need to do anything else + // + return TRUE; + } + // // re-inject #BP back to the guest if not handled by the hidden breakpoint // - if (g_KernelDebuggerState) { // - // Kernel debugger is attached, let's halt everything - // - GuestRip = VmFuncGetRip(); - - // - // A breakpoint triggered and two things might be happened, - // first, a breakpoint is triggered randomly in the computer and - // we shouldn't do anything on it (won't change the instruction) - // second, the breakpoint is because of the 'bp' command, we should - // replace it with exact byte + // *** Kernel debugger is attached, let's halt everything *** // - if (!BreakpointCheckAndHandleDebuggerDefinedBreakpoints(DbgState, - GuestRip, - DEBUGGEE_PAUSING_REASON_DEBUGGEE_SOFTWARE_BREAKPOINT_HIT, - FALSE)) + // + // To avoid the computer crash situation from the HyperDbg's breakpoint hitting while the interception is on + // we should always call BreakpointCheckAndHandleDebuggerDefinedBreakpoints first to handle the breakpoint + // + + if (g_InterceptBreakpoints || g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer) { // - // To avoid the computer crash situation from the HyperDbg's breakpoint hitting while the interception is on - // we should always call BreakpointCheckAndHandleDebuggerDefinedBreakpoints first to handle the breakpoint + // re-inject back to the guest as not handled if the interception is on and the breakpoint is not from the Hyperdbg's breakpoints // + return FALSE; + } - if (g_InterceptBreakpoints || g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer) - { - // - // re-inject back to the guest as not handled if the interception is on and the breakpoint is not from the Hyperdbg's breakpoints - // - return FALSE; - } + // + // It's a random breakpoint byte + // + TargetContext.Context = (PVOID)GuestRip; + KdHandleBreakpointAndDebugBreakpoints(DbgState, + DEBUGGEE_PAUSING_REASON_DEBUGGEE_SOFTWARE_BREAKPOINT_HIT, + &TargetContext); + // + // Increment rip + // + VmFuncPerformRipIncrement(DbgState->CoreId); + + // + // By default, we handle the random breakpoints if the kernel debugger is attached + // + return TRUE; + } + else if (g_UserDebuggerState) + { + // + // *** User debugger is attached, let's halt the process *** + // + + // + // Check if it's a random breakpoint byte + // + if (UdHandleInstantBreak(DbgState, + DEBUGGEE_PAUSING_REASON_DEBUGGEE_SOFTWARE_BREAKPOINT_HIT, + NULL)) + { // - // It's a random breakpoint byte + // if the above function returns true, it's handled in the user debugger // - TargetContext.Context = (PVOID)GuestRip; - KdHandleBreakpointAndDebugBreakpoints(DbgState, - DEBUGGEE_PAUSING_REASON_DEBUGGEE_SOFTWARE_BREAKPOINT_HIT, - &TargetContext); // // Increment rip // VmFuncPerformRipIncrement(DbgState->CoreId); + + return TRUE; } - } - else - { + // - // re-inject back to the guest as not handled here + // By default, we won't handle the random (unrelated) breakpoints in the user debugger // return FALSE; } - return TRUE; + // + // *** re-inject back to the guest as not handled here *** + // + return FALSE; } /** @@ -754,11 +772,12 @@ BreakpointHandleBreakpoints(UINT32 CoreId) * @detail this function won't remove the descriptor from the list * * @param BreakpointDescriptor + * @param SwitchToTargetMemoryLayout If TRUE, it will switch to the target memory layout * * @return BOOLEAN */ BOOLEAN -BreakpointWrite(PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor) +BreakpointWrite(PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor, BOOLEAN SwitchToTargetMemoryLayout) { BYTE PreviousByte = NULL_ZERO; BYTE BreakpointByte = 0xcc; // int 3 @@ -766,15 +785,44 @@ BreakpointWrite(PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor) // // Check if address is safe (only one byte for 0xcc) // - if (!CheckAccessValidityAndSafety(BreakpointDescriptor->Address, sizeof(BYTE))) + + if (SwitchToTargetMemoryLayout) { - return FALSE; + if (!CheckAccessValidityAndSafetyByProcessId(BreakpointDescriptor->Address, sizeof(BYTE), BreakpointDescriptor->Pid)) + { + return FALSE; + } + } + else + { + if (!CheckAccessValidityAndSafety(BreakpointDescriptor->Address, sizeof(BYTE))) + { + return FALSE; + } } // // Read and save previous byte and save it to the descriptor // - MemoryMapperReadMemorySafeOnTargetProcess(BreakpointDescriptor->Address, &PreviousByte, sizeof(BYTE)); + if (SwitchToTargetMemoryLayout) + { + MemoryMapperReadMemoryUnsafe( + BreakpointDescriptor->Address, + &PreviousByte, + sizeof(BYTE), + BreakpointDescriptor->Pid); + } + else + { + MemoryMapperReadMemorySafeOnTargetProcess( + BreakpointDescriptor->Address, + &PreviousByte, + sizeof(BYTE)); + } + + // + // Store the previous byte + // BreakpointDescriptor->PreviousByte = PreviousByte; // @@ -786,9 +834,18 @@ BreakpointWrite(PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor) // // Apply the breakpoint // - MemoryMapperWriteMemorySafeByPhysicalAddress(BreakpointDescriptor->PhysAddress, - (UINT64)&BreakpointByte, - sizeof(BYTE)); + if (SwitchToTargetMemoryLayout) + { + MemoryMapperWriteMemorySafeFromVmxNonRootyPhysicalAddress(BreakpointDescriptor->PhysAddress, + (PVOID)&BreakpointByte, + sizeof(BYTE)); + } + else + { + MemoryMapperWriteMemorySafeByPhysicalAddress(BreakpointDescriptor->PhysAddress, + (UINT64)&BreakpointByte, + sizeof(BYTE)); + } return TRUE; } @@ -885,34 +942,46 @@ BreakpointGetEntryByAddress(UINT64 Address) /** * @brief Add new breakpoints * @param BpDescriptor + * @param SwitchToTargetMemoryLayout * * @return BOOLEAN */ BOOLEAN -BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg) +BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg, BOOLEAN SwitchToTargetMemoryLayout) { - PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor = NULL; CR3_TYPE GuestCr3 = {0}; + PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor = NULL; BOOLEAN IsAddress32Bit = FALSE; // // Find the current process cr3 // - GuestCr3.Flags = LayoutGetCurrentProcessCr3().Flags; + if (SwitchToTargetMemoryLayout) + { + // + // Check if the process id is valid or not + // + if (BpDescriptorArg->Pid != DEBUGGEE_BP_APPLY_TO_ALL_PROCESSES && + !CommonIsProcessExist(BpDescriptorArg->Pid)) + { + // + // Process id is invalid (Set the error) + // + BpDescriptorArg->Result = DEBUGGER_ERROR_INVALID_PROCESS_ID; + return FALSE; + } + + GuestCr3.Flags = LayoutGetCr3ByProcessId(BpDescriptorArg->Pid).Flags; + } + else + { + GuestCr3.Flags = LayoutGetCurrentProcessCr3().Flags; + } // // *** Validate arguments *** // - // - // Check if address is safe (only one byte for 0xcc) - // - if (!CheckAccessValidityAndSafety(BpDescriptorArg->Address, sizeof(BYTE))) - { - BpDescriptorArg->Result = DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS; - return FALSE; - } - // // Check if the core number is not invalid // @@ -939,7 +1008,27 @@ BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg) } // - // We won't check for process id and thread id, if these arguments are invalid + // Check if address is safe (only one byte for 0xcc) + // + if (SwitchToTargetMemoryLayout) + { + if (!CheckAccessValidityAndSafetyByProcessId(BpDescriptorArg->Address, sizeof(BYTE), BpDescriptorArg->Pid)) + { + BpDescriptorArg->Result = DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS; + return FALSE; + } + } + else + { + if (!CheckAccessValidityAndSafety(BpDescriptorArg->Address, sizeof(BYTE))) + { + BpDescriptorArg->Result = DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS; + return FALSE; + } + } + + // + // On the debugger mode, we won't check for process id and thread id, if these arguments are invalid // then the HyperDbg simply ignores the breakpoints but it makes the computer slow // it just won't be triggered // @@ -952,7 +1041,8 @@ BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg) // // Get the pre-allocated buffer // - BreakpointDescriptor = (DEBUGGEE_BP_DESCRIPTOR *)PoolManagerRequestPool(BREAKPOINT_DEFINITION_STRUCTURE, TRUE, sizeof(DEBUGGEE_BP_DESCRIPTOR)); + BreakpointDescriptor = (DEBUGGEE_BP_DESCRIPTOR *) + PoolManagerRequestPool(BREAKPOINT_DEFINITION_STRUCTURE, TRUE, sizeof(DEBUGGEE_BP_DESCRIPTOR)); if (BreakpointDescriptor == NULL) { @@ -994,15 +1084,32 @@ BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg) // The address is not a kernel address, thus, we check whether the debuggee is running on user-mode // or not // - IsAddress32Bit = KdIsGuestOnUsermode32Bit(); + if (SwitchToTargetMemoryLayout) + { + UserAccessIsWow64Process((HANDLE)BpDescriptorArg->Pid, &IsAddress32Bit); + } + else + { + IsAddress32Bit = KdIsGuestOnUsermode32Bit(); + } } // // Use length disassembler engine to get the instruction length // - BreakpointDescriptor->InstructionLength = (UINT16)DisassemblerLengthDisassembleEngineInVmxRootOnTargetProcess( - (PVOID)BpDescriptorArg->Address, - IsAddress32Bit); + if (SwitchToTargetMemoryLayout) + { + BreakpointDescriptor->InstructionLength = (UINT16)DisassemblerLengthDisassembleEngineByProcessId( + (PVOID)BpDescriptorArg->Address, + IsAddress32Bit, + BpDescriptorArg->Pid); + } + else + { + BreakpointDescriptor->InstructionLength = (UINT16)DisassemblerLengthDisassembleEngineInVmxRootOnTargetProcess( + (PVOID)BpDescriptorArg->Address, + IsAddress32Bit); + } // // Breakpoints are enabled by default @@ -1017,7 +1124,7 @@ BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg) // // Apply the breakpoint // - BreakpointWrite(BreakpointDescriptor); + BreakpointWrite(BreakpointDescriptor, SwitchToTargetMemoryLayout); // // Show that operation was successful @@ -1081,11 +1188,12 @@ BreakpointListAllBreakpoint() /** * @brief List of modify breakpoints * @param ListOrModifyBreakpoints + * @param SwitchToTargetMemoryLayout * * @return BOOLEAN */ BOOLEAN -BreakpointListOrModify(PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET ListOrModifyBreakpoints) +BreakpointListOrModify(PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET ListOrModifyBreakpoints, BOOLEAN SwitchToTargetMemoryLayout) { PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor = NULL; @@ -1118,7 +1226,7 @@ BreakpointListOrModify(PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET ListOrModifyBreakpoint // // Set the breakpoint (without removing from list) // - BreakpointWrite(BreakpointDescriptor); + BreakpointWrite(BreakpointDescriptor, SwitchToTargetMemoryLayout); } else if (ListOrModifyBreakpoints->Request == DEBUGGEE_BREAKPOINT_MODIFICATION_REQUEST_DISABLE) { diff --git a/hyperdbg/hprdbgkd/code/debugger/commands/Callstack.c b/hyperdbg/hyperkd/code/debugger/commands/Callstack.c similarity index 86% rename from hyperdbg/hprdbgkd/code/debugger/commands/Callstack.c rename to hyperdbg/hyperkd/code/debugger/commands/Callstack.c index e7d220dc..6587d5b5 100644 --- a/hyperdbg/hprdbgkd/code/debugger/commands/Callstack.c +++ b/hyperdbg/hyperkd/code/debugger/commands/Callstack.c @@ -15,6 +15,7 @@ * @brief Walkthrough the stack * * @param AddressToSaveFrames + * @param FrameCount * @param StackBaseAddress * @param Size * @param Is32Bit @@ -23,6 +24,7 @@ */ BOOLEAN CallstackWalkthroughStack(PDEBUGGER_SINGLE_CALLSTACK_FRAME AddressToSaveFrames, + UINT32 * FrameCount, UINT64 StackBaseAddress, UINT32 Size, BOOLEAN Is32Bit) @@ -57,12 +59,13 @@ 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 // CurrentStackAddress = StackBaseAddress + (i * AddressMode); + *FrameCount = FrameIndex; if (!CheckAccessValidityAndSafety(CurrentStackAddress, AddressMode)) { @@ -71,7 +74,20 @@ CallstackWalkthroughStack(PDEBUGGER_SINGLE_CALLSTACK_FRAME AddressToSaveFrames, // // Stack is no longer valid or available to access from here // - return FALSE; + if (FrameIndex == 0) + { + // + // Stack is invalid + // + return FALSE; + } + else + { + // + // Stack is invalid, but there are frames that are still valid + // + return TRUE; + } } // diff --git a/hyperdbg/hprdbgkd/code/debugger/commands/DebuggerCommands.c b/hyperdbg/hyperkd/code/debugger/commands/DebuggerCommands.c similarity index 90% rename from hyperdbg/hprdbgkd/code/debugger/commands/DebuggerCommands.c rename to hyperdbg/hyperkd/code/debugger/commands/DebuggerCommands.c index 9fea5784..940d0946 100644 --- a/hyperdbg/hprdbgkd/code/debugger/commands/DebuggerCommands.c +++ b/hyperdbg/hyperkd/code/debugger/commands/DebuggerCommands.c @@ -12,6 +12,55 @@ */ #include "pch.h" +/** + * @brief read registers + * @param Regs + * @param ReadRegisterRequest + * + * @return BOOLEAN + */ +BOOLEAN +DebuggerCommandReadRegisters(GUEST_REGS * Regs, + PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterRequest) +{ + GUEST_EXTRA_REGISTERS ERegs = {0}; + + if (ReadRegisterRequest->RegisterId == DEBUGGEE_SHOW_ALL_REGISTERS) + { + // + // Add General purpose registers + // + memcpy((PVOID)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION)), + Regs, + sizeof(GUEST_REGS)); + + // + // Read Extra registers + // + ERegs.CS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_CS); + ERegs.SS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_SS); + ERegs.DS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_DS); + ERegs.ES = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_ES); + ERegs.FS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_FS); + ERegs.GS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_GS); + ERegs.RFLAGS = DebuggerGetRegValueWrapper(NULL, REGISTER_RFLAGS); + ERegs.RIP = DebuggerGetRegValueWrapper(NULL, REGISTER_RIP); + + // + // copy at the end of ReadRegisterRequest structure + // + memcpy((PVOID)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) + sizeof(GUEST_REGS)), + &ERegs, + sizeof(GUEST_EXTRA_REGISTERS)); + } + else + { + ReadRegisterRequest->Value = DebuggerGetRegValueWrapper(Regs, ReadRegisterRequest->RegisterId); + } + + return TRUE; +} + /** * @brief Read memory for different commands * @@ -59,7 +108,7 @@ DebuggerCommandReadMemory(PDEBUGGER_READ_MEMORY ReadMemRequest, PVOID UserBuffer // // Check if the address is on a 32-bit mode process or not (just in case of disassembling) // - if (ReadMemRequest->MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS && ReadMemRequest->IsForDisasm) + if (ReadMemRequest->MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS && ReadMemRequest->GetAddressMode) { // // Check if the address is in the canonical range for kernel space @@ -69,7 +118,7 @@ DebuggerCommandReadMemory(PDEBUGGER_READ_MEMORY ReadMemRequest, PVOID UserBuffer // // The address is in the range of canonical kernel space, so it's 64-bit process // - ReadMemRequest->Is32BitAddress = FALSE; + ReadMemRequest->AddressMode = DEBUGGER_READ_ADDRESS_MODE_64_BIT; } else { @@ -80,7 +129,14 @@ DebuggerCommandReadMemory(PDEBUGGER_READ_MEMORY ReadMemRequest, PVOID UserBuffer // if (UserAccessIsWow64Process((HANDLE)ReadMemRequest->Pid, &Is32BitProcess)) { - ReadMemRequest->Is32BitAddress = Is32BitProcess; + if (Is32BitProcess) + { + ReadMemRequest->AddressMode = DEBUGGER_READ_ADDRESS_MODE_32_BIT; + } + else + { + ReadMemRequest->AddressMode = DEBUGGER_READ_ADDRESS_MODE_64_BIT; + } } else { @@ -88,7 +144,7 @@ DebuggerCommandReadMemory(PDEBUGGER_READ_MEMORY ReadMemRequest, PVOID UserBuffer // We couldn't determine the type of process, let's assume that it's a // 64-bit process by default // - ReadMemRequest->Is32BitAddress = FALSE; + ReadMemRequest->AddressMode = DEBUGGER_READ_ADDRESS_MODE_64_BIT; } } } @@ -152,7 +208,7 @@ DebuggerCommandReadMemoryVmxRoot(PDEBUGGER_READ_MEMORY ReadMemRequest, UCHAR * U // if (!CheckAddressPhysical(Address)) { - ReadMemRequest->KernelStatus = DEBUGGER_ERROR_INVALID_ADDRESS; + ReadMemRequest->KernelStatus = DEBUGGER_ERROR_INVALID_PHYSICAL_ADDRESS; return FALSE; } @@ -219,7 +275,7 @@ DebuggerCommandReadMemoryVmxRoot(PDEBUGGER_READ_MEMORY ReadMemRequest, UCHAR * U // // Check if the address is on a 32-bit mode process or not (just in case of disassembling) // - if (ReadMemRequest->MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS && ReadMemRequest->IsForDisasm) + if (ReadMemRequest->MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS && ReadMemRequest->GetAddressMode) { // // Check if the address is in the canonical range for kernel space @@ -229,7 +285,7 @@ DebuggerCommandReadMemoryVmxRoot(PDEBUGGER_READ_MEMORY ReadMemRequest, UCHAR * U // // The address is in the range of canonical kernel space, so it's 64-bit process // - ReadMemRequest->Is32BitAddress = FALSE; + ReadMemRequest->AddressMode = DEBUGGER_READ_ADDRESS_MODE_64_BIT; } else { @@ -240,7 +296,14 @@ DebuggerCommandReadMemoryVmxRoot(PDEBUGGER_READ_MEMORY ReadMemRequest, UCHAR * U // if (UserAccessIsWow64ProcessByEprocess(PsGetCurrentProcess(), &Is32BitProcess)) { - ReadMemRequest->Is32BitAddress = Is32BitProcess; + if (Is32BitProcess) + { + ReadMemRequest->AddressMode = DEBUGGER_READ_ADDRESS_MODE_32_BIT; + } + else + { + ReadMemRequest->AddressMode = DEBUGGER_READ_ADDRESS_MODE_64_BIT; + } } else { @@ -248,7 +311,7 @@ DebuggerCommandReadMemoryVmxRoot(PDEBUGGER_READ_MEMORY ReadMemRequest, UCHAR * U // We couldn't determine the type of process, let's assume that it's a // 64-bit process by default // - ReadMemRequest->Is32BitAddress = FALSE; + ReadMemRequest->AddressMode = DEBUGGER_READ_ADDRESS_MODE_64_BIT; } } } @@ -294,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; @@ -348,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; } @@ -362,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; } @@ -479,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))); @@ -488,21 +551,38 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest) // Instead of directly accessing the memory we use the MemoryMapperWriteMemorySafe // It is because the target page might be read-only so we can make it writable // + // RtlCopyBytes(DestinationAddress, SourceAddress, LengthOfEachChunk); MemoryMapperWriteMemoryUnsafe((UINT64)DestinationAddress, SourceAddress, LengthOfEachChunk, EditMemRequest->ProcessId); } } else if (EditMemRequest->MemoryType == EDIT_PHYSICAL_MEMORY) { + // + // Check whether the physical address + // + if (!CheckAddressPhysical(EditMemRequest->Address)) + { + EditMemRequest->Result = DEBUGGER_ERROR_INVALID_ADDRESS; + return STATUS_UNSUCCESSFUL; + } + // // 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))); - MemoryMapperWriteMemorySafeByPhysicalAddress((UINT64)DestinationAddress, (UINT64)SourceAddress, LengthOfEachChunk); + // MemoryMapperWriteMemorySafeByPhysicalAddress((UINT64)DestinationAddress, (UINT64)SourceAddress, LengthOfEachChunk); + // WritePhysicalMemoryUsingMapIoSpace((PVOID)SourceAddress, (PVOID)DestinationAddress, LengthOfEachChunk); + + if (MemoryManagerWritePhysicalMemoryNormal((PVOID)DestinationAddress, (PVOID)SourceAddress, (SIZE_T)LengthOfEachChunk) == FALSE) + { + EditMemRequest->Result = DEBUGGER_ERROR_INVALID_ADDRESS; + return STATUS_UNSUCCESSFUL; + } } } else @@ -515,7 +595,7 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest) } // - // Set the resutls + // Set the results // EditMemRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; @@ -572,14 +652,14 @@ DebuggerCommandEditMemoryVmxRoot(PDEBUGGER_EDIT_MEMORY EditMemRequest) if (!CheckAccessValidityAndSafety(EditMemRequest->Address, EditMemRequest->ByteSize * EditMemRequest->CountOf64Chunks)) { - EditMemRequest->KernelStatus = DEBUGGER_ERROR_INVALID_ADDRESS; + EditMemRequest->Result = DEBUGGER_ERROR_INVALID_ADDRESS; return FALSE; } // // 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))); @@ -595,10 +675,19 @@ DebuggerCommandEditMemoryVmxRoot(PDEBUGGER_EDIT_MEMORY EditMemRequest) } else if (EditMemRequest->MemoryType == EDIT_PHYSICAL_MEMORY) { + // + // Check whether the physical address + // + if (!CheckAddressPhysical(EditMemRequest->Address)) + { + EditMemRequest->Result = DEBUGGER_ERROR_INVALID_ADDRESS; + return FALSE; + } + // // 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))); @@ -616,10 +705,9 @@ DebuggerCommandEditMemoryVmxRoot(PDEBUGGER_EDIT_MEMORY EditMemRequest) } // - // Set the resutls + // Set the results // EditMemRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - return TRUE; } @@ -717,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 *** @@ -756,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 ;) @@ -1133,7 +1221,7 @@ DebuggerCommandSearchMemory(PDEBUGGER_SEARCH_MEMORY SearchMemRequest) // // We support up to MaximumSearchResults search results // - SearchResultsStorage = CrsAllocateZeroedNonPagedPool(MaximumSearchResults * sizeof(UINT64)); + SearchResultsStorage = PlatformMemAllocateZeroedNonPagedPool(MaximumSearchResults * sizeof(UINT64)); if (SearchResultsStorage == NULL) { @@ -1164,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]; @@ -1189,7 +1277,7 @@ DebuggerCommandSearchMemory(PDEBUGGER_SEARCH_MEMORY SearchMemRequest) // // Free the results pool // - CrsFreePool(SearchResultsStorage); + PlatformMemFreePool(SearchResultsStorage); return STATUS_SUCCESS; } @@ -1416,7 +1504,7 @@ DebuggerCommandPreactivateFunctionality(PDEBUGGER_PREACTIVATE_COMMAND Preactivat case DEBUGGER_PREACTIVATE_COMMAND_TYPE_MODE: // - // Request for allocating the mode mechanism + // Request for enabling the mode mechanism // ConfigureInitializeExecTrapOnAllProcessors(); diff --git a/hyperdbg/hprdbgkd/code/debugger/commands/ExtensionCommands.c b/hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c similarity index 62% rename from hyperdbg/hprdbgkd/code/debugger/commands/ExtensionCommands.c rename to hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c index 22e7b30b..4f16b619 100644 --- a/hyperdbg/hprdbgkd/code/debugger/commands/ExtensionCommands.c +++ b/hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c @@ -12,6 +12,97 @@ */ #include "pch.h" +/** + * @brief Perform actions regarding APIC + * + * @param ApicRequest + * + * @return UINT32 Size to send to the debuggee + */ +UINT32 +ExtensionCommandPerformActionsForApicRequests(PDEBUGGER_APIC_REQUEST ApicRequest) +{ + BOOLEAN IsUsingX2APIC = FALSE; + PLAPIC_PAGE BufferToStoreLApic = (LAPIC_PAGE *)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)); + PIO_APIC_ENTRY_PACKETS BufferToStoreIoApic = (IO_APIC_ENTRY_PACKETS *)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)); + + if (ApicRequest->ApicType == DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC) + { + if (VmFuncApicStoreLocalApicFields(BufferToStoreLApic, &IsUsingX2APIC)) + { + // + // The status was okay + // + ApicRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + ApicRequest->IsUsingX2APIC = IsUsingX2APIC; + + return sizeof(DEBUGGER_APIC_REQUEST) + sizeof(LAPIC_PAGE); + } + else + { + // + // There was an error performing the action + // + ApicRequest->KernelStatus = DEBUGGER_ERROR_APIC_ACTIONS_ERROR; + + return sizeof(DEBUGGER_APIC_REQUEST); + } + } + else if (ApicRequest->ApicType == DEBUGGER_APIC_REQUEST_TYPE_READ_IO_APIC) + { + if (VmFuncApicStoreIoApicFields(BufferToStoreIoApic)) + { + // + // The status was okay + // + ApicRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + return sizeof(DEBUGGER_APIC_REQUEST) + sizeof(IO_APIC_ENTRY_PACKETS); + } + else + { + // + // There was an error performing the action + // + ApicRequest->KernelStatus = DEBUGGER_ERROR_APIC_ACTIONS_ERROR; + + return sizeof(DEBUGGER_APIC_REQUEST); + } + } + else + { + // + // Invalid request + // + ApicRequest->KernelStatus = DEBUGGER_ERROR_APIC_ACTIONS_ERROR; + + return sizeof(DEBUGGER_APIC_REQUEST); + } +} + +/** + * @brief Perform query for IDT entries + * + * @param IdtQueryRequest + * @param ReadFromVmxRoot + * + * @return VOID + */ +VOID +ExtensionCommandPerformQueryIdtEntriesRequest(PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtQueryRequest, + BOOLEAN ReadFromVmxRoot) +{ + // + // Perform the query + // + VmFuncIdtQueryEntries(IdtQueryRequest, ReadFromVmxRoot); + + // + // Operation was successful + // + IdtQueryRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; +} + /** * @brief routines for !va2pa and !pa2va commands * @@ -593,3 +684,151 @@ ExtensionCommandIoBitmapResetAllCores() // BroadcastIoBitmapResetAllCores(); } + +/** + * @brief routines for PCIe tree + * + * @param PcitreePacket + * @param OperateOnVmxRoot + * + * @return VOID + */ +VOID +ExtensionCommandPcitree(PDEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET PcitreePacket, BOOLEAN OperateOnVmxRoot) +{ + DWORD DeviceIdVendorId = 0xFFFFFFFF; + DWORD ClassCode = 0xFFFFFFFF; + UINT8 DevNum = 0; + + // + // We currently don't use OperateOnVmxRoot, but we might in the future + // + UNREFERENCED_PARAMETER(OperateOnVmxRoot); + + for (UINT8 b = 0; b < BUS_MAX_NUM; b++) + { + for (UINT8 d = 0; d < DEVICE_MAX_NUM; d++) + { + for (UINT8 f = 0; f < FUNCTION_MAX_NUM; f++) + { + DeviceIdVendorId = (DWORD)PciReadCam(b, d, f, 0, sizeof(DWORD)); + + if (DeviceIdVendorId != 0xFFFFFFFF) + { + PcitreePacket->DeviceInfoList[DevNum].Bus = b; + PcitreePacket->DeviceInfoList[DevNum].Device = d; + PcitreePacket->DeviceInfoList[DevNum].Function = f; + PcitreePacket->DeviceInfoList[DevNum].ConfigSpace.VendorId = (UINT16)(DeviceIdVendorId & 0xFFFF); + PcitreePacket->DeviceInfoList[DevNum].ConfigSpace.DeviceId = (UINT16)(DeviceIdVendorId >> 16); + + ClassCode = (DWORD)PciReadCam(b, d, f, 0, sizeof(DWORD)); + PcitreePacket->DeviceInfoList[DevNum].ConfigSpace.ClassCode[0] = (UINT8)((ClassCode >> 24) & 0xFF); + PcitreePacket->DeviceInfoList[DevNum].ConfigSpace.ClassCode[1] = (UINT8)((ClassCode >> 16) & 0xFF); + PcitreePacket->DeviceInfoList[DevNum].ConfigSpace.ClassCode[2] = (UINT8)((ClassCode >> 8) & 0xFF); + + DevNum++; + if (DevNum == DEV_MAX_NUM) + { + LogError("Reached maximum number of devices (%u) that can be stored in debuggee response packet.\n", DEV_MAX_NUM); + break; + } + } + } + } + } + PcitreePacket->DeviceInfoListNum = DevNum; + + if (PcitreePacket->DeviceInfoListNum) + { + PcitreePacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + else + { + PcitreePacket->KernelStatus = DEBUGGER_ERROR_INVALID_ADDRESS; + } +} + +/** + * @brief Request PCI device info. + * + * @param PcidevinfoPacket + * @param OperateOnVmxRoot + * + * @return VOID + */ +VOID +ExtensionCommandPcidevinfo(PDEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET PcidevinfoPacket, BOOLEAN OperateOnVmxRoot) +{ + DWORD DeviceIdVendorId = 0xFFFFFFFF; + + // + // We currently don't use OperateOnVmxRoot, but we might in the future + // + UNREFERENCED_PARAMETER(OperateOnVmxRoot); + + DeviceIdVendorId = (DWORD)PciReadCam(PcidevinfoPacket->DeviceInfo.Bus, PcidevinfoPacket->DeviceInfo.Device, PcidevinfoPacket->DeviceInfo.Function, 0, 4); + if (DeviceIdVendorId != 0xFFFFFFFF) + { + DWORD * cs = (DWORD *)&PcidevinfoPacket->DeviceInfo.ConfigSpace; // Overflows into .ConfigSpaceAdditional - no padding due to pack(0) + for (UINT16 i = 0; i < CAM_CONFIG_SPACE_LENGTH; i += 4) + { + *cs = (DWORD)PciReadCam(PcidevinfoPacket->DeviceInfo.Bus, PcidevinfoPacket->DeviceInfo.Device, PcidevinfoPacket->DeviceInfo.Function, (BYTE)i, 4); + cs++; + } + + // + // For endpoints, determine MMIO BAR addressable range and size (if any). + // Do not determine BAR size if user has requested raw dump. + // + if ((PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01) << 7 == 0 // Endpoint + && !PcidevinfoPacket->PrintRaw) + { + for (UINT8 i = 0; i < 5; i++) + { + if ((PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x1) == 0) // Memory I/O + { + if (((PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1) == 2) // 64-bit BAR + { + UINT64 BarMsb = PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i + 1]; + UINT64 BarLsb = PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i]; + UINT64 Bar64 = ((BarMsb & 0xFFFFFFFF) << 32) + (BarLsb & 0xFFFFFFF0); + + PcidevinfoPacket->DeviceInfo.MmioBarInfo[i].Is64Bit = TRUE; + if (Bar64 == 0) + { + PcidevinfoPacket->DeviceInfo.MmioBarInfo[i].IsEnabled = FALSE; + continue; + } + + PcidevinfoPacket->DeviceInfo.MmioBarInfo[i].Is64Bit = TRUE; + PcidevinfoPacket->DeviceInfo.MmioBarInfo[i].IsEnabled = TRUE; + + i++; + } + else // 32-bit BAR + { + UINT32 Bar32 = (PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0xFFFFFFF0); + + PcidevinfoPacket->DeviceInfo.MmioBarInfo[i].Is64Bit = FALSE; + if (Bar32 == 0) + { + PcidevinfoPacket->DeviceInfo.MmioBarInfo[i].IsEnabled = FALSE; + continue; + } + + PcidevinfoPacket->DeviceInfo.MmioBarInfo[i].Is64Bit = FALSE; + PcidevinfoPacket->DeviceInfo.MmioBarInfo[i].IsEnabled = TRUE; + } + } + } + } + + PcidevinfoPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + else + { + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.DeviceId = 0xFFFF; + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.VendorId = 0xFFFF; + PcidevinfoPacket->KernelStatus = DEBUGGER_ERROR_INVALID_ADDRESS; + } +} diff --git a/hyperdbg/hprdbgkd/code/debugger/communication/SerialConnection.c b/hyperdbg/hyperkd/code/debugger/communication/SerialConnection.c similarity index 94% rename from hyperdbg/hprdbgkd/code/debugger/communication/SerialConnection.c rename to hyperdbg/hyperkd/code/debugger/communication/SerialConnection.c index e1791071..f7c55d7a 100644 --- a/hyperdbg/hprdbgkd/code/debugger/communication/SerialConnection.c +++ b/hyperdbg/hyperkd/code/debugger/communication/SerialConnection.c @@ -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); } @@ -160,13 +160,13 @@ SerialConnectionSend(CHAR * Buffer, UINT32 Length) if (Length + SERIAL_END_OF_BUFFER_CHARS_COUNT > MaxSerialPacketSize) { LogError("Err, buffer is above the maximum buffer size that can be sent to debuggee (%d > %d), " - "for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/increase-communication-buffer-size", + "for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/increase-communication-buffer-size", Length + SERIAL_END_OF_BUFFER_CHARS_COUNT, MaxSerialPacketSize); return FALSE; } - for (size_t i = 0; i < Length; i++) + for (SIZE_T i = 0; i < Length; i++) { KdHyperDbgSendByte(Buffer[i], TRUE); } @@ -197,7 +197,7 @@ SerialConnectionSendTwoBuffers(CHAR * Buffer1, UINT32 Length1, CHAR * Buffer2, U if ((Length1 + Length2 + SERIAL_END_OF_BUFFER_CHARS_COUNT) > MaxSerialPacketSize) { LogError("Err, buffer is above the maximum buffer size that can be sent to debuggee (%d > %d), " - "for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/increase-communication-buffer-size", + "for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/increase-communication-buffer-size", Length1 + Length2 + SERIAL_END_OF_BUFFER_CHARS_COUNT, MaxSerialPacketSize); return FALSE; @@ -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); } @@ -252,7 +252,7 @@ SerialConnectionSendThreeBuffers(CHAR * Buffer1, if ((Length1 + Length2 + Length3 + SERIAL_END_OF_BUFFER_CHARS_COUNT) > MaxSerialPacketSize) { LogError("Err, buffer is above the maximum buffer size that can be sent to debuggee (%d > %d), " - "for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/increase-communication-buffer-size", + "for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/increase-communication-buffer-size", Length1 + Length2 + Length3 + SERIAL_END_OF_BUFFER_CHARS_COUNT, MaxSerialPacketSize); return FALSE; @@ -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); } diff --git a/hyperdbg/hprdbgkd/code/debugger/core/Debugger.c b/hyperdbg/hyperkd/code/debugger/core/Debugger.c similarity index 92% rename from hyperdbg/hprdbgkd/code/debugger/core/Debugger.c rename to hyperdbg/hyperkd/code/debugger/core/Debugger.c index fb714589..4b7b65ad 100644 --- a/hyperdbg/hprdbgkd/code/debugger/core/Debugger.c +++ b/hyperdbg/hyperkd/code/debugger/core/Debugger.c @@ -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 // @@ -111,87 +176,8 @@ DebuggerInitialize() InitializeListHead(&g_Events->TrapExecutionInstructionTraceEventsHead); InitializeListHead(&g_Events->ControlRegister3ModifiedEventsHead); 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 = CrsAllocateNonPagedPool(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->ScriptEngineCoreSpecificLocalVariable) - { - CurrentDebuggerState->ScriptEngineCoreSpecificLocalVariable = CrsAllocateNonPagedPool(MAX_VAR_COUNT * sizeof(UINT64)); - } - - if (!CurrentDebuggerState->ScriptEngineCoreSpecificLocalVariable) - { - // - // Out of resource, initialization of script engine's local variable holders failed - // - return FALSE; - } - - if (!CurrentDebuggerState->ScriptEngineCoreSpecificTempVariable) - { - CurrentDebuggerState->ScriptEngineCoreSpecificTempVariable = CrsAllocateNonPagedPool(MAX_TEMP_COUNT * sizeof(UINT64)); - } - - if (!CurrentDebuggerState->ScriptEngineCoreSpecificTempVariable) - { - // - // Out of resource, initialization of script engine's local variable holders failed - // - return FALSE; - } - - // - // Zero the local and temp variables memory - // - RtlZeroMemory(CurrentDebuggerState->ScriptEngineCoreSpecificLocalVariable, MAX_VAR_COUNT * sizeof(UINT64)); - RtlZeroMemory(CurrentDebuggerState->ScriptEngineCoreSpecificTempVariable, MAX_TEMP_COUNT * sizeof(UINT64)); - } // // Initialize NMI broadcasting mechanism @@ -199,16 +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); // + // Set initial state of triggering events for CPUIDs + // + VmFuncSetTriggerEventForCpuids(FALSE); + + // // Pre-allocate pools for possible EPT hooks // ConfigureEptHookReservePreallocatedPoolsForEptHooks(MAXIMUM_NUMBER_OF_INITIAL_PREALLOCATED_EPT_HOOKS); @@ -222,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 *** // @@ -253,7 +314,7 @@ DebuggerUninitialize() // // Disable triggering events // - g_EnableDebuggerEvents = FALSE; + g_EnableDebuggerVmxEvents = FALSE; // // Clear all events (Check if the kernel debugger is enable @@ -282,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 @@ -293,7 +373,7 @@ DebuggerUninitialize() // if (g_ScriptGlobalVariables != NULL) { - CrsFreePool(g_ScriptGlobalVariables); + PlatformMemFreePool(g_ScriptGlobalVariables); g_ScriptGlobalVariables = NULL; } @@ -304,16 +384,10 @@ DebuggerUninitialize() { CurrentDebuggerState = &g_DbgState[i]; - if (CurrentDebuggerState->ScriptEngineCoreSpecificLocalVariable != NULL) + if (CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer != NULL) { - CrsFreePool(CurrentDebuggerState->ScriptEngineCoreSpecificLocalVariable); - CurrentDebuggerState->ScriptEngineCoreSpecificLocalVariable = NULL; - } - - if (CurrentDebuggerState->ScriptEngineCoreSpecificTempVariable != NULL) - { - CrsFreePool(CurrentDebuggerState->ScriptEngineCoreSpecificTempVariable); - CurrentDebuggerState->ScriptEngineCoreSpecificTempVariable = NULL; + PlatformMemFreePool(CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer); + CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer = NULL; } } @@ -440,7 +514,7 @@ DebuggerCreateEvent(BOOLEAN Enabled, // // If it's not coming from the VMX-root mode then we're allocating it from the OS buffers // - Event = CrsAllocateZeroedNonPagedPool(EventBufferSize); + Event = PlatformMemAllocateZeroedNonPagedPool(EventBufferSize); if (!Event) { @@ -600,7 +674,7 @@ DebuggerAllocateSafeRequestedBuffer(SIZE_T SizeOfRequ } else { - RequestedBuffer = CrsAllocateZeroedNonPagedPool(SizeOfRequestedSafeBuffer); + RequestedBuffer = PlatformMemAllocateZeroedNonPagedPool(SizeOfRequestedSafeBuffer); if (!RequestedBuffer) { @@ -751,7 +825,7 @@ DebuggerAddActionToEvent(PDEBUGGER_EVENT Event, // // If it's not coming from the VMX-root mode then we're allocating it from the OS buffers // - Action = CrsAllocateZeroedNonPagedPool(ActionBufferSize); + Action = PlatformMemAllocateZeroedNonPagedPool(ActionBufferSize); if (Action == NULL) { @@ -791,7 +865,7 @@ DebuggerAddActionToEvent(PDEBUGGER_EVENT Event, } else { - CrsFreePool(Action); + PlatformMemFreePool(Action); } // @@ -819,7 +893,7 @@ DebuggerAddActionToEvent(PDEBUGGER_EVENT Event, } else { - CrsFreePool(Action); + PlatformMemFreePool(Action); } // @@ -859,7 +933,7 @@ DebuggerAddActionToEvent(PDEBUGGER_EVENT Event, } else { - CrsFreePool(Action); + PlatformMemFreePool(Action); } // @@ -887,7 +961,7 @@ DebuggerAddActionToEvent(PDEBUGGER_EVENT Event, } else { - CrsFreePool(Action); + PlatformMemFreePool(Action); } // @@ -925,11 +999,11 @@ DebuggerAddActionToEvent(PDEBUGGER_EVENT Event, } else { - CrsFreePool(Action); + PlatformMemFreePool(Action); if (RequestedBuffer != NULL) { - CrsFreePool(RequestedBuffer); + PlatformMemFreePool(RequestedBuffer); } } @@ -975,11 +1049,11 @@ DebuggerAddActionToEvent(PDEBUGGER_EVENT Event, } else { - CrsFreePool(Action); + PlatformMemFreePool(Action); if (RequestedBuffer != 0) { - CrsFreePool(RequestedBuffer); + PlatformMemFreePool(RequestedBuffer); } } @@ -997,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 @@ -1077,17 +1151,18 @@ DebuggerTriggerEvents(VMM_EVENT_TYPE_ENUM EventType, BOOLEAN * PostEventRequired, GUEST_REGS * Regs) { + PROCESSOR_DEBUGGING_STATE * DbgState = NULL; DebuggerCheckForCondition * ConditionFunc; DEBUGGER_TRIGGERED_EVENT_DETAILS EventTriggerDetail = {0}; PEPT_HOOKS_CONTEXT EptContext; - PLIST_ENTRY TempList = 0; - PLIST_ENTRY TempList2 = 0; - PROCESSOR_DEBUGGING_STATE * DbgState = NULL; + PLIST_ENTRY TempList = 0; + PLIST_ENTRY TempList2 = 0; + const PVOID OriginalContext = Context; // // Check if triggering debugging actions are allowed or not // - if (!g_EnableDebuggerEvents || g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer) + if (!g_EnableDebuggerVmxEvents || g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer) { // // Debugger is not enabled @@ -1152,7 +1227,8 @@ DebuggerTriggerEvents(VMM_EVENT_TYPE_ENUM EventType, } // - // Check event type specific conditions + // Check event type specific conditions, if the event is not mentioned + // here, it means that it doesn't have any special condition // switch (CurrentEvent->EventType) { @@ -1188,14 +1264,17 @@ DebuggerTriggerEvents(VMM_EVENT_TYPE_ENUM EventType, // we get the events for all hidden hooks in a page granularity // - EptContext = (PEPT_HOOKS_CONTEXT)Context; + // + // Here the OriginalContext is used because the context + // might be changed but the OriginalContext is constant + // + EptContext = (PEPT_HOOKS_CONTEXT)OriginalContext; // - // Context should be checked with hooking tag + // EPT context should be checked with hooking tag // The hooking tag is same as the event tag if both // of them match together // - if (EptContext->HookingTag != CurrentEvent->Tag) { // @@ -1237,6 +1316,12 @@ DebuggerTriggerEvents(VMM_EVENT_TYPE_ENUM EventType, case HIDDEN_HOOK_EXEC_DETOURS: + // + // Here the OriginalContext is used because the context + // might be changed but the OriginalContext is constant + // + EptContext = (PEPT_HOOKS_CONTEXT)OriginalContext; + // // Here we check if it's HIDDEN_HOOK_EXEC_DETOURS // then it means that it's detours hidden hook exec so we have @@ -1248,7 +1333,7 @@ DebuggerTriggerEvents(VMM_EVENT_TYPE_ENUM EventType, // This way we are sure that no one can bypass our hook by remapping // address to another virtual address as everything is physical // - if (((PEPT_HOOKS_CONTEXT)Context)->PhysicalAddress != CurrentEvent->Options.OptionalParam1) + if (EptContext->PhysicalAddress != CurrentEvent->Options.OptionalParam1) { // // Context is the physical address @@ -1264,7 +1349,7 @@ DebuggerTriggerEvents(VMM_EVENT_TYPE_ENUM EventType, // // Convert it to virtual address // - Context = (PVOID)(((PEPT_HOOKS_CONTEXT)Context)->VirtualAddress); + Context = (PVOID)(EptContext->VirtualAddress); } break; @@ -1386,7 +1471,22 @@ DebuggerTriggerEvents(VMM_EVENT_TYPE_ENUM EventType, break; - default: + case XSETBV_INSTRUCTION_EXECUTION: + + // + // check if XSETBV is what we want or not + // + if (CurrentEvent->Options.OptionalParam1 != (UINT64)NULL /*FALSE*/ && CurrentEvent->Options.OptionalParam2 != (UINT64)Context) + { + // + // The XCR is not what we want (and the user didn't intend to get all XSETBVs) + // + continue; + } + + break; + + default: // All other events that don't have conditions break; } @@ -1564,10 +1664,10 @@ DebuggerPerformRunScript(PROCESSOR_DEBUGGING_STATE * DbgState, DEBUGGEE_SCRIPT_PACKET * ScriptDetails, DEBUGGER_TRIGGERED_EVENT_DETAILS * EventTriggerDetail) { - SYMBOL_BUFFER CodeBuffer = {0}; - ACTION_BUFFER ActionBuffer = {0}; - SYMBOL ErrorSymbol = {0}; - SCRIPT_ENGINE_VARIABLES_LIST VariablesList = {0}; + SYMBOL_BUFFER CodeBuffer = {0}; + ACTION_BUFFER ActionBuffer = {0}; + SYMBOL ErrorSymbol = {0}; + SCRIPT_ENGINE_GENERAL_REGISTERS ScriptGeneralRegisters = {0}; if (Action != NULL) { @@ -1636,11 +1736,13 @@ DebuggerPerformRunScript(PROCESSOR_DEBUGGING_STATE * DbgState, } // - // Fill the variables list for this run + // Fill the stack buffer for this run // - VariablesList.GlobalVariablesList = g_ScriptGlobalVariables; - VariablesList.LocalVariablesList = DbgState->ScriptEngineCoreSpecificLocalVariable; - VariablesList.TempList = DbgState->ScriptEngineCoreSpecificTempVariable; + ScriptGeneralRegisters.StackBuffer = DbgState->ScriptEngineCoreSpecificStackBuffer; + ScriptGeneralRegisters.GlobalVariablesList = g_ScriptGlobalVariables; + RtlZeroMemory(ScriptGeneralRegisters.StackBuffer, MAX_STACK_BUFFER_COUNT * sizeof(UINT64)); + + UINT64 EXECUTENUMBER = 0; for (UINT64 i = 0; i < CodeBuffer.Pointer;) { @@ -1650,20 +1752,27 @@ DebuggerPerformRunScript(PROCESSOR_DEBUGGING_STATE * DbgState, if (ScriptEngineExecute(DbgState->Regs, &ActionBuffer, - &VariablesList, + &ScriptGeneralRegisters, &CodeBuffer, &i, - NULL, - NULL, - NULL, - NULL, &ErrorSymbol) == TRUE) { - CHAR NameOfOperator[MAX_FUNCTION_NAME_LENGTH] = {0}; - ScriptEngineGetOperatorName(&ErrorSymbol, NameOfOperator); - LogInfo("Invalid returning address for operator: %s", NameOfOperator); + LogInfo("Err, ScriptEngineExecute, function = % s\n ", + FunctionNames[ErrorSymbol.Value]); break; } + else if (ScriptGeneralRegisters.StackIndx >= MAX_STACK_BUFFER_COUNT) + { + LogInfo("Err, stack buffer overflow (more information: https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/change-script-engine-limitations)\n"); + break; + } + else if (EXECUTENUMBER >= MAX_EXECUTION_COUNT) + { + LogInfo("Err, exceeding the max execution count (more information: https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/change-script-engine-limitations)\n"); + break; + } + + EXECUTENUMBER++; } return TRUE; @@ -1735,7 +1844,6 @@ DebuggerPerformRunTheCustomCode(PROCESSOR_DEBUGGING_STATE * DbgState, * @param DbgState The state of the debugger on the current core * @param Tag Tag of event * @param Action Action object - * @param Context Optional parameter * @param EventTriggerDetail Event trigger detail * * @return VOID @@ -1786,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; @@ -1830,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; @@ -1887,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; @@ -1939,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; @@ -2091,6 +2199,9 @@ DebuggerGetEventListByEventType(VMM_EVENT_TYPE_ENUM EventType) case CONTROL_REGISTER_MODIFIED: ResultList = &g_Events->ControlRegisterModifiedEventsHead; break; + case XSETBV_INSTRUCTION_EXECUTION: + ResultList = &g_Events->XsetbvInstructionExecutionEventsHead; + break; default: // @@ -2450,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; @@ -2502,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); // @@ -2525,7 +2636,7 @@ DebuggerRemoveAllActionsFromEvent(PDEBUGGER_EVENT Event, BOOLEAN PoolManagerAllo } else { - CrsFreePool((PVOID)CurrentAction->RequestedBuffer.RequstBufferAddress); + PlatformMemFreePool((PVOID)CurrentAction->RequestedBuffer.RequstBufferAddress); } } @@ -2534,14 +2645,18 @@ 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); } else { - CrsFreePool(CurrentAction); + PlatformMemFreePool(CurrentAction); } + + TempList = NextList; } // // Remember to free the pool @@ -2612,7 +2727,7 @@ DebuggerRemoveEvent(UINT64 Tag, BOOLEAN PoolManagerAllocatedMemory) } else { - CrsFreePool(Event); + PlatformMemFreePool(Event); } return TRUE; @@ -2994,6 +3109,15 @@ DebuggerApplyEvent(PDEBUGGER_EVENT Event, break; } + case XSETBV_INSTRUCTION_EXECUTION: + { + // + // Apply the XSETBV instruction execution events + // + ApplyEventXsetbvExecutionEvent(Event, ResultsToReturn, InputFromVmxRoot); + + break; + } default: { // @@ -3565,6 +3689,16 @@ DebuggerTerminateEvent(UINT64 Tag, BOOLEAN InputFromVmxRoot) break; } + case XSETBV_INSTRUCTION_EXECUTION: + { + // + // Call XSETBV instruction execution event terminator + // + TerminateXsetbvExecutionEvent(Event, InputFromVmxRoot); + Result = TRUE; + + break; + } default: LogError("Err, unknown event for termination"); Result = FALSE; diff --git a/hyperdbg/hprdbgkd/code/debugger/core/DebuggerVmcalls.c b/hyperdbg/hyperkd/code/debugger/core/DebuggerVmcalls.c similarity index 100% rename from hyperdbg/hprdbgkd/code/debugger/core/DebuggerVmcalls.c rename to hyperdbg/hyperkd/code/debugger/core/DebuggerVmcalls.c diff --git a/hyperdbg/hprdbgkd/code/debugger/core/HaltedCore.c b/hyperdbg/hyperkd/code/debugger/core/HaltedCore.c similarity index 99% rename from hyperdbg/hprdbgkd/code/debugger/core/HaltedCore.c rename to hyperdbg/hyperkd/code/debugger/core/HaltedCore.c index 2b0696d7..8cae1122 100644 --- a/hyperdbg/hprdbgkd/code/debugger/core/HaltedCore.c +++ b/hyperdbg/hyperkd/code/debugger/core/HaltedCore.c @@ -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) { diff --git a/hyperdbg/hprdbgkd/code/debugger/events/ApplyEvents.c b/hyperdbg/hyperkd/code/debugger/events/ApplyEvents.c similarity index 87% rename from hyperdbg/hprdbgkd/code/debugger/events/ApplyEvents.c rename to hyperdbg/hyperkd/code/debugger/events/ApplyEvents.c index 8e6f0d5d..1fea130a 100644 --- a/hyperdbg/hprdbgkd/code/debugger/events/ApplyEvents.c +++ b/hyperdbg/hyperkd/code/debugger/events/ApplyEvents.c @@ -35,12 +35,6 @@ ApplyEventMonitorEvent(PDEBUGGER_EVENT Event, UINT64 TempStartAddress; UINT64 TempEndAddress; UINT64 TempNextPageAddr; - UINT64 RemainingSizeRestore; - UINT64 PagesBytesRestore; - UINT64 ConstEndAddressRestore; - UINT64 TempNextPageAddrRestore; - UINT64 TempStartAddressRestore; - UINT64 TempEndAddressRestore; EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR HookingAddresses = {0}; if (InputFromVmxRoot) @@ -140,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) { @@ -181,6 +175,15 @@ ApplyEventMonitorEvent(PDEBUGGER_EVENT Event, HookingAddresses.StartAddress = TempStartAddress; HookingAddresses.EndAddress = TempEndAddress; + if ((DEBUGGER_HOOK_MEMORY_TYPE)Event->InitOptions.OptionalParam3 == DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS) + { + HookingAddresses.MemoryType = DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS; + } + else + { + HookingAddresses.MemoryType = DEBUGGER_MEMORY_HOOK_VIRTUAL_ADDRESS; + } + // // Apply the hook // @@ -198,85 +201,24 @@ ApplyEventMonitorEvent(PDEBUGGER_EVENT Event, // // Now we should restore the previously applied events (if any) // - - TempStartAddressRestore = Event->InitOptions.OptionalParam1; - TempEndAddressRestore = Event->InitOptions.OptionalParam2; - ConstEndAddressRestore = TempEndAddressRestore; - - PagesBytesRestore = (UINT64)PAGE_ALIGN(TempStartAddressRestore); - PagesBytesRestore = TempEndAddressRestore - PagesBytesRestore; - PagesBytesRestore = PagesBytesRestore / PAGE_SIZE; - - RemainingSizeRestore = TempEndAddressRestore - TempStartAddressRestore; - - // LogInfo("Discard changes from, Start address: %llx, end address: %llx\n\n\n", - // TempStartAddressRestore, - // TempEndAddressRestore, - // RemainingSizeRestore); - - for (size_t j = 0; j <= PagesBytesRestore; j++) + if (InputFromVmxRoot) { // - // Check if the previous hook is applied + // EPT hooking tag is same as event tag, so we can use it to unhook // - if (j == i) - { - // - // It means this index is not applied successfully, - // so we're not needed to remove as it's not successfully applied - // - break; - } - - if (RemainingSizeRestore >= PAGE_SIZE) - { - TempEndAddressRestore = (TempStartAddressRestore + ((UINT64)PAGE_ALIGN(TempStartAddressRestore + PAGE_SIZE) - TempStartAddressRestore)) - 1; - RemainingSizeRestore = ConstEndAddressRestore - TempEndAddressRestore - 1; - } - else - { - TempNextPageAddrRestore = (UINT64)PAGE_ALIGN(TempStartAddressRestore + RemainingSizeRestore); - - // - // Check if by adding the remaining size, we'll go to the next - // page boundary or not - // - if (TempNextPageAddrRestore > ((UINT64)PAGE_ALIGN(TempStartAddressRestore))) - { - // - // It goes to the next page boundary - // - TempEndAddressRestore = TempNextPageAddrRestore - 1; - RemainingSizeRestore = RemainingSizeRestore - (TempEndAddressRestore - TempStartAddressRestore) - 1; - } - else - { - TempEndAddressRestore = TempStartAddressRestore + RemainingSizeRestore; - RemainingSizeRestore = 0; - } - } - + TerminateEptHookUnHookAllHooksByHookingTagFromVmxRootAndApplyInvalidation(Event->Tag); + } + else + { // - // Remove the hook + // EPT hooking tag is same as event tag, so we can use it to unhook // - if (InputFromVmxRoot) - { - TerminateEptHookUnHookSingleAddressFromVmxRootAndApplyInvalidation(TempStartAddressRestore, - (UINT64)NULL); - } - else - { - ConfigureEptHookUnHookSingleAddress(TempStartAddressRestore, - (UINT64)NULL, - Event->ProcessId); - } - - // - // Swap the temporary start address and temporary end address - // - TempStartAddressRestore = TempEndAddressRestore + 1; + ConfigureEptHookUnHookAllByHookingTag(Event->Tag); } + // + // Break from the loop + // break; } else @@ -311,19 +253,33 @@ ApplyEventMonitorEvent(PDEBUGGER_EVENT Event, } // - // We convert the Event's optional parameters physical address because - // vm-exit occurs and we have the physical address to compare in the case of - // hidden hook rw events. + // Check if address is virtual or physical // - if (InputFromVmxRoot) + if ((DEBUGGER_HOOK_MEMORY_TYPE)Event->Options.OptionalParam3 == DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS) { - Event->Options.OptionalParam1 = VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)Event->InitOptions.OptionalParam1); - Event->Options.OptionalParam2 = VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)Event->InitOptions.OptionalParam2); + // + // It's a physical address so we just save the addresses without conversion + // + Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1; + Event->Options.OptionalParam2 = Event->InitOptions.OptionalParam2; } else { - Event->Options.OptionalParam1 = VirtualAddressToPhysicalAddressByProcessId((PVOID)Event->InitOptions.OptionalParam1, TempProcessId); - Event->Options.OptionalParam2 = VirtualAddressToPhysicalAddressByProcessId((PVOID)Event->InitOptions.OptionalParam2, TempProcessId); + // + // It's a virtual address, we convert the Event's optional parameters physical address + // because vm-exit occurs and we have the physical address to compare in the case of + // hidden hook rw events + // + if (InputFromVmxRoot) + { + Event->Options.OptionalParam1 = VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)Event->InitOptions.OptionalParam1); + Event->Options.OptionalParam2 = VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)Event->InitOptions.OptionalParam2); + } + else + { + Event->Options.OptionalParam1 = VirtualAddressToPhysicalAddressByProcessId((PVOID)Event->InitOptions.OptionalParam1, TempProcessId); + Event->Options.OptionalParam2 = VirtualAddressToPhysicalAddressByProcessId((PVOID)Event->InitOptions.OptionalParam2, TempProcessId); + } } // @@ -331,6 +287,7 @@ ApplyEventMonitorEvent(PDEBUGGER_EVENT Event, // Event->Options.OptionalParam3 = Event->InitOptions.OptionalParam1; Event->Options.OptionalParam4 = Event->InitOptions.OptionalParam2; + Event->Options.OptionalParam5 = Event->InitOptions.OptionalParam3; // This parameter shows whether the address is physical or virtual // // Check if we should restore the event if it was not successful @@ -1248,15 +1205,6 @@ ApplyEventTrapModeChangeEvent(PDEBUGGER_EVENT Event, // or not and if it's activated then we can just add the current process // to the watchlist, otherwise the user needs to preactivate this event // - - // - // Technically, it's possible to initiate this mechanism at this point - // but it involves preallocating huge buffers so we prefer not to allocate - // these amount of buffers by default in HyperDbg as the users might not - // really use this mechanism and it would be a waste of system resources - // so, if the user needs to use this mechanism, it can use the 'preactivate' - // command to first activate this mechanism and then use it - // if (VmFuncQueryModeExecTrap()) { // @@ -1326,6 +1274,12 @@ ApplyEventCpuidExecutionEvent(PDEBUGGER_EVENT Event, // their custom optional parameters // VmFuncSetTriggerEventForCpuids(TRUE); + + // + // Setting an indicator to CPUID EAX index (if any) + // + Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1; + Event->Options.OptionalParam2 = Event->InitOptions.OptionalParam2; } /** @@ -1356,3 +1310,30 @@ ApplyEventTracingEvent(PDEBUGGER_EVENT Event, // Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1; } + +/** + * @brief Applying XSETBV instruction execution events + * + * @param Event The created event object + * @param ResultsToReturn Result buffer that should be returned to + * the user-mode + * @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL + * + * @return VOID + */ +VOID +ApplyEventXsetbvExecutionEvent(PDEBUGGER_EVENT Event, + PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn, + BOOLEAN InputFromVmxRoot) +{ + UNREFERENCED_PARAMETER(Event); + UNREFERENCED_PARAMETER(ResultsToReturn); + UNREFERENCED_PARAMETER(InputFromVmxRoot); + + // + // Enable triggering events for XSETBVs. This event doesn't support custom optional + // parameter(s) because it's unconditional. Users can use condition(s) to check for + // their custom optional parameters + // + VmFuncSetTriggerEventForXsetbvs(TRUE); +} diff --git a/hyperdbg/hprdbgkd/code/debugger/events/DebuggerEvents.c b/hyperdbg/hyperkd/code/debugger/events/DebuggerEvents.c similarity index 100% rename from hyperdbg/hprdbgkd/code/debugger/events/DebuggerEvents.c rename to hyperdbg/hyperkd/code/debugger/events/DebuggerEvents.c diff --git a/hyperdbg/hprdbgkd/code/debugger/events/Termination.c b/hyperdbg/hyperkd/code/debugger/events/Termination.c similarity index 90% rename from hyperdbg/hprdbgkd/code/debugger/events/Termination.c rename to hyperdbg/hyperkd/code/debugger/events/Termination.c index 979f3e39..b6f59de4 100644 --- a/hyperdbg/hprdbgkd/code/debugger/events/Termination.c +++ b/hyperdbg/hyperkd/code/debugger/events/Termination.c @@ -107,81 +107,19 @@ TerminateExternalInterruptEvent(PDEBUGGER_EVENT Event, BOOLEAN InputFromVmxRoot) VOID TerminateHiddenHookReadAndWriteAndExecuteEvent(PDEBUGGER_EVENT Event, BOOLEAN InputFromVmxRoot) { - UINT64 RemainingSize; - UINT64 PagesBytes; - UINT64 ConstEndAddress; - UINT64 TempNextPageAddr; - UINT64 TempStartAddress = Event->Options.OptionalParam3; - UINT64 TempEndAddress = Event->Options.OptionalParam4; - ConstEndAddress = TempEndAddress; - - // - // Because there are different EPT hooks, like READ, WRITE, EXECUTE, - // DETOURS INLINE HOOK, HIDDEN BREAKPOINT HOOK and all of them are - // unhooked with a same routine, we will not check whether the list of - // all of them is empty or not and instead, we remove just a single - // hook, this way is better as hidden hooks and ept modifications are - // not dependent to a single bit and if we remove or add any other hook - // then it won't cause any problem for other hooks - // - - PagesBytes = (UINT64)PAGE_ALIGN(TempStartAddress); - PagesBytes = TempEndAddress - PagesBytes; - PagesBytes = PagesBytes / PAGE_SIZE; - - RemainingSize = TempEndAddress - TempStartAddress; - - // LogInfo("Monitor termination, Start address: %llx, end address: %llx\n\n\n", - // TempStartAddress, - // TempEndAddress, - // RemainingSize); - - for (size_t i = 0; i <= PagesBytes; i++) + if (InputFromVmxRoot) { - if (RemainingSize >= PAGE_SIZE) - { - TempEndAddress = (TempStartAddress + ((UINT64)PAGE_ALIGN(TempStartAddress + PAGE_SIZE) - TempStartAddress)) - 1; - RemainingSize = ConstEndAddress - TempEndAddress - 1; - } - else - { - TempNextPageAddr = (UINT64)PAGE_ALIGN(TempStartAddress + RemainingSize); - - // - // Check if by adding the remaining size, we'll go to the next - // page boundary or not - // - if (TempNextPageAddr > ((UINT64)PAGE_ALIGN(TempStartAddress))) - { - // - // It goes to the next page boundary - // - TempEndAddress = TempNextPageAddr - 1; - RemainingSize = RemainingSize - (TempEndAddress - TempStartAddress) - 1; - } - else - { - TempEndAddress = TempStartAddress + RemainingSize; - RemainingSize = 0; - } - } - - if (InputFromVmxRoot) - { - TerminateEptHookUnHookSingleAddressFromVmxRootAndApplyInvalidation((UINT64)TempStartAddress, - (UINT64)NULL); - } - else - { - ConfigureEptHookUnHookSingleAddress((UINT64)TempStartAddress, - (UINT64)NULL, - Event->ProcessId); - } - // - // Swap the temporary start address and temporary end address + // EPT hooking tag is same as event tag, so we can use it to unhook // - TempStartAddress = TempEndAddress + 1; + TerminateEptHookUnHookAllHooksByHookingTagFromVmxRootAndApplyInvalidation(Event->Tag); + } + else + { + // + // EPT hooking tag is same as event tag, so we can use it to unhook + // + ConfigureEptHookUnHookAllByHookingTag(Event->Tag); } } @@ -1192,7 +1130,7 @@ TerminateSyscallHookEferEvent(PDEBUGGER_EVENT Event, BOOLEAN InputFromVmxRoot) // // For this event we should also check for sysret instructions events too // because both of them are emulated by a single bit in vmx controls - // and a MSR so if there is anything in out events list then we can + // and an MSR so if there is anything in out events list then we can // remove all the events // if (DebuggerEventListCount(&g_Events->SyscallHooksEferSyscallEventsHead) > 1 || @@ -1283,7 +1221,7 @@ TerminateSysretHookEferEvent(PDEBUGGER_EVENT Event, BOOLEAN InputFromVmxRoot) // // For this event we should also check for syscall instructions events too // because both of them are emulated by a single bit in vmx controls - // and a MSR so if there is anything in out events list then we can + // and an MSR so if there is anything in out events list then we can // remove all the events // if (DebuggerEventListCount(&g_Events->SyscallHooksEferSysretEventsHead) > 1 || @@ -1642,11 +1580,54 @@ TerminateQueryDebuggerResourceMovToCr3Exiting(UINT32 return FALSE; } +/** + * @brief Check and modify state of save and load debug controls (DR7 and IA32_DEBUGCTLS) + * on exit and entry VM controls + * + * @param CoreId Core specific resource + * @param PassOver The pass over option + * + * @return BOOLEAN + */ +BOOLEAN +TerminateQueryDebuggerResourceSaveAndLoadDebugControls(UINT32 CoreId, + PROTECTED_HV_RESOURCES_PASSING_OVERS PassOver) +{ + UNREFERENCED_PARAMETER(PassOver); + + // + // Check if debug register load and save on entry and exit controls are needed for thread interception + // + if (ThreadQueryDebugRegisterInterceptionStateByCoreId(CoreId)) + { + // + // We should ignore it as we want this to interception of thread to work + // + return TRUE; + } + + // + // Query the hypertrace project about this controls since there might be using this load and save controls + // + if (HyperTraceLbrQueryStateOfLbrSaveAndLoadVmExitAndEntryControls(CoreId)) + { + // + // We should ignore it since LBR feature of hypertrace is still using it + // + return TRUE; + } + + // + // Do not terminate + // + return FALSE; +} + /** * @brief Remove single hook from the hooked pages list and invalidate TLB * @details Should be called from vmx root-mode * - * @param VirtualAddress Virtual address to unhook + * @param VirtualAddress Virtual address to unhook (optional) * @param PhysAddress Physical address to unhook (optional) * * @return BOOLEAN If unhook was successful it returns true or if it was not successful returns false @@ -1698,6 +1679,69 @@ TerminateEptHookUnHookSingleAddressFromVmxRootAndApplyInvalidation(UINT64 Virtua return FALSE; } +/** + * @brief Remove all hooks from the hooked pages list and invalidate TLB using hooking tag + * @details Should be called from vmx root-mode + * + * @param HookingTag The hooking tag to unhook + * + * @return BOOLEAN If unhook was successful it returns true or if it was not successful returns false + */ +BOOLEAN +TerminateEptHookUnHookAllHooksByHookingTagFromVmxRootAndApplyInvalidation(UINT64 HookingTag) +{ + BOOLEAN Result = FALSE; + BOOLEAN IsAtLeastOneHookRemoved = FALSE; + EPT_SINGLE_HOOK_UNHOOKING_DETAILS TargetUnhookingDetails = {0}; + +UnhookNextPossibleTag: + // + // Perform unhooking directly from VMX-root mode using hooking tag + // + Result = ConfigureEptHookUnHookSingleHookByHookingTagFromVmxRoot(HookingTag, + &TargetUnhookingDetails); + + if (Result == TRUE) + { + // + // At least one hook was removed + // + IsAtLeastOneHookRemoved = TRUE; + + // + // It's the responsibility of the caller to restore EPT entries and + // invalidate EPT caches + // + if (TargetUnhookingDetails.CallerNeedsToRestoreEntryAndInvalidateEpt) + { + HaltedBroadcastUnhookSinglePageAllCores(&TargetUnhookingDetails); + } + + // + // It's the responsibility of the caller to clear #BPs directly from + // VMX-root mode if applied from VMX-root mode + // + if (TargetUnhookingDetails.RemoveBreakpointInterception) + { + // + // The hook was the last hook and we can broadcast to + // not intercept #BPs anymore + // + HaltedBroadcastUnSetExceptionBitmapAllCores(EXCEPTION_VECTOR_BREAKPOINT); + } + + // + // Keep unhooking until there is no hook with the same hooking tag + // + goto UnhookNextPossibleTag; + } + + // + // The result of removing EPT hook + // + return IsAtLeastOneHookRemoved; +} + /** * @brief Termination query state of debugger * @@ -1754,6 +1798,12 @@ TerminateQueryDebuggerResource(UINT32 CoreId, break; + case PROTECTED_HV_RESOURCES_SAVE_AND_LOAD_DEBUG_CONTROLS: + + Result = TerminateQueryDebuggerResourceSaveAndLoadDebugControls(CoreId, PassOver); + + break; + default: Result = FALSE; @@ -1768,3 +1818,46 @@ TerminateQueryDebuggerResource(UINT32 CoreId, // return Result; } + +/** + * @brief Termination function for XSETBV Instruction events + * + * @param Event Target Event Object + * @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL + * + * @return VOID + */ +VOID +TerminateXsetbvExecutionEvent(PDEBUGGER_EVENT Event, BOOLEAN InputFromVmxRoot) +{ + UNREFERENCED_PARAMETER(Event); + UNREFERENCED_PARAMETER(InputFromVmxRoot); + + if (DebuggerEventListCount(&g_Events->XsetbvInstructionExecutionEventsHead) > 1) + { + // + // There are still other events in the queue (list), we should only remove + // this special event (not all events) + // + + // + // Nothing we can do for this event type, let it work because of other events + // + return; + } + else + { + // + // Nothing else is in the list, we have to restore everything to default + // as the current event is the only event in the list + // + + // + // We set the global variable related to the xsetbv to FALSE + // so the vm-exit handler, no longer triggers events related + // to the xsetbvs (still they cause vm-exits as xsetbv is an + // unconditional instruction for vm-exit) + // + VmFuncSetTriggerEventForXsetbvs(FALSE); + } +} diff --git a/hyperdbg/hprdbgkd/code/debugger/events/ValidateEvents.c b/hyperdbg/hyperkd/code/debugger/events/ValidateEvents.c similarity index 83% rename from hyperdbg/hprdbgkd/code/debugger/events/ValidateEvents.c rename to hyperdbg/hyperkd/code/debugger/events/ValidateEvents.c index d886915a..72f552d0 100644 --- a/hyperdbg/hprdbgkd/code/debugger/events/ValidateEvents.c +++ b/hyperdbg/hyperkd/code/debugger/events/ValidateEvents.c @@ -55,32 +55,55 @@ ValidateEventMonitor(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, // Check whether address is valid or not based on whether the event needs // to be applied directly from VMX-root mode or not // - if (InputFromVmxRoot) + if ((DEBUGGER_HOOK_MEMORY_TYPE)EventDetails->Options.OptionalParam3 == DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS) { - if (VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)EventDetails->Options.OptionalParam1) == (UINT64)NULL || - VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)EventDetails->Options.OptionalParam2) == (UINT64)NULL) + // + // Validation of a physical address + // + if (CheckAddressPhysical(EventDetails->Options.OptionalParam1) == FALSE || + CheckAddressPhysical(EventDetails->Options.OptionalParam2) == FALSE) { // - // Address is invalid (Set the error) + // Physical address is invalid (Set the error) // ResultsToReturn->IsSuccessful = FALSE; - ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_PHYSICAL_ADDRESS; return FALSE; } } else { - if (VirtualAddressToPhysicalAddressByProcessId((PVOID)EventDetails->Options.OptionalParam1, TempPid) == (UINT64)NULL || - VirtualAddressToPhysicalAddressByProcessId((PVOID)EventDetails->Options.OptionalParam2, TempPid) == (UINT64)NULL) + // + // Validation of a virtual address + // + if (InputFromVmxRoot) { - // - // Address is invalid (Set the error) - // + if (VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)EventDetails->Options.OptionalParam1) == (UINT64)NULL || + VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)EventDetails->Options.OptionalParam2) == (UINT64)NULL) + { + // + // Virtual address is invalid (Set the error) + // - ResultsToReturn->IsSuccessful = FALSE; - ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS; - return FALSE; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS; + return FALSE; + } + } + else + { + if (VirtualAddressToPhysicalAddressByProcessId((PVOID)EventDetails->Options.OptionalParam1, TempPid) == (UINT64)NULL || + VirtualAddressToPhysicalAddressByProcessId((PVOID)EventDetails->Options.OptionalParam2, TempPid) == (UINT64)NULL) + { + // + // Address is invalid (Set the error) + // + + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS; + return FALSE; + } } } diff --git a/hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c b/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c similarity index 86% rename from hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c rename to hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c index 1de14fd1..f3f7017b 100644 --- a/hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c +++ b/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c @@ -24,9 +24,9 @@ KdInitializeKernelDebugger() // // Allocate DPC routine // - // for (size_t i = 0; i < CoreCount; i++) + // for (SIZE_T i = 0; i < CoreCount; i++) // { - // g_DbgState[i].KdDpcObject = CrsAllocateNonPagedPool(sizeof(KDPC)); + // g_DbgState[i].KdDpcObject = PlatformMemAllocateNonPagedPool(sizeof(KDPC)); // // if (g_DbgState[i].KdDpcObject == NULL) // { @@ -35,13 +35,6 @@ KdInitializeKernelDebugger() // } // } - // - // Request pages for breakpoint detail - // - PoolManagerRequestAllocation(sizeof(DEBUGGEE_BP_DESCRIPTOR), - MAXIMUM_BREAKPOINTS_WITHOUT_CONTINUE, - BREAKPOINT_DEFINITION_STRUCTURE); - // // Enable vm-exit on Hardware debug exceptions and breakpoints // so, intercept #DBs and #BP by changing exception bitmap (one core) @@ -53,12 +46,6 @@ KdInitializeKernelDebugger() // RtlZeroMemory(&g_IgnoreBreaksToDebugger, sizeof(DEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT)); - // - // Initialize list of breakpoints and breakpoint id - // - g_MaximumBreakpointId = 0; - InitializeListHead(&g_BreakpointsListHead); - // // Initial the needed pools for instant events // @@ -258,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 * @@ -414,6 +419,62 @@ KdLoggingResponsePacketToDebugger( return Result; } +/** + * @brief Regular step-over, step one instruction to the debuggee if + * there is a call then it jumps the call + * + * @param LastRip Last RIP register + * @param IsNextInstructionACall + * @param CallLength + * + * @return VOID + */ +VOID +KdRegularStepOver(UINT64 LastRip, BOOLEAN IsNextInstructionACall, UINT32 CallLength) +{ + UINT64 NextAddressForHardwareDebugBp = 0; + ULONG ProcessorsCount; + + // LogInfo("Last Rip: %llx, IsNextInstructionACall: %s, Call length: %x", + // LastRip, + // IsNextInstructionACall ? "true" : "false", + // CallLength); + + if (IsNextInstructionACall) + { + // + // It's a call, we should put a hardware debug register breakpoint + // on the next instruction + // + NextAddressForHardwareDebugBp = LastRip + CallLength; + + ProcessorsCount = KeQueryActiveProcessorCount(0); + + // + // Store the detail of the hardware debug register to avoid trigger + // in other processes + // + g_HardwareDebugRegisterDetailsForStepOver.Address = NextAddressForHardwareDebugBp; + g_HardwareDebugRegisterDetailsForStepOver.ProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId()); + g_HardwareDebugRegisterDetailsForStepOver.ThreadId = HANDLE_TO_UINT32(PsGetCurrentThreadId()); + + // + // Add hardware debug breakpoints on all core on vm-entry + // + for (SIZE_T i = 0; i < ProcessorsCount; i++) + { + g_DbgState[i].HardwareDebugRegisterForStepping = NextAddressForHardwareDebugBp; + } + } + else + { + // + // Any instruction other than call (regular step) + // + TracingRegularStepInInstruction(); + } +} + /** * @brief Handles debug events when kernel-debugger is attached * @@ -600,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); } @@ -627,124 +688,37 @@ KdContinueDebuggeeJustCurrentCore(PROCESSOR_DEBUGGING_STATE * DbgState) SpinlockUnlock(&DbgState->Lock); } -/** - * @brief read registers - * @param DbgState The state of the debugger on the current core - * @param ReadRegisterRequest - * - * @return BOOLEAN - */ -_Use_decl_annotations_ -BOOLEAN -KdReadRegisters(PROCESSOR_DEBUGGING_STATE * DbgState, PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterRequest) -{ - GUEST_EXTRA_REGISTERS ERegs = {0}; - - if (ReadRegisterRequest->RegisterID == DEBUGGEE_SHOW_ALL_REGISTERS) - { - // - // Add General purpose registers - // - memcpy((void *)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION)), - DbgState->Regs, - sizeof(GUEST_REGS)); - - // - // Read Extra registers - // - ERegs.CS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_CS); - ERegs.SS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_SS); - ERegs.DS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_DS); - ERegs.ES = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_ES); - ERegs.FS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_FS); - ERegs.GS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_GS); - ERegs.RFLAGS = DebuggerGetRegValueWrapper(NULL, REGISTER_RFLAGS); - ERegs.RIP = DebuggerGetRegValueWrapper(NULL, REGISTER_RIP); - - // - // copy at the end of ReadRegisterRequest structure - // - memcpy((void *)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) + sizeof(GUEST_REGS)), - &ERegs, - sizeof(GUEST_EXTRA_REGISTERS)); - } - else - { - ReadRegisterRequest->Value = DebuggerGetRegValueWrapper(DbgState->Regs, ReadRegisterRequest->RegisterID); - } - - return TRUE; -} - -/** - * @brief read registers - * @param Regs - * @param ReadRegisterRequest - * - * @return BOOLEAN - */ -_Use_decl_annotations_ -BOOLEAN -KdReadMemory(PGUEST_REGS Regs, PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterRequest) -{ - GUEST_EXTRA_REGISTERS ERegs = {0}; - - if (ReadRegisterRequest->RegisterID == DEBUGGEE_SHOW_ALL_REGISTERS) - { - // - // Add General purpose registers - // - memcpy((void *)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION)), - Regs, - sizeof(GUEST_REGS)); - - // - // Read Extra registers - // - ERegs.CS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_CS); - ERegs.SS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_SS); - ERegs.DS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_DS); - ERegs.ES = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_ES); - ERegs.FS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_FS); - ERegs.GS = (UINT16)DebuggerGetRegValueWrapper(NULL, REGISTER_GS); - ERegs.RFLAGS = DebuggerGetRegValueWrapper(NULL, REGISTER_RFLAGS); - ERegs.RIP = DebuggerGetRegValueWrapper(NULL, REGISTER_RIP); - - // - // copy at the end of ReadRegisterRequest structure - // - memcpy((void *)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) + sizeof(GUEST_REGS)), - &ERegs, - sizeof(GUEST_EXTRA_REGISTERS)); - } - else - { - ReadRegisterRequest->Value = DebuggerGetRegValueWrapper(Regs, ReadRegisterRequest->RegisterID); - } - - return TRUE; -} - /** * @brief change the current operating core to new core * * @param DbgState The state of the debugger on the current core - * @param NewCore + * @param ChangeCorePacket * @return BOOLEAN */ BOOLEAN -KdSwitchCore(PROCESSOR_DEBUGGING_STATE * DbgState, UINT32 NewCore) +KdSwitchCore(PROCESSOR_DEBUGGING_STATE * DbgState, + DEBUGGEE_CHANGE_CORE_PACKET * ChangeCorePacket) { ULONG ProcessorsCount = KeQueryActiveProcessorCount(0); + if (DbgState->CoreId == ChangeCorePacket->NewCore) + { + // + // The operating core and the target core is the same, no need for further action + // + ChangeCorePacket->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + return FALSE; // Return FALSE to not unlock anything + } + // // Check if core is valid or not // - if (NewCore >= ProcessorsCount) + if (ChangeCorePacket->NewCore >= ProcessorsCount) { // // Invalid core count // + ChangeCorePacket->Result = DEBUGGER_ERROR_PREPARING_DEBUGGEE_INVALID_CORE_IN_REMOTE_DEBUGGE; return FALSE; } @@ -752,6 +726,15 @@ KdSwitchCore(PROCESSOR_DEBUGGING_STATE * DbgState, UINT32 NewCore) // *** Core is valid *** // + // + // Check to see whether this core is locked or not + // + if (!KdCheckTargetCoreIsLocked(ChangeCorePacket->NewCore)) + { + ChangeCorePacket->Result = DEBUGGER_ERROR_TARGET_SWITCHING_CORE_IS_NOT_LOCKED; + return FALSE; + } + // // Check if we should enable interrupts in this core or not // @@ -768,14 +751,14 @@ KdSwitchCore(PROCESSOR_DEBUGGING_STATE * DbgState, UINT32 NewCore) // // Set new operating core // - g_DbgState[NewCore].MainDebuggingCore = TRUE; + g_DbgState[ChangeCorePacket->NewCore].MainDebuggingCore = TRUE; // // Unlock the new core // *** We should not unlock the spinlock here as the other core might // simultaneously start sending packets and corrupt our packets *** // - + ChangeCorePacket->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; return TRUE; } @@ -871,7 +854,7 @@ KdNotifyDebuggeeForUserInput(DEBUGGEE_USER_INPUT_PACKET * Descriptor, UINT32 Len } /** - * @brief Notify user-mode to unload the debuggee and close the connections + * @brief Send the result of formats command to the kernel debugger * @param Value * * @return VOID @@ -965,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 *** @@ -980,9 +963,9 @@ KdCustomDebuggerBreakSpinlockLock(PROCESSOR_DEBUGGING_STATE * DbgState, volatile while (!SpinlockTryLock(Lock)) { - for (unsigned i = 0; i < wait; ++i) + for (UINT32 i = 0; i < Wait; ++i) { - _mm_pause(); + CpuPause(); } // @@ -1019,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; } } } @@ -1111,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 // @@ -1142,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 @@ -1179,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 @@ -1290,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 @@ -1400,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 @@ -1485,74 +1539,6 @@ KdCheckGuestOperatingModeChanges(UINT16 PreviousCsSelector, UINT16 CurrentCsSele return TRUE; } -/** - * @brief Regular step-in | step one instruction to the debuggee - * @param DbgState The state of the debugger on the current core - * - * @return VOID - */ -VOID -KdRegularStepInInstruction(PROCESSOR_DEBUGGING_STATE * DbgState) -{ - TracingPerformRegularStepInInstruction(DbgState); - - // - // Unset the trap flag on the next VM-exit - // - BreakpointRestoreTheTrapFlagOnceTriggered(HANDLE_TO_UINT32(PsGetCurrentProcessId()), HANDLE_TO_UINT32(PsGetCurrentThreadId())); -} - -/** - * @brief Regular step-over | step one instruction to the debuggee if - * there is a call then it jumps the call - * - * @param DbgState The state of the debugger on the current core - * @param IsNextInstructionACall - * @param CallLength - * - * @return VOID - */ -VOID -KdRegularStepOver(PROCESSOR_DEBUGGING_STATE * DbgState, BOOLEAN IsNextInstructionACall, UINT32 CallLength) -{ - UINT64 NextAddressForHardwareDebugBp = 0; - ULONG ProcessorsCount; - - if (IsNextInstructionACall) - { - // - // It's a call, we should put a hardware debug register breakpoint - // on the next instruction - // - NextAddressForHardwareDebugBp = VmFuncGetLastVmexitRip(DbgState->CoreId) + CallLength; - - ProcessorsCount = KeQueryActiveProcessorCount(0); - - // - // Store the detail of the hardware debug register to avoid trigger - // in other processes - // - g_HardwareDebugRegisterDetailsForStepOver.Address = NextAddressForHardwareDebugBp; - g_HardwareDebugRegisterDetailsForStepOver.ProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId()); - g_HardwareDebugRegisterDetailsForStepOver.ThreadId = HANDLE_TO_UINT32(PsGetCurrentThreadId()); - - // - // Add hardware debug breakpoints on all core on vm-entry - // - for (size_t i = 0; i < ProcessorsCount; i++) - { - g_DbgState[i].HardwareDebugRegisterForStepping = NextAddressForHardwareDebugBp; - } - } - else - { - // - // Any instruction other than call (regular step) - // - KdRegularStepInInstruction(DbgState); - } -} - /** * @brief Send event registration buffer to user-mode to register the event * @param EventDetailHeader @@ -1572,9 +1558,20 @@ KdPerformRegisterEvent(PDEBUGGEE_EVENT_AND_ACTION_HEADER_FOR_REMOTE_PACKET Event sizeof(DEBUGGEE_EVENT_AND_ACTION_HEADER_FOR_REMOTE_PACKET)); // - // Parse event from the VMX-root mode + // Check to see whether all cores are halted (in instant event) // - DebuggerParseEvent(GeneralEventDetail, DebuggerEventAndActionResult, TRUE); + if (!KdCheckAllCoresAreLocked()) + { + DebuggerEventAndActionResult->IsSuccessful = FALSE; + DebuggerEventAndActionResult->Error = DEBUGGER_ERROR_NOT_ALL_CORES_ARE_LOCKED_FOR_APPLYING_INSTANT_EVENT; + } + else + { + // + // Parse event from the VMX-root mode + // + DebuggerParseEvent(GeneralEventDetail, DebuggerEventAndActionResult, TRUE); + } return FALSE; @@ -1652,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, @@ -1661,6 +1658,67 @@ KdQueryRflagTrapState() } } +/** + * @brief Check whether all cores are locked or not + * + * @return BOOLEAN + */ +BOOLEAN +KdCheckAllCoresAreLocked() +{ + ULONG ProcessorsCount; + + ProcessorsCount = KeQueryActiveProcessorCount(0); + + // + // Query core debugging Lock info + // + for (SIZE_T i = 0; i < ProcessorsCount; i++) + { + if (!SpinlockCheckLock(&g_DbgState[i].Lock)) + { + // + // We found one core that is not locked + // + return FALSE; + } + } + + // + // Reaching here means all cores are locked + // + return TRUE; +} + +/** + * @brief Check whether a specific target core is locked or not + * @param CoreNumber + * + * @return BOOLEAN + */ +BOOLEAN +KdCheckTargetCoreIsLocked(UINT32 CoreNumber) +{ + // + // Query core debugging Lock info + // + + if (!SpinlockCheckLock(&g_DbgState[CoreNumber].Lock)) + { + // + // This core is not locked + // + return FALSE; + } + else + { + // + // Target core is locked + // + return TRUE; + } +} + /** * @brief Query state of the system * @@ -1678,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)) { @@ -1696,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) { @@ -2206,6 +2264,7 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) PDEBUGGER_SINGLE_CALLSTACK_FRAME CallstackFrameBuffer; PDEBUGGER_DEBUGGER_TEST_QUERY_BUFFER TestQueryPacket; PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterPacket; + PDEBUGGEE_REGISTER_WRITE_DESCRIPTION WriteRegisterPacket; PDEBUGGER_READ_MEMORY ReadMemoryPacket; PDEBUGGER_EDIT_MEMORY EditMemoryPacket; PDEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET ChangeProcessPacket; @@ -2215,6 +2274,11 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) PDEBUGGER_SEARCH_MEMORY SearchQueryPacket; PDEBUGGEE_BP_PACKET BpPacket; PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PtePacket; + PSMI_OPERATION_PACKETS SmiOperationPacket; + PHYPERTRACE_LBR_DUMP_PACKETS HyperTraceLbrdumpPacket; + PHYPERTRACE_PT_OPERATION_PACKETS HyperTracePtOperationPacket; + PDEBUGGER_APIC_REQUEST ApicPacket; + PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtEntryPacket; PDEBUGGER_PAGE_IN_REQUEST PageinPacket; PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS Va2paPa2vaPacket; PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET BpListOrModifyPacket; @@ -2228,6 +2292,8 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) UINT32 ReturnSize = 0; DEBUGGEE_RESULT_OF_SEARCH_PACKET SearchPacketResult = {0}; DEBUGGER_EVENT_AND_ACTION_RESULT DebuggerEventAndActionResult = {0}; + PDEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET PcitreePacket = {0}; + PDEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET PcidevinfoPacket = {0}; while (TRUE) { @@ -2338,7 +2404,10 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) // // Step-over (p command) // - KdRegularStepOver(DbgState, SteppingPacket->IsCurrentInstructionACall, SteppingPacket->CallLength); + KdRegularStepOver( + VmFuncGetLastVmexitRip(DbgState->CoreId), + SteppingPacket->IsCurrentInstructionACall, + SteppingPacket->CallLength); // // Unlock other cores @@ -2364,9 +2433,9 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) // // - // Indicate a step + // Indicate a step-in // - KdRegularStepInInstruction(DbgState); + TracingRegularStepInInstruction(); // // Unlock other cores @@ -2409,36 +2478,20 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) ChangeCorePacket = (DEBUGGEE_CHANGE_CORE_PACKET *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); - if (DbgState->CoreId != ChangeCorePacket->NewCore) + // + // Switch to new core + // + if (KdSwitchCore(DbgState, ChangeCorePacket)) { // - // Switch to new core + // No need to wait for new commands // - if (KdSwitchCore(DbgState, ChangeCorePacket->NewCore)) - { - // - // No need to wait for new commands - // - EscapeFromTheLoop = TRUE; + EscapeFromTheLoop = TRUE; - // - // Unlock the new core - // - UnlockTheNewCore = TRUE; - - ChangeCorePacket->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - } - else - { - ChangeCorePacket->Result = DEBUGGER_ERROR_PREPARING_DEBUGGEE_INVALID_CORE_IN_REMOTE_DEBUGGE; - } - } - else - { // - // The operating core and the target core is the same, no need for further action + // Unlock the new core // - ChangeCorePacket->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + UnlockTheNewCore = TRUE; } // @@ -2497,6 +2550,7 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) // Feel the callstack frames the buffers // if (CallstackWalkthroughStack(CallstackFrameBuffer, + &CallstackPacket->FrameCount, CallstackPacket->BaseAddress, CallstackPacket->Size, CallstackPacket->Is32Bit)) @@ -2540,10 +2594,11 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_READ_REGISTERS: ReadRegisterPacket = (DEBUGGEE_REGISTER_READ_DESCRIPTION *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + // // Read registers // - if (KdReadRegisters(DbgState, ReadRegisterPacket)) + if (DebuggerCommandReadRegisters(DbgState->Regs, ReadRegisterPacket)) { ReadRegisterPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; } @@ -2552,7 +2607,7 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) ReadRegisterPacket->KernelStatus = DEBUGGER_ERROR_INVALID_REGISTER_NUMBER; } - if (ReadRegisterPacket->RegisterID == DEBUGGEE_SHOW_ALL_REGISTERS) + if (ReadRegisterPacket->RegisterId == DEBUGGEE_SHOW_ALL_REGISTERS) { SizeToSend = sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) + sizeof(GUEST_REGS) + sizeof(GUEST_EXTRA_REGISTERS); } @@ -2570,6 +2625,32 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_WRITE_REGISTER: + + WriteRegisterPacket = (DEBUGGEE_REGISTER_WRITE_DESCRIPTION *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Write register + // + if (SetRegValue(DbgState->Regs, WriteRegisterPacket->RegisterId, WriteRegisterPacket->Value)) + { + WriteRegisterPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + else + { + WriteRegisterPacket->KernelStatus = DEBUGGER_ERROR_INVALID_REGISTER_NUMBER; + } + + // + // Send the result of writing register back to the debuggee + // + KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_WRITE_REGISTER, + (CHAR *)WriteRegisterPacket, + sizeof(DEBUGGEE_REGISTER_WRITE_DESCRIPTION)); + + break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_READ_MEMORY: ReadMemoryPacket = (DEBUGGER_READ_MEMORY *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); @@ -2603,17 +2684,11 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_EDIT_MEMORY: EditMemoryPacket = (PDEBUGGER_EDIT_MEMORY)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + // // Edit memory // - if (DebuggerCommandEditMemoryVmxRoot(EditMemoryPacket)) - { - EditMemoryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - } - else - { - EditMemoryPacket->KernelStatus = DEBUGGER_ERROR_INVALID_ADDRESS; - } + DebuggerCommandEditMemoryVmxRoot(EditMemoryPacket); // // Send the result of reading memory back to the debuggee @@ -2864,8 +2939,10 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) // // Perform the action + // This is on the vmx-root mode for the kernel debugger, thus, no need to switch + // to the target process memory layout as we are already in it // - BreakpointAddNew(BpPacket); + BreakpointAddNew(BpPacket, FALSE); // // Send the result of the 'bp' back to the debuggee @@ -2896,6 +2973,101 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_SMI_OPERATION: + + SmiOperationPacket = (SMI_OPERATION_PACKETS *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Perform the SMI operations (it's in vmx-root) + // + VmFuncSmmPerformSmiOperation(SmiOperationPacket, TRUE); + + // + // Send the result of the '!smi' back to the debuggee + // + KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_SMI_OPERATION_REQUESTS, + (CHAR *)SmiOperationPacket, + SIZEOF_SMI_OPERATION_PACKETS); + + break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_HYPERTRACE_LBR_DUMP: + + HyperTraceLbrdumpPacket = (HYPERTRACE_LBR_DUMP_PACKETS *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Perform the HyperTrace LBR dump (it's in vmx-root) + // + HyperTraceLbrPerformDump(HyperTraceLbrdumpPacket); + + // + // Send the result of the HyperTrace LBR dump back to the debuggee + // + KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_HYPERTRACE_LBR_DUMP_REQUESTS, + (CHAR *)HyperTraceLbrdumpPacket, + SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS); + + break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_HYPERTRACE_PT_OPERATION: + + HyperTracePtOperationPacket = (HYPERTRACE_PT_OPERATION_PACKETS *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Perform the HyperTrace PT operations (it's in vmx-root) + // + HyperTracePtPerformOperation(HyperTracePtOperationPacket); + + // + // Send the result of the HyperTrace PT back to the debuggee + // + KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_HYPERTRACE_PT_OPERATION_REQUESTS, + (CHAR *)HyperTracePtOperationPacket, + SIZEOF_HYPERTRACE_PT_OPERATION_PACKETS); + + break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_ACTIONS_ON_APIC: + + ApicPacket = (DEBUGGER_APIC_REQUEST *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Call APIC handler (size to send is computed by this function) + // + SizeToSend = ExtensionCommandPerformActionsForApicRequests(ApicPacket); + + // + // Send the result of the APIC requests back to the debuggee + // + KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_APIC_REQUESTS, + (CHAR *)ApicPacket, + SizeToSend); + + break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_READ_IDT_ENTRIES: + + IdtEntryPacket = (INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Call IDT query handler (read from VMX root-mode) + // + ExtensionCommandPerformQueryIdtEntriesRequest(IdtEntryPacket, TRUE); + + // + // Send the result of the IDT entries requests to the debuggee + // + KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_QUERY_IDT_ENTRIES_REQUESTS, + (CHAR *)IdtEntryPacket, + SIZEOF_INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS); + + break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_INJECT_PAGE_FAULT: PageinPacket = (DEBUGGER_PAGE_IN_REQUEST *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); @@ -2941,8 +3113,9 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) // // Perform the action + // No need to switch to the target process memory layout as we are already in it // - BreakpointListOrModify(BpListOrModifyPacket); + BreakpointListOrModify(BpListOrModifyPacket, FALSE); // // Send the result of modify or list breakpoints to the debuggee @@ -2975,6 +3148,44 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_QUERY_PCITREE: + + PcitreePacket = (DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Enumerate PCI tree + // + ExtensionCommandPcitree(PcitreePacket, TRUE); + + // + // Send the result of '!pcitree' back to the debugger + // + KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_PCITREE, + (CHAR *)PcitreePacket, + sizeof(DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET)); + + break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_QUERY_PCIDEVINFO: + + PcidevinfoPacket = (DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Retrieve PCI device info (CAM) + // + ExtensionCommandPcidevinfo(PcidevinfoPacket, TRUE); + + // + // Send the result back to the debugger + // + KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_PCIDEVINFO, + (CHAR *)PcidevinfoPacket, + sizeof(DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET)); + + break; + default: LogError("Err, unknown packet action received from the debugger\n"); break; diff --git a/hyperdbg/hprdbgkd/code/debugger/memory/Allocations.c b/hyperdbg/hyperkd/code/debugger/memory/Allocations.c similarity index 87% rename from hyperdbg/hprdbgkd/code/debugger/memory/Allocations.c rename to hyperdbg/hyperkd/code/debugger/memory/Allocations.c index efc12bc6..84c66297 100644 --- a/hyperdbg/hprdbgkd/code/debugger/memory/Allocations.c +++ b/hyperdbg/hyperkd/code/debugger/memory/Allocations.c @@ -25,7 +25,7 @@ GlobalDebuggingStateAllocateZeroedMemory(VOID) // // Allocate global variable to hold Debugging(s) state // - g_DbgState = CrsAllocateZeroedNonPagedPool(BufferSizeInByte); + g_DbgState = PlatformMemAllocateZeroedNonPagedPool(BufferSizeInByte); if (!g_DbgState) { @@ -48,7 +48,7 @@ GlobalDebuggingStateAllocateZeroedMemory(VOID) VOID GlobalDebuggingStateFreeMemory(VOID) { - CrsFreePool(g_DbgState); + PlatformMemFreePool(g_DbgState); g_DbgState = NULL; } @@ -65,7 +65,7 @@ GlobalEventsAllocateZeroedMemory(VOID) // if (!g_Events) { - g_Events = CrsAllocateNonPagedPool(sizeof(DEBUGGER_CORE_EVENTS)); + g_Events = PlatformMemAllocateNonPagedPool(sizeof(DEBUGGER_CORE_EVENTS)); } if (g_Events) @@ -89,7 +89,7 @@ GlobalEventsFreeMemory(VOID) { if (g_Events != NULL) { - CrsFreePool(g_Events); + PlatformMemFreePool(g_Events); g_Events = NULL; } } diff --git a/hyperdbg/hprdbghv/code/memory/PoolManager.c b/hyperdbg/hyperkd/code/debugger/memory/PoolManager.c similarity index 84% rename from hyperdbg/hprdbghv/code/memory/PoolManager.c rename to hyperdbg/hyperkd/code/debugger/memory/PoolManager.c index 3fbcd2d7..3c195e68 100644 --- a/hyperdbg/hprdbghv/code/memory/PoolManager.c +++ b/hyperdbg/hyperkd/code/debugger/memory/PoolManager.c @@ -23,7 +23,7 @@ PlmgrAllocateRequestNewAllocation(SIZE_T NumberOfBytes) // // Allocate global requesting variable // - g_RequestNewAllocation = CrsAllocateZeroedNonPagedPool(NumberOfBytes); + g_RequestNewAllocation = PlatformMemAllocateZeroedNonPagedPool(NumberOfBytes); if (!g_RequestNewAllocation) { @@ -36,7 +36,7 @@ PlmgrAllocateRequestNewAllocation(SIZE_T NumberOfBytes) VOID PlmgrFreeRequestNewAllocation(VOID) { - CrsFreePool(g_RequestNewAllocation); + PlatformMemFreePool(g_RequestNewAllocation); g_RequestNewAllocation = NULL; } @@ -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,39 +92,51 @@ PoolManagerInitialize() VOID PoolManagerUninitialize() { - PLIST_ENTRY ListTemp = 0; - ListTemp = &g_ListOfAllocatedPoolsHead; + PLIST_ENTRY Link; + + // + // Pool manager is not initialized anymore + // + g_PoolManagerInitialized = FALSE; SpinlockLock(&LockForReadingPool); - while (&g_ListOfAllocatedPoolsHead != ListTemp->Flink) + Link = g_ListOfAllocatedPoolsHead.Flink; + + while (Link != &g_ListOfAllocatedPoolsHead) { - ListTemp = ListTemp->Flink; + PLIST_ENTRY Next = Link->Flink; // // Get the head of the record // - PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(ListTemp, POOL_TABLE, PoolsList); + PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(Link, POOL_TABLE, PoolsList); // // Free the alloocated buffer (if not already changed) // if (!PoolTable->AlreadyFreed) { - CrsFreePool((PVOID)PoolTable->Address); + PlatformMemFreePool((PVOID)PoolTable->Address); } // // Unlink the PoolTable // - RemoveEntryList(&PoolTable->PoolsList); + RemoveEntryList(Link); // // Free the record itself // - CrsFreePool(PoolTable); + PlatformMemFreePool(PoolTable); + + Link = Next; } + InitializeListHead(&g_ListOfAllocatedPoolsHead); + g_IsNewRequestForDeAllocation = FALSE; + g_IsNewRequestForAllocationReceived = FALSE; + SpinlockUnlock(&LockForReadingPool); PlmgrFreeRequestNewAllocation(); @@ -252,11 +270,11 @@ 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; - SinglePool = CrsAllocateZeroedNonPagedPool(sizeof(POOL_TABLE)); + SinglePool = PlatformMemAllocateZeroedNonPagedPool(sizeof(POOL_TABLE)); if (!SinglePool) { @@ -267,11 +285,11 @@ PoolManagerAllocateAndAddToPoolTable(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_ // // Allocate the buffer // - SinglePool->Address = (UINT64)CrsAllocateZeroedNonPagedPool(Size); + SinglePool->Address = (UINT64)PlatformMemAllocateZeroedNonPagedPool(Size); if (!SinglePool->Address) { - CrsFreePool(SinglePool); + PlatformMemFreePool(SinglePool); LogError("Err, insufficient memory"); return FALSE; @@ -301,16 +319,17 @@ PoolManagerAllocateAndAddToPoolTable(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_ BOOLEAN PoolManagerCheckAndPerformAllocationAndDeallocation() { - BOOLEAN Result = TRUE; - PLIST_ENTRY ListTemp = 0; + BOOLEAN Result = TRUE; // - // 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 +339,8 @@ PoolManagerCheckAndPerformAllocationAndDeallocation() // PAGED_CODE(); + SpinlockLock(&LockForReadingPool); + // // Check for new allocation // @@ -350,18 +371,16 @@ PoolManagerCheckAndPerformAllocationAndDeallocation() // if (g_IsNewRequestForDeAllocation) { - ListTemp = &g_ListOfAllocatedPoolsHead; + PLIST_ENTRY Link = g_ListOfAllocatedPoolsHead.Flink; - SpinlockLock(&LockForReadingPool); - - while (&g_ListOfAllocatedPoolsHead != ListTemp->Flink) + while (Link != &g_ListOfAllocatedPoolsHead) { - ListTemp = ListTemp->Flink; + PLIST_ENTRY Next = Link->Flink; // // Get the head of the record // - PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(ListTemp, POOL_TABLE, PoolsList); + PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(Link, POOL_TABLE, PoolsList); // // Check whether this pool should be freed or not and @@ -377,21 +396,21 @@ PoolManagerCheckAndPerformAllocationAndDeallocation() // // This item should be freed // - CrsFreePool((PVOID)PoolTable->Address); + PlatformMemFreePool((PVOID)PoolTable->Address); // // Now we should remove the entry from the g_ListOfAllocatedPoolsHead // - RemoveEntryList(&PoolTable->PoolsList); + RemoveEntryList(Link); // // Free the structure pool // - CrsFreePool(PoolTable); + PlatformMemFreePool(PoolTable); } - } - SpinlockUnlock(&LockForReadingPool); + Link = Next; + } } // @@ -400,6 +419,8 @@ PoolManagerCheckAndPerformAllocationAndDeallocation() g_IsNewRequestForDeAllocation = FALSE; g_IsNewRequestForAllocationReceived = FALSE; + SpinlockUnlock(&LockForReadingPool); + return Result; } diff --git a/hyperdbg/hprdbgkd/code/debugger/meta-events/MetaDispatch.c b/hyperdbg/hyperkd/code/debugger/meta-events/MetaDispatch.c similarity index 100% rename from hyperdbg/hprdbgkd/code/debugger/meta-events/MetaDispatch.c rename to hyperdbg/hyperkd/code/debugger/meta-events/MetaDispatch.c diff --git a/hyperdbg/hprdbgkd/code/debugger/meta-events/Tracing.c b/hyperdbg/hyperkd/code/debugger/meta-events/Tracing.c similarity index 78% rename from hyperdbg/hprdbgkd/code/debugger/meta-events/Tracing.c rename to hyperdbg/hyperkd/code/debugger/meta-events/Tracing.c index 52af8b00..8a7837ca 100644 --- a/hyperdbg/hprdbgkd/code/debugger/meta-events/Tracing.c +++ b/hyperdbg/hyperkd/code/debugger/meta-events/Tracing.c @@ -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 @@ -104,16 +104,36 @@ TracingCheckForContinuingSteps(PROCESSOR_DEBUGGING_STATE * DbgState) } /** - * @brief Regular step-in | step one instruction to the debuggee - * @param DbgState The state of the debugger on the current core + * @brief Regular step-in, step one instruction to the debuggee * * @return VOID */ VOID -TracingPerformRegularStepInInstruction(PROCESSOR_DEBUGGING_STATE * DbgState) +TracingRegularStepInInstruction() { - UNREFERENCED_PARAMETER(DbgState); + // + // Perform the step-in + // + TracingPerformRegularStepInInstruction(); + // + // Unset the trap flag on the next VM-exit + // + if (!BreakpointRestoreTheTrapFlagOnceTriggered(HANDLE_TO_UINT32(PsGetCurrentProcessId()), HANDLE_TO_UINT32(PsGetCurrentThreadId()))) + { + LogWarning("Warning, it is currently not possible to add the current process/thread to the list of processes " + "where the trap flag should be masked. Please ensure that you manually unset the trap flag"); + } +} + +/** + * @brief Regular step-in, step one instruction to the debuggee + * + * @return VOID + */ +VOID +TracingPerformRegularStepInInstruction() +{ UINT64 Interruptibility; UINT64 InterruptibilityOld = NULL64_ZERO; diff --git a/hyperdbg/hprdbgkd/code/debugger/objects/Process.c b/hyperdbg/hyperkd/code/debugger/objects/Process.c similarity index 100% rename from hyperdbg/hprdbgkd/code/debugger/objects/Process.c rename to hyperdbg/hyperkd/code/debugger/objects/Process.c diff --git a/hyperdbg/hprdbgkd/code/debugger/objects/Thread.c b/hyperdbg/hyperkd/code/debugger/objects/Thread.c similarity index 95% rename from hyperdbg/hprdbgkd/code/debugger/objects/Thread.c rename to hyperdbg/hyperkd/code/debugger/objects/Thread.c index 63bb4aa5..c209c10b 100644 --- a/hyperdbg/hprdbgkd/code/debugger/objects/Thread.c +++ b/hyperdbg/hyperkd/code/debugger/objects/Thread.c @@ -1,4 +1,4 @@ -/** +/** * @file Thread.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief Implementation of kernel debugger functions for threads @@ -280,9 +280,9 @@ ThreadShowList(PDEBUGGEE_THREAD_LIST_NEEDED_DETAILS ThreadListSymb SavingEntries[EnumerationCount - 1].ThreadId = HANDLE_TO_UINT32(ThreadCid.UniqueThread); SavingEntries[EnumerationCount - 1].Ethread = Thread; - RtlCopyMemory(&SavingEntries[EnumerationCount - 1].ImageFileName, - CommonGetProcessNameFromProcessControlBlock((PEPROCESS)ThreadListSymbolInfo->Process), - 15); + MemoryMapperReadMemorySafe((UINT64)CommonGetProcessNameFromProcessControlBlock((PEPROCESS)ThreadListSymbolInfo->Process), + &SavingEntries[EnumerationCount - 1].ImageFileName, + 15); break; @@ -442,7 +442,7 @@ ThreadDetectChangeByDebugRegisterOnGs(PROCESSOR_DEBUGGING_STATE * DbgState, // from user-mode then IA32_KERNEL_GS_BASE should be used // but it's not for our case // - MsrGsBase = __readmsr(IA32_GS_BASE); + MsrGsBase = CpuReadMsr(IA32_GS_BASE); // // Now, we have the gs base on MSR @@ -467,8 +467,8 @@ ThreadDetectChangeByDebugRegisterOnGs(PROCESSOR_DEBUGGING_STATE * DbgState, // want dr7 and dr0 remove their configuration on vm-exits and also // we'll be able to change the dr7 of the guest on VMCS // - VmFuncSetLoadDebugControls(TRUE); - VmFuncSetSaveDebugControls(TRUE); + VmFuncSetLoadDebugControls(DbgState->CoreId, TRUE); + VmFuncSetSaveDebugControls(DbgState->CoreId, TRUE); // // Intercept #DBs by changing exception bitmap (one core) @@ -528,8 +528,8 @@ ThreadDetectChangeByDebugRegisterOnGs(PROCESSOR_DEBUGGING_STATE * DbgState, // Disable load debug controls and save debug controls because // no longer needed // - VmFuncSetLoadDebugControls(FALSE); - VmFuncSetSaveDebugControls(FALSE); + VmFuncSetLoadDebugControls(DbgState->CoreId, FALSE); + VmFuncSetSaveDebugControls(DbgState->CoreId, FALSE); // // Disable intercepting #DBs @@ -543,6 +543,23 @@ ThreadDetectChangeByDebugRegisterOnGs(PROCESSOR_DEBUGGING_STATE * DbgState, } } +/** + * @brief Query for deubg register interception state + * @param CoreId + * + * @return BOOLEAN whether it's activated or not + */ +BOOLEAN +ThreadQueryDebugRegisterInterceptionStateByCoreId(UINT32 CoreId) +{ + BOOLEAN Result = FALSE; + PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId]; + + Result = DbgState->ThreadOrProcessTracingDetails.DebugRegisterInterceptionState; + + return Result; +} + /** * @brief Enable or disable the thread change monitoring detection * on the running core based on intercepting clock interrupts diff --git a/hyperdbg/hyperkd/code/debugger/script-engine/ScriptEngine.c b/hyperdbg/hyperkd/code/debugger/script-engine/ScriptEngine.c new file mode 100644 index 00000000..90b65bba --- /dev/null +++ b/hyperdbg/hyperkd/code/debugger/script-engine/ScriptEngine.c @@ -0,0 +1,123 @@ +/** + * @file ScriptEngine.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @author M.H. Gholamrezaei (mh@hyperdbg.org) + * @brief Script engine parser and wrapper functions + * @details + * @version 0.1 + * @date 2020-10-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Get current ip from the debugger frame + * + * @return UINT64 returns the rip of the current debuggee state frame + */ +UINT64 +ScriptEngineWrapperGetInstructionPointer() +{ + // + // Check if we are in vmx-root or not + // + if (VmFuncVmxGetCurrentExecutionMode() == TRUE) + { + return VmFuncGetRip(); + } + else + { + // + // Otherwise $ip doesn't mean anything + // + return (UINT64)NULL; + } +} + +/** + * @brief Get the address of reserved buffer + * + * @param Action Corresponding action + * @return UINT64 returns the requested buffer address from user + */ +UINT64 +ScriptEngineWrapperGetAddressOfReservedBuffer(PDEBUGGER_EVENT_ACTION Action) +{ + return Action->RequestedBuffer.RequstBufferAddress; +} + +/** + * @brief Create and update the target core date and time + * @param DbgState The processor debugging state + * + * @return VOID + */ +VOID +ScriptEngineUpdateTargetCoreDateTime(PROCESSOR_DEBUGGING_STATE * DbgState) +{ + LARGE_INTEGER SystemTime, LocalTime; + KeQuerySystemTime(&SystemTime); + ExSystemTimeToLocalTime(&SystemTime, &LocalTime); + RtlTimeToTimeFields(&LocalTime, &DbgState->DateTimeHolder.TimeFields); + + sprintf_s(DbgState->DateTimeHolder.TimeBuffer, + RTL_NUMBER_OF(DbgState->DateTimeHolder.TimeBuffer), + "%02hd:%02hd:%02hd.%03hd", + DbgState->DateTimeHolder.TimeFields.Hour, + DbgState->DateTimeHolder.TimeFields.Minute, + DbgState->DateTimeHolder.TimeFields.Second, + DbgState->DateTimeHolder.TimeFields.Milliseconds); + + sprintf_s(DbgState->DateTimeHolder.DateBuffer, + RTL_NUMBER_OF(DbgState->DateTimeHolder.DateBuffer), + "%04hd-%02hd-%02hd", + DbgState->DateTimeHolder.TimeFields.Year, + DbgState->DateTimeHolder.TimeFields.Month, + DbgState->DateTimeHolder.TimeFields.Day); +} + +/** + * @brief Update core's date time and return time + * + * @return UINT64 + */ +UINT64 +ScriptEngineGetTargetCoreTime() +{ + ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CurrentCore]; + + // + // Update the core's date time + // + ScriptEngineUpdateTargetCoreDateTime(DbgState); + + // + // Return the time + // + return (UINT64)&DbgState->DateTimeHolder.TimeBuffer; +} + +/** + * @brief Update core's date time and return date + * + * @return UINT64 + */ +UINT64 +ScriptEngineGetTargetCoreDate() +{ + ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CurrentCore]; + + // + // Update the core's date time + // + ScriptEngineUpdateTargetCoreDateTime(DbgState); + + // + // Return the date + // + return (UINT64)&DbgState->DateTimeHolder.DateBuffer; +} diff --git a/hyperdbg/hyperkd/code/debugger/tests/KernelTests.c b/hyperdbg/hyperkd/code/debugger/tests/KernelTests.c new file mode 100644 index 00000000..03f304ba --- /dev/null +++ b/hyperdbg/hyperkd/code/debugger/tests/KernelTests.c @@ -0,0 +1,29 @@ +/** + * @file KernelTests.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of kernel-side test functions + * @details + * + * @version 0.1 + * @date 2021-04-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Perform the kernel-side tests + * + * @param KernelTestRequest user-mode buffer to fill kernel test information + * @return VOID + */ +VOID +TestKernelPerformTests(PDEBUGGER_PERFORM_KERNEL_TESTS KernelTestRequest) +{ + LogInfo("Starting kernel-test process..."); + + LogInfo("All the kernel events are triggered"); + + KernelTestRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; +} diff --git a/hyperdbg/hprdbgkd/code/debugger/user-level/Attaching.c b/hyperdbg/hyperkd/code/debugger/user-level/Attaching.c similarity index 86% rename from hyperdbg/hprdbgkd/code/debugger/user-level/Attaching.c rename to hyperdbg/hyperkd/code/debugger/user-level/Attaching.c index c68e75a4..7b83da01 100644 --- a/hyperdbg/hprdbgkd/code/debugger/user-level/Attaching.c +++ b/hyperdbg/hyperkd/code/debugger/user-level/Attaching.c @@ -93,7 +93,6 @@ AttachingInitialize() * @param Is32Bit * @param Eprocess * @param PebAddressToMonitor - * @param UsermodeReservedBuffer * @return UINT64 returns the unique token */ UINT64 @@ -102,8 +101,7 @@ AttachingCreateProcessDebuggingDetails(UINT32 ProcessId, BOOLEAN Is32Bit, BOOLEAN CheckCallbackAtFirstInstruction, PEPROCESS Eprocess, - UINT64 PebAddressToMonitor, - UINT64 UsermodeReservedBuffer) + UINT64 PebAddressToMonitor) { PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail; @@ -111,7 +109,7 @@ AttachingCreateProcessDebuggingDetails(UINT32 ProcessId, // Allocate the buffer // ProcessDebuggingDetail = (USERMODE_DEBUGGING_PROCESS_DETAILS *) - CrsAllocateZeroedNonPagedPool(sizeof(USERMODE_DEBUGGING_PROCESS_DETAILS)); + PlatformMemAllocateZeroedNonPagedPool(sizeof(USERMODE_DEBUGGING_PROCESS_DETAILS)); if (!ProcessDebuggingDetail) { @@ -132,14 +130,13 @@ AttachingCreateProcessDebuggingDetails(UINT32 ProcessId, ProcessDebuggingDetail->CheckCallBackForInterceptingFirstInstruction = CheckCallbackAtFirstInstruction; ProcessDebuggingDetail->Eprocess = Eprocess; ProcessDebuggingDetail->PebAddressToMonitor = (PVOID)PebAddressToMonitor; - ProcessDebuggingDetail->UsermodeReservedBuffer = UsermodeReservedBuffer; // // Allocate a thread holder buffer for this process // if (!ThreadHolderAssignThreadHolderToProcessDebuggingDetails(ProcessDebuggingDetail)) { - CrsFreePool(ProcessDebuggingDetail); + PlatformMemFreePool(ProcessDebuggingDetail); return (UINT64)NULL; } @@ -243,7 +240,7 @@ AttachingRemoveAndFreeAllProcessDebuggingDetails() // // Unallocate the pool // - CrsFreePool(ProcessDebuggingDetails); + PlatformMemFreePool(ProcessDebuggingDetails); } } @@ -284,7 +281,7 @@ AttachingRemoveProcessDebuggingDetailsByToken(UINT64 Token) // // Unallocate the pool // - CrsFreePool(ProcessDebuggingDetails); + PlatformMemFreePool(ProcessDebuggingDetails); return TRUE; } @@ -385,8 +382,11 @@ AttachingReachedToValidLoadedModule(PROCESSOR_DEBUGGING_STATE * DbgState // // Register the breakpoint + // Note that, even though it's a user-mode breakpoint, we are currently + // in the memory layout of the target process, thus, no switching memory + // layout is needed // - if (!BreakpointAddNew(&BpRequest)) + if (!BreakpointAddNew(&BpRequest, FALSE)) { LogError("Err, unable to set breakpoint on the entrypoint module"); return FALSE; @@ -409,14 +409,19 @@ AttachingReachedToValidLoadedModule(PROCESSOR_DEBUGGING_STATE * DbgState DEBUGGEE_PAUSING_REASON_DEBUGGEE_STARTING_MODULE_LOADED, NULL); } - else + else if (g_UserDebuggerState) { // // Handling state through the user-mode debugger // - UdCheckAndHandleBreakpointsAndDebugBreaks(DbgState, - DEBUGGEE_PAUSING_REASON_DEBUGGEE_STARTING_MODULE_LOADED, - NULL); + UdHandleInstantBreak(DbgState, + DEBUGGEE_PAUSING_REASON_DEBUGGEE_STARTING_MODULE_LOADED, + ProcessDebuggingDetail); + } + else + { + LogError("Err, no debugger is attached to handle the entrypoint interception"); + return FALSE; } // @@ -574,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) @@ -610,45 +615,31 @@ AttachingAdjustNopSledBuffer(UINT64 ReservedBuffAddress, UINT32 ProcessId) } /** - * @brief Check page-faults with user-debugger - * @param CoreId - * @param Address - * @param PageFaultErrorCode + * @brief Check thread interceptions with user-mode debugger * - * @return BOOLEAN if TRUE show that the page-fault injection should be ignored + * @param CoreId + * + * @return BOOLEAN if TRUE show that the thread interceptin is handled otherwise FALSE */ BOOLEAN -AttachingCheckPageFaultsWithUserDebugger(UINT32 CoreId, - UINT64 Address, - UINT32 PageFaultErrorCode) +AttachingCheckThreadInterceptionWithUserDebugger(UINT32 CoreId) { - UNREFERENCED_PARAMETER(Address); - UNREFERENCED_PARAMETER(PageFaultErrorCode); - - PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail; PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId]; + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail; // // Check whether user-debugger is initialized or not // - if (g_UserDebuggerState == FALSE) + if (!g_UserDebuggerState) { return FALSE; } - // - // Check if thread is in user-mode - // - if (VmFuncGetLastVmexitRip(CoreId) & 0xf000000000000000) - { - // - // We won't intercept threads in kernel-mode - // - return FALSE; - } - ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId())); + // + // Check if the process debugging detail is found + // if (!ProcessDebuggingDetail) { // @@ -658,23 +649,24 @@ AttachingCheckPageFaultsWithUserDebugger(UINT32 CoreId, } // - // Check if thread is in intercepting phase + // Check if thread is in the intercepting phase // if (ProcessDebuggingDetail->IsOnThreadInterceptingPhase) { // // Handling state through the user-mode debugger // - UdCheckAndHandleBreakpointsAndDebugBreaks(DbgState, - DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_THREAD_INTERCEPTED, - NULL); + if (UdCheckAndHandleBreakpointsAndDebugBreaks(DbgState, + DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_THREAD_INTERCEPTED, + NULL)) + { + // + // Check for possible commands that need to be executed + // + UdCheckForCommand(DbgState, ProcessDebuggingDetail); - // - // related to user debugger - // - VmFuncSuppressRipIncrement(CoreId); - - return TRUE; + return TRUE; + } } // @@ -715,56 +707,32 @@ AttachingConfigureInterceptingThreads(UINT64 ProcessDebuggingToken, BOOLEAN Enab return FALSE; } - // - // if the user want to disable the intercepting phase, we just ignore the - // request without a message - // - if (!Enable && !ProcessDebuggingDetail->IsOnThreadInterceptingPhase) - { - return FALSE; - } - // // We're or we're not in thread intercepting phase now // ProcessDebuggingDetail->IsOnThreadInterceptingPhase = Enable; + // + // Intercepting threads is enabled + // if (Enable) { // - // Intercept all mov 2 cr3s + // Add the process to the watching list to be able to intercept the threads // - DebuggerEventEnableMovToCr3ExitingOnAllProcessors(); + ConfigureExecTrapAddProcessToWatchingList(ProcessDebuggingDetail->ProcessId); } else { // - // Removing the mov to cr3 vm-exits + // Unpause the threads of the target process // - DebuggerEventDisableMovToCr3ExitingOnAllProcessors(); - } + ThreadHolderUnpauseAllThreadsInProcess(ProcessDebuggingDetail); - // - // Set the supervisor bit to 1 when we want to continue all the threads - // - if (!Enable) - { - for (size_t i = 0; i < MAX_CR3_IN_A_PROCESS; i++) - { - if (ProcessDebuggingDetail->InterceptedCr3[i].Flags != (UINT64)NULL) - { - // - // This cr3 should not be intercepted on threads' user mode execution - // - if (!MemoryMapperSetSupervisorBitWithoutSwitchingByCr3(NULL, - TRUE, - PagingLevelPageMapLevel4, - ProcessDebuggingDetail->InterceptedCr3[i])) - { - return FALSE; - } - } - } + // + // Remove the process from the watching list + // + ConfigureExecTrapRemoveProcessFromWatchingList(ProcessDebuggingDetail->ProcessId); } return TRUE; @@ -810,7 +778,6 @@ AttachingPerformAttachToProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS Attach PEPROCESS SourceProcess; UINT64 ProcessDebuggingToken; UINT64 PebAddressToMonitor; - UINT64 UsermodeReservedBuffer; BOOLEAN ResultOfApplyingEvent; BOOLEAN Is32Bit; PUSERMODE_DEBUGGING_PROCESS_DETAILS TempProcessDebuggingDetail; @@ -882,32 +849,6 @@ AttachingPerformAttachToProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS Attach return FALSE; } - // - // allocate memory in the target user-mode process - // - UsermodeReservedBuffer = MemoryMapperReserveUsermodeAddressOnTargetProcess(AttachRequest->ProcessId, TRUE); - - if (UsermodeReservedBuffer == (UINT64)NULL) - { - AttachRequest->Result = DEBUGGER_ERROR_UNABLE_TO_ATTACH_TO_TARGET_USER_MODE_PROCESS; - return FALSE; - } - - // - // Adjust the nop sled buffer - // - if (!AttachingAdjustNopSledBuffer(UsermodeReservedBuffer, - AttachRequest->ProcessId)) - { - AttachRequest->Result = DEBUGGER_ERROR_UNABLE_TO_ATTACH_TO_TARGET_USER_MODE_PROCESS; - return FALSE; - } - - // - // Log for test - // - // LogInfo("Reserved address on the target process: %llx\n", UsermodeReservedBuffer); - // // Create the debugging detail for process // @@ -916,8 +857,7 @@ AttachingPerformAttachToProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS Attach Is32Bit, AttachRequest->CheckCallbackAtFirstInstruction, SourceProcess, - PebAddressToMonitor, - UsermodeReservedBuffer); + PebAddressToMonitor); // // Check if we successfully get the token @@ -1024,72 +964,6 @@ AttachingPerformAttachToProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS Attach return TRUE; } -/** - * @brief Handle the cr3 vm-exits for thread interception - * @details this function should be called in vmx-root - * - * @param CoreId - * @param NewCr3 - * @return BOOLEAN - */ -BOOLEAN -AttachingHandleCr3VmexitsForThreadInterception(UINT32 CoreId, CR3_TYPE NewCr3) -{ - PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail; - - ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId())); - - // - // Check if process is valid or if thread is in intercepting phase - // - if (!ProcessDebuggingDetail || !ProcessDebuggingDetail->IsOnThreadInterceptingPhase) - { - // - // not related to user debugger - // - VmFuncUnsetExceptionBitmap(CoreId, EXCEPTION_VECTOR_PAGE_FAULT); - return FALSE; - } - - // - // Save the cr3 for future continuing the thread - // - for (size_t i = 0; i < MAX_CR3_IN_A_PROCESS; i++) - { - if (ProcessDebuggingDetail->InterceptedCr3[i].Flags == NewCr3.Flags) - { - // - // We found it saved previously, no need any further action - // - break; - } - - if (ProcessDebuggingDetail->InterceptedCr3[i].Flags == (UINT64)NULL) - { - // - // Save the cr3 - // - ProcessDebuggingDetail->InterceptedCr3[i].Flags = NewCr3.Flags; - break; - } - } - - // - // This thread should be intercepted - // - if (!MemoryMapperSetSupervisorBitWithoutSwitchingByCr3(NULL, FALSE, PagingLevelPageMapLevel4, NewCr3)) - { - return FALSE; - } - - // - // Intercept #PFs - // - VmFuncSetExceptionBitmap(CoreId, EXCEPTION_VECTOR_PAGE_FAULT); - - return TRUE; -} - /** * @brief handling unhandled EPT violations * @param CoreId @@ -1199,6 +1073,50 @@ AttachingPauseProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS PauseRequest) } } +/** + * @brief Continues the target process + * @details this function should not be called in vmx-root + * + * @param ContinueRequest + * @return BOOLEAN + */ +BOOLEAN +AttachingContinueProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS ContinueRequest) +{ + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails; + + // + // Get the thread debugging detail + // + ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByToken(ContinueRequest->Token); + + // + // Check if token is valid or not + // + if (!ProcessDebuggingDetails) + { + ContinueRequest->Result = DEBUGGER_ERROR_INVALID_THREAD_DEBUGGING_TOKEN; + return FALSE; + } + + // + // Configure the intercepting threads to be disabled + // + if (AttachingConfigureInterceptingThreads(ContinueRequest->Token, FALSE)) + { + // + // The continuing operation was successful + // + ContinueRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + return TRUE; + } + else + { + ContinueRequest->Result = DEBUGGER_ERROR_UNABLE_TO_PAUSE_THE_PROCESS_THREADS; + return FALSE; + } +} + /** * @brief Kill the target process from kernel-mode * @details this function should not be called in vmx-root @@ -1332,16 +1250,9 @@ AttachingPerformDetach(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS DetachRequest) } // - // Free the reserved memory in the target process + // Remove the process from interception mechanisms // - if (!MemoryMapperFreeMemoryOnTargetProcess(DetachRequest->ProcessId, - (PVOID)ProcessDebuggingDetail->UsermodeReservedBuffer)) - { - // - // Still, we continue, no need to abort the operation - // - LogError("Err, cannot deallocate reserved buffer in the detached process"); - } + AttachingConfigureInterceptingThreads(ProcessDebuggingDetail->Token, FALSE); // // Remove the entry from the process debugging details list @@ -1430,11 +1341,17 @@ AttachingSwitchProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS SwitchRequest) // // Fill the needed details by user mode // - SwitchRequest->Token = ProcessDebuggingDetail->Token; - SwitchRequest->ProcessId = ProcessDebuggingDetail->ProcessId; - SwitchRequest->ThreadId = ThreadDebuggingDetail->ThreadId; - SwitchRequest->Is32Bit = ProcessDebuggingDetail->Is32Bit; - SwitchRequest->IsPaused = ThreadDebuggingDetail->IsPaused; + SwitchRequest->Token = ProcessDebuggingDetail->Token; + SwitchRequest->ProcessId = ProcessDebuggingDetail->ProcessId; + SwitchRequest->ThreadId = ThreadDebuggingDetail->ThreadId; + SwitchRequest->Is32Bit = ProcessDebuggingDetail->Is32Bit; + SwitchRequest->Rip = ThreadDebuggingDetail->ThreadRip; + SwitchRequest->IsPaused = ThreadDebuggingDetail->IsPaused; + SwitchRequest->SizeOfInstruction = ThreadDebuggingDetail->SizeOfInstruction; + + memcpy(&SwitchRequest->InstructionBytesOnRip[0], + &ThreadDebuggingDetail->InstructionBytesOnRip[0], + ThreadDebuggingDetail->SizeOfInstruction); SwitchRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; return TRUE; @@ -1510,7 +1427,11 @@ AttachingTargetProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS Request) // // As we're here, we need to initialize the user-mode debugger // - UdInitializeUserDebugger(); + if (!UdInitializeUserDebugger()) + { + Request->Result = DEBUGGER_ERROR_DEBUGGER_NOT_INITIALIZED; + return; + } switch (Request->Action) { @@ -1538,6 +1459,12 @@ AttachingTargetProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS Request) break; + case DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_CONTINUE_PROCESS: + + AttachingContinueProcess(Request); + + break; + case DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_PAUSE_PROCESS: AttachingPauseProcess(Request); diff --git a/hyperdbg/hprdbgkd/code/debugger/user-level/ThreadHolder.c b/hyperdbg/hyperkd/code/debugger/user-level/ThreadHolder.c similarity index 89% rename from hyperdbg/hprdbgkd/code/debugger/user-level/ThreadHolder.c rename to hyperdbg/hyperkd/code/debugger/user-level/ThreadHolder.c index def1abfa..0d37c3b6 100644 --- a/hyperdbg/hprdbgkd/code/debugger/user-level/ThreadHolder.c +++ b/hyperdbg/hyperkd/code/debugger/user-level/ThreadHolder.c @@ -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) { @@ -98,6 +98,42 @@ ThreadHolderIsAnyPausedThreadInProcess(PUSERMODE_DEBUGGING_PROCESS_DETAILS Proce return FALSE; } +/** + * @brief Unpause all threads in the process debugging details + * + * @param ProcessDebuggingDetail + * @return BOOLEAN + */ +BOOLEAN +ThreadHolderUnpauseAllThreadsInProcess(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail) +{ + PLIST_ENTRY TempList = 0; + BOOLEAN AtLeastOneThreadUnpaused = FALSE; + + TempList = &ProcessDebuggingDetail->ThreadsListHead; + + while (&ProcessDebuggingDetail->ThreadsListHead != TempList->Flink) + { + TempList = TempList->Flink; + 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++) + { + if (ThreadHolder->Threads[i].ThreadId != NULL_ZERO && ThreadHolder->Threads[i].IsPaused) + { + // + // At least one thread is paused, let's unpause it + // + ThreadHolder->Threads[i].IsPaused = FALSE; + AtLeastOneThreadUnpaused = TRUE; + } + } + } + + return AtLeastOneThreadUnpaused; +} + /** * @brief Find the active threads of the process from process id * @@ -129,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) { @@ -177,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) { @@ -226,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) { @@ -269,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) { @@ -301,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) { @@ -379,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) { @@ -418,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) { @@ -518,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) { @@ -595,16 +631,18 @@ 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) { // // A paused thread should be saved // - BufferToStoreDetails[CurrentIndex].IsProcess = FALSE; - BufferToStoreDetails[CurrentIndex].ProcessId = ProcessDebuggingDetails->ProcessId; - BufferToStoreDetails[CurrentIndex].ThreadId = ThreadHolder->Threads[i].ThreadId; + BufferToStoreDetails[CurrentIndex].IsProcess = FALSE; + BufferToStoreDetails[CurrentIndex].ProcessId = ProcessDebuggingDetails->ProcessId; + BufferToStoreDetails[CurrentIndex].ThreadId = ThreadHolder->Threads[i].ThreadId; + BufferToStoreDetails[CurrentIndex].NumberOfBlockedContextSwitches = ThreadHolder->Threads[i].NumberOfBlockedContextSwitches; + CurrentIndex++; if (MaxCount == CurrentIndex) { diff --git a/hyperdbg/hyperkd/code/debugger/user-level/Ud.c b/hyperdbg/hyperkd/code/debugger/user-level/Ud.c new file mode 100644 index 00000000..3d0a7e84 --- /dev/null +++ b/hyperdbg/hyperkd/code/debugger/user-level/Ud.c @@ -0,0 +1,992 @@ +/** + * @file Ud.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Routines related to user mode debugging + * @details + * @version 0.1 + * @date 2022-01-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief initialize user debugger + * @details this function should be called on vmx non-root + * + * @return BOOLEAN + */ +BOOLEAN +UdInitializeUserDebugger() +{ + // + // Check if it's already initialized or not, we'll ignore it if it's + // previously initialized + // + if (g_UserDebuggerState) + { + return TRUE; + } + + // + // Configure the exec-trap on all processors + // + if (!ConfigureInitializeExecTrapOnAllProcessors()) + { + return FALSE; + } + + // + // Check if we have functions we need for attaching mechanism + // + if (g_PsGetProcessPeb == NULL || g_PsGetProcessWow64Process == NULL || g_ZwQueryInformationProcess == NULL) + { + LogError("Err, unable to find needed functions for user-debugger"); + // return FALSE; + } + + // + // Start the seed of user-mode debugging thread + // + g_SeedOfUserDebuggingDetails = DebuggerThreadDebuggingTagStartSeed; + + // + // Initialize the thread debugging details list + // + InitializeListHead(&g_ProcessDebuggingDetailsListHead); + + // + // Enable vm-exit on Hardware debug exceptions and breakpoints + // so, intercept #DBs and #BP by changing exception bitmap (one core) + // + BroadcastEnableDbAndBpExitingAllCores(); + + // + // Request to allocate buffers for thread holder of threads + // + ThreadHolderAllocateThreadHoldingBuffers(); + + // + // Initialize command waiting event + // + SynchronizationInitializeEvent(&g_UserDebuggerWaitingCommandEvent); + + // + // Indicate that the user debugger is active + // + g_UserDebuggerState = TRUE; + + return TRUE; +} + +/** + * @brief uninitialize user debugger + * @details this function should be called on vmx non-root + * + * @return VOID + */ +VOID +UdUninitializeUserDebugger() +{ + if (g_UserDebuggerState) + { + // + // Indicate that the user debugger is not active + // + g_UserDebuggerState = FALSE; + + // + // Uninitialize the exec-trap on all processors + // + ConfigureUninitializeExecTrapOnAllProcessors(); + + // + // Free and deallocate all the buffers (pools) relating to + // thread debugging details + // + AttachingRemoveAndFreeAllProcessDebuggingDetails(); + } +} + +/** + * @brief Handle cases where we instant break is needed on the user debugger + * + * @param DbgState The state of the debugger on the current core + * @param Reason The reason of the pausing + * @param ProcessDebuggingDetail + * + * @return BOOLEAN + */ +BOOLEAN +UdHandleInstantBreak(PROCESSOR_DEBUGGING_STATE * DbgState, + DEBUGGEE_PAUSING_REASON Reason, + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail) +{ + // + // Check if the process debugging details is available or not + // + if (ProcessDebuggingDetail == NULL) + { + // + // If the process debugging detail is not available, we should + // find it by the current process id + // + ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId())); + + if (ProcessDebuggingDetail == NULL) + { + // + // If we reached here, it means that the process debugging detail is not found + // so, we should return FALSE to indicate that we couldn't handle the instant break + // + return FALSE; + } + } + + // + // Add the process to the watching list to be able to intercept the threads + // + if (AttachingConfigureInterceptingThreads(ProcessDebuggingDetail->Token, TRUE)) + { + // + // Since the adding it to the watching list will take effect from the next + // CR3 vm-exit, we should change the state of the core to prevent further execution + // + ConfigureExecTrapApplyMbecConfiguratinFromKernelSide(DbgState->CoreId); + + // + // Handling state through the user-mode debugger + // + return UdCheckAndHandleBreakpointsAndDebugBreaks(DbgState, + Reason, + NULL); + } + + // + // If we reached here, it means that we couldn't add the process to the + // + return FALSE; +} + +/** + * @brief Apply hardware debug registers to all cores + * + * @param TargetAddress + * + * @return VOID + */ +VOID +UdApplyHardwareDebugRegister(PVOID TargetAddress) +{ + SetDebugRegisters(DEBUGGER_DEBUG_REGISTER_FOR_STEP_OVER, + BREAK_ON_INSTRUCTION_FETCH, + FALSE, + (UINT64)TargetAddress); +} + +/** + * @brief Send the result of formats command to the user debugger + * @param Value + * + * @return VOID + */ +VOID +UdSendFormatsFunctionResult(UINT64 Value) +{ + g_UserDebuggerFormatsResultPacket.Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + g_UserDebuggerFormatsResultPacket.Value = Value; +} + +/** + * @brief routines to broadcast setting hardware debug registers on all cores + * @param TargetAddress + * + * @return VOID + */ +VOID +UdBroadcastSetHardwareDebugRegistersAllCores(PVOID TargetAddress) +{ + // + // Broadcast to all cores + // + KeGenericCallDpc(DpcRoutineSetHardwareDebugRegisters, TargetAddress); +} + +/** + * @brief Regular step-over, step one instruction to the debuggee on user debugger if + * there is a call then it jumps the call + * + * @param LastRip Last RIP register + * @param IsNextInstructionACall + * @param CallLength + * + * @return VOID + */ +VOID +UdRegularStepOver(UINT64 LastRip, BOOLEAN IsNextInstructionACall, UINT32 CallLength) +{ + UINT64 NextAddressForHardwareDebugBp = 0; + + // LogInfo("Last Rip: %llx, IsNextInstructionACall: %s, Call length: %x", + // LastRip, + // IsNextInstructionACall ? "true" : "false", + // CallLength); + + if (IsNextInstructionACall) + { + // + // It's a call, we should put a hardware debug register breakpoint + // on the next instruction + // + NextAddressForHardwareDebugBp = LastRip + CallLength; + + // + // Broadcast to apply hardware debug registers to all cores + // + UdBroadcastSetHardwareDebugRegistersAllCores((PVOID)NextAddressForHardwareDebugBp); + } + else + { + // + // Any instruction other than call (regular step) + // + TracingRegularStepInInstruction(); + } +} + +/** + * @brief Handles debug events when user-debugger is attached + * + * @param DbgState The state of the debugger on the current core + * @param TrapSetByDebugger Shows whether a trap set by debugger or not + * + * @return BOOLEAN + */ +BOOLEAN +UdHandleDebugEventsWhenUserDebuggerIsAttached(PROCESSOR_DEBUGGING_STATE * DbgState, + BOOLEAN TrapSetByDebugger) +{ + UNREFERENCED_PARAMETER(TrapSetByDebugger); + + if (UdHandleInstantBreak(DbgState, + DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_DEBUG_BREAK, + NULL)) + { + // + // Handled by user debugger + // + return TRUE; + } + else + { + // + // Not handled by user debugger + // + return FALSE; + } +} + +/** + * @brief Perform stepping though the instructions in the target thread + * + * @param DbgState The state of the debugger on the current core + * @param ProcessDebuggingDetail + * @param ThreadDebuggingDetails + * @param SteppingType + * @param IsCurrentInstructionACall + * @param CallInstructionSize + * + * @return VOID + */ +VOID +UdStepInstructions(PROCESSOR_DEBUGGING_STATE * DbgState, + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail, + PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, + DEBUGGER_REMOTE_STEPPING_REQUEST SteppingType, + BOOLEAN IsCurrentInstructionACall, + UINT32 CallInstructionSize) +{ + UNREFERENCED_PARAMETER(ThreadDebuggingDetails); + + switch (SteppingType) + { + case DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_IN: + + // + // Apply step-in (t command) + // + TracingRegularStepInInstruction(); + + // + // Continue the debuggee process + // + AttachingConfigureInterceptingThreads(ProcessDebuggingDetail->Token, FALSE); + + break; + + case DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER: + + // + // Apply Step-over (p command) + // + UdRegularStepOver( + VmFuncGetLastVmexitRip(DbgState->CoreId), + IsCurrentInstructionACall, + CallInstructionSize); + + // + // Continue the debuggee process + // + AttachingConfigureInterceptingThreads(ProcessDebuggingDetail->Token, FALSE); + + break; + + default: + break; + } +} + +/** + * @brief Perform reading register(s) in the target thread + * + * @param DbgState The state of the debugger on the current core + * @param RegisterId + * + * @return VOID + */ +VOID +UdReadRegisters(PROCESSOR_DEBUGGING_STATE * DbgState, + UINT32 RegisterId) +{ + UNREFERENCED_PARAMETER(DbgState); + UNREFERENCED_PARAMETER(RegisterId); + + PDEBUGGER_UD_COMMAND_PACKET ActionRequest; + PDEBUGGEE_REGISTER_READ_DESCRIPTION RegDesc; + + // + // Recover the action request buffer and optional storage buffer + // + ActionRequest = (DEBUGGER_UD_COMMAND_PACKET *)g_UserDebuggerWaitingCommandBuffer; + RegDesc = (PDEBUGGEE_REGISTER_READ_DESCRIPTION)((UINT8 *)g_UserDebuggerWaitingCommandBuffer + sizeof(DEBUGGER_UD_COMMAND_PACKET)); + + // + // *** Here, we should read the registers and put them in the optional storage buffer *** + // + DebuggerCommandReadRegisters(DbgState->Regs, RegDesc); + + // + // Set the register request result + // + RegDesc->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + // + // Set the action request result + // + ActionRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + // + // Set the event to indicate that the command is completed + // + SynchronizationSetEvent(&g_UserDebuggerWaitingCommandEvent); +} + +/** + * @brief Perform running script in the target thread + * + * @param DbgState The state of the debugger on the current core + * + * @return VOID + */ +VOID +UdRunScript(PROCESSOR_DEBUGGING_STATE * DbgState) +{ + PDEBUGGER_UD_COMMAND_PACKET ActionRequest; + DEBUGGEE_SCRIPT_PACKET * ScriptPacket; + DEBUGGER_TRIGGERED_EVENT_DETAILS EventTriggerDetail = {0}; + + // + // Recover the action request buffer and optional storage buffer + // + ActionRequest = (DEBUGGER_UD_COMMAND_PACKET *)g_UserDebuggerWaitingCommandBuffer; + ScriptPacket = (DEBUGGEE_SCRIPT_PACKET *)((UINT8 *)g_UserDebuggerWaitingCommandBuffer + sizeof(DEBUGGER_UD_COMMAND_PACKET)); + + // + // *** Here, we should execute script buffer and put them in the optional storage buffer *** + // + + // + // Set a tag to the script so it shows the message is from script engine + // + EventTriggerDetail.Tag = OPERATION_LOG_MESSAGE_MANDATORY; + + // + // Run the script in the target process (thread) + // + if (DebuggerPerformRunScript(DbgState, + NULL, + ScriptPacket, + &EventTriggerDetail)) + { + // + // Check if we need to format the output or not + // + if (ScriptPacket->IsFormat) + { + // + // For the format, we need to get the result from the script engine + // through global variables, we store the result of format into + // optional parameters + // + ScriptPacket->Result = g_UserDebuggerFormatsResultPacket.Result; + ScriptPacket->FormatValue = g_UserDebuggerFormatsResultPacket.Value; + } + else + { + // + // Set status + // + ScriptPacket->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + } + else + { + // + // Set status + // + ScriptPacket->Result = DEBUGGER_ERROR_PREPARING_DEBUGGEE_TO_RUN_SCRIPT; + } + + // + // Set the action request result + // + ActionRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + // + // Set the event to indicate that the command is completed + // + SynchronizationSetEvent(&g_UserDebuggerWaitingCommandEvent); +} + +/** + * @brief Perform the user-mode commands + * + * @param DbgState The state of the debugger on the current core + * @param ProcessDebuggingDetails + * @param ThreadDebuggingDetails + * @param UserAction + * @param OptionalParam1 + * @param OptionalParam2 + * @param OptionalParam3 + * @param OptionalParam4 + * + * @return BOOLEAN + */ +BOOLEAN +UdPerformCommand(PROCESSOR_DEBUGGING_STATE * DbgState, + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail, + PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, + DEBUGGER_UD_COMMAND_ACTION_TYPE UserAction, + UINT64 OptionalParam1, + UINT64 OptionalParam2, + UINT64 OptionalParam3, + UINT64 OptionalParam4) +{ + UNREFERENCED_PARAMETER(OptionalParam4); + + // + // Perform the command + // + switch (UserAction) + { + case DEBUGGER_UD_COMMAND_ACTION_TYPE_REGULAR_STEP: + + // + // Stepping through the instructions + // + UdStepInstructions(DbgState, + ProcessDebuggingDetail, + ThreadDebuggingDetails, + (DEBUGGER_REMOTE_STEPPING_REQUEST)OptionalParam1, + (BOOLEAN)OptionalParam2, + (UINT32)OptionalParam3); + + break; + + case DEBUGGER_UD_COMMAND_ACTION_TYPE_READ_REGISTERS: + + // + // Read the registers + // + UdReadRegisters(DbgState, + (UINT32)OptionalParam1); + + break; + + case DEBUGGER_UD_COMMAND_ACTION_TYPE_EXECUTE_SCRIPT_BUFFER: + + // + // Execute the script buffer + // + UdRunScript(DbgState); + + break; + + default: + + // + // Invalid user action + // + return FALSE; + + break; + } + + return TRUE; +} + +/** + * @brief Check for the user-mode commands + * + * @param DbgState The state of the debugger on the current core + * @param ProcessDebuggingDetail + * + * @return BOOLEAN + */ +BOOLEAN +UdCheckForCommand(PROCESSOR_DEBUGGING_STATE * DbgState, + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail) +{ + PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails; + BOOLEAN CommandFound = FALSE; + + ThreadDebuggingDetails = ThreadHolderGetProcessThreadDetailsByProcessIdAndThreadId(HANDLE_TO_UINT32(PsGetCurrentProcessId()), + HANDLE_TO_UINT32(PsGetCurrentThreadId())); + + if (!ThreadDebuggingDetails) + { + return FALSE; + } + + // + // If we reached here, the current thread is in debugger attached mechanism + // now we check whether it's paused or not + // + if (!ThreadDebuggingDetails->IsPaused) + { + return FALSE; + } + + // + // 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++) + { + if (ThreadDebuggingDetails->UdAction[i].ActionType != DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE) + { + // + // We found a command for this thread + // + CommandFound = TRUE; + + // + // Perform the command + // + UdPerformCommand(DbgState, + ProcessDebuggingDetail, + ThreadDebuggingDetails, + ThreadDebuggingDetails->UdAction[i].ActionType, + ThreadDebuggingDetails->UdAction[i].OptionalParam1, + ThreadDebuggingDetails->UdAction[i].OptionalParam2, + ThreadDebuggingDetails->UdAction[i].OptionalParam3, + ThreadDebuggingDetails->UdAction[i].OptionalParam4); + + // + // Remove the command + // + ThreadDebuggingDetails->UdAction[i].OptionalParam1 = (UINT64)NULL; + ThreadDebuggingDetails->UdAction[i].OptionalParam2 = (UINT64)NULL; + ThreadDebuggingDetails->UdAction[i].OptionalParam3 = (UINT64)NULL; + ThreadDebuggingDetails->UdAction[i].OptionalParam4 = (UINT64)NULL; + + // + // At last disable it + // + ThreadDebuggingDetails->UdAction[i].ActionType = DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE; + + // + // only one command at a time + // + break; + } + } + + // + // Return whether we found a command or not + // + return CommandFound; +} + +/** + * @brief Dispatch the user-mode commands + * + * @param ActionRequest + * @param ActionRequestInputLength + * @param ActionRequestOutputLength + * + * @return BOOLEAN + */ +BOOLEAN +UdDispatchUsermodeCommands(PDEBUGGER_UD_COMMAND_PACKET ActionRequest, + UINT32 ActionRequestInputLength, + UINT32 ActionRequestOutputLength) +{ + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails; + BOOLEAN Result; + + // + // Find the thread debugging detail of the thread + // + ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByToken(ActionRequest->ProcessDebuggingDetailToken); + + if (!ProcessDebuggingDetails) + { + // + // Token not found! + // + ActionRequest->Result = DEBUGGER_ERROR_INVALID_THREAD_DEBUGGING_TOKEN; + + return FALSE; + } + + // + // Check if this command needs the action request to be waited for completion or not + // + if (ActionRequest->WaitForEventCompletion) + { + // + // Set the command event buffer + // + g_UserDebuggerWaitingCommandBuffer = (PVOID)ActionRequest; + + // + // Set the input command buffer length + // + g_UserDebuggerWaitingCommandInputBufferLength = ActionRequestInputLength; + + // + // Set the output command buffer length + // + g_UserDebuggerWaitingCommandOutputBufferLength = ActionRequestOutputLength; + } + + // + // Apply the command to all threads or just one thread + // + Result = ThreadHolderApplyActionToPausedThreads(ProcessDebuggingDetails, ActionRequest); + + // + // Check if we need to wait for the command event completion or not + // + if (Result && ActionRequest->WaitForEventCompletion) + { + // + // Wait for the command to be completed + // + SynchronizationWaitForEvent(&g_UserDebuggerWaitingCommandEvent); + } + + // + // Since the command is applied successfully, we can set the result + // Note that if the command contains another layer of optional buffers + // the result of that optional buffer might be different than this result + // this one is just for applying the command itself + // + if (Result) + { + // + // If we are not waiting for the event completion, we should set the + // result of the action request here as we successfully applied the command + // + ActionRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + else + { + ActionRequest->Result = DEBUGGER_ERROR_UNABLE_TO_APPLY_COMMAND_TO_THE_TARGET_THREAD; + } + + return Result; +} + +/** + * @brief Set the thread pausing state + * + * @param ThreadDebuggingDetails + * @param ProcessDebuggingDetails + * @param InstructionBytesBuffer + * @param SizeOfInstruction + * + * @return VOID + */ +VOID +UdSetThreadPausingState(PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails, + PVOID InstructionBytesBuffer, + UINT32 SizeOfInstruction) +{ + UNREFERENCED_PARAMETER(ProcessDebuggingDetails); + + // + // Save the RIP for future return + // + ThreadDebuggingDetails->ThreadRip = VmFuncGetRip(); + + // + // Set the number of context switches to one (reset it if already set) + // + ThreadDebuggingDetails->NumberOfBlockedContextSwitches = 1; + + // + // Indicate that it's spinning + // + ThreadDebuggingDetails->IsPaused = TRUE; + + // + // Set size of instruction + // + ThreadDebuggingDetails->SizeOfInstruction = SizeOfInstruction; + + // + // Copy the current running instruction + // + memcpy(&ThreadDebuggingDetails->InstructionBytesOnRip[0], InstructionBytesBuffer, SizeOfInstruction); +} + +/** + * @brief Handle special reasons pre-pausings + * @details This function can be used in vmx-root + * + * @param DbgState The state of the debugger on the current core + * @param ThreadDebuggingDetails + * @param Reason + * @param EventDetails + * @return VOID + */ +VOID +UdPrePausingReasons(PROCESSOR_DEBUGGING_STATE * DbgState, + PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, + DEBUGGEE_PAUSING_REASON Reason, + PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails) + +{ + UNREFERENCED_PARAMETER(DbgState); + UNREFERENCED_PARAMETER(ThreadDebuggingDetails); + UNREFERENCED_PARAMETER(EventDetails); + + // + // *** Handle events before pausing *** + // + switch (Reason) + { + case DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_DEBUG_BREAK: + + break; + + default: + break; + } +} + +/** + * @brief Handle #DBs and #BPs for kernel debugger + * @details This function can be used in vmx-root + * + * @param DbgState The state of the debugger on the current core + * @param Reason + * @param EventDetails + * @return BOOLEAN + */ +BOOLEAN +UdCheckAndHandleBreakpointsAndDebugBreaks(PROCESSOR_DEBUGGING_STATE * DbgState, + DEBUGGEE_PAUSING_REASON Reason, + PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails) +{ + DEBUGGEE_UD_PAUSED_PACKET PausePacket; + ULONG ExitInstructionLength = 0; + UINT32 SizeOfSafeBufferToRead = 0; + RFLAGS Rflags = {0}; + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails = NULL; + PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails = NULL; + UINT64 LastVmexitRip = VmFuncGetLastVmexitRip(DbgState->CoreId); + + // + // Breaking only supported if user-debugger is loaded + // + if (!g_UserDebuggerState) + { + return FALSE; + } + + // + // Check entry of paused thread + // + ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId())); + + if (!ProcessDebuggingDetails) + { + // + // Token not found! + // + return FALSE; + } + + // + // Find the thread entry and if not found, create one for it + // + ThreadDebuggingDetails = ThreadHolderFindOrCreateThreadDebuggingDetail(HANDLE_TO_UINT32(PsGetCurrentThreadId()), ProcessDebuggingDetails); + + if (!ThreadDebuggingDetails) + { + // + // Sth went wrong! + // + return FALSE; + } + + // + // Check if the thread is already paused or not + // + if (ThreadDebuggingDetails->IsPaused) + { + // + // Increase the number of context switches + // + ThreadDebuggingDetails->NumberOfBlockedContextSwitches++; + + // + // The thread is already paused, so we don't need to pause it again + // + return TRUE; + } + + // + // Set it as active thread debugging + // + ProcessDebuggingDetails->ActiveThreadId = ThreadDebuggingDetails->ThreadId; + + // + // Perform the pre-pausing tasks + // + UdPrePausingReasons(DbgState, ThreadDebuggingDetails, Reason, EventDetails); + + // + // *** Fill the pausing structure *** + // + + RtlZeroMemory(&PausePacket, sizeof(DEBUGGEE_UD_PAUSED_PACKET)); + + // + // Set the pausing reason + // + PausePacket.PausingReason = Reason; + + // + // Set process debugging information + // + PausePacket.ProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId()); + PausePacket.ThreadId = HANDLE_TO_UINT32(PsGetCurrentThreadId()); + PausePacket.ProcessDebuggingToken = ProcessDebuggingDetails->Token; + + // + // Set the RIP and mode of execution + // + PausePacket.Rip = LastVmexitRip; + PausePacket.Is32Bit = KdIsGuestOnUsermode32Bit(); + + // + // Set rflags for finding the results of conditional jumps + // + Rflags.AsUInt = VmFuncGetRflags(); + PausePacket.Rflags = Rflags.AsUInt; + + // + // Set the event tag (if it's an event) + // + if (EventDetails != NULL) + { + PausePacket.EventTag = EventDetails->Tag; + PausePacket.EventCallingStage = EventDetails->Stage; + } + + // + // Read the instruction len + // + if (DbgState->InstructionLengthHint != 0) + { + ExitInstructionLength = DbgState->InstructionLengthHint; + } + else + { + // + // Reading instruction length (VMCS_VMEXIT_INSTRUCTION_LENGTH) proved to + // provide wrong results, so we won't use it + // + + // + // Compute the amount of buffer we can read without problem + // + SizeOfSafeBufferToRead = (UINT32)(LastVmexitRip & 0xfff); + SizeOfSafeBufferToRead += MAXIMUM_INSTR_SIZE; + + if (SizeOfSafeBufferToRead >= PAGE_SIZE) + { + SizeOfSafeBufferToRead = SizeOfSafeBufferToRead - PAGE_SIZE; + SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE - SizeOfSafeBufferToRead; + } + else + { + SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE; + } + + // + // Set the length to notify debuggee + // + ExitInstructionLength = SizeOfSafeBufferToRead; + } + + // + // Set the reading length of bytes (for instruction disassembling) + // + PausePacket.ReadInstructionLen = (UINT16)ExitInstructionLength; + + // + // Find the current instruction + // + MemoryMapperReadMemorySafeOnTargetProcess(LastVmexitRip, + &PausePacket.InstructionBytesOnRip, + ExitInstructionLength); + + // + // Send the pause packet, along with RIP and an indication + // to pause to the user debugger + // + LogCallbackSendBuffer(OPERATION_NOTIFICATION_FROM_USER_DEBUGGER_PAUSE, + &PausePacket, + sizeof(DEBUGGEE_UD_PAUSED_PACKET), + TRUE); + + // + // Set the thread debugging details + // + UdSetThreadPausingState(ThreadDebuggingDetails, + ProcessDebuggingDetails, + &PausePacket.InstructionBytesOnRip, + ExitInstructionLength); + + // + // Everything was okay + // + return TRUE; +} diff --git a/hyperdbg/hprdbgkd/code/debugger/user-level/UserAccess.c b/hyperdbg/hyperkd/code/debugger/user-level/UserAccess.c similarity index 98% rename from hyperdbg/hprdbgkd/code/debugger/user-level/UserAccess.c rename to hyperdbg/hyperkd/code/debugger/user-level/UserAccess.c index 7ccfb9a6..ea97ce52 100644 --- a/hyperdbg/hprdbgkd/code/debugger/user-level/UserAccess.c +++ b/hyperdbg/hyperkd/code/debugger/user-level/UserAccess.c @@ -100,7 +100,7 @@ UserAccessAllocateAndGetImagePathFromProcessId(HANDLE ProcessId, // // Allocate a temporary buffer to store the path name // - Buffer = CrsAllocateZeroedNonPagedPool(ReturnedLength); + Buffer = PlatformMemAllocateZeroedNonPagedPool(ReturnedLength); if (Buffer == NULL) { @@ -128,7 +128,7 @@ UserAccessAllocateAndGetImagePathFromProcessId(HANDLE ProcessId, // ProcessImageName->Length = 0; ProcessImageName->MaximumLength = (USHORT)SizeOfImageNameToBeAllocated; - ProcessImageName->Buffer = (PWSTR)CrsAllocateZeroedNonPagedPool(SizeOfImageNameToBeAllocated); + ProcessImageName->Buffer = (PWSTR)PlatformMemAllocateZeroedNonPagedPool(SizeOfImageNameToBeAllocated); if (ProcessImageName->Buffer == NULL) { @@ -145,7 +145,7 @@ UserAccessAllocateAndGetImagePathFromProcessId(HANDLE ProcessId, // // Free the temp buffer which stored the path // - CrsFreePool(Buffer); + PlatformMemFreePool(Buffer); return TRUE; } @@ -155,7 +155,7 @@ UserAccessAllocateAndGetImagePathFromProcessId(HANDLE ProcessId, // There was an error in ZwQueryInformationProcess // Free the temp buffer which stored the path // - CrsFreePool(Buffer); + PlatformMemFreePool(Buffer); return FALSE; } } @@ -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++; } diff --git a/hyperdbg/hprdbgkd/code/driver/Driver.c b/hyperdbg/hyperkd/code/driver/Driver.c similarity index 96% rename from hyperdbg/hprdbgkd/code/driver/Driver.c rename to hyperdbg/hyperkd/code/driver/Driver.c index 2cbe2ecf..053eb828 100644 --- a/hyperdbg/hprdbgkd/code/driver/Driver.c +++ b/hyperdbg/hyperkd/code/driver/Driver.c @@ -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); diff --git a/hyperdbg/hyperkd/code/driver/Ioctl.c b/hyperdbg/hyperkd/code/driver/Ioctl.c new file mode 100644 index 00000000..ddd88593 --- /dev/null +++ b/hyperdbg/hyperkd/code/driver/Ioctl.c @@ -0,0 +1,1814 @@ +/** + * @file Ioctl.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief IOCTL Functions form user mode and other parts + * @details + * + * @version 0.1 + * @date 2020-06-01 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Validates amd adjusts the parameters of an IOCTL request + * @param BufferSize The expected size of the input buffer + * @param Irp The IRP representing the IOCTL request + * @IrpStack The current stack location of the IRP + * @InBuffLength Output parameter to receive the actual input buffer length + * @OutBuffLength Output parameter to receive the actual output buffer length + * + * @return TRUE if the parameters are valid, FALSE otherwise + */ +BOOLEAN +DrvValidateAndAdjustIoctlParameter(UINT32 BufferSize, + PVOID * TargetBuffer, + PIRP Irp, + PIO_STACK_LOCATION IrpStack, + ULONG * InBuffLength, + ULONG * OutBuffLength) +{ + // + // First validate the parameters + // + if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < BufferSize || Irp->AssociatedIrp.SystemBuffer == NULL) + { + LogError("Err, invalid parameter to IOCTL dispatcher"); + return FALSE; + } + + *InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; + *OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; + + if (!*InBuffLength || !*OutBuffLength) + { + return FALSE; + } + + // + // Set the target buffer to the system buffer of the IRP + // + *TargetBuffer = Irp->AssociatedIrp.SystemBuffer; + + // + // Validation was successful + // + return TRUE; +} + +/** + * @brief Adjusts the status and output buffer size for an IOCTL request + * + * @param ExpectedOutputBufferSize The expected size of the output buffer + * @param DoNotChangeInformation Output parameter to indicate whether to change the information field of the IRP's I/O status block + * @param Irp The IRP representing the IOCTL request + * @param Status Output parameter to receive the status to be set in the IRP's I/O status block + * + * @return VOID + */ +VOID +DrvAdjustStatusAndSetOutputSize(UINT32 ExpectedOutputBufferSize, + BOOLEAN * DoNotChangeInformation, + PIRP Irp, + NTSTATUS * Status) +{ + Irp->IoStatus.Information = ExpectedOutputBufferSize; + *Status = STATUS_SUCCESS; + + // + // Avoid zeroing it + // + *DoNotChangeInformation = TRUE; +} + +/** + * @brief Checks whether the IOCTL request is allowed based on the current state of the driver and the system + * @param Ioctl The IOCTL code of the request + * + * @return BOOLEAN TRUE if the IOCTL request is allowed, FALSE otherwise + */ +BOOLEAN +IoctlCheckIoctlAllowed(ULONG Ioctl) +{ + ULONG IoctlFunction = CTL_CODE_FUNCTION(Ioctl); + + // + // First 100 IOCTLs are about loading and initializing modules + // + if (IoctlFunction > IOCTL_BASIC_IOCTL && IoctlFunction <= IOCTL_BASIC_IOCTL + 0x100) + { + // + // Always allow these IOCTLs even if we don't allow IOCTL from user-mode, because they are used for loading and initializing the driver and its components + // + return TRUE; + } + else if (IoctlFunction > IOCTL_KD_IOCTL && IoctlFunction <= IOCTL_KD_IOCTL + 0x100) + { + // + // Allow if the KD module is initialized + // + return g_KdInitialized; + } + else if (IoctlFunction > IOCTL_VMM_IOCTL && IoctlFunction <= IOCTL_VMM_IOCTL + 0x100) + { + // + // Allow if the VMM module is initialized + // + return g_VmmInitialized; + } + else if (IoctlFunction > IOCTL_HYPERTRACE_IOCTL && IoctlFunction <= IOCTL_HYPERTRACE_IOCTL + 0x100) + { + // + // Allow if the HyperTrace module is initialized + // + return g_HyperTraceInitialized; + } + else + { + // + // For other (unknown) IOCTLs, we don't allow them + // + return FALSE; + } +} + +/** + * @brief Resolve a process id to the CR3 the Intel PT engine should match. + * + * @details Intel PT's CR3 filter compares the live CR3, which differs between + * user and kernel mode when KVA shadowing (KPTI) is enabled: + * - kernel-mode runs under _KPROCESS.DirectoryTableBase + * - user-mode runs under _KPROCESS.UserDirectoryTableBase (shadow) + * So pick the kernel CR3 for kernel-only traces, otherwise the user + * (shadow) CR3 — falling back to the kernel CR3 when KVA shadowing is + * off (UserDirectoryTableBase has a zero page base in that case, i.e. + * user-mode also runs under the kernel CR3). + * + * @param ProcessId Target process id + * @param TraceUser Whether CPL>0 will be traced + * @param TraceKernel Whether CPL==0 will be traced + * + * @return UINT64 CR3 page base (low 12 bits cleared), or 0 if the pid is gone + */ +static UINT64 +DrvResolvePtTargetCr3(UINT32 ProcessId, BOOLEAN TraceUser, BOOLEAN TraceKernel) +{ + // + // _KPROCESS.UserDirectoryTableBase offset (x64 Windows 10 1803+ / 11). + // Only this one constant is build-specific; adjust it if the user CR3 + // ever reads wrong on a newer kernel. + // + const ULONG UserDirTableBaseOffset = 0x388; + + PEPROCESS TargetProcess; + UINT64 KernelCr3; + UINT64 UserCr3; + UINT64 Chosen; + + if (PsLookupProcessByProcessId((HANDLE)(ULONG_PTR)ProcessId, &TargetProcess) != STATUS_SUCCESS) + { + return 0; + } + + KernelCr3 = (UINT64)((NT_KPROCESS *)TargetProcess)->DirectoryTableBase; + UserCr3 = *(UINT64 *)((UCHAR *)TargetProcess + UserDirTableBaseOffset); + + ObDereferenceObject(TargetProcess); + + if (TraceKernel && !TraceUser) + { + // + // Kernel-only trace — match the kernel CR3 + // + Chosen = KernelCr3; + } + else if ((UserCr3 & ~0xFFFULL) != 0) + { + // + // KVA shadowing on — user mode runs under the shadow CR3 + // + Chosen = UserCr3; + } + else + { + // + // KVA shadowing off — user mode runs under the kernel CR3 + // + Chosen = KernelCr3; + } + + return Chosen & ~0xFFFULL; +} + +/** + * @brief IOCTL Dispatcher for Basic IOCTLs (initialization and event registration) + * + * @param Irp + * @param IrpStack + * @param DoNotChangeInformation + * @return NTSTATUS + */ +NTSTATUS +DrvDispatchBasicIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN * DoNotChangeInformation) +{ + PREGISTER_NOTIFY_BUFFER RegisterEventRequest; + PDEBUGGER_INIT_VMM_PACKET InitVmmRequest; + PDEBUGGER_INIT_HYPERTRACE_PACKET InitHyperTraceRequest; + ULONG InBuffLength; + ULONG OutBuffLength; + NTSTATUS Status = STATUS_SUCCESS; + UINT32 Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode; + + switch (Ioctl) + { + case IOCTL_INIT_VMM: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_INIT_VMM_PACKET, + (PVOID *)&InitVmmRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Initialize the debugger and the vmm + // + if (LoaderInitDebuggerAndVmm(InitVmmRequest)) + { + Status = STATUS_SUCCESS; + } + else + { + // + // There was a problem, so not loaded + // + Status = STATUS_UNSUCCESSFUL; + } + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_INIT_VMM_PACKET, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_INIT_HYPERTRACE: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_INIT_HYPERTRACE_PACKET, + (PVOID *)&InitHyperTraceRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Initialize the HyperTrace (if supported by the processor) + // + LoaderInitHyperTrace(InitHyperTraceRequest, TRUE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_INIT_HYPERTRACE_PACKET, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_REGISTER_EVENT: + + // + // First validate the parameters. + // + if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_REGISTER_EVENT || Irp->AssociatedIrp.SystemBuffer == NULL) + { + Status = STATUS_INVALID_PARAMETER; + LogError("Err, invalid parameter to IOCTL dispatcher"); + break; + } + + // + // IRPs supply a pointer to a buffer at Irp->AssociatedIrp.SystemBuffer. + // This buffer represents both the input buffer and the output buffer that + // are specified in calls to DeviceIoControl + // + RegisterEventRequest = (PREGISTER_NOTIFY_BUFFER)Irp->AssociatedIrp.SystemBuffer; + + switch (RegisterEventRequest->Type) + { + case IRP_BASED: + + LogRegisterIrpBasedNotification((PVOID)Irp, &Status); + + break; + case EVENT_BASED: + + if (LogRegisterEventBasedNotification((PVOID)Irp)) + { + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_UNSUCCESSFUL; + } + + break; + default: + LogError("Err, unknown notification type from user-mode"); + Status = STATUS_INVALID_PARAMETER; + break; + } + + break; + + case IOCTL_RETURN_IRP_PENDING_PACKETS_AND_DISALLOW_IOCTL: + + // + // Send an immediate message, and we're no longer get new IRP + // + LogCallbackSendBuffer(OPERATION_HYPERVISOR_DRIVER_END_OF_IRPS, + "$", + sizeof(CHAR), + TRUE); + + Status = STATUS_SUCCESS; + + break; + + default: + LogError("Err, unknown IOCTL"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + return Status; +} + +/** + * @brief IOCTL Dispatcher for KD (Kernel Debugger) IOCTLs + * + * @param Irp + * @param IrpStack + * @param DoNotChangeInformation + * @return NTSTATUS + */ +NTSTATUS +DrvDispatchKdIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN * DoNotChangeInformation) +{ + NTSTATUS Status = STATUS_SUCCESS; + UINT32 Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode; + + UNREFERENCED_PARAMETER(Irp); + UNREFERENCED_PARAMETER(DoNotChangeInformation); + + switch (Ioctl) + { + default: + LogError("Err, unknown IOCTL"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + return Status; +} + +/** + * @brief IOCTL Dispatcher for VMM IOCTLs + * + * @param Irp + * @param IrpStack + * @param DoNotChangeInformation + * @return NTSTATUS + */ +NTSTATUS +DrvDispatchVmmIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN * DoNotChangeInformation) +{ + PDEBUGGER_READ_MEMORY DebuggerReadMemRequest; + PDEBUGGER_READ_AND_WRITE_ON_MSR DebuggerReadOrWriteMsrRequest; + PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE DebuggerHideAndUnhideRequest; + PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS DebuggerPteRequest; + PDEBUGGER_PAGE_IN_REQUEST DebuggerPageinRequest; + PDEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET PcitreeRequest; + PDEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET PcidevinfoRequest; + PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS DebuggerVa2paAndPa2vaRequest; + PDEBUGGER_EDIT_MEMORY DebuggerEditMemoryRequest; + PDEBUGGER_SEARCH_MEMORY DebuggerSearchMemoryRequest; + PDEBUGGER_GENERAL_EVENT_DETAIL DebuggerNewEventRequest; + PDEBUGGER_MODIFY_EVENTS DebuggerModifyEventRequest; + PDEBUGGER_FLUSH_LOGGING_BUFFERS DebuggerFlushBuffersRequest; + PDEBUGGER_PREALLOC_COMMAND DebuggerReservePreallocPoolRequest; + PDEBUGGER_PREACTIVATE_COMMAND DebuggerPreactivationRequest; + PDEBUGGER_APIC_REQUEST DebuggerApicRequest; + PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS DebuggerQueryIdtRequest; + PDEBUGGEE_BP_PACKET DebuggerBreakpointRequest; + PDEBUGGER_UD_COMMAND_PACKET DebuggerUdCommandRequest; + PUSERMODE_LOADED_MODULE_DETAILS DebuggerUsermodeModulesRequest; + PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS DebuggerUsermodeProcessOrThreadQueryRequest; + PDEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET GetInformationProcessRequest; + PREVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST RevServiceRequest; + PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET GetInformationThreadRequest; + PDEBUGGER_PERFORM_KERNEL_TESTS DebuggerKernelTestRequest; + PDEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL DebuggerCommandExecutionFinishedRequest; + PDEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER DebuggerSendUsermodeMessageRequest; + PDEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER DebuggerSendBufferFromDebuggeeToDebuggerRequest; + PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS DebuggerAttachOrDetachToThreadRequest; + PDEBUGGER_PREPARE_DEBUGGEE DebuggeeRequest; + PDEBUGGER_PAUSE_PACKET_RECEIVED DebuggerPauseKernelRequest; + PDEBUGGER_GENERAL_ACTION DebuggerNewActionRequest; + PSMI_OPERATION_PACKETS SmiOperationRequest; + PVOID BufferToStoreThreadsAndProcessesDetails; + ULONG InBuffLength; // Input buffer length + ULONG OutBuffLength; // Output buffer length + SIZE_T ReturnSize; + NTSTATUS Status = STATUS_SUCCESS; + UINT32 Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode; + + switch (Ioctl) + { + case IOCTL_TERMINATE_VMX: + + // + // Uninitialize the VMM and the debugger + // + LoaderUninitVmmAndDebugger(); + + Status = STATUS_SUCCESS; + + break; + + case IOCTL_DEBUGGER_READ_MEMORY: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_READ_MEMORY, + (PVOID *)&DebuggerReadMemRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + if (DebuggerCommandReadMemory(DebuggerReadMemRequest, + ((CHAR *)DebuggerReadMemRequest) + SIZEOF_DEBUGGER_READ_MEMORY, + &ReturnSize) == TRUE) + { + // + // Return the header a read bytes + // + DrvAdjustStatusAndSetOutputSize((UINT32)(ReturnSize + SIZEOF_DEBUGGER_READ_MEMORY), DoNotChangeInformation, Irp, &Status); + } + else + { + // + // Just return the header to the user-mode + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_READ_MEMORY, DoNotChangeInformation, Irp, &Status); + } + + break; + + case IOCTL_DEBUGGER_READ_OR_WRITE_MSR: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_READ_AND_WRITE_ON_MSR, + (PVOID *)&DebuggerReadOrWriteMsrRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place + // + Status = DebuggerReadOrWriteMsr(DebuggerReadOrWriteMsrRequest, (UINT64 *)DebuggerReadOrWriteMsrRequest, &ReturnSize); + + // + // Set the size + // + if (Status == STATUS_SUCCESS) + { + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize((UINT32)ReturnSize, DoNotChangeInformation, Irp, &Status); + } + + break; + + case IOCTL_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS, + (PVOID *)&DebuggerPteRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place (it's not in vmx-root) + // + ExtensionCommandPte(DebuggerPteRequest, FALSE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_DEBUGGER_REGISTER_EVENT: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_GENERAL_EVENT_DETAIL, + (PVOID *)&DebuggerNewEventRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place (not coming from the VMX-root mode) + // + DebuggerParseEvent(DebuggerNewEventRequest, + (PDEBUGGER_EVENT_AND_ACTION_RESULT)Irp->AssociatedIrp.SystemBuffer, + FALSE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(sizeof(DEBUGGER_EVENT_AND_ACTION_RESULT), DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_DEBUGGER_ADD_ACTION_TO_EVENT: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_GENERAL_ACTION, + (PVOID *)&DebuggerNewActionRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place + // + DebuggerParseAction(DebuggerNewActionRequest, + (PDEBUGGER_EVENT_AND_ACTION_RESULT)Irp->AssociatedIrp.SystemBuffer, + FALSE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(sizeof(DEBUGGER_EVENT_AND_ACTION_RESULT), DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_DEBUGGER_HIDE_AND_UNHIDE_TO_TRANSPARENT_THE_DEBUGGER: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE, + (PVOID *)&DebuggerHideAndUnhideRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // check if it's a !hide or !unhide command + // + if (DebuggerHideAndUnhideRequest->IsHide == TRUE) + { + // + // It's a hide request + // + TransparentHideDebuggerWrapper(DebuggerHideAndUnhideRequest); + } + else + { + // + // It's a unhide request + // + TransparentUnhideDebuggerWrapper(DebuggerHideAndUnhideRequest); + } + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_DEBUGGER_VA2PA_AND_PA2VA_COMMANDS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_VA2PA_AND_PA2VA_COMMANDS, + (PVOID *)&DebuggerVa2paAndPa2vaRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place (we're not in vmx-root here) + // + ExtensionCommandVa2paAndPa2va(DebuggerVa2paAndPa2vaRequest, FALSE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_VA2PA_AND_PA2VA_COMMANDS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_DEBUGGER_EDIT_MEMORY: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_EDIT_MEMORY, + (PVOID *)&DebuggerEditMemoryRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Here we should validate whether the input parameter is + // valid or in other words whether we received enough space or not + // + if (IrpStack->Parameters.DeviceIoControl.InputBufferLength != SIZEOF_DEBUGGER_EDIT_MEMORY + DebuggerEditMemoryRequest->CountOf64Chunks * sizeof(UINT64)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place + // + DebuggerCommandEditMemory(DebuggerEditMemoryRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_EDIT_MEMORY, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_DEBUGGER_SEARCH_MEMORY: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_SEARCH_MEMORY, + (PVOID *)&DebuggerSearchMemoryRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // The OutBuffLength should have at least MaximumSearchResults * sizeof(UINT64) + // free space to store the results + // + if (OutBuffLength < MaximumSearchResults * sizeof(UINT64)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Here we should validate whether the input parameter is + // valid or in other words whether we received enough space or not + // + if (IrpStack->Parameters.DeviceIoControl.InputBufferLength != SIZEOF_DEBUGGER_SEARCH_MEMORY + DebuggerSearchMemoryRequest->CountOf64Chunks * sizeof(UINT64)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place + // + if (DebuggerCommandSearchMemory(DebuggerSearchMemoryRequest) != STATUS_SUCCESS) + { + // + // It is because it was not valid in any of the ways to the function + // then we're sure that the usermode code won't interpret it's previous + // buffer as a valid buffer and will not show it to the user + // + RtlZeroMemory(DebuggerSearchMemoryRequest, MaximumSearchResults * sizeof(UINT64)); + } + + // + // Configure IRP status, and also we send the results + // buffer, with it's null values (if any) + // + DrvAdjustStatusAndSetOutputSize(MaximumSearchResults * sizeof(UINT64), DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_DEBUGGER_MODIFY_EVENTS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_MODIFY_EVENTS, + (PVOID *)&DebuggerModifyEventRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place + // + DebuggerParseEventsModification(DebuggerModifyEventRequest, FALSE, EnableInstantEventMechanism ? g_KernelDebuggerState : FALSE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_MODIFY_EVENTS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_DEBUGGER_FLUSH_LOGGING_BUFFERS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_FLUSH_LOGGING_BUFFERS, + (PVOID *)&DebuggerFlushBuffersRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the flush + // + DebuggerCommandFlush(DebuggerFlushBuffersRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_FLUSH_LOGGING_BUFFERS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, + (PVOID *)&DebuggerAttachOrDetachToThreadRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the attach to the target process + // + AttachingTargetProcess(DebuggerAttachOrDetachToThreadRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PREPARE_DEBUGGEE: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_PREPARE_DEBUGGEE, + (PVOID *)&DebuggeeRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the action + // + SerialConnectionPrepare(DebuggeeRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_PREPARE_DEBUGGEE, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PAUSE_PACKET_RECEIVED: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_PAUSE_PACKET_RECEIVED, + (PVOID *)&DebuggerPauseKernelRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the action + // + KdHaltSystem(DebuggerPauseKernelRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_PAUSE_PACKET_RECEIVED, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_SEND_SIGNAL_EXECUTION_IN_DEBUGGEE_FINISHED: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL, + (PVOID *)&DebuggerCommandExecutionFinishedRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the signal operation + // + DebuggerCommandSignalExecutionState(DebuggerCommandExecutionFinishedRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_SEND_USERMODE_MESSAGES_TO_DEBUGGER: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER, + (PVOID *)&DebuggerSendUsermodeMessageRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Second validation phase + // + if (DebuggerSendUsermodeMessageRequest->Length == NULL_ZERO || + IrpStack->Parameters.DeviceIoControl.InputBufferLength != SIZEOF_DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER + DebuggerSendUsermodeMessageRequest->Length) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the signal operation + // + DebuggerCommandSendMessage(DebuggerSendUsermodeMessageRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_SEND_GENERAL_BUFFER_FROM_DEBUGGEE_TO_DEBUGGER: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER, + (PVOID *)&DebuggerSendBufferFromDebuggeeToDebuggerRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Second validation phase + // + if (DebuggerSendBufferFromDebuggeeToDebuggerRequest->LengthOfBuffer == NULL_ZERO || + IrpStack->Parameters.DeviceIoControl.InputBufferLength != SIZEOF_DEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER + DebuggerSendBufferFromDebuggeeToDebuggerRequest->LengthOfBuffer) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the signal operation + // + DebuggerCommandSendGeneralBufferToDebugger(DebuggerSendBufferFromDebuggeeToDebuggerRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PERFORM_KERNEL_SIDE_TESTS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_PERFORM_KERNEL_TESTS, + (PVOID *)&DebuggerKernelTestRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the kernel-side tests + // + TestKernelPerformTests(DebuggerKernelTestRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_PERFORM_KERNEL_TESTS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_RESERVE_PRE_ALLOCATED_POOLS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_PREALLOC_COMMAND, + (PVOID *)&DebuggerReservePreallocPoolRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the reservation pools + // + DebuggerCommandReservePreallocatedPools(DebuggerReservePreallocPoolRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_PREALLOC_COMMAND, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PREACTIVATE_FUNCTIONALITY: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_PREACTIVATE_COMMAND, + (PVOID *)&DebuggerPreactivationRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the activation of the functionality + // + DebuggerCommandPreactivateFunctionality(DebuggerPreactivationRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_PREACTIVATE_COMMAND, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PERFORM_ACTIONS_ON_APIC: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_APIC_REQUEST, + (PVOID *)&DebuggerApicRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(ExtensionCommandPerformActionsForApicRequests(DebuggerApicRequest), DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_QUERY_IDT_ENTRY: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS, + (PVOID *)&DebuggerQueryIdtRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the query of IDT entries (not from vmx-root) + // + ExtensionCommandPerformQueryIdtEntriesRequest(DebuggerQueryIdtRequest, FALSE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_SET_BREAKPOINT_USER_DEBUGGER: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGEE_BP_PACKET, + (PVOID *)&DebuggerBreakpointRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform setting the breakpoint (for the user mode debugger) + // Switching to the target process memory is needed as we are + // in HyperDbg's process memory layout and we need to switch to + // the target process memory layout to set the breakpoint + // + BreakpointAddNew(DebuggerBreakpointRequest, TRUE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGEE_BP_PACKET, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PERFORM_SMI_OPERATION: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_SMI_OPERATION_PACKETS, + (PVOID *)&SmiOperationRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the SMI operation (it's not from vmx-root) + // + VmFuncSmmPerformSmiOperation(SmiOperationRequest, FALSE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_SMI_OPERATION_PACKETS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_SEND_USER_DEBUGGER_COMMANDS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_UD_COMMAND_PACKET, + (PVOID *)&DebuggerUdCommandRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the dispatching of user debugger command + // + UdDispatchUsermodeCommands(DebuggerUdCommandRequest, InBuffLength, OutBuffLength); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(OutBuffLength, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_GET_DETAIL_OF_ACTIVE_THREADS_AND_PROCESSES: + + OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; + + if (!OutBuffLength) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode is here + // + BufferToStoreThreadsAndProcessesDetails = (PVOID)Irp->AssociatedIrp.SystemBuffer; + + // + // Perform the dispatching of user debugger command + // + AttachingQueryDetailsOfActiveDebuggingThreadsAndProcesses(BufferToStoreThreadsAndProcessesDetails, OutBuffLength); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(OutBuffLength, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_GET_USER_MODE_MODULE_DETAILS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_USERMODE_LOADED_MODULE_DETAILS, + (PVOID *)&DebuggerUsermodeModulesRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Getting the modules details + // + UserAccessGetLoadedModules(DebuggerUsermodeModulesRequest, OutBuffLength); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(OutBuffLength, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_QUERY_COUNT_OF_ACTIVE_PROCESSES_OR_THREADS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS, + (PVOID *)&DebuggerUsermodeProcessOrThreadQueryRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Getting the count result + // + if (DebuggerUsermodeProcessOrThreadQueryRequest->QueryType == DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_QUERY_PROCESS_COUNT) + { + ProcessQueryCount(DebuggerUsermodeProcessOrThreadQueryRequest); + } + else if (DebuggerUsermodeProcessOrThreadQueryRequest->QueryType == DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_QUERY_THREAD_COUNT) + { + ThreadQueryCount(DebuggerUsermodeProcessOrThreadQueryRequest); + } + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_GET_LIST_OF_THREADS_AND_PROCESSES: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS, + (PVOID *)&DebuggerUsermodeProcessOrThreadQueryRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Getting the list of processes or threads + // + if (DebuggerUsermodeProcessOrThreadQueryRequest->QueryType == DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_QUERY_PROCESS_LIST) + { + ProcessQueryList(DebuggerUsermodeProcessOrThreadQueryRequest, + DebuggerUsermodeProcessOrThreadQueryRequest, + OutBuffLength); + } + else if (DebuggerUsermodeProcessOrThreadQueryRequest->QueryType == DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_QUERY_THREAD_LIST) + { + ThreadQueryList(DebuggerUsermodeProcessOrThreadQueryRequest, + DebuggerUsermodeProcessOrThreadQueryRequest, + OutBuffLength); + } + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(OutBuffLength, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_QUERY_CURRENT_THREAD: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET, + (PVOID *)&GetInformationThreadRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Get the information + // + ThreadQueryDetails(GetInformationThreadRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_QUERY_CURRENT_PROCESS: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET, + (PVOID *)&GetInformationProcessRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Get the information + // + ProcessQueryDetails(GetInformationProcessRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_REQUEST_REV_MACHINE_SERVICE: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_REVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST, + (PVOID *)&RevServiceRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the service request + // + ConfigureInitializeExecTrapOnAllProcessors(); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_REVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_DEBUGGER_BRING_PAGES_IN: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_PAGE_IN_REQUEST, + (PVOID *)&DebuggerPageinRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place (it's in VMI-mode) + // + DebuggerCommandBringPagein(DebuggerPageinRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_PAGE_IN_REQUEST, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PCIE_ENDPOINT_ENUM: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET, + (PVOID *)&PcitreeRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place (it's in VMI-mode) + // + ExtensionCommandPcitree(PcitreeRequest, FALSE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PCIDEVINFO_ENUM: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET, + (PVOID *)&PcidevinfoRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place (it's in VMI-mode) + // + ExtensionCommandPcidevinfo(PcidevinfoRequest, FALSE); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET, DoNotChangeInformation, Irp, &Status); + + break; + + default: + LogError("Err, unknown IOCTL"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + return Status; +} + +/** + * @brief IOCTL Dispatcher for HyperTrace IOCTLs + * + * @param Irp + * @param IrpStack + * @param DoNotChangeInformation + * @return NTSTATUS + */ +NTSTATUS +DrvDispatchHyperTraceIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN * DoNotChangeInformation) +{ + PHYPERTRACE_LBR_OPERATION_PACKETS HyperTraceLbrOperationRequest; + PHYPERTRACE_LBR_DUMP_PACKETS HyperTraceLbrdumpRequest; + PHYPERTRACE_PT_OPERATION_PACKETS HyperTracePtOperationRequest; + PHYPERTRACE_PT_MMAP_PACKETS HyperTracePtMmapRequest; + ULONG InBuffLength; + ULONG OutBuffLength; + NTSTATUS Status = STATUS_SUCCESS; + UINT32 Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode; + + switch (Ioctl) + { + case IOCTL_PERFORM_HYPERTRACE_UNLOAD: + + // + // Perform the unload of HyperTrace (there is no parameter for this IOCTL) + // + LoaderUninitHyperTrace(); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(0, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PERFORM_HYPERTRACE_LBR_OPERATION: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_HYPERTRACE_LBR_OPERATION_PACKETS, + (PVOID *)&HyperTraceLbrOperationRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the HyperTrace LBR operation + // + HyperTraceLbrPerformOperation(HyperTraceLbrOperationRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_HYPERTRACE_LBR_OPERATION_PACKETS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PERFORM_HYPERTRACE_LBR_DUMP: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS, + (PVOID *)&HyperTraceLbrdumpRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Perform the HyperTrace LBR dump operation + // + HyperTraceLbrPerformDump(HyperTraceLbrdumpRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PERFORM_HYPERTRACE_PT_OPERATION: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_HYPERTRACE_PT_OPERATION_PACKETS, + (PVOID *)&HyperTracePtOperationRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // If the caller asked to filter by a process id (and didn't + // already provide an explicit CR3), resolve the PID to the CR3 + // the PT engine should match here — hyperkd owns the NT_KPROCESS + // layout, whereas the hypertrace engine only consumes a CR3. The + // kernel/user CR3 is chosen based on the requested trace mode so + // it works whether or not KVA shadowing (KPTI) is enabled. + // + if (HyperTracePtOperationRequest->EnableOptions.Pid != 0 && + HyperTracePtOperationRequest->EnableOptions.Cr3 == 0) + { + HyperTracePtOperationRequest->EnableOptions.Cr3 = + DrvResolvePtTargetCr3(HyperTracePtOperationRequest->EnableOptions.Pid, + (BOOLEAN)(HyperTracePtOperationRequest->FilterOptions.TraceUser != 0), + (BOOLEAN)(HyperTracePtOperationRequest->FilterOptions.TraceKernel != 0)); + } + + // + // Perform the HyperTrace PT operation + // + HyperTracePtPerformOperation(HyperTracePtOperationRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_HYPERTRACE_PT_OPERATION_PACKETS, DoNotChangeInformation, Irp, &Status); + + break; + + case IOCTL_PERFORM_HYPERTRACE_PT_MMAP: + + // + // Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP + // + if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_HYPERTRACE_PT_MMAP_PACKETS, + (PVOID *)&HyperTracePtMmapRequest, + Irp, + IrpStack, + &InBuffLength, + &OutBuffLength)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Map the per-CPU PT output buffers into the calling user process + // + HyperTracePtMmap(HyperTracePtMmapRequest); + + // + // Adjust the status and output size + // + DrvAdjustStatusAndSetOutputSize(SIZEOF_HYPERTRACE_PT_MMAP_PACKETS, DoNotChangeInformation, Irp, &Status); + + break; + + default: + LogError("Err, unknown IOCTL"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + return Status; +} + +/** + * @brief Driver IOCTL Dispatcher + * + * @param DeviceObject + * @param Irp + * @return NTSTATUS + */ +NTSTATUS +DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + UNREFERENCED_PARAMETER(DeviceObject); + + PIO_STACK_LOCATION IrpStack; + NTSTATUS Status = STATUS_SUCCESS; + BOOLEAN DoNotChangeInformation = FALSE; + UINT32 Ioctl = 0; + ULONG IoctlFunction = 0; + + // + // Here's the best place to see if there is any allocation pending + // to be allocated as we're in PASSIVE_LEVEL + // + PoolManagerCheckAndPerformAllocationAndDeallocation(); + + // + // Get the current stack location of the IRP to access the parameters of the IOCTL request + // + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + // + // Get the IOCTL code from the parameters + // + Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode; + + // + // If we don't allow IOCTL from user-mode, we just complete the request with success, and return + // + if (!IoctlCheckIoctlAllowed(Ioctl)) + { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; + } + + // + // Dispatch to the appropriate handler based on the IOCTL range + // + IoctlFunction = CTL_CODE_FUNCTION(Ioctl); + + if (IoctlFunction > IOCTL_BASIC_IOCTL && IoctlFunction <= IOCTL_BASIC_IOCTL + 0x100) + { + Status = DrvDispatchBasicIoControl(Irp, IrpStack, &DoNotChangeInformation); + } + else if (IoctlFunction > IOCTL_KD_IOCTL && IoctlFunction <= IOCTL_KD_IOCTL + 0x100) + { + Status = DrvDispatchKdIoControl(Irp, IrpStack, &DoNotChangeInformation); + } + else if (IoctlFunction > IOCTL_VMM_IOCTL && IoctlFunction <= IOCTL_VMM_IOCTL + 0x100) + { + Status = DrvDispatchVmmIoControl(Irp, IrpStack, &DoNotChangeInformation); + } + else if (IoctlFunction > IOCTL_HYPERTRACE_IOCTL && IoctlFunction <= IOCTL_HYPERTRACE_IOCTL + 0x100) + { + Status = DrvDispatchHyperTraceIoControl(Irp, IrpStack, &DoNotChangeInformation); + } + else + { + Status = STATUS_NOT_IMPLEMENTED; + } + + if (Status != STATUS_PENDING) + { + Irp->IoStatus.Status = Status; + if (!DoNotChangeInformation) + { + Irp->IoStatus.Information = 0; + } + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + return Status; +} diff --git a/hyperdbg/hyperkd/code/driver/Loader.c b/hyperdbg/hyperkd/code/driver/Loader.c new file mode 100644 index 00000000..0ae0309d --- /dev/null +++ b/hyperdbg/hyperkd/code/driver/Loader.c @@ -0,0 +1,451 @@ +/** + * @file Loader.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief The functions used in loading the debugger and VMM + * @version 0.2 + * @date 2023-01-15 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Initialize the hyper trace module + * + * @param RunningOnHypervisorEnvironment Whether the initialization is being done for hypervisor environment or not + * + * @return BOOLEAN + */ +BOOLEAN +LoaderInitHyperTrace(PDEBUGGER_INIT_HYPERTRACE_PACKET InitHyperTracePacket, BOOLEAN RunningOnHypervisorEnvironment) +{ + HYPERTRACE_CALLBACKS HyperTraceCallbacks = {0}; + + // + // *** Fill the callbacks for using hypertrace *** + // + + // + // Fill the callbacks for using hyperlog in hypertrace + // We use the callbacks directly to avoid two calls to the same function + // + HyperTraceCallbacks.LogCallbackPrepareAndSendMessageToQueueWrapper = LogCallbackPrepareAndSendMessageToQueueWrapper; + HyperTraceCallbacks.LogCallbackSendMessageToQueue = LogCallbackSendMessageToQueue; + HyperTraceCallbacks.LogCallbackSendBuffer = LogCallbackSendBuffer; + HyperTraceCallbacks.LogCallbackCheckIfBufferIsFull = LogCallbackCheckIfBufferIsFull; + + // + // Fill the callbacks for using hyperhv in hypertrace + // + HyperTraceCallbacks.VmFuncVmxGetCurrentExecutionMode = VmFuncVmxGetCurrentExecutionMode; + + // + // *** Legacy LBR callbacks *** + // + + HyperTraceCallbacks.VmFuncCheckCpuSupportForSaveAndLoadDebugControls = VmFuncCheckCpuSupportForSaveAndLoadDebugControls; + + HyperTraceCallbacks.VmFuncGetDebugctl = VmFuncGetDebugctl; + HyperTraceCallbacks.VmFuncGetDebugctlVmcallOnTargetCore = VmFuncGetDebugctlVmcallOnTargetCore; + HyperTraceCallbacks.VmFuncSetDebugctl = VmFuncSetDebugctl; + HyperTraceCallbacks.VmFuncSetDebugctlVmcallOnTargetCore = VmFuncSetDebugctlVmcallOnTargetCore; + + HyperTraceCallbacks.VmFuncSetLoadDebugControls = VmFuncSetLoadDebugControls; + HyperTraceCallbacks.VmFuncSetLoadDebugControlsVmcallOnTargetCore = VmFuncSetLoadDebugControlsVmcallOnTargetCore; + HyperTraceCallbacks.VmFuncSetSaveDebugControls = VmFuncSetSaveDebugControls; + HyperTraceCallbacks.VmFuncSetSaveDebugControlsVmcallOnTargetCore = VmFuncSetSaveDebugControlsVmcallOnTargetCore; + + HyperTraceCallbacks.VmFuncSetLbrSelect = VmFuncSetLbrSelect; + HyperTraceCallbacks.VmFuncSetLbrSelectVmcallOnTargetCore = VmFuncSetLbrSelectVmcallOnTargetCore; + + // + // *** Architectural LBR callbacks *** + // + + HyperTraceCallbacks.VmFuncCheckCpuSupportForLoadAndClearGuestIa32LbrCtlControls = VmFuncCheckCpuSupportForLoadAndClearGuestIa32LbrCtlControls; + + HyperTraceCallbacks.VmFuncGetGuestIa32LbrCtl = VmFuncGetGuestIa32LbrCtl; + HyperTraceCallbacks.VmFuncGetGuestIa32LbrCtlVmcallOnTargetCore = VmFuncGetGuestIa32LbrCtlVmcallOnTargetCore; + HyperTraceCallbacks.VmFuncSetGuestIa32LbrCtl = VmFuncSetGuestIa32LbrCtl; + HyperTraceCallbacks.VmFuncSetGuestIa32LbrCtlVmcallOnTargetCore = VmFuncSetGuestIa32LbrCtlVmcallOnTargetCore; + + HyperTraceCallbacks.VmFuncSetLoadGuestIa32LbrCtl = VmFuncSetLoadGuestIa32LbrCtl; + HyperTraceCallbacks.VmFuncSetLoadGuestIa32LbrCtlVmcallOnTargetCore = VmFuncSetLoadGuestIa32LbrCtlVmcallOnTargetCore; + HyperTraceCallbacks.VmFuncSetClearGuestIa32LbrCtl = VmFuncSetClearGuestIa32LbrCtl; + HyperTraceCallbacks.VmFuncSetClearGuestIa32LbrCtlVmcallOnTargetCore = VmFuncSetClearGuestIa32LbrCtlVmcallOnTargetCore; + + // + // Initialize hypertrace module + // + 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 + { + // + // 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 hyper log module + * + * @return BOOLEAN + */ +BOOLEAN +LoaderInitHyperLog() +{ + MESSAGE_TRACING_CALLBACKS MsgTracingCallbacks = {0}; + + // + // *** Fill the callbacks for the message tracer *** + // + MsgTracingCallbacks.VmxOperationCheck = VmFuncVmxGetCurrentExecutionMode; + 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 *** + // + VmmCallbacks.LogCallbackPrepareAndSendMessageToQueueWrapper = LogCallbackPrepareAndSendMessageToQueueWrapper; + VmmCallbacks.LogCallbackSendMessageToQueue = LogCallbackSendMessageToQueue; + VmmCallbacks.LogCallbackSendBuffer = LogCallbackSendBuffer; + VmmCallbacks.LogCallbackCheckIfBufferIsFull = LogCallbackCheckIfBufferIsFull; + + // + // Fill the HyperTrace callback(s) + // + VmmCallbacks.HyperTraceCallbackLbrIsSupported = HyperTraceLbrIsSupported; + + // + // Fill the VMM callbacks + // + VmmCallbacks.VmmCallbackTriggerEvents = DebuggerTriggerEvents; + VmmCallbacks.VmmCallbackSetLastError = DebuggerSetLastError; + VmmCallbacks.VmmCallbackVmcallHandler = DebuggerVmcallHandler; + 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.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 + // + VmmCallbacks.InterceptionCallbackTriggerCr3ProcessChange = ProcessTriggerCr3ProcessChange; + + // + // Initialize VMX + // + if (VmFuncInitVmm(&VmmCallbacks)) + { + LogDebugInfo("HyperDbg's hypervisor loaded successfully"); + + // + // Initialize VMM opeartions (event related state from the debugger) + // + if (!DebuggerInitializeVmmOperations()) + { + return FALSE; + } + + // + // VMM module initialized + // + g_VmmInitialized = TRUE; + + return TRUE; + } + else + { + 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; + } + + // + // The debugger is not initialized, so we try to initialize it + // + 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 +LoaderUninitLogTracer() +{ +#if !UseDbgPrintInsteadOfUsermodeMessageTracking + + LogDebugInfo("Unloading hyperlog...\n"); + + // + // Uinitialize log buffer if it was initialized + // + if (g_HyperLogInitialized) + { + g_HyperLogInitialized = FALSE; + LogUnInitialize(); + } +#endif +} diff --git a/hyperdbg/hprdbgkd/header/assembly/Assembly.h b/hyperdbg/hyperkd/header/assembly/Assembly.h similarity index 61% rename from hyperdbg/hprdbgkd/header/assembly/Assembly.h rename to hyperdbg/hyperkd/header/assembly/Assembly.h index 45f19848..f68e409e 100644 --- a/hyperdbg/hprdbgkd/header/assembly/Assembly.h +++ b/hyperdbg/hyperkd/header/assembly/Assembly.h @@ -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(); diff --git a/hyperdbg/hprdbgkd/header/common/Common.h b/hyperdbg/hyperkd/header/common/Common.h similarity index 100% rename from hyperdbg/hprdbgkd/header/common/Common.h rename to hyperdbg/hyperkd/header/common/Common.h diff --git a/hyperdbg/hyperkd/header/common/Synchronization.h b/hyperdbg/hyperkd/header/common/Synchronization.h new file mode 100644 index 00000000..6833c241 --- /dev/null +++ b/hyperdbg/hyperkd/header/common/Synchronization.h @@ -0,0 +1,26 @@ +/** + * @file Synchronization.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Routines for synchronization objects + * @details + * + * @version 0.16 + * @date 2025-08-30 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +SynchronizationInitializeEvent(PRKEVENT Event); + +VOID +SynchronizationSetEvent(PRKEVENT Event); + +VOID +SynchronizationWaitForEvent(PRKEVENT Event); diff --git a/hyperdbg/hprdbgkd/header/debugger/broadcast/DpcRoutines.h b/hyperdbg/hyperkd/header/debugger/broadcast/DpcRoutines.h similarity index 89% rename from hyperdbg/hprdbgkd/header/debugger/broadcast/DpcRoutines.h rename to hyperdbg/hyperkd/header/debugger/broadcast/DpcRoutines.h index 0a300664..50e24308 100644 --- a/hyperdbg/hprdbgkd/header/debugger/broadcast/DpcRoutines.h +++ b/hyperdbg/hyperkd/header/debugger/broadcast/DpcRoutines.h @@ -32,3 +32,6 @@ DpcRoutineReadMsrToAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgum VOID DpcRoutineVmExitAndHaltSystemAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineSetHardwareDebugRegisters(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); diff --git a/hyperdbg/hprdbgkd/header/debugger/broadcast/HaltedBroadcast.h b/hyperdbg/hyperkd/header/debugger/broadcast/HaltedBroadcast.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/broadcast/HaltedBroadcast.h rename to hyperdbg/hyperkd/header/debugger/broadcast/HaltedBroadcast.h diff --git a/hyperdbg/hprdbgkd/header/debugger/broadcast/HaltedRoutines.h b/hyperdbg/hyperkd/header/debugger/broadcast/HaltedRoutines.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/broadcast/HaltedRoutines.h rename to hyperdbg/hyperkd/header/debugger/broadcast/HaltedRoutines.h diff --git a/hyperdbg/hprdbgkd/header/debugger/commands/BreakpointCommands.h b/hyperdbg/hyperkd/header/debugger/commands/BreakpointCommands.h similarity index 82% rename from hyperdbg/hprdbgkd/header/debugger/commands/BreakpointCommands.h rename to hyperdbg/hyperkd/header/debugger/commands/BreakpointCommands.h index e001a1fa..9fc7c4b5 100644 --- a/hyperdbg/hprdbgkd/header/debugger/commands/BreakpointCommands.h +++ b/hyperdbg/hyperkd/header/debugger/commands/BreakpointCommands.h @@ -29,10 +29,11 @@ VOID BreakpointRemoveAllBreakpoints(); BOOLEAN -BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg); +BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg, BOOLEAN SwitchToTargetMemoryLayout); BOOLEAN -BreakpointListOrModify(PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET ListOrModifyBreakpoints); +BreakpointListOrModify(PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET ListOrModifyBreakpoints, + BOOLEAN SwitchToTargetMemoryLayout); BOOLEAN BreakpointHandleBreakpoints(UINT32 CoreId); @@ -44,7 +45,7 @@ BreakpointCheckAndHandleDebuggerDefinedBreakpoints(PROCESSOR_DEBUGGING_STATE * D BOOLEAN ChangeMtfState); BOOLEAN -BreakpointCheckAndHandleReApplyingBreakpoint(UINT32 CoreId); +BreakpointCheckAndHandleReApplyingBreakpoint(PROCESSOR_DEBUGGING_STATE * DbgState); BOOLEAN BreakpointCheckAndHandleDebugBreakpoint(UINT32 CoreId); diff --git a/hyperdbg/hprdbgkd/header/debugger/commands/Callstack.h b/hyperdbg/hyperkd/header/debugger/commands/Callstack.h similarity index 90% rename from hyperdbg/hprdbgkd/header/debugger/commands/Callstack.h rename to hyperdbg/hyperkd/header/debugger/commands/Callstack.h index 09dc52eb..960a16bb 100644 --- a/hyperdbg/hprdbgkd/header/debugger/commands/Callstack.h +++ b/hyperdbg/hyperkd/header/debugger/commands/Callstack.h @@ -17,6 +17,7 @@ BOOLEAN CallstackWalkthroughStack(PDEBUGGER_SINGLE_CALLSTACK_FRAME AddressToSaveFrames, + UINT32 * FrameCount, UINT64 StackBaseAddress, UINT32 Size, BOOLEAN Is32Bit); diff --git a/hyperdbg/hprdbgkd/header/debugger/commands/DebuggerCommands.h b/hyperdbg/hyperkd/header/debugger/commands/DebuggerCommands.h similarity index 93% rename from hyperdbg/hprdbgkd/header/debugger/commands/DebuggerCommands.h rename to hyperdbg/hyperkd/header/debugger/commands/DebuggerCommands.h index 586756fe..c0043a3f 100644 --- a/hyperdbg/hprdbgkd/header/debugger/commands/DebuggerCommands.h +++ b/hyperdbg/hyperkd/header/debugger/commands/DebuggerCommands.h @@ -17,6 +17,10 @@ // Functions // ////////////////////////////////////////////////// +BOOLEAN +DebuggerCommandReadRegisters(GUEST_REGS * Regs, + PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterRequest); + BOOLEAN DebuggerCommandReadMemory(PDEBUGGER_READ_MEMORY ReadMemRequest, PVOID UserBuffer, PSIZE_T ReturnSize); diff --git a/hyperdbg/hprdbgkd/header/debugger/commands/ExtensionCommands.h b/hyperdbg/hyperkd/header/debugger/commands/ExtensionCommands.h similarity index 81% rename from hyperdbg/hprdbgkd/header/debugger/commands/ExtensionCommands.h rename to hyperdbg/hyperkd/header/debugger/commands/ExtensionCommands.h index c854408f..03e27dd9 100644 --- a/hyperdbg/hprdbgkd/header/debugger/commands/ExtensionCommands.h +++ b/hyperdbg/hyperkd/header/debugger/commands/ExtensionCommands.h @@ -18,6 +18,12 @@ BOOLEAN ExtensionCommandPte(PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PteDetails, BOOLEAN IsOperatingInVmxRoot); +UINT32 +ExtensionCommandPerformActionsForApicRequests(PDEBUGGER_APIC_REQUEST ApicRequest); + +VOID +ExtensionCommandPerformQueryIdtEntriesRequest(PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtQueryRequest, BOOLEAN ReadFromVmxRoot); + VOID ExtensionCommandVa2paAndPa2va(PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS AddressDetails, BOOLEAN OperateOnVmxRoot); @@ -83,3 +89,9 @@ ExtensionCommandEnableMovControlRegisterExitingAllCores(PDEBUGGER_EVENT Event); VOID ExtensionCommandDisableMov2ControlRegsExitingForClearingEventsAllCores(PDEBUGGER_EVENT Event); + +VOID +ExtensionCommandPcitree(PDEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET PcitreePacket, BOOLEAN OperateOnVmxRoot); + +VOID +ExtensionCommandPcidevinfo(PDEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET PcidevinfoPacket, BOOLEAN OperateOnVmxRoot); diff --git a/hyperdbg/hprdbgkd/header/debugger/communication/SerialConnection.h b/hyperdbg/hyperkd/header/debugger/communication/SerialConnection.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/communication/SerialConnection.h rename to hyperdbg/hyperkd/header/debugger/communication/SerialConnection.h diff --git a/hyperdbg/hprdbgkd/header/debugger/core/Debugger.h b/hyperdbg/hyperkd/header/debugger/core/Debugger.h similarity index 97% rename from hyperdbg/hprdbgkd/header/debugger/core/Debugger.h rename to hyperdbg/hyperkd/header/debugger/core/Debugger.h index c9bada08..3553e20a 100644 --- a/hyperdbg/hprdbgkd/header/debugger/core/Debugger.h +++ b/hyperdbg/hyperkd/header/debugger/core/Debugger.h @@ -68,6 +68,7 @@ typedef struct _DEBUGGER_CORE_EVENTS LIST_ENTRY TrapExecutionInstructionTraceEventsHead; // TRAP_EXECUTION_INSTRUCTION_TRACE LIST_ENTRY ControlRegister3ModifiedEventsHead; // CONTROL_REGISTER_3_MODIFIED LIST_ENTRY ControlRegisterModifiedEventsHead; // CONTROL_REGISTER_MODIFIED + LIST_ENTRY XsetbvInstructionExecutionEventsHead; // XSETBV_INSTRUCTION_EXECUTION } DEBUGGER_CORE_EVENTS, *PDEBUGGER_CORE_EVENTS; @@ -187,9 +188,21 @@ DebuggerGetLastError(); VOID DebuggerSetLastError(UINT32 LastError); +BOOLEAN +DebuggerInitializeScriptEngine(); + +BOOLEAN +DebuggerInitializeTrapsAndBreakpoints(); + +BOOLEAN +DebuggerInitializeVmmOperations(); + BOOLEAN DebuggerInitialize(); +VOID +DebuggerUninitializeVmmOperations(); + VOID DebuggerUninitialize(); diff --git a/hyperdbg/hprdbgkd/header/debugger/core/DebuggerVmcalls.h b/hyperdbg/hyperkd/header/debugger/core/DebuggerVmcalls.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/core/DebuggerVmcalls.h rename to hyperdbg/hyperkd/header/debugger/core/DebuggerVmcalls.h diff --git a/hyperdbg/hprdbgkd/header/debugger/core/HaltedCore.h b/hyperdbg/hyperkd/header/debugger/core/HaltedCore.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/core/HaltedCore.h rename to hyperdbg/hyperkd/header/debugger/core/HaltedCore.h diff --git a/hyperdbg/hprdbgkd/header/debugger/core/State.h b/hyperdbg/hyperkd/header/debugger/core/State.h similarity index 92% rename from hyperdbg/hprdbgkd/header/debugger/core/State.h rename to hyperdbg/hyperkd/header/debugger/core/State.h index 77fe102e..7a41c1a0 100644 --- a/hyperdbg/hprdbgkd/header/debugger/core/State.h +++ b/hyperdbg/hyperkd/header/debugger/core/State.h @@ -80,7 +80,6 @@ typedef struct _DEBUGGEE_BP_DESCRIPTOR UINT32 Core; UINT16 InstructionLength; BYTE PreviousByte; - BOOLEAN SetRflagsIFBitOnMtf; BOOLEAN AvoidReApplyBreakpoint; BOOLEAN RemoveAfterHit; BOOLEAN CheckForCallbacks; @@ -106,7 +105,7 @@ typedef struct _DEBUGGER_PROCESS_THREAD_INFORMATION { union { - UINT64 asUInt; + UINT64 AsUInt; struct { @@ -143,6 +142,18 @@ typedef struct _DEBUGGEE_HALTED_CORE_TASK } DEBUGGEE_HALTED_CORE_TASK, *PDEBUGGEE_HALTED_CORE_TASK; +/** + * @brief Timer for the core + * + */ +typedef struct _DATE_TIME_HOLDER +{ + TIME_FIELDS TimeFields; + CHAR TimeBuffer[14]; + CHAR DateBuffer[12]; + +} DATE_TIME_HOLDER, *PDATE_TIME_HOLDER; + /** * @brief Saves the debugger state * @details Each logical processor contains one of this structure which describes about the @@ -157,19 +168,20 @@ typedef struct _PROCESSOR_DEBUGGING_STATE UINT32 CoreId; BOOLEAN ShortCircuitingEvent; BOOLEAN IgnoreDisasmInNextPacket; - PROCESSOR_DEBUGGING_MSR_READ_OR_WRITE MsrState; - PDEBUGGEE_BP_DESCRIPTOR SoftwareBreakpointState; - DEBUGGEE_INSTRUMENTATION_STEP_IN_TRACE InstrumentationStepInTrace; + BOOLEAN BreakStarterCore; + BOOLEAN Test; // Used for testing purposes BOOLEAN DoNotNmiNotifyOtherCoresByThisCore; BOOLEAN TracingMode; // Indicate that the target processor is on the tracing mode or not + PROCESSOR_DEBUGGING_MSR_READ_OR_WRITE MsrState; + DATE_TIME_HOLDER DateTimeHolder; + PDEBUGGEE_BP_DESCRIPTOR SoftwareBreakpointState; + DEBUGGEE_INSTRUMENTATION_STEP_IN_TRACE InstrumentationStepInTrace; DEBUGGEE_PROCESS_OR_THREAD_TRACING_DETAILS ThreadOrProcessTracingDetails; KD_NMI_STATE NmiState; DEBUGGEE_HALTED_CORE_TASK HaltedCoreTask; - BOOLEAN BreakStarterCore; UINT16 InstructionLengthHint; UINT64 HardwareDebugRegisterForStepping; - UINT64 * ScriptEngineCoreSpecificLocalVariable; - UINT64 * ScriptEngineCoreSpecificTempVariable; + UINT64 * ScriptEngineCoreSpecificStackBuffer; PKDPC KdDpcObject; // DPC object to be used in kernel debugger CHAR KdRecvBuffer[MaxSerialPacketSize]; // Used for debugging buffers (receiving buffers from serial devices) diff --git a/hyperdbg/hprdbgkd/header/debugger/events/ApplyEvents.h b/hyperdbg/hyperkd/header/debugger/events/ApplyEvents.h similarity index 95% rename from hyperdbg/hprdbgkd/header/debugger/events/ApplyEvents.h rename to hyperdbg/hyperkd/header/debugger/events/ApplyEvents.h index 17238173..bde54526 100644 --- a/hyperdbg/hprdbgkd/header/debugger/events/ApplyEvents.h +++ b/hyperdbg/hyperkd/header/debugger/events/ApplyEvents.h @@ -105,3 +105,8 @@ VOID ApplyEventTracingEvent(PDEBUGGER_EVENT Event, PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn, BOOLEAN InputFromVmxRoot); + +VOID +ApplyEventXsetbvExecutionEvent(PDEBUGGER_EVENT Event, + PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn, + BOOLEAN InputFromVmxRoot); diff --git a/hyperdbg/hprdbgkd/header/debugger/events/DebuggerEvents.h b/hyperdbg/hyperkd/header/debugger/events/DebuggerEvents.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/events/DebuggerEvents.h rename to hyperdbg/hyperkd/header/debugger/events/DebuggerEvents.h diff --git a/hyperdbg/hprdbgkd/header/debugger/events/Termination.h b/hyperdbg/hyperkd/header/debugger/events/Termination.h similarity index 92% rename from hyperdbg/hprdbgkd/header/debugger/events/Termination.h rename to hyperdbg/hyperkd/header/debugger/events/Termination.h index 663b5922..3e240938 100644 --- a/hyperdbg/hprdbgkd/header/debugger/events/Termination.h +++ b/hyperdbg/hyperkd/header/debugger/events/Termination.h @@ -74,8 +74,14 @@ BOOLEAN TerminateEptHookUnHookSingleAddressFromVmxRootAndApplyInvalidation(UINT64 VirtualAddress, UINT64 PhysAddress); +BOOLEAN +TerminateEptHookUnHookAllHooksByHookingTagFromVmxRootAndApplyInvalidation(UINT64 HookingTag); + BOOLEAN TerminateQueryDebuggerResource(UINT32 CoreId, PROTECTED_HV_RESOURCES_TYPE ResourceType, PVOID Context, PROTECTED_HV_RESOURCES_PASSING_OVERS PassOver); + +VOID +TerminateXsetbvExecutionEvent(PDEBUGGER_EVENT Event, BOOLEAN InputFromVmxRoot); diff --git a/hyperdbg/hprdbgkd/header/debugger/events/ValidateEvents.h b/hyperdbg/hyperkd/header/debugger/events/ValidateEvents.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/events/ValidateEvents.h rename to hyperdbg/hyperkd/header/debugger/events/ValidateEvents.h diff --git a/hyperdbg/hprdbgkd/header/debugger/kernel-level/Kd.h b/hyperdbg/hyperkd/header/debugger/kernel-level/Kd.h similarity index 91% rename from hyperdbg/hprdbgkd/header/debugger/kernel-level/Kd.h rename to hyperdbg/hyperkd/header/debugger/kernel-level/Kd.h index 991eef82..bf98f656 100644 --- a/hyperdbg/hprdbgkd/header/debugger/kernel-level/Kd.h +++ b/hyperdbg/hyperkd/header/debugger/kernel-level/Kd.h @@ -113,14 +113,8 @@ static VOID KdContinueDebuggeeJustCurrentCore(PROCESSOR_DEBUGGING_STATE * DbgState); static BOOLEAN -KdReadRegisters(_In_ PROCESSOR_DEBUGGING_STATE * DbgState, - _Inout_ PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterRequest); -static BOOLEAN -KdReadMemory(_In_ PGUEST_REGS Regs, - _Inout_ PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterRequest); - -static BOOLEAN -KdSwitchCore(PROCESSOR_DEBUGGING_STATE * DbgState, UINT32 NewCore); +KdSwitchCore(PROCESSOR_DEBUGGING_STATE * DbgState, + DEBUGGEE_CHANGE_CORE_PACKET * ChangeCorePacket); static VOID KdCloseConnectionAndUnloadDebuggee(); @@ -134,12 +128,6 @@ KdNotifyDebuggeeForUserInput(DEBUGGEE_USER_INPUT_PACKET * Descriptor, UINT32 Len static VOID KdGuaranteedStepInstruction(PROCESSOR_DEBUGGING_STATE * DbgState); -static VOID -KdRegularStepInInstruction(PROCESSOR_DEBUGGING_STATE * DbgState); - -static VOID -KdRegularStepOver(PROCESSOR_DEBUGGING_STATE * DbgState, BOOLEAN IsNextInstructionACall, UINT32 CallLength); - static BOOLEAN KdPerformRegisterEvent(PDEBUGGEE_EVENT_AND_ACTION_HEADER_FOR_REMOTE_PACKET EventDetailHeader, DEBUGGER_EVENT_AND_ACTION_RESULT * DebuggerEventAndActionResult); @@ -151,6 +139,12 @@ KdPerformAddActionToEvent(PDEBUGGEE_EVENT_AND_ACTION_HEADER_FOR_REMOTE_PACKET Ac static VOID KdQuerySystemState(); +static BOOLEAN +KdCheckAllCoresAreLocked(); + +static BOOLEAN +KdCheckTargetCoreIsLocked(UINT32 CoreNumber); + static BOOLEAN KdPerformEventQueryAndModification(PDEBUGGER_MODIFY_EVENTS ModifyAndQueryEvent); @@ -173,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); @@ -203,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); @@ -241,3 +233,6 @@ KdCheckTheHaltedCore(PROCESSOR_DEBUGGING_STATE * DbgState); BOOLEAN KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId(UINT32 CoreId, DEBUGGER_THREAD_PROCESS_TRACING TracingType); + +BOOLEAN +KdQueryIgnoreHandlingMov2DebugRegs(UINT32 CoreId); diff --git a/hyperdbg/hprdbgkd/header/debugger/memory/Allocations.h b/hyperdbg/hyperkd/header/debugger/memory/Allocations.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/memory/Allocations.h rename to hyperdbg/hyperkd/header/debugger/memory/Allocations.h diff --git a/hyperdbg/hprdbgkd/header/debugger/memory/Memory.h b/hyperdbg/hyperkd/header/debugger/memory/Memory.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/memory/Memory.h rename to hyperdbg/hyperkd/header/debugger/memory/Memory.h diff --git a/hyperdbg/hprdbghv/header/memory/PoolManager.h b/hyperdbg/hyperkd/header/debugger/memory/PoolManager.h similarity index 86% rename from hyperdbg/hprdbghv/header/memory/PoolManager.h rename to hyperdbg/hyperkd/header/debugger/memory/PoolManager.h index 5c5dbc7b..ef4af344 100644 --- a/hyperdbg/hprdbghv/header/memory/PoolManager.h +++ b/hyperdbg/hyperkd/header/debugger/memory/PoolManager.h @@ -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); diff --git a/hyperdbg/hprdbgkd/header/debugger/meta-events/MetaDispatch.h b/hyperdbg/hyperkd/header/debugger/meta-events/MetaDispatch.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/meta-events/MetaDispatch.h rename to hyperdbg/hyperkd/header/debugger/meta-events/MetaDispatch.h diff --git a/hyperdbg/hprdbgkd/header/debugger/meta-events/Tracing.h b/hyperdbg/hyperkd/header/debugger/meta-events/Tracing.h similarity index 89% rename from hyperdbg/hprdbgkd/header/debugger/meta-events/Tracing.h rename to hyperdbg/hyperkd/header/debugger/meta-events/Tracing.h index 42eb7fb1..f444fdb8 100644 --- a/hyperdbg/hprdbgkd/header/debugger/meta-events/Tracing.h +++ b/hyperdbg/hyperkd/header/debugger/meta-events/Tracing.h @@ -28,4 +28,7 @@ VOID TracingPerformInstrumentationStepIn(PROCESSOR_DEBUGGING_STATE * DbgState); VOID -TracingPerformRegularStepInInstruction(PROCESSOR_DEBUGGING_STATE * DbgState); +TracingRegularStepInInstruction(); + +VOID +TracingPerformRegularStepInInstruction(); diff --git a/hyperdbg/hprdbgkd/header/debugger/objects/Process.h b/hyperdbg/hyperkd/header/debugger/objects/Process.h similarity index 100% rename from hyperdbg/hprdbgkd/header/debugger/objects/Process.h rename to hyperdbg/hyperkd/header/debugger/objects/Process.h diff --git a/hyperdbg/hprdbgkd/header/debugger/objects/Thread.h b/hyperdbg/hyperkd/header/debugger/objects/Thread.h similarity index 94% rename from hyperdbg/hprdbgkd/header/debugger/objects/Thread.h rename to hyperdbg/hyperkd/header/debugger/objects/Thread.h index 1133e68d..b68e6fc9 100644 --- a/hyperdbg/hprdbgkd/header/debugger/objects/Thread.h +++ b/hyperdbg/hyperkd/header/debugger/objects/Thread.h @@ -38,3 +38,6 @@ ThreadQueryList(PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS DebuggerUsermodeProc BOOLEAN ThreadQueryDetails(PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET GetInformationThreadRequest); + +BOOLEAN +ThreadQueryDebugRegisterInterceptionStateByCoreId(UINT32 CoreId); diff --git a/hyperdbg/hprdbgkd/header/debugger/script-engine/ScriptEngine.h b/hyperdbg/hyperkd/header/debugger/script-engine/ScriptEngine.h similarity index 73% rename from hyperdbg/hprdbgkd/header/debugger/script-engine/ScriptEngine.h rename to hyperdbg/hyperkd/header/debugger/script-engine/ScriptEngine.h index 5d6626e2..7a6d065b 100644 --- a/hyperdbg/hprdbgkd/header/debugger/script-engine/ScriptEngine.h +++ b/hyperdbg/hyperkd/header/debugger/script-engine/ScriptEngine.h @@ -17,3 +17,12 @@ ScriptEngineWrapperGetInstructionPointer(); UINT64 ScriptEngineWrapperGetAddressOfReservedBuffer(PDEBUGGER_EVENT_ACTION Action); + +VOID +ScriptEngineUpdateTargetCoreDateTime(PROCESSOR_DEBUGGING_STATE * DbgState); + +UINT64 +ScriptEngineGetTargetCoreTime(); + +UINT64 +ScriptEngineGetTargetCoreDate(); diff --git a/hyperdbg/hprdbgkd/header/debugger/tests/KernelTests.h b/hyperdbg/hyperkd/header/debugger/tests/KernelTests.h similarity index 83% rename from hyperdbg/hprdbgkd/header/debugger/tests/KernelTests.h rename to hyperdbg/hyperkd/header/debugger/tests/KernelTests.h index 9c127634..ae28ea45 100644 --- a/hyperdbg/hprdbgkd/header/debugger/tests/KernelTests.h +++ b/hyperdbg/hyperkd/header/debugger/tests/KernelTests.h @@ -17,6 +17,3 @@ VOID TestKernelPerformTests(PDEBUGGER_PERFORM_KERNEL_TESTS KernelTestRequest); - -UINT32 -TestKernelGetInformation(PDEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION InfoRequest); diff --git a/hyperdbg/hyperkd/header/debugger/user-level/Attaching.h b/hyperdbg/hyperkd/header/debugger/user-level/Attaching.h new file mode 100644 index 00000000..465de531 --- /dev/null +++ b/hyperdbg/hyperkd/header/debugger/user-level/Attaching.h @@ -0,0 +1,68 @@ +/** + * @file Attaching.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Header for attaching and detaching for debugging user-mode processes + * @details + * @version 0.1 + * @date 2021-12-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Constants // +////////////////////////////////////////////////// + +/** + * @brief Maximum actions in paused threads storage + * + */ +#define MAX_USER_ACTIONS_FOR_THREADS 3 + +/** + * @brief Maximum threads that a process thread holder might have + * + */ +#define MAX_THREADS_IN_A_PROCESS_HOLDER 100 + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +AttachingInitialize(); + +BOOLEAN +AttachingCheckThreadInterceptionWithUserDebugger(UINT32 CoreId); + +BOOLEAN +AttachingConfigureInterceptingThreads(UINT64 ProcessDebuggingToken, BOOLEAN Enable); + +VOID +AttachingTargetProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS Request); + +VOID +AttachingHandleEntrypointInterception(PROCESSOR_DEBUGGING_STATE * DbgState); + +VOID +AttachingRemoveAndFreeAllProcessDebuggingDetails(); + +PUSERMODE_DEBUGGING_PROCESS_DETAILS +AttachingFindProcessDebuggingDetailsByToken(UINT64 Token); + +PUSERMODE_DEBUGGING_PROCESS_DETAILS +AttachingFindProcessDebuggingDetailsByProcessId(UINT32 ProcessId); + +BOOLEAN +AttachingQueryDetailsOfActiveDebuggingThreadsAndProcesses(PVOID BufferToStoreDetails, UINT32 BufferSize); + +BOOLEAN +AttachingCheckUnhandledEptViolation(UINT32 CoreId, + UINT64 ViolationQualification, + UINT64 GuestPhysicalAddr); + +BOOLEAN +AttachingReachedToValidLoadedModule(PROCESSOR_DEBUGGING_STATE * DbgState, + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail); diff --git a/hyperdbg/hprdbgkd/header/debugger/user-level/ThreadHolder.h b/hyperdbg/hyperkd/header/debugger/user-level/ThreadHolder.h similarity index 90% rename from hyperdbg/hprdbgkd/header/debugger/user-level/ThreadHolder.h rename to hyperdbg/hyperkd/header/debugger/user-level/ThreadHolder.h index f0ddd9af..7b59f644 100644 --- a/hyperdbg/hprdbgkd/header/debugger/user-level/ThreadHolder.h +++ b/hyperdbg/hyperkd/header/debugger/user-level/ThreadHolder.h @@ -34,6 +34,9 @@ typedef struct _USERMODE_DEBUGGING_THREAD_DETAILS UINT32 ThreadId; UINT64 ThreadRip; // if IsPaused is TRUE BOOLEAN IsPaused; + BYTE InstructionBytesOnRip[MAXIMUM_INSTR_SIZE]; + UINT32 SizeOfInstruction; + UINT64 NumberOfBlockedContextSwitches; DEBUGGER_UD_COMMAND_ACTION UdAction[MAX_USER_ACTIONS_FOR_THREADS]; } USERMODE_DEBUGGING_THREAD_DETAILS, *PUSERMODE_DEBUGGING_THREAD_DETAILS; @@ -62,6 +65,9 @@ ThreadHolderAssignThreadHolderToProcessDebuggingDetails(PUSERMODE_DEBUGGING_PROC BOOLEAN ThreadHolderIsAnyPausedThreadInProcess(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail); +BOOLEAN +ThreadHolderUnpauseAllThreadsInProcess(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail); + PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadHolderGetProcessThreadDetailsByProcessIdAndThreadId(UINT32 ProcessId, UINT32 ThreadId); diff --git a/hyperdbg/hyperkd/header/debugger/user-level/Ud.h b/hyperdbg/hyperkd/header/debugger/user-level/Ud.h new file mode 100644 index 00000000..b9134e0f --- /dev/null +++ b/hyperdbg/hyperkd/header/debugger/user-level/Ud.h @@ -0,0 +1,81 @@ +/** + * @file Ud.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Header for routines related to user mode debugging + * @details + * @version 0.1 + * @date 2022-01-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +/** + * @brief Description of each active thread in user-mode attaching + * mechanism + * + */ +typedef struct _USERMODE_DEBUGGING_PROCESS_DETAILS +{ + UINT64 Token; + BOOLEAN Enabled; + PVOID PebAddressToMonitor; + UINT32 ActiveThreadId; // active thread + GUEST_REGS Registers; // active thread + UINT64 Context; // $context + LIST_ENTRY AttachedProcessList; + UINT64 EntrypointOfMainModule; + UINT64 BaseAddressOfMainModule; + PEPROCESS Eprocess; + UINT32 ProcessId; + BOOLEAN Is32Bit; + BOOLEAN IsOnTheStartingPhase; + BOOLEAN IsOnThreadInterceptingPhase; + BOOLEAN CheckCallBackForInterceptingFirstInstruction; // checks for the callbacks for interceptions of the very first instruction (used by RE Machine) + LIST_ENTRY ThreadsListHead; + +} USERMODE_DEBUGGING_PROCESS_DETAILS, *PUSERMODE_DEBUGGING_PROCESS_DETAILS; + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +UdInitializeUserDebugger(); + +VOID +UdUninitializeUserDebugger(); + +BOOLEAN +UdHandleInstantBreak(PROCESSOR_DEBUGGING_STATE * DbgState, + DEBUGGEE_PAUSING_REASON Reason, + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail); + +VOID +UdApplyHardwareDebugRegister(PVOID TargetAddress); + +BOOLEAN +UdCheckAndHandleBreakpointsAndDebugBreaks(PROCESSOR_DEBUGGING_STATE * DbgState, + DEBUGGEE_PAUSING_REASON Reason, + PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails); + +BOOLEAN +UdDispatchUsermodeCommands(PDEBUGGER_UD_COMMAND_PACKET ActionRequest, + UINT32 ActionRequestInputLength, + UINT32 ActionRequestOutputLength); + +BOOLEAN +UdCheckForCommand(PROCESSOR_DEBUGGING_STATE * DbgState, + PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail); + +BOOLEAN +UdHandleDebugEventsWhenUserDebuggerIsAttached(PROCESSOR_DEBUGGING_STATE * DbgState, + BOOLEAN TrapSetByDebugger); + +VOID +UdSendFormatsFunctionResult(UINT64 Value); diff --git a/hyperdbg/hprdbgkd/header/debugger/user-level/UserAccess.h b/hyperdbg/hyperkd/header/debugger/user-level/UserAccess.h similarity index 99% rename from hyperdbg/hprdbgkd/header/debugger/user-level/UserAccess.h rename to hyperdbg/hyperkd/header/debugger/user-level/UserAccess.h index cb2c8c40..4acb1b8e 100644 --- a/hyperdbg/hprdbgkd/header/debugger/user-level/UserAccess.h +++ b/hyperdbg/hyperkd/header/debugger/user-level/UserAccess.h @@ -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 diff --git a/hyperdbg/hprdbgkd/header/driver/Driver.h b/hyperdbg/hyperkd/header/driver/Driver.h similarity index 68% rename from hyperdbg/hprdbgkd/header/driver/Driver.h rename to hyperdbg/hyperkd/header/driver/Driver.h index b5739220..e3233b0b 100644 --- a/hyperdbg/hprdbgkd/header/driver/Driver.h +++ b/hyperdbg/hyperkd/header/driver/Driver.h @@ -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); diff --git a/hyperdbg/hprdbgkd/header/driver/Loader.h b/hyperdbg/hyperkd/header/driver/Loader.h similarity index 57% rename from hyperdbg/hprdbgkd/header/driver/Loader.h rename to hyperdbg/hyperkd/header/driver/Loader.h index 955231cf..6d34e67d 100644 --- a/hyperdbg/hprdbgkd/header/driver/Loader.h +++ b/hyperdbg/hyperkd/header/driver/Loader.h @@ -17,7 +17,19 @@ ////////////////////////////////////////////////// BOOLEAN -LoaderInitVmmAndDebugger(); +LoaderInitHyperLog(); + +BOOLEAN +LoaderInitHyperTrace(PDEBUGGER_INIT_HYPERTRACE_PACKET InitHyperTracePacket, BOOLEAN RunningOnHypervisorEnvironment); + +BOOLEAN +LoaderInitDebuggerAndVmm(PDEBUGGER_INIT_VMM_PACKET InitVmmPacket); VOID -LoaderUninitializeLogTracer(); +LoaderUninitVmmAndDebugger(); + +VOID +LoaderUninitHyperTrace(); + +VOID +LoaderUninitLogTracer(); diff --git a/hyperdbg/hprdbgkd/header/globals/Global.h b/hyperdbg/hyperkd/header/globals/Global.h similarity index 74% rename from hyperdbg/hprdbgkd/header/globals/Global.h rename to hyperdbg/hyperkd/header/globals/Global.h index 4d5828c8..02195709 100644 --- a/hyperdbg/hprdbgkd/header/globals/Global.h +++ b/hyperdbg/hyperkd/header/globals/Global.h @@ -16,6 +16,54 @@ */ 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 + * + */ +KEVENT g_UserDebuggerWaitingCommandEvent; + +/** + * @brief Buffer to hold the command from user debugger + * + */ +PVOID g_UserDebuggerWaitingCommandBuffer; + +/** + * @brief Length of the input command buffer from user debugger + * + */ +UINT32 g_UserDebuggerWaitingCommandInputBufferLength; + +/** + * @brief Length of the output command buffer from user debugger + * + */ +UINT32 g_UserDebuggerWaitingCommandOutputBufferLength; + /** * @brief Holder of script engines global variables * @@ -35,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) * @@ -60,6 +102,12 @@ DEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT g_IgnoreBreaksToDebugger; */ HARDWARE_DEBUG_REGISTER_DETAILS g_HardwareDebugRegisterDetailsForStepOver; +/** + * @brief Holds the result of user debugger formats command + * + */ +DEBUGGEE_FORMATS_PACKET g_UserDebuggerFormatsResultPacket; + /** * @brief Process switch to EPROCESS or Process ID * @@ -82,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 @@ -151,33 +199,6 @@ BOOLEAN g_IsWaitingForReturnAndRunFromPageFault; */ LIST_ENTRY g_ProcessDebuggingDetailsListHead; -/** - * @brief Target function for kernel tests - * - */ -PVOID g_KernelTestTargetFunction; - -/** - * @brief Tag1 for kernel tests - * - */ -UINT64 g_KernelTestTag1; - -/** - * @brief Tag2 for kernel tests - * - */ -UINT64 g_KernelTestTag2; - -/** - * @brief Temp registers for kernel tests - * - */ -UINT64 g_KernelTestR15; -UINT64 g_KernelTestR14; -UINT64 g_KernelTestR13; -UINT64 g_KernelTestR12; - /** * @brief Whether the thread attaching mechanism is waiting for #DB or not * @@ -191,3 +212,9 @@ BOOLEAN g_IsWaitingForUserModeProcessEntryToBeCalled; * */ BOOLEAN g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer; + +/** + * @brief Global test flag (for testing purposes) + * + */ +BOOLEAN g_TestFlag; diff --git a/hyperdbg/hprdbgkd/header/pch.h b/hyperdbg/hyperkd/header/pch.h similarity index 74% rename from hyperdbg/hprdbgkd/header/pch.h rename to hyperdbg/hyperkd/header/pch.h index 638be9f6..630ee6b9 100644 --- a/hyperdbg/hprdbgkd/header/pch.h +++ b/hyperdbg/hyperkd/header/pch.h @@ -19,15 +19,21 @@ #define HYPERDBG_DEBUGGER #define SCRIPT_ENGINE_KERNEL_MODE +// +// Environment headers +// +#include "platform/general/header/Environment.h" + +#ifdef HYPERDBG_ENV_WINDOWS + // // General WDK headers // -#include -#include -#include -#include -#include -#include +# include +# include +# include + +#endif // HYPERDBG_ENV_WINDOWS // // Definition of Intel primitives (External header) @@ -37,8 +43,8 @@ // // Import Configuration and Definitions // -#include "Configuration.h" -#include "Definition.h" +#include "config/Configuration.h" +#include "config/Definition.h" // // Macros @@ -53,15 +59,15 @@ // // Import HyperLog Module // -#include "SDK/Modules/HyperLog.h" -#include "SDK/Imports/HyperDbgHyperLogImports.h" -#include "SDK/Imports/HyperDbgHyperLogIntrinsics.h" +#include "SDK/modules/HyperLog.h" +#include "SDK/imports/kernel/HyperDbgHyperLogImports.h" +#include "SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h" // // Import VMM Module // -#include "SDK/Modules/VMM.h" -#include "SDK/Imports/HyperDbgVmmImports.h" +#include "SDK/modules/VMM.h" +#include "SDK/imports/kernel/HyperDbgVmmImports.h" // // Local Debugger headers @@ -75,6 +81,15 @@ // #include "components/spinlock/header/Spinlock.h" +// +// Platform independent headers +// +#include "platform/kernel/header/PlatformMem.h" +#include "platform/kernel/header/PlatformIntrinsics.h" +#include "platform/kernel/header/PlatformBroadcast.h" +#include "platform/kernel/header/PlatformProcess.h" +#include "platform/kernel/header/PlatformCpu.h" + // // Optimization algorithms // @@ -99,6 +114,8 @@ #include "header/debugger/script-engine/ScriptEngine.h" #include "header/debugger/memory/Memory.h" #include "header/common/Common.h" +#include "header/common/Synchronization.h" +#include "header/debugger/memory/PoolManager.h" #include "header/debugger/memory/Allocations.h" #include "header/debugger/kernel-level/Kd.h" #include "header/debugger/user-level/Ud.h" @@ -122,11 +139,6 @@ #include "header/debugger/broadcast/HaltedRoutines.h" #include "header/debugger/broadcast/HaltedBroadcast.h" -// -// DPC Headers -// -#include "header/common/Dpc.h" - // // Events & Meta events // @@ -140,9 +152,14 @@ // // Script engine headers // -#include "../script-eval/header/ScriptEngineCommonDefinitions.h" #include "../script-eval/header/ScriptEngineHeader.h" +// +// Tracing (hypertrace) headers +// +#include "SDK/modules/HyperTrace.h" +#include "SDK/imports/kernel/HyperDbgHyperTrace.h" + // // Global variables // diff --git a/hyperdbg/hprdbgkd/hprdbgkd.vcxproj b/hyperdbg/hyperkd/hyperkd.vcxproj similarity index 69% rename from hyperdbg/hprdbgkd/hprdbgkd.vcxproj rename to hyperdbg/hyperkd/hyperkd.vcxproj index f1057228..b165f75d 100644 --- a/hyperdbg/hprdbgkd/hprdbgkd.vcxproj +++ b/hyperdbg/hyperkd/hyperkd.vcxproj @@ -1,5 +1,8 @@  + + + debug @@ -17,7 +20,7 @@ 12.0 Debug x64 - hprdbgkd + hyperkd $(LatestTargetPlatformVersion) @@ -27,7 +30,7 @@ WindowsKernelModeDriver10.0 Driver KMDF - Universal + Desktop false @@ -36,7 +39,7 @@ WindowsKernelModeDriver10.0 Driver KMDF - Universal + Desktop false @@ -51,13 +54,16 @@ DbgengKernelDebugger $(SolutionDir)build\bin\$(Configuration)\ $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - true + + + false DbgengKernelDebugger $(SolutionDir)build\bin\$(Configuration)\ $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - true + + false @@ -71,11 +77,12 @@ true Create pch.h + stdcpp20 true DriverEntry - $(SolutionDir)build\bin\$(Configuration)\hyperlog.lib;$(SolutionDir)build\bin\$(Configuration)\hprdbghv.lib;$(SolutionDir)build\bin\$(Configuration)\kdserial.lib;%(AdditionalDependencies) + $(SolutionDir)build\bin\$(Configuration)\hyperlog.lib;$(SolutionDir)build\bin\$(Configuration)\hyperhv.lib;$(SolutionDir)build\bin\$(Configuration)\kdserial.lib;$(SolutionDir)build\bin\$(Configuration)\hypertrace.lib;%(AdditionalDependencies) @@ -89,11 +96,13 @@ true Create pch.h + stdcpp20 + Full true DriverEntry - $(SolutionDir)build\bin\$(Configuration)\hyperlog.lib;$(SolutionDir)build\bin\$(Configuration)\hprdbghv.lib;$(SolutionDir)build\bin\$(Configuration)\kdserial.lib;%(AdditionalDependencies) + $(SolutionDir)build\bin\$(Configuration)\hyperlog.lib;$(SolutionDir)build\bin\$(Configuration)\hyperhv.lib;$(SolutionDir)build\bin\$(Configuration)\kdserial.lib;$(SolutionDir)build\bin\$(Configuration)\hypertrace.lib;%(AdditionalDependencies) @@ -105,12 +114,18 @@ + + + + + + @@ -128,6 +143,7 @@ + @@ -149,9 +165,14 @@ + + + + + - + @@ -171,6 +192,7 @@ + @@ -188,9 +210,21 @@ - + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/hyperdbg/hprdbgkd/hprdbgkd.vcxproj.filters b/hyperdbg/hyperkd/hyperkd.vcxproj.filters similarity index 89% rename from hyperdbg/hprdbgkd/hprdbgkd.vcxproj.filters rename to hyperdbg/hyperkd/hyperkd.vcxproj.filters index 4ad2e780..8a1a1c5b 100644 --- a/hyperdbg/hprdbgkd/hprdbgkd.vcxproj.filters +++ b/hyperdbg/hyperkd/hyperkd.vcxproj.filters @@ -130,6 +130,12 @@ {f308a8ae-1e28-465b-ae2f-4d307fa48177} + + {63a2a7a9-943a-43a6-9c81-4831088d3628} + + + {49d6a936-9fcf-4c74-af16-445b1b3625d2} + @@ -255,6 +261,27 @@ code\debugger\meta-events + + code\platform + + + code\common + + + code\platform + + + code\platform + + + code\platform + + + code\platform + + + code\debugger\memory + @@ -338,9 +365,6 @@ header\macros - - header\common - header\assembly @@ -383,13 +407,34 @@ header\debugger\meta-events + + header\platform + + + header\common + + + header\platform + + + header\platform + + + header\platform + + + header\platform + + + header\debugger\memory + - - code\assembly - code\assembly + + + \ No newline at end of file diff --git a/hyperdbg/hyperkd/packages.config b/hyperdbg/hyperkd/packages.config new file mode 100644 index 00000000..eb276766 --- /dev/null +++ b/hyperdbg/hyperkd/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/hyperdbg/hyperlog/CMakeLists.txt b/hyperdbg/hyperlog/CMakeLists.txt new file mode 100644 index 00000000..d6e772a5 --- /dev/null +++ b/hyperdbg/hyperlog/CMakeLists.txt @@ -0,0 +1,22 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "../include/components/spinlock/code/Spinlock.c" + "../include/platform/kernel/code/PlatformMem.c" + "code/Logging.c" + "code/UnloadDll.c" + "../include/components/spinlock/header/Spinlock.h" + "../include/platform/kernel/header/Environment.h" + "../include/platform/kernel/header/PlatformMem.h" + "header/Logging.h" + "header/pch.h" + "header/UnloadDll.h" + "hyperlog.def" +) +include_directories( + "../include" + "header" +) +wdk_add_library(hyperlog SHARED + KMDF 1.15 + ${SourceFiles} +) diff --git a/hyperdbg/hyperlog/code/Logging.c b/hyperdbg/hyperlog/code/Logging.c index 66020e2e..1cc3111f 100644 --- a/hyperdbg/hyperlog/code/Logging.c +++ b/hyperdbg/hyperlog/code/Logging.c @@ -9,18 +9,7 @@ * @copyright This project is released under the GNU Public License v3. * */ -#include -#include -#include - -#define HYPERDBG_KERNEL_MODE -#define HYPERDBG_HYPER_LOG - -#include "SDK/HyperDbgSdk.h" -#include "SDK/Modules/HyperLog.h" -#include "SDK/Imports/HyperDbgHyperLogImports.h" -#include "components/spinlock/header/Spinlock.h" -#include "Logging.h" +#include "pch.h" /** * @brief Checks whether the message tracing operates on vmx-root mode or not @@ -110,47 +99,42 @@ LogInitialize(MESSAGE_TRACING_CALLBACKS * MsgTracingCallbacks) { ULONG ProcessorsCount; - ProcessorsCount = KeQueryActiveProcessorCount(0); + ProcessorsCount = PlatformCpuGetActiveProcessorCount(); // // Initialize buffers for trace message and data messages //(we have two buffers one for vmx root and one for vmx non-root) // - MessageBufferInformation = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(LOG_BUFFER_INFORMATION) * 2, POOLTAG); + g_MessageBufferInformation = PlatformMemAllocateZeroedNonPagedPool(sizeof(LOG_BUFFER_INFORMATION) * 2); - if (!MessageBufferInformation) + if (!g_MessageBufferInformation) { return FALSE; // STATUS_INSUFFICIENT_RESOURCES } // - // Zeroing the memory + // Allocate g_VmxTempMessage and g_VmxLogMessage // - RtlZeroMemory(MessageBufferInformation, sizeof(LOG_BUFFER_INFORMATION) * 2); + g_VmxTempMessage = NULL; + g_VmxTempMessage = PlatformMemAllocateZeroedNonPagedPool(PacketChunkSize * ProcessorsCount); - // - // Allocate VmxTempMessage and VmxLogMessage - // - VmxTempMessage = NULL; - VmxTempMessage = ExAllocatePool2(POOL_FLAG_NON_PAGED, PacketChunkSize * ProcessorsCount, POOLTAG); - - if (!VmxTempMessage) + if (!g_VmxTempMessage) { - ExFreePoolWithTag(MessageBufferInformation, POOLTAG); - MessageBufferInformation = NULL; + PlatformMemFreePool(g_MessageBufferInformation); + g_MessageBufferInformation = NULL; return FALSE; // STATUS_INSUFFICIENT_RESOURCES } - VmxLogMessage = NULL; - VmxLogMessage = ExAllocatePool2(POOL_FLAG_NON_PAGED, PacketChunkSize * ProcessorsCount, POOLTAG); + g_VmxLogMessage = NULL; + g_VmxLogMessage = PlatformMemAllocateZeroedNonPagedPool(PacketChunkSize * ProcessorsCount); - if (!VmxLogMessage) + if (!g_VmxLogMessage) { - ExFreePoolWithTag(MessageBufferInformation, POOLTAG); - MessageBufferInformation = NULL; + PlatformMemFreePool(g_MessageBufferInformation); + g_MessageBufferInformation = NULL; - ExFreePoolWithTag(VmxTempMessage, POOLTAG); - VmxTempMessage = NULL; + PlatformMemFreePool(g_VmxTempMessage); + g_VmxTempMessage = NULL; return FALSE; // STATUS_INSUFFICIENT_RESOURCES } @@ -158,12 +142,12 @@ LogInitialize(MESSAGE_TRACING_CALLBACKS * MsgTracingCallbacks) // // Initialize the lock for Vmx-root mode (HIGH_IRQL Spinlock) // - VmxRootLoggingLock = 0; + g_VmxRootLoggingLock = 0; // // Allocate buffer for messages and initialize the core buffer information // - for (int i = 0; i < 2; i++) + for (UINT32 i = 0; i < 2; i++) { // // initialize the lock @@ -171,17 +155,17 @@ LogInitialize(MESSAGE_TRACING_CALLBACKS * MsgTracingCallbacks) // for both but the second buffer spinlock is useless // as we use our custom spinlock // - KeInitializeSpinLock(&MessageBufferInformation[i].BufferLock); - KeInitializeSpinLock(&MessageBufferInformation[i].BufferLockForNonImmMessage); + PlatformSpinlockInitialize(&g_MessageBufferInformation[i].BufferLock); + PlatformSpinlockInitialize(&g_MessageBufferInformation[i].BufferLockForNonImmMessage); // // allocate the buffer for regular buffers // - MessageBufferInformation[i].BufferStartAddress = (UINT64)ExAllocatePool2(POOL_FLAG_NON_PAGED, LogBufferSize, POOLTAG); - MessageBufferInformation[i].BufferForMultipleNonImmediateMessage = (UINT64)ExAllocatePool2(POOL_FLAG_NON_PAGED, PacketChunkSize, POOLTAG); + g_MessageBufferInformation[i].BufferStartAddress = (UINT64)PlatformMemAllocateNonPagedPool(LogBufferSize); + g_MessageBufferInformation[i].BufferForMultipleNonImmediateMessage = (UINT64)PlatformMemAllocateNonPagedPool(PacketChunkSize); - if (!MessageBufferInformation[i].BufferStartAddress || - !MessageBufferInformation[i].BufferForMultipleNonImmediateMessage) + if (!g_MessageBufferInformation[i].BufferStartAddress || + !g_MessageBufferInformation[i].BufferForMultipleNonImmediateMessage) { return FALSE; // STATUS_INSUFFICIENT_RESOURCES } @@ -189,9 +173,9 @@ LogInitialize(MESSAGE_TRACING_CALLBACKS * MsgTracingCallbacks) // // allocate the buffer for priority buffers // - MessageBufferInformation[i].BufferStartAddressPriority = (UINT64)ExAllocatePool2(POOL_FLAG_NON_PAGED, LogBufferSizePriority, POOLTAG); + g_MessageBufferInformation[i].BufferStartAddressPriority = (UINT64)PlatformMemAllocateNonPagedPool(LogBufferSizePriority); - if (!MessageBufferInformation[i].BufferStartAddressPriority) + if (!g_MessageBufferInformation[i].BufferStartAddressPriority) { return FALSE; // STATUS_INSUFFICIENT_RESOURCES } @@ -199,21 +183,21 @@ LogInitialize(MESSAGE_TRACING_CALLBACKS * MsgTracingCallbacks) // // Zeroing the buffer // - RtlZeroMemory((void *)MessageBufferInformation[i].BufferStartAddress, LogBufferSize); - RtlZeroMemory((void *)MessageBufferInformation[i].BufferForMultipleNonImmediateMessage, PacketChunkSize); - RtlZeroMemory((void *)MessageBufferInformation[i].BufferStartAddressPriority, LogBufferSizePriority); + PlatformZeroMemory((PVOID)g_MessageBufferInformation[i].BufferStartAddress, LogBufferSize); + PlatformZeroMemory((PVOID)g_MessageBufferInformation[i].BufferForMultipleNonImmediateMessage, PacketChunkSize); + PlatformZeroMemory((PVOID)g_MessageBufferInformation[i].BufferStartAddressPriority, LogBufferSizePriority); // // Set the end address // - MessageBufferInformation[i].BufferEndAddress = (UINT64)MessageBufferInformation[i].BufferStartAddress + LogBufferSize; - MessageBufferInformation[i].BufferEndAddressPriority = (UINT64)MessageBufferInformation[i].BufferStartAddressPriority + LogBufferSizePriority; + g_MessageBufferInformation[i].BufferEndAddress = (UINT64)g_MessageBufferInformation[i].BufferStartAddress + LogBufferSize; + g_MessageBufferInformation[i].BufferEndAddressPriority = (UINT64)g_MessageBufferInformation[i].BufferStartAddressPriority + LogBufferSizePriority; } // // Copy the callbacks into the global callback holder // - RtlCopyBytes(&g_MsgTracingCallbacks, MsgTracingCallbacks, sizeof(MESSAGE_TRACING_CALLBACKS)); + PlatformWriteMemory(&g_MsgTracingCallbacks, MsgTracingCallbacks, sizeof(MESSAGE_TRACING_CALLBACKS)); return TRUE; } @@ -231,30 +215,41 @@ LogUnInitialize() // for (int i = 0; i < 2; i++) { + // + // Check if the buffer is allocated or not + // + if (g_MessageBufferInformation == NULL64_ZERO) + { + continue; // No need to free the buffers + } + // // Free each buffers // - if (MessageBufferInformation[i].BufferStartAddress != NULL64_ZERO) + if (g_MessageBufferInformation[i].BufferStartAddress != NULL64_ZERO) { - ExFreePoolWithTag((PVOID)MessageBufferInformation[i].BufferStartAddress, POOLTAG); + PlatformMemFreePool((PVOID)g_MessageBufferInformation[i].BufferStartAddress); } - if (MessageBufferInformation[i].BufferStartAddressPriority != NULL64_ZERO) + if (g_MessageBufferInformation[i].BufferStartAddressPriority != NULL64_ZERO) { - ExFreePoolWithTag((PVOID)MessageBufferInformation[i].BufferStartAddressPriority, POOLTAG); + PlatformMemFreePool((PVOID)g_MessageBufferInformation[i].BufferStartAddressPriority); } - if (MessageBufferInformation[i].BufferForMultipleNonImmediateMessage != NULL64_ZERO) + if (g_MessageBufferInformation[i].BufferForMultipleNonImmediateMessage != NULL64_ZERO) { - ExFreePoolWithTag((PVOID)MessageBufferInformation[i].BufferForMultipleNonImmediateMessage, POOLTAG); + PlatformMemFreePool((PVOID)g_MessageBufferInformation[i].BufferForMultipleNonImmediateMessage); } } // - // de-allocate buffers for trace message and data messages + // de-allocate buffers for trace message and data messages if they are allocated // - ExFreePoolWithTag((PVOID)MessageBufferInformation, POOLTAG); - MessageBufferInformation = NULL; + if (g_MessageBufferInformation != NULL64_ZERO) + { + PlatformMemFreePool((PVOID)g_MessageBufferInformation); + g_MessageBufferInformation = NULL; + } } /** @@ -296,9 +291,9 @@ LogCallbackCheckIfBufferIsFull(BOOLEAN Priority) // if (Priority) { - CurrentIndexToWritePriority = MessageBufferInformation[Index].CurrentIndexToWritePriority; + CurrentIndexToWritePriority = g_MessageBufferInformation[Index].CurrentIndexToWritePriority; - if (MessageBufferInformation[Index].CurrentIndexToWritePriority > MaximumPacketsCapacityPriority - 1) + if (g_MessageBufferInformation[Index].CurrentIndexToWritePriority > MaximumPacketsCapacityPriority - 1) { // // start from the beginning @@ -308,9 +303,9 @@ LogCallbackCheckIfBufferIsFull(BOOLEAN Priority) } else { - CurrentIndexToWrite = MessageBufferInformation[Index].CurrentIndexToWrite; + CurrentIndexToWrite = g_MessageBufferInformation[Index].CurrentIndexToWrite; - if (MessageBufferInformation[Index].CurrentIndexToWrite > MaximumPacketsCapacity - 1) + if (g_MessageBufferInformation[Index].CurrentIndexToWrite > MaximumPacketsCapacity - 1) { // // start from the beginning @@ -326,11 +321,11 @@ LogCallbackCheckIfBufferIsFull(BOOLEAN Priority) if (Priority) { - Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddressPriority + (CurrentIndexToWritePriority * (PacketChunkSize + sizeof(BUFFER_HEADER)))); + Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddressPriority + (CurrentIndexToWritePriority * (PacketChunkSize + sizeof(BUFFER_HEADER)))); } else { - Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddress + (CurrentIndexToWrite * (PacketChunkSize + sizeof(BUFFER_HEADER)))); + Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddress + (CurrentIndexToWrite * (PacketChunkSize + sizeof(BUFFER_HEADER)))); } // @@ -389,7 +384,7 @@ LogCallbackSendBuffer(UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, B // // vmx non-root // - OldIRQL = KeRaiseIrqlToDpcLevel(); + OldIRQL = PlatformIrqlRaiseToDpcLevel(); } // @@ -408,7 +403,7 @@ LogCallbackSendBuffer(UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, B // // vmx non-root // - KeLowerIrql(OldIRQL); + PlatformIrqlLower(OldIRQL); } return TRUE; @@ -424,7 +419,7 @@ LogCallbackSendBuffer(UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, B // Set the index // Index = 1; - SpinlockLock(&VmxRootLoggingLock); + SpinlockLock(&g_VmxRootLoggingLock); } else { @@ -436,7 +431,7 @@ LogCallbackSendBuffer(UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, B // // Acquire the lock // - KeAcquireSpinLock(&MessageBufferInformation[Index].BufferLock, &OldIRQL); + PlatformSpinlockAcquire(&g_MessageBufferInformation[Index].BufferLock, &OldIRQL); } // @@ -444,22 +439,22 @@ LogCallbackSendBuffer(UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, B // if (Priority) { - if (MessageBufferInformation[Index].CurrentIndexToWritePriority > MaximumPacketsCapacityPriority - 1) + if (g_MessageBufferInformation[Index].CurrentIndexToWritePriority > MaximumPacketsCapacityPriority - 1) { // // start from the beginning // - MessageBufferInformation[Index].CurrentIndexToWritePriority = 0; + g_MessageBufferInformation[Index].CurrentIndexToWritePriority = 0; } } else { - if (MessageBufferInformation[Index].CurrentIndexToWrite > MaximumPacketsCapacity - 1) + if (g_MessageBufferInformation[Index].CurrentIndexToWrite > MaximumPacketsCapacity - 1) { // // start from the beginning // - MessageBufferInformation[Index].CurrentIndexToWrite = 0; + g_MessageBufferInformation[Index].CurrentIndexToWrite = 0; } } @@ -470,11 +465,11 @@ LogCallbackSendBuffer(UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, B if (Priority) { - Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddressPriority + (MessageBufferInformation[Index].CurrentIndexToWritePriority * (PacketChunkSize + sizeof(BUFFER_HEADER)))); + Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddressPriority + (g_MessageBufferInformation[Index].CurrentIndexToWritePriority * (PacketChunkSize + sizeof(BUFFER_HEADER)))); } else { - Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddress + (MessageBufferInformation[Index].CurrentIndexToWrite * (PacketChunkSize + sizeof(BUFFER_HEADER)))); + Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddress + (g_MessageBufferInformation[Index].CurrentIndexToWrite * (PacketChunkSize + sizeof(BUFFER_HEADER)))); } // @@ -495,28 +490,28 @@ LogCallbackSendBuffer(UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, B if (Priority) { - SavingBuffer = (PVOID)((UINT64)MessageBufferInformation[Index].BufferStartAddressPriority + (MessageBufferInformation[Index].CurrentIndexToWritePriority * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER)); + SavingBuffer = (PVOID)((UINT64)g_MessageBufferInformation[Index].BufferStartAddressPriority + (g_MessageBufferInformation[Index].CurrentIndexToWritePriority * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER)); } else { - SavingBuffer = (PVOID)((UINT64)MessageBufferInformation[Index].BufferStartAddress + (MessageBufferInformation[Index].CurrentIndexToWrite * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER)); + SavingBuffer = (PVOID)((UINT64)g_MessageBufferInformation[Index].BufferStartAddress + (g_MessageBufferInformation[Index].CurrentIndexToWrite * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER)); } // // Copy the buffer // - RtlCopyBytes(SavingBuffer, Buffer, BufferLength); + PlatformWriteMemory(SavingBuffer, Buffer, BufferLength); // // Increment the next index to write // if (Priority) { - MessageBufferInformation[Index].CurrentIndexToWritePriority = MessageBufferInformation[Index].CurrentIndexToWritePriority + 1; + g_MessageBufferInformation[Index].CurrentIndexToWritePriority = g_MessageBufferInformation[Index].CurrentIndexToWritePriority + 1; } else { - MessageBufferInformation[Index].CurrentIndexToWrite = MessageBufferInformation[Index].CurrentIndexToWrite + 1; + g_MessageBufferInformation[Index].CurrentIndexToWrite = g_MessageBufferInformation[Index].CurrentIndexToWrite + 1; } // @@ -536,7 +531,7 @@ LogCallbackSendBuffer(UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, B // // Insert dpc to queue // - KeInsertQueueDpc(&g_GlobalNotifyRecord->Dpc, g_GlobalNotifyRecord, NULL); + PlatformDpcInsertQueueDpc(&g_GlobalNotifyRecord->Dpc, g_GlobalNotifyRecord, NULL); // // set notify routine to null @@ -550,14 +545,14 @@ LogCallbackSendBuffer(UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, B // if (IsVmxRoot) { - SpinlockUnlock(&VmxRootLoggingLock); + SpinlockUnlock(&g_VmxRootLoggingLock); } else { // // Release the lock // - KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL); + PlatformSpinlockRelease(&g_MessageBufferInformation[Index].BufferLock, OldIRQL); } return TRUE; @@ -591,7 +586,7 @@ LogMarkAllAsRead(BOOLEAN IsVmxRoot) // // Acquire the lock // - SpinlockLock(&VmxRootLoggingLock); + SpinlockLock(&g_VmxRootLoggingLock); } else { @@ -603,19 +598,19 @@ LogMarkAllAsRead(BOOLEAN IsVmxRoot) // // Acquire the lock // - KeAcquireSpinLock(&MessageBufferInformation[Index].BufferLock, &OldIRQL); + PlatformSpinlockAcquire(&g_MessageBufferInformation[Index].BufferLock, &OldIRQL); } // // We have iterate through the all indexes // - for (size_t i = 0; i < MaximumPacketsCapacity; i++) + for (SIZE_T i = 0; i < MaximumPacketsCapacity; i++) { // // Compute the current buffer to read // - BUFFER_HEADER * Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddress + - (MessageBufferInformation[Index].CurrentIndexToSend * + BUFFER_HEADER * Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddress + + (g_MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER)))); if (!Header->Valid) @@ -630,14 +625,14 @@ LogMarkAllAsRead(BOOLEAN IsVmxRoot) // if (IsVmxRoot) { - SpinlockUnlock(&VmxRootLoggingLock); + SpinlockUnlock(&g_VmxRootLoggingLock); } else { // // Release the lock // - KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL); + PlatformSpinlockRelease(&g_MessageBufferInformation[Index].BufferLock, OldIRQL); } return ResultsOfBuffersSetToRead; @@ -651,7 +646,7 @@ LogMarkAllAsRead(BOOLEAN IsVmxRoot) // // Second, save the buffer contents // - PVOID SendingBuffer = (PVOID)((UINT64)MessageBufferInformation[Index].BufferStartAddress + (MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER)); + PVOID SendingBuffer = (PVOID)((UINT64)g_MessageBufferInformation[Index].BufferStartAddress + (g_MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER)); // // Finally, set the current index to invalid as we sent it @@ -663,21 +658,21 @@ LogMarkAllAsRead(BOOLEAN IsVmxRoot) // there might be multiple messages on the start of the queue that didn't read yet) // we don't free the header // - RtlZeroMemory(SendingBuffer, Header->BufferLength); + PlatformZeroMemory(SendingBuffer, Header->BufferLength); // // Check to see whether we passed the index or not // - if (MessageBufferInformation[Index].CurrentIndexToSend > MaximumPacketsCapacity - 2) + if (g_MessageBufferInformation[Index].CurrentIndexToSend > MaximumPacketsCapacity - 2) { - MessageBufferInformation[Index].CurrentIndexToSend = 0; + g_MessageBufferInformation[Index].CurrentIndexToSend = 0; } else { // // Increment the next index to read // - MessageBufferInformation[Index].CurrentIndexToSend = MessageBufferInformation[Index].CurrentIndexToSend + 1; + g_MessageBufferInformation[Index].CurrentIndexToSend = g_MessageBufferInformation[Index].CurrentIndexToSend + 1; } } @@ -687,14 +682,14 @@ LogMarkAllAsRead(BOOLEAN IsVmxRoot) // if (IsVmxRoot) { - SpinlockUnlock(&VmxRootLoggingLock); + SpinlockUnlock(&g_VmxRootLoggingLock); } else { // // Release the lock // - KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL); + PlatformSpinlockRelease(&g_MessageBufferInformation[Index].BufferLock, OldIRQL); } return ResultsOfBuffersSetToRead; @@ -730,7 +725,7 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen // // Acquire the lock // - SpinlockLock(&VmxRootLoggingLock); + SpinlockLock(&g_VmxRootLoggingLock); } else { @@ -742,7 +737,7 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen // // Acquire the lock // - KeAcquireSpinLock(&MessageBufferInformation[Index].BufferLock, &OldIRQL); + PlatformSpinlockAcquire(&g_MessageBufferInformation[Index].BufferLock, &OldIRQL); } // @@ -753,14 +748,14 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen // // Check for priority message // - Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddressPriority + (MessageBufferInformation[Index].CurrentIndexToSendPriority * (PacketChunkSize + sizeof(BUFFER_HEADER)))); + Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddressPriority + (g_MessageBufferInformation[Index].CurrentIndexToSendPriority * (PacketChunkSize + sizeof(BUFFER_HEADER)))); if (!Header->Valid) { // // Check for regular message // - Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddress + (MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER)))); + Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddress + (g_MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER)))); if (!Header->Valid) { @@ -774,14 +769,14 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen // if (IsVmxRoot) { - SpinlockUnlock(&VmxRootLoggingLock); + SpinlockUnlock(&g_VmxRootLoggingLock); } else { // // Release the lock // - KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL); + PlatformSpinlockRelease(&g_MessageBufferInformation[Index].BufferLock, OldIRQL); } return FALSE; @@ -799,7 +794,7 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen // // First copy the header // - RtlCopyBytes(BufferToSaveMessage, &Header->OperationNumber, sizeof(UINT32)); + PlatformWriteMemory(BufferToSaveMessage, &Header->OperationNumber, sizeof(UINT32)); // // Second, save the buffer contents @@ -808,11 +803,11 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen if (PriorityMessageIsAvailable) { - SendingBuffer = (PVOID)((UINT64)MessageBufferInformation[Index].BufferStartAddressPriority + (MessageBufferInformation[Index].CurrentIndexToSendPriority * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER)); + SendingBuffer = (PVOID)((UINT64)g_MessageBufferInformation[Index].BufferStartAddressPriority + (g_MessageBufferInformation[Index].CurrentIndexToSendPriority * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER)); } else { - SendingBuffer = (PVOID)((UINT64)MessageBufferInformation[Index].BufferStartAddress + (MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER)); + SendingBuffer = (PVOID)((UINT64)g_MessageBufferInformation[Index].BufferStartAddress + (g_MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER))) + sizeof(BUFFER_HEADER)); } // @@ -820,7 +815,7 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen // PVOID SavingAddress = (PVOID)((UINT64)BufferToSaveMessage + sizeof(UINT32)); - RtlCopyBytes(SavingAddress, SendingBuffer, Header->BufferLength); + PlatformWriteMemory(SavingAddress, SendingBuffer, Header->BufferLength); #if ShowMessagesOnDebugger @@ -835,21 +830,21 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen // if (Header->BufferLength > DbgPrintLimitation) { - for (size_t i = 0; i <= Header->BufferLength / DbgPrintLimitation; i++) + for (SIZE_T i = 0; i <= Header->BufferLength / DbgPrintLimitation; i++) { if (i != 0) { - DbgPrint("%s", (char *)((UINT64)SendingBuffer + (DbgPrintLimitation * i) - 2)); + PlatformDbgPrint("%s", (CHAR *)((UINT64)SendingBuffer + (DbgPrintLimitation * i) - 2)); } else { - DbgPrint("%s", (char *)((UINT64)SendingBuffer + (DbgPrintLimitation * i))); + PlatformDbgPrint("%s", (CHAR *)((UINT64)SendingBuffer + (DbgPrintLimitation * i))); } } } else { - DbgPrint("%s", (char *)SendingBuffer); + PlatformDbgPrint("%s", (CHAR *)SendingBuffer); } } #endif @@ -869,23 +864,23 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen // there might be multiple messages on the start of the queue that didn't read yet) // we don't free the header // - RtlZeroMemory(SendingBuffer, Header->BufferLength); + PlatformZeroMemory(SendingBuffer, Header->BufferLength); if (PriorityMessageIsAvailable) { // // Check to see whether we passed the index or not // - if (MessageBufferInformation[Index].CurrentIndexToSendPriority > MaximumPacketsCapacityPriority - 2) + if (g_MessageBufferInformation[Index].CurrentIndexToSendPriority > MaximumPacketsCapacityPriority - 2) { - MessageBufferInformation[Index].CurrentIndexToSendPriority = 0; + g_MessageBufferInformation[Index].CurrentIndexToSendPriority = 0; } else { // // Increment the next index to read // - MessageBufferInformation[Index].CurrentIndexToSendPriority = MessageBufferInformation[Index].CurrentIndexToSendPriority + 1; + g_MessageBufferInformation[Index].CurrentIndexToSendPriority = g_MessageBufferInformation[Index].CurrentIndexToSendPriority + 1; } } else @@ -893,16 +888,16 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen // // Check to see whether we passed the index or not // - if (MessageBufferInformation[Index].CurrentIndexToSend > MaximumPacketsCapacity - 2) + if (g_MessageBufferInformation[Index].CurrentIndexToSend > MaximumPacketsCapacity - 2) { - MessageBufferInformation[Index].CurrentIndexToSend = 0; + g_MessageBufferInformation[Index].CurrentIndexToSend = 0; } else { // // Increment the next index to read // - MessageBufferInformation[Index].CurrentIndexToSend = MessageBufferInformation[Index].CurrentIndexToSend + 1; + g_MessageBufferInformation[Index].CurrentIndexToSend = g_MessageBufferInformation[Index].CurrentIndexToSend + 1; } } @@ -912,14 +907,14 @@ LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 * ReturnedLen // if (IsVmxRoot) { - SpinlockUnlock(&VmxRootLoggingLock); + SpinlockUnlock(&g_VmxRootLoggingLock); } else { // // Release the lock // - KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL); + PlatformSpinlockRelease(&g_MessageBufferInformation[Index].BufferLock, OldIRQL); } return TRUE; @@ -955,11 +950,11 @@ LogCheckForNewMessage(BOOLEAN IsVmxRoot, BOOLEAN Priority) if (Priority) { - Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddressPriority + (MessageBufferInformation[Index].CurrentIndexToSendPriority * (PacketChunkSize + sizeof(BUFFER_HEADER)))); + Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddressPriority + (g_MessageBufferInformation[Index].CurrentIndexToSendPriority * (PacketChunkSize + sizeof(BUFFER_HEADER)))); } else { - Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddress + (MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER)))); + Header = (BUFFER_HEADER *)((UINT64)g_MessageBufferInformation[Index].BufferStartAddress + (g_MessageBufferInformation[Index].CurrentIndexToSend * (PacketChunkSize + sizeof(BUFFER_HEADER)))); } if (!Header->Valid) @@ -993,17 +988,17 @@ LogCallbackPrepareAndSendMessageToQueueWrapper(UINT32 OperationCode, BOOLEAN IsImmediateMessage, BOOLEAN ShowCurrentSystemTime, BOOLEAN Priority, - const char * Fmt, + const CHAR * Fmt, va_list ArgList) { - int SprintfResult; - size_t WrittenSize; + INT32 SprintfResult; + SIZE_T WrittenSize; BOOLEAN IsVmxRootMode; BOOLEAN Result = FALSE; // by default, we assume error happens - char * LogMessage = NULL; - char * TempMessage = NULL; - char TimeBuffer[20] = {0}; - ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + CHAR * LogMessage = NULL; + CHAR * TempMessage = NULL; + CHAR TimeBuffer[20] = {0}; + ULONG CurrentCore = PlatformCpuGetCurrentProcessorNumber(); // // Set Vmx State @@ -1016,15 +1011,15 @@ LogCallbackPrepareAndSendMessageToQueueWrapper(UINT32 OperationCode, // if (IsVmxRootMode) { - LogMessage = &VmxLogMessage[CurrentCore * PacketChunkSize]; - TempMessage = &VmxTempMessage[CurrentCore * PacketChunkSize]; + LogMessage = &g_VmxLogMessage[CurrentCore * PacketChunkSize]; + TempMessage = &g_VmxTempMessage[CurrentCore * PacketChunkSize]; } else { // // To avoid buffer collision and buffer re-writing in VMX non-root, allocate pool // - LogMessage = ExAllocatePool2(POOL_FLAG_NON_PAGED, PacketChunkSize, POOLTAG); + LogMessage = PlatformMemAllocateNonPagedPool(PacketChunkSize); if (LogMessage == NULL) { @@ -1033,14 +1028,14 @@ LogCallbackPrepareAndSendMessageToQueueWrapper(UINT32 OperationCode, // return FALSE; } - TempMessage = ExAllocatePool2(POOL_FLAG_NON_PAGED, PacketChunkSize, POOLTAG); + TempMessage = PlatformMemAllocateNonPagedPool(PacketChunkSize); if (TempMessage == NULL) { // // Insufficient space // - ExFreePoolWithTag(LogMessage, POOLTAG); + PlatformMemFreePool(LogMessage); return FALSE; } } @@ -1074,9 +1069,10 @@ LogCallbackPrepareAndSendMessageToQueueWrapper(UINT32 OperationCode, // TIME_FIELDS TimeFields; LARGE_INTEGER SystemTime, LocalTime; - KeQuerySystemTime(&SystemTime); - ExSystemTimeToLocalTime(&SystemTime, &LocalTime); - RtlTimeToTimeFields(&LocalTime, &TimeFields); + PlatformTimeQuerySystemTime(&SystemTime); + PlatformTimeConvertToLocalTime(&SystemTime, &LocalTime); + PlatformTimeConvertToTimeFields(&LocalTime, &TimeFields); + // // We won't use this because we can't use in any IRQL // Status = RtlStringCchPrintfA(TimeBuffer, RTL_NUMBER_OF(TimeBuffer), @@ -1159,8 +1155,8 @@ FreeBufferAndReturn: if (!IsVmxRootMode) { - ExFreePoolWithTag(LogMessage, POOLTAG); - ExFreePoolWithTag(TempMessage, POOLTAG); + PlatformMemFreePool(LogMessage); + PlatformMemFreePool(TempMessage); } return Result; @@ -1183,7 +1179,7 @@ LogCallbackPrepareAndSendMessageToQueue(UINT32 OperationCode, BOOLEAN IsImmediateMessage, BOOLEAN ShowCurrentSystemTime, BOOLEAN Priority, - const char * Fmt, + const CHAR * Fmt, ...) { va_list ArgList; @@ -1279,7 +1275,7 @@ LogCallbackSendMessageToQueue(UINT32 OperationCode, BOOLEAN IsImmediateMessage, // Set the index // Index = 1; - SpinlockLock(&VmxRootLoggingLockForNonImmBuffers); + SpinlockLock(&g_VmxRootLoggingLockForNonImmBuffers); } else { @@ -1291,7 +1287,7 @@ LogCallbackSendMessageToQueue(UINT32 OperationCode, BOOLEAN IsImmediateMessage, // // Acquire the lock // - KeAcquireSpinLock(&MessageBufferInformation[Index].BufferLockForNonImmMessage, &OldIRQL); + PlatformSpinlockAcquire(&g_MessageBufferInformation[Index].BufferLockForNonImmMessage, &OldIRQL); } // // Set the result to True @@ -1301,50 +1297,50 @@ LogCallbackSendMessageToQueue(UINT32 OperationCode, BOOLEAN IsImmediateMessage, // // If log message WrittenSize is above the buffer then we have to send the previous buffer // - if ((MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer + BufferLen) > PacketChunkSize - 1 && MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer != 0) + if ((g_MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer + BufferLen) > PacketChunkSize - 1 && g_MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer != 0) { // // Send the previous buffer (non-immediate message), // accumulated messages don't have priority // Result = LogCallbackSendBuffer(OPERATION_LOG_NON_IMMEDIATE_MESSAGE, - (PVOID)MessageBufferInformation[Index].BufferForMultipleNonImmediateMessage, - MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer, + (PVOID)g_MessageBufferInformation[Index].BufferForMultipleNonImmediateMessage, + g_MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer, FALSE); // // Free the immediate buffer // - MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer = 0; - RtlZeroMemory((void *)MessageBufferInformation[Index].BufferForMultipleNonImmediateMessage, PacketChunkSize); + g_MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer = 0; + PlatformZeroMemory((PVOID)g_MessageBufferInformation[Index].BufferForMultipleNonImmediateMessage, PacketChunkSize); } // // We have to save the message // - RtlCopyBytes((void *)(MessageBufferInformation[Index].BufferForMultipleNonImmediateMessage + - MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer), - LogMessage, - BufferLen); + PlatformWriteMemory((PVOID)(g_MessageBufferInformation[Index].BufferForMultipleNonImmediateMessage + + g_MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer), + LogMessage, + BufferLen); // // add the length // - MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer += BufferLen; + g_MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer += BufferLen; // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock, // if not we use the windows spinlock // if (IsVmxRootMode) { - SpinlockUnlock(&VmxRootLoggingLockForNonImmBuffers); + SpinlockUnlock(&g_VmxRootLoggingLockForNonImmBuffers); } else { // // Release the lock // - KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLockForNonImmMessage, OldIRQL); + PlatformSpinlockRelease(&g_MessageBufferInformation[Index].BufferLockForNonImmMessage, OldIRQL); } return Result; @@ -1394,18 +1390,18 @@ LogNotifyUsermodeCallback(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument // if (!(Irp->CurrentLocation <= Irp->StackCount + 1)) { - DbgPrint("Err, probably two or more functions called DPC for an object"); + PlatformDbgPrint("Err, probably two or more functions called DPC for an object"); return; } - IrpSp = IoGetCurrentIrpStackLocation(Irp); + IrpSp = PlatformIoGetCurrentIrpStackLocation(Irp); InBuffLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; OutBuffLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; if (!InBuffLength || !OutBuffLength) { Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + PlatformIoCompleteRequest(Irp, IO_NO_INCREMENT); break; } @@ -1432,14 +1428,14 @@ LogNotifyUsermodeCallback(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument // we have to return here as there is nothing to send here // Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + PlatformIoCompleteRequest(Irp, IO_NO_INCREMENT); break; } Irp->IoStatus.Information = Length; Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + PlatformIoCompleteRequest(Irp, IO_NO_INCREMENT); } break; @@ -1447,12 +1443,12 @@ LogNotifyUsermodeCallback(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument // // Signal the Event created in user-mode. // - KeSetEvent(NotifyRecord->Message.Event, 0, FALSE); + PlatformEventSet(NotifyRecord->Message.Event, 0, FALSE); // // Dereference the object as we are done with it. // - ObDereferenceObject(NotifyRecord->Message.Event); + PlatformObjectDereference(NotifyRecord->Message.Event); break; @@ -1463,25 +1459,25 @@ LogNotifyUsermodeCallback(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument if (NotifyRecord != NULL) { - ExFreePoolWithTag(NotifyRecord, POOLTAG); + PlatformMemFreePool(NotifyRecord); } } /** * @brief Register a new IRP Pending thread which listens for new buffers * - * @param DeviceObject - * @param Irp - * @return NTSTATUS + * @param TargetIrp + * @param Status + * + * @return BOOLEAN */ -NTSTATUS -LogRegisterIrpBasedNotification(PDEVICE_OBJECT DeviceObject, PIRP Irp) +BOOLEAN +LogRegisterIrpBasedNotification(PVOID TargetIrp, LONG * Status) { - UNREFERENCED_PARAMETER(DeviceObject); - PNOTIFY_RECORD NotifyRecord; PIO_STACK_LOCATION IrpStack; PREGISTER_NOTIFY_BUFFER RegisterEvent; + PIRP Irp = (PIRP)TargetIrp; // // check if current core has another thread with pending IRP, @@ -1492,28 +1488,29 @@ LogRegisterIrpBasedNotification(PDEVICE_OBJECT DeviceObject, PIRP Irp) if (g_GlobalNotifyRecord == NULL) { - IrpStack = IoGetCurrentIrpStackLocation(Irp); + IrpStack = PlatformIoGetCurrentIrpStackLocation(Irp); RegisterEvent = (PREGISTER_NOTIFY_BUFFER)Irp->AssociatedIrp.SystemBuffer; // // Allocate a record and save all the event context // - NotifyRecord = ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_USE_QUOTA, sizeof(NOTIFY_RECORD), POOLTAG); + NotifyRecord = PlatformMemAllocateNonPagedPoolWithQuota(sizeof(NOTIFY_RECORD)); if (NULL == NotifyRecord) { - return STATUS_INSUFFICIENT_RESOURCES; + *Status = (LONG)STATUS_INSUFFICIENT_RESOURCES; + return FALSE; } NotifyRecord->Type = IRP_BASED; NotifyRecord->Message.PendingIrp = Irp; - KeInitializeDpc(&NotifyRecord->Dpc, // Dpc - LogNotifyUsermodeCallback, // DeferredRoutine - NotifyRecord // DeferredContext + PlatformDpcInitialize(&NotifyRecord->Dpc, // Dpc + LogNotifyUsermodeCallback, // DeferredRoutine + NotifyRecord // DeferredContext ); - IoMarkIrpPending(Irp); + PlatformIoMarkIrpPending(Irp); // // check for new message (for both Vmx-root mode or Vmx non root-mode) @@ -1530,7 +1527,7 @@ LogRegisterIrpBasedNotification(PDEVICE_OBJECT DeviceObject, PIRP Irp) // // Insert dpc to queue // - KeInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL); + PlatformDpcInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL); } else if (LogCheckForNewMessage(TRUE, TRUE)) { @@ -1541,7 +1538,7 @@ LogRegisterIrpBasedNotification(PDEVICE_OBJECT DeviceObject, PIRP Irp) // // Insert dpc to queue // - KeInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL); + PlatformDpcInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL); } else if (LogCheckForNewMessage(FALSE, FALSE)) { @@ -1553,7 +1550,7 @@ LogRegisterIrpBasedNotification(PDEVICE_OBJECT DeviceObject, PIRP Irp) // // Insert dpc to queue // - KeInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL); + PlatformDpcInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL); } else if (LogCheckForNewMessage(TRUE, FALSE)) { @@ -1564,7 +1561,7 @@ LogRegisterIrpBasedNotification(PDEVICE_OBJECT DeviceObject, PIRP Irp) // // Insert dpc to queue // - KeInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL); + PlatformDpcInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL); } else { @@ -1576,73 +1573,75 @@ LogRegisterIrpBasedNotification(PDEVICE_OBJECT DeviceObject, PIRP Irp) // // We will return pending as we have marked the IRP pending // - return STATUS_PENDING; + + *Status = (LONG)STATUS_PENDING; + return TRUE; } else { - return STATUS_SUCCESS; + *Status = (LONG)STATUS_SUCCESS; + return TRUE; } } /** * @brief Create an event-based usermode notifying mechanism * - * @param DeviceObject - * @param Irp - * @return NTSTATUS + * @param TargetIrp + * @return BOOLEAN */ -NTSTATUS -LogRegisterEventBasedNotification(PDEVICE_OBJECT DeviceObject, PIRP Irp) +BOOLEAN +LogRegisterEventBasedNotification(PVOID TargetIrp) { - UNREFERENCED_PARAMETER(DeviceObject); - PNOTIFY_RECORD NotifyRecord; NTSTATUS Status; PIO_STACK_LOCATION IrpStack; PREGISTER_NOTIFY_BUFFER RegisterEvent; + PIRP Irp = (PIRP)TargetIrp; - IrpStack = IoGetCurrentIrpStackLocation(Irp); + IrpStack = PlatformIoGetCurrentIrpStackLocation(Irp); RegisterEvent = (PREGISTER_NOTIFY_BUFFER)Irp->AssociatedIrp.SystemBuffer; // // Allocate a record and save all the event context // - NotifyRecord = ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_USE_QUOTA, sizeof(NOTIFY_RECORD), POOLTAG); + NotifyRecord = PlatformMemAllocateNonPagedPoolWithQuota(sizeof(NOTIFY_RECORD)); if (NULL == NotifyRecord) { - return STATUS_INSUFFICIENT_RESOURCES; + PlatformDbgPrint("Err, unable to allocate memory for notify record\n"); + return FALSE; } NotifyRecord->Type = EVENT_BASED; - KeInitializeDpc(&NotifyRecord->Dpc, // Dpc - LogNotifyUsermodeCallback, // DeferredRoutine - NotifyRecord // DeferredContext + PlatformDpcInitialize(&NotifyRecord->Dpc, // Dpc + LogNotifyUsermodeCallback, // DeferredRoutine + NotifyRecord // DeferredContext ); // // Get the object pointer from the handle // Note we must be in the context of the process that created the handle // - Status = ObReferenceObjectByHandle(RegisterEvent->hEvent, - SYNCHRONIZE | EVENT_MODIFY_STATE, - *ExEventObjectType, - Irp->RequestorMode, - &NotifyRecord->Message.Event, - NULL); + Status = PlatformObjectReferenceByHandle(RegisterEvent->hEvent, + SYNCHRONIZE | EVENT_MODIFY_STATE, + *ExEventObjectType, + Irp->RequestorMode, + &NotifyRecord->Message.Event, + NULL); if (!NT_SUCCESS(Status)) { - DbgPrint("Err, unable to reference user mode event object, status = 0x%x", Status); - ExFreePoolWithTag(NotifyRecord, POOLTAG); - return Status; + PlatformDbgPrint("Err, unable to reference user mode event object, status = 0x%x\n", Status); + PlatformMemFreePool(NotifyRecord); + return FALSE; } // // Insert dpc to the queue // - KeInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL); + PlatformDpcInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL); - return STATUS_SUCCESS; + return TRUE; } diff --git a/hyperdbg/hyperlog/code/UnloadDll.c b/hyperdbg/hyperlog/code/UnloadDll.c index be8c9ba6..0f82e50e 100644 --- a/hyperdbg/hyperlog/code/UnloadDll.c +++ b/hyperdbg/hyperlog/code/UnloadDll.c @@ -28,7 +28,7 @@ DllInitialize( } NTSTATUS -DllUnload(void) +DllUnload(VOID) { return STATUS_SUCCESS; } diff --git a/hyperdbg/hyperlog/header/Logging.h b/hyperdbg/hyperlog/header/Logging.h index 87065edc..c098d883 100644 --- a/hyperdbg/hyperlog/header/Logging.h +++ b/hyperdbg/hyperlog/header/Logging.h @@ -20,13 +20,13 @@ * @brief VMX buffer for logging messages * */ -char * VmxLogMessage; +CHAR * g_VmxLogMessage; /** * @brief VMX temporary buffer for logging messages * */ -char * VmxTempMessage; +CHAR * g_VmxTempMessage; ////////////////////////////////////////////////// // Structures // @@ -70,8 +70,8 @@ typedef struct _LOG_BUFFER_INFORMATION KSPIN_LOCK BufferLock; // SpinLock to protect access to the queue KSPIN_LOCK BufferLockForNonImmMessage; // SpinLock to protect access to the queue of non-imm messages - UINT64 BufferForMultipleNonImmediateMessage; // Start address of the buffer for accumulating non-immadiate messages - UINT32 CurrentLengthOfNonImmBuffer; // the current size of the buffer for accumulating non-immadiate messages + UINT64 BufferForMultipleNonImmediateMessage; // Start address of the buffer for accumulating non-immediate messages + UINT32 CurrentLengthOfNonImmBuffer; // the current size of the buffer for accumulating non-immediate messages // // Regular buffers @@ -101,19 +101,19 @@ typedef struct _LOG_BUFFER_INFORMATION * @brief Global Variable for buffer on all cores * */ -LOG_BUFFER_INFORMATION * MessageBufferInformation; +LOG_BUFFER_INFORMATION * g_MessageBufferInformation; /** * @brief Vmx-root lock for logging * */ -volatile LONG VmxRootLoggingLock; +volatile LONG g_VmxRootLoggingLock; /** * @brief Vmx-root lock for logging * */ -volatile LONG VmxRootLoggingLockForNonImmBuffers; +volatile LONG g_VmxRootLoggingLockForNonImmBuffers; ////////////////////////////////////////////////// // Illustration // diff --git a/hyperdbg/hyperlog/header/UnloadDll.h b/hyperdbg/hyperlog/header/UnloadDll.h index c6388ac7..b4801b98 100644 --- a/hyperdbg/hyperlog/header/UnloadDll.h +++ b/hyperdbg/hyperlog/header/UnloadDll.h @@ -17,4 +17,4 @@ __declspec(dllexport) NTSTATUS DllInitialize(_In_ PUNICODE_STRING RegistryPath); -__declspec(dllexport) NTSTATUS DllUnload(void); +__declspec(dllexport) NTSTATUS DllUnload(VOID); diff --git a/hyperdbg/hyperlog/header/pch.h b/hyperdbg/hyperlog/header/pch.h index 773e3b12..17cd5fec 100644 --- a/hyperdbg/hyperlog/header/pch.h +++ b/hyperdbg/hyperlog/header/pch.h @@ -9,10 +9,51 @@ * @copyright This project is released under the GNU Public License v3. * */ + #pragma once +#define _NO_CRT_STDIO_INLINE + #pragma warning(disable : 4201) // Suppress nameless struct/union warning -#include +// +// Environment headers +// +#include "platform/general/header/Environment.h" + +#ifdef HYPERDBG_ENV_WINDOWS + +// +// Windows defined functions +// +# include +# include +# include + +#endif // HYPERDBG_ENV_WINDOWS + +// +// Scope definitions +// +#define HYPERDBG_KERNEL_MODE +#define HYPERDBG_HYPER_LOG #include "UnloadDll.h" +#include "SDK/HyperDbgSdk.h" +#include "SDK/modules/HyperLog.h" +#include "SDK/imports/kernel/HyperDbgHyperLogImports.h" +#include "components/spinlock/header/Spinlock.h" +#include "Logging.h" + +// +// Platform independent headers +// +#include "platform/kernel/header/PlatformCpu.h" +#include "platform/kernel/header/PlatformDbg.h" +#include "platform/kernel/header/PlatformDpc.h" +#include "platform/kernel/header/PlatformEvent.h" +#include "platform/kernel/header/PlatformIo.h" +#include "platform/kernel/header/PlatformIrql.h" +#include "platform/kernel/header/PlatformMem.h" +#include "platform/kernel/header/PlatformSpinlock.h" +#include "platform/kernel/header/PlatformTime.h" diff --git a/hyperdbg/hyperlog/hyperlog.inf b/hyperdbg/hyperlog/hyperlog.inf deleted file mode 100644 index 8601163e..00000000 --- a/hyperdbg/hyperlog/hyperlog.inf +++ /dev/null @@ -1,77 +0,0 @@ -; -; hyperlog.inf -; - -[Version] -Signature="$WINDOWS NT$" -Class=System ; TODO: specify appropriate Class -ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} ; TODO: specify appropriate ClassGuid -Provider=%ManufacturerName% -CatalogFile=hyperlog.cat -DriverVer= ; TODO: set DriverVer in stampinf property pages -PnpLockdown=1 - -[DestinationDirs] -DefaultDestDir = 12 -hyperlog_Device_CoInstaller_CopyFiles = 11 - -[SourceDisksNames] -1 = %DiskName%,,,"" - -[SourceDisksFiles] -hyperlog.sys = 1,, -WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames - -;***************************************** -; Install Section -;***************************************** - -[Manufacturer] -%ManufacturerName%=Standard,NT$ARCH$ - -[Standard.NT$ARCH$] -%hyperlog.DeviceDesc%=hyperlog_Device, Root\hyperlog ; TODO: edit hw-id - -[hyperlog_Device.NT] -CopyFiles=Drivers_Dir - -[Drivers_Dir] -hyperlog.sys - -;-------------- Service installation -[hyperlog_Device.NT.Services] -AddService = hyperlog,%SPSVCINST_ASSOCSERVICE%, hyperlog_Service_Inst - -; -------------- hyperlog driver install sections -[hyperlog_Service_Inst] -DisplayName = %hyperlog.SVCDESC% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 1 ; SERVICE_ERROR_NORMAL -ServiceBinary = %12%\hyperlog.sys - -; -;--- hyperlog_Device Coinstaller installation ------ -; - -[hyperlog_Device.NT.CoInstallers] -AddReg=hyperlog_Device_CoInstaller_AddReg -CopyFiles=hyperlog_Device_CoInstaller_CopyFiles - -[hyperlog_Device_CoInstaller_AddReg] -HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" - -[hyperlog_Device_CoInstaller_CopyFiles] -WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll - -[hyperlog_Device.NT.Wdf] -KmdfService = hyperlog, hyperlog_wdfsect -[hyperlog_wdfsect] -KmdfLibraryVersion = $KMDFVERSION$ - -[Strings] -SPSVCINST_ASSOCSERVICE= 0x00000002 -ManufacturerName="" ;TODO: Replace with your manufacturer name -DiskName = "hyperlog Installation Disk" -hyperlog.DeviceDesc = "hyperlog Device" -hyperlog.SVCDESC = "hyperlog Service" diff --git a/hyperdbg/hyperlog/hyperlog.vcxproj b/hyperdbg/hyperlog/hyperlog.vcxproj index 31875ca9..5e0ba787 100644 --- a/hyperdbg/hyperlog/hyperlog.vcxproj +++ b/hyperdbg/hyperlog/hyperlog.vcxproj @@ -1,5 +1,8 @@  + + + debug @@ -27,7 +30,7 @@ WindowsKernelModeDriver10.0 DynamicLibrary KMDF - Universal + Desktop false @@ -36,7 +39,7 @@ WindowsKernelModeDriver10.0 DynamicLibrary KMDF - Universal + Desktop false @@ -66,6 +69,9 @@ $(SolutionDir)\include;$(ProjectDir)header;%(AdditionalIncludeDirectories) true + Create + pch.h + stdcpp20 true @@ -81,6 +87,10 @@ $(SolutionDir)\include;$(ProjectDir)header;%(AdditionalIncludeDirectories) true + Create + pch.h + stdcpp20 + Full true @@ -89,24 +99,51 @@ hyperlog.def - - - + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/hyperdbg/hyperlog/hyperlog.vcxproj.filters b/hyperdbg/hyperlog/hyperlog.vcxproj.filters index 8019ed0c..b7765775 100644 --- a/hyperdbg/hyperlog/hyperlog.vcxproj.filters +++ b/hyperdbg/hyperlog/hyperlog.vcxproj.filters @@ -13,11 +13,12 @@ {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd - - - - Driver Files - + + {1ab177b4-9e6c-460e-834a-8fced04b42a3} + + + {21f0281e-fc2a-4e13-97ac-e4b35a05a31e} + @@ -29,6 +30,33 @@ code + + code\platform + + + code\platform + + + code\platform + + + code\platform + + + code\platform + + + code\platform + + + code\platform + + + code\platform + + + code\platform + @@ -43,5 +71,32 @@ header + + header\platform + + + header\platform + + + header\platform + + + header\platform + + + header\platform + + + header\platform + + + header\platform + + + header\platform + + + + \ No newline at end of file diff --git a/hyperdbg/hyperlog/packages.config b/hyperdbg/hyperlog/packages.config new file mode 100644 index 00000000..eb276766 --- /dev/null +++ b/hyperdbg/hyperlog/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/hyperdbg/hyperperf/CMakeLists.txt b/hyperdbg/hyperperf/CMakeLists.txt new file mode 100644 index 00000000..d6b1310f --- /dev/null +++ b/hyperdbg/hyperperf/CMakeLists.txt @@ -0,0 +1,22 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "../include/components/spinlock/code/Spinlock.c" + "../include/platform/kernel/code/PlatformMem.c" + "code/Logging.c" + "code/UnloadDll.c" + "../include/components/spinlock/header/Spinlock.h" + "../include/platform/kernel/header/Environment.h" + "../include/platform/kernel/header/PlatformMem.h" + "header/Logging.h" + "header/pch.h" + "header/UnloadDll.h" + "hyperperf.def" +) +include_directories( + "../include" + "header" +) +wdk_add_library(hyperperf SHARED + KMDF 1.15 + ${SourceFiles} +) diff --git a/hyperdbg/hyperperf/code/api/PerfApi.c b/hyperdbg/hyperperf/code/api/PerfApi.c new file mode 100644 index 00000000..59cef4c4 --- /dev/null +++ b/hyperdbg/hyperperf/code/api/PerfApi.c @@ -0,0 +1,84 @@ +/** + * @file PerfApi.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief PMU routines for HyperPerf module + * @details + * @version 0.21 + * @date 2026-06-22 + * + * @copyright This project is released under the GNU Public License v3. + */ +#include "pch.h" + +/** + * @brief Initialize the hyperperf module callbacks + * @details This only for callback initialization, not for PMU, etc. initialization + * + * @param HyperPerfCallbacks Pointer to the HyperPerf callbacks structure to be registered + * @param RunningOnHypervisorEnvironment Whether the initialization is being done for hypervisor environment or not, + * it can be used to skip some of the initialization steps if it is not for hypervisor environment and behave differently based on that + * + * @return BOOLEAN + */ +BOOLEAN +HyperPerfInitCallback(HYPERPERF_CALLBACKS * HyperPerfCallbacks, + BOOLEAN RunningOnHypervisorEnvironment) +{ + // + // Check if any of the required callbacks are NULL + // + for (UINT32 i = 0; i < sizeof(HYPERPERF_CALLBACKS) / sizeof(UINT64); i++) + { + if (((PVOID *)HyperPerfCallbacks)[i] == NULL) + { + // + // The callback has null entry, so we cannot proceed + // + return FALSE; + } + } + + // + // Save the callbacks + // + PlatformWriteMemory(&g_Callbacks, HyperPerfCallbacks, sizeof(HYPERPERF_CALLBACKS)); + + // + // Set the flag to indicate whether the initialization is being done for hypervisor environment or not + // + g_RunningOnHypervisorEnvironment = RunningOnHypervisorEnvironment; + + // + // Enable callbacks and set the initialized flag + // + g_HyperPerfCallbacksInitialized = TRUE; + + return TRUE; +} + +/** + * @brief Uninitialize the hypertrace module + * + * @return VOID + */ +VOID +HyperPerfUninit() +{ + // + // Check if the callbacks are initialized, if not, we don't need to handle anymore + // + if (!g_HyperPerfCallbacksInitialized) + { + return; + } + + // + // Reset the environment flag to default value + // + g_RunningOnHypervisorEnvironment = FALSE; + + // + // Set callbacks to not initialized + // + g_HyperPerfCallbacksInitialized = FALSE; +} diff --git a/hyperdbg/hyperperf/code/broadcast/Broadcast.c b/hyperdbg/hyperperf/code/broadcast/Broadcast.c new file mode 100644 index 00000000..ad97bd34 --- /dev/null +++ b/hyperdbg/hyperperf/code/broadcast/Broadcast.c @@ -0,0 +1,26 @@ +/** + * @file Broadcast.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Broadcasting functions + * @details + * @version 0.21 + * @date 2026-06-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Routines to enable LBR on all cores + * + * @return VOID + */ +VOID +BroadcastEnableLbrOnAllCores() +{ + // + // Broadcast to all cores + // + KeGenericCallDpc(DpcRoutineTestPmu, NULL); +} diff --git a/hyperdbg/hyperperf/code/broadcast/DpcRoutines.c b/hyperdbg/hyperperf/code/broadcast/DpcRoutines.c new file mode 100644 index 00000000..f5443618 --- /dev/null +++ b/hyperdbg/hyperperf/code/broadcast/DpcRoutines.c @@ -0,0 +1,35 @@ +/** + * @file DpcRoutines.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief DPC routines + * @details + * @version 0.21 + * @date 2026-06-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Broadcast enabling LBR + * + * @param Dpc + * @param DeferredContext + * @param SystemArgument1 + * @param SystemArgument2 + * @return BOOLEAN + */ +BOOLEAN +DpcRoutineTestPmu(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} diff --git a/hyperdbg/hyperperf/code/common/UnloadDll.c b/hyperdbg/hyperperf/code/common/UnloadDll.c new file mode 100644 index 00000000..17321dbf --- /dev/null +++ b/hyperdbg/hyperperf/code/common/UnloadDll.c @@ -0,0 +1,45 @@ +/** + * @file UnloadDll.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Unloading DLL in the target Windows + * @details + * @version 0.4 + * @date 2023-07-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// We'll add these functions, so whenever HyperDbg's driver is unloaded +// DllUnload will be called to unload this dll from the memory. +// this way we can remove the HyperDbg after unloading as there is no +// 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) +{ + UNREFERENCED_PARAMETER(RegistryPath); + + return STATUS_SUCCESS; +} + +/** + * @brief Routine called on DLL unload + * + * @return NTSTATUS + */ +NTSTATUS +DllUnload(VOID) +{ + return STATUS_SUCCESS; +} diff --git a/hyperdbg/hyperperf/header/api/PerfApi.h b/hyperdbg/hyperperf/header/api/PerfApi.h new file mode 100644 index 00000000..660f4d20 --- /dev/null +++ b/hyperdbg/hyperperf/header/api/PerfApi.h @@ -0,0 +1,19 @@ +/** + * @file PerfApi.h + * @author + * @brief Header for general PMU routines for HyperPerf module + * @details + * @version 0.21 + * @date 2026-06-22 + * + * @copyright This project is released under the GNU Public License v3. + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +// +// Most of the functions are defined and exported +// diff --git a/hyperdbg/hyperperf/header/broadcast/Broadcast.h b/hyperdbg/hyperperf/header/broadcast/Broadcast.h new file mode 100644 index 00000000..8698872f --- /dev/null +++ b/hyperdbg/hyperperf/header/broadcast/Broadcast.h @@ -0,0 +1,20 @@ + +/** + * @file Broadcast.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for broadcasting functions + * @details + * @version 0.21 + * @date 2026-06-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +BroadcastTestPmuOnAllCores(); diff --git a/hyperdbg/hyperperf/header/broadcast/DpcRoutines.h b/hyperdbg/hyperperf/header/broadcast/DpcRoutines.h new file mode 100644 index 00000000..397ef8b1 --- /dev/null +++ b/hyperdbg/hyperperf/header/broadcast/DpcRoutines.h @@ -0,0 +1,20 @@ + +/** + * @file DpcRoutines.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Definition for DPC functions + * @details + * @version 0.21 + * @date 2026-06-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +DpcRoutineTestPmu(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); diff --git a/hyperdbg/hyperperf/header/common/UnloadDll.h b/hyperdbg/hyperperf/header/common/UnloadDll.h new file mode 100644 index 00000000..9bb252d2 --- /dev/null +++ b/hyperdbg/hyperperf/header/common/UnloadDll.h @@ -0,0 +1,22 @@ +/** + * @file UnloadDll.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for unloading DLL in the target Windows + * + * @version 0.4 + * @date 2023-07-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Exported Functions // +////////////////////////////////////////////////// + +__declspec(dllexport) NTSTATUS +DllInitialize(_In_ PUNICODE_STRING RegistryPath); + +__declspec(dllexport) NTSTATUS + DllUnload(VOID); diff --git a/hyperdbg/hyperperf/header/globals/GlobalVariables.h b/hyperdbg/hyperperf/header/globals/GlobalVariables.h new file mode 100644 index 00000000..79c0f02e --- /dev/null +++ b/hyperdbg/hyperperf/header/globals/GlobalVariables.h @@ -0,0 +1,35 @@ + +/** + * @file GlobalVariables.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Definition for global variables + * @details + * @version 0.21 + * @date 2026-06-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Global Variables // +////////////////////////////////////////////////// + +/** + * @brief List of callbacks + * + */ +HYPERPERF_CALLBACKS g_Callbacks; + +/** + * @brief The flag indicating whether the hyperperf module callbacks is initialized or not + * + */ +BOOLEAN g_HyperPerfCallbacksInitialized; + +/** + * @brief The flag indicating whether the initialization is being done for hypervisor environment or not + * + */ +BOOLEAN g_RunningOnHypervisorEnvironment; diff --git a/hyperdbg/hyperperf/header/pch.h b/hyperdbg/hyperperf/header/pch.h new file mode 100644 index 00000000..35e14b66 --- /dev/null +++ b/hyperdbg/hyperperf/header/pch.h @@ -0,0 +1,111 @@ + +/** + * @file pch.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers of Message logging and tracing + * @details + * @version 0.21 + * @date 2026-06-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#define _NO_CRT_STDIO_INLINE + +#pragma warning(disable : 4201) // Suppress nameless struct/union warning + +// +// Environment headers +// +#include "platform/general/header/Environment.h" + +#ifdef HYPERDBG_ENV_WINDOWS + +// +// Windows defined functions +// +# include +# include +# include + +#endif // HYPERDBG_ENV_WINDOWS + +// +// Scope definitions +// +#define HYPERDBG_KERNEL_MODE +#define HYPERDBG_HYPERPERF + +// +// Add ia32-doc +// +#include "ia32-doc/out/ia32.h" + +// +// SDK headers +// +#include "SDK/HyperDbgSdk.h" + +// +// Configuration +// +#include "config/Configuration.h" + +// +// Platform independent headers +// +#include "platform/kernel/header/PlatformMem.h" +#include "platform/kernel/header/PlatformIntrinsics.h" +#include "platform/kernel/header/PlatformBroadcast.h" +#include "platform/kernel/header/PlatformCpu.h" +#include "platform/kernel/header/PlatformSpinlock.h" +#include "platform/kernel/header/PlatformIrql.h" +#include "platform/kernel/header/PlatformDpc.h" +#include "platform/kernel/header/PlatformTime.h" +#include "platform/kernel/header/PlatformDbg.h" +#include "platform/kernel/header/PlatformIo.h" +#include "platform/kernel/header/PlatformEvent.h" + +// +// Unload function (to be called when the driver is unloaded) +// +#include "common/UnloadDll.h" + +// +// Hyperlog headers +// +#include "components/callback/header/HyperLogCallback.h" +#include "SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h" + +// +// Spinlock headers +// +#include "components/spinlock/header/Spinlock.h" + +// +// HyperPerf Callbacks +// +#include "SDK/modules/HyperPerf.h" + +// +// Definition of general tracing types +// +#include "api/PerfApi.h" + +// +// DPC and broadcasting function headers +// +#include "broadcast/DpcRoutines.h" +#include "broadcast/Broadcast.h" + +// +// Export functions +// +#include "SDK/imports/kernel/HyperDbgHyperPerf.h" + +// +// Global variables +// +#include "globals/GlobalVariables.h" diff --git a/hyperdbg/hyperperf/header/pt/Pt.h b/hyperdbg/hyperperf/header/pt/Pt.h new file mode 100644 index 00000000..07a10506 --- /dev/null +++ b/hyperdbg/hyperperf/header/pt/Pt.h @@ -0,0 +1,167 @@ +/** + * @file Pt.h + * @author Masoud Rahimi Jafari (Masoodrahimy1379@gmail.com) + * @brief Header for Processor Trace (PT) tracing routines for HyperTrace module + * @details Engine that programs Intel PT MSRs from VMX root or kernel context. + * Buffer / ToPA management is kept here; user-visible PT structures + * live in the SDK header [PtDefinitions.h]. + * @version 0.19 + * @date 2026-04-29 + * + * @copyright This project is released under the GNU Public License v3. + */ +#pragma once + +////////////////////////////////////////////////// +// Constants // +////////////////////////////////////////////////// + +// +// Pool tag for PT contiguous allocations (ASCII "PtHd") +// +#define POOL_TAG_PT 'dHtP' + +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +/** + * @brief Narrow input descriptor for PtFilter. + * + * These are the only fields a caller is allowed to set per-CPU + * when reconfiguring an active PT trace. Engine-internal options + * (BranchEn, TscEn, MtcEn, CycEn, RetCompression, *Freq, etc.) + * stay under the engine's control and are NOT exposed here. + * + * BufferSize == 0 means "keep whatever the per-CPU slot already + * has" — pure filter changes don't touch the ToPA / output / + * overflow buffers and can run from a DPC. + */ +typedef struct _PT_FILTER_OPTIONS +{ + BOOLEAN TraceUser; + BOOLEAN TraceKernel; + UINT64 TargetCr3; + UINT64 BufferSize; + UINT32 NumAddrRanges; + PT_ADDR_RANGE AddrRanges[PT_MAX_ADDR_RANGES]; + +} PT_FILTER_OPTIONS, *PPT_FILTER_OPTIONS; + +/** + * @brief Per-CPU bookkeeping for the user-mode mmap surface. + * + * One MDL + user VA per CPU describes the main output buffer + * immediately followed by the 4 KB overflow page as a single + * virtually contiguous region in the mapping process. Lives in + * g_PtUserMappings; lifetime tied to the PT enable cycle. + */ +typedef struct _PT_USER_MAPPING +{ + PMDL Mdl; + PVOID UserVa; + +} PT_USER_MAPPING, *PPT_USER_MAPPING; + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +// +// HyperDbg-style wrappers (mirroring Lbr*) +// + +BOOLEAN +PtCheck(); + +BOOLEAN +PtStart(); + +VOID +PtStop(); + +VOID +PtPause(); + +VOID +PtResume(); + +UINT64 +PtSize(); + +VOID +PtDump(); + +VOID +PtFlush(); + +// +// LBR-style filter wrapper, one CPU at a time. Mirrors LbrFilter in shape: +// caller passes a PT_FILTER_OPTIONS describing only the user-tunable bits +// (TraceUser, TraceKernel, TargetCr3, BufferSize, NumAddrRanges, AddrRanges), +// and PtFilter handles the stop / config-update / start sequence on the +// CURRENT CPU. Engine-internal config (BranchEn, TscEn, etc.) is left +// untouched in the per-CPU PT_TRACE_CONFIG. +// +VOID +PtFilter(const PT_FILTER_OPTIONS * FilterOptions); + +// +// PASSIVE_LEVEL helpers — call before / after the per-core DPC broadcasts. +// Required because MmAllocateContiguousMemorySpecifyCache and +// MmFreeContiguousMemory must run at IRQL == PASSIVE_LEVEL. +// + +BOOLEAN +PtAllocateAllCpuBuffers(); + +VOID +PtFreeAllCpuBuffers(); + +// +// User-mode mmap surface: map every per-CPU main output + overflow +// buffer into the calling user process. Idempotent within an enable +// cycle; torn down by PtFreeAllCpuBuffers (i.e. PT disable / flush). +// +INT32 +PtMmapAllCpuBuffersToUser(PT_USER_BUFFER_DESC * OutDescs, UINT32 MaxDescs, UINT32 * OutNumCpus); + +VOID +PtUnmapAllCpuBuffersFromUser(); + +// +// Engine routines (operate on a specific PT_PER_CPU instance) +// + +INT32 +PtEngineQueryCapabilities(PT_CAPABILITIES * OutCaps); + +VOID +PtEngineInitDefaultConfig(PT_TRACE_CONFIG * Config); + +INT32 +PtEngineAllocateBuffers(PT_PER_CPU * Cpu, const PT_TRACE_CONFIG * Config); + +VOID +PtEngineFreeBuffers(PT_PER_CPU * Cpu); + +INT32 +PtEngineStart(PT_PER_CPU * Cpu); + +UINT64 +PtEngineStop(PT_PER_CPU * Cpu, PT_OUTPUT_BUFFER * Out); + +INT32 +PtEnginePause(PT_PER_CPU * Cpu); + +INT32 +PtEngineResume(PT_PER_CPU * Cpu); + +UINT64 +PtEngineHandlePmi(PT_PER_CPU * Cpu, PT_OUTPUT_BUFFER * Out); + +BOOLEAN +PtEngineIsPtPmi(); + +INT32 +PtEngineSizeToTopaEncoding(UINT64 SizeInBytes); diff --git a/hyperdbg/hyperperf/hyperperf.def b/hyperdbg/hyperperf/hyperperf.def new file mode 100644 index 00000000..1415f880 --- /dev/null +++ b/hyperdbg/hyperperf/hyperperf.def @@ -0,0 +1,6 @@ +LIBRARY hyperperf + +EXPORTS + + DllInitialize PRIVATE + DllUnload PRIVATE \ No newline at end of file diff --git a/hyperdbg/hyperperf/hyperperf.vcxproj b/hyperdbg/hyperperf/hyperperf.vcxproj new file mode 100644 index 00000000..20624659 --- /dev/null +++ b/hyperdbg/hyperperf/hyperperf.vcxproj @@ -0,0 +1,145 @@ + + + + + + + + debug + x64 + + + release + x64 + + + + {360E54B1-0B92-4BCA-8111-4BF384292621} + {1bc93793-694f-48fe-9372-81e2b05556fd} + v4.5 + 12.0 + Debug + x64 + hyperperf + $(LatestTargetPlatformVersion) + + + + Windows10 + true + WindowsKernelModeDriver10.0 + DynamicLibrary + KMDF + Desktop + false + + + Windows10 + false + WindowsKernelModeDriver10.0 + DynamicLibrary + KMDF + Desktop + false + + + + + + + + + + + DbgengKernelDebugger + $(SolutionDir)build\bin\$(Configuration)\ + $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + false + + + DbgengKernelDebugger + $(SolutionDir)build\bin\$(Configuration)\ + $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + false + + + + sha256 + + + $(SolutionDir)\include;$(ProjectDir)header;$(SolutionDir)dependencies;%(AdditionalIncludeDirectories) + true + Create + pch.h + stdcpp20 + + + true + + true + hyperperf.def + + + + + sha256 + + + $(SolutionDir)\include;$(ProjectDir)header;$(SolutionDir)dependencies;%(AdditionalIncludeDirectories) + true + Create + pch.h + stdcpp20 + Full + + + true + + true + hyperperf.def + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + \ No newline at end of file diff --git a/hyperdbg/hyperperf/hyperperf.vcxproj.filters b/hyperdbg/hyperperf/hyperperf.vcxproj.filters new file mode 100644 index 00000000..d4254192 --- /dev/null +++ b/hyperdbg/hyperperf/hyperperf.vcxproj.filters @@ -0,0 +1,119 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {1ab177b4-9e6c-460e-834a-8fced04b42a3} + + + {21f0281e-fc2a-4e13-97ac-e4b35a05a31e} + + + {09d5457a-bade-4a3f-a171-641110492d57} + + + {b8b32a09-61fb-433a-ad79-eb7cfc5f3437} + + + {32ea8333-847b-443d-8992-4140d54dc1d3} + + + {df6eb164-34b2-4f2a-9530-b88443662fb7} + + + {cb4e742a-6e43-4798-af4a-72bcb11089c9} + + + {ab21116d-5f5b-4ef8-82bb-6585ac3dec95} + + + {57d56081-eede-41a3-b9f0-e7019d32c986} + + + {4f62540b-d186-479e-83a0-1b550134f487} + + + {9fe877a7-e261-4579-9752-a3156b6e69d9} + + + {8bc2336a-b1c5-4e93-9793-23a5cfdc741d} + + + {fc73555b-2be3-4898-bcdb-df83fa3e1388} + + + + + code\platform + + + code\broadcast + + + code\broadcast + + + code\common + + + code\api + + + code\platform + + + code\broadcast + + + code\platform + + + code\components\callback + + + + + header\platform + + + header\broadcast + + + header\broadcast + + + header\common + + + header\globals + + + header\api + + + header\platform + + + header\platform + + + header\platform + + + header\components\callback + + + header + + + + + + \ No newline at end of file diff --git a/hyperdbg/hyperperf/packages.config b/hyperdbg/hyperperf/packages.config new file mode 100644 index 00000000..eb276766 --- /dev/null +++ b/hyperdbg/hyperperf/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/hyperdbg/hypertrace/CMakeLists.txt b/hyperdbg/hypertrace/CMakeLists.txt new file mode 100644 index 00000000..ec2c68bb --- /dev/null +++ b/hyperdbg/hypertrace/CMakeLists.txt @@ -0,0 +1,22 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "../include/components/spinlock/code/Spinlock.c" + "../include/platform/kernel/code/PlatformMem.c" + "code/Logging.c" + "code/UnloadDll.c" + "../include/components/spinlock/header/Spinlock.h" + "../include/platform/kernel/header/Environment.h" + "../include/platform/kernel/header/PlatformMem.h" + "header/Logging.h" + "header/pch.h" + "header/UnloadDll.h" + "hypertrace.def" +) +include_directories( + "../include" + "header" +) +wdk_add_library(hypertrace SHARED + KMDF 1.15 + ${SourceFiles} +) diff --git a/hyperdbg/hypertrace/code/api/LbrApi.c b/hyperdbg/hypertrace/code/api/LbrApi.c new file mode 100644 index 00000000..f0e92040 --- /dev/null +++ b/hyperdbg/hypertrace/code/api/LbrApi.c @@ -0,0 +1,586 @@ +/** + * @file LbrApi.c + * @author Hari Mishal (harimishal6@gmail.com) + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Tracing routines for HyperTrace module (Intel Last Branch Record) + * @details + * @version 0.18 + * @date 2025-12-02 + * + * @copyright This project is released under the GNU Public License v3. + */ +#include "pch.h" + +/** + * @brief Example of performing LBR trace + * + * @return VOID + */ +VOID +HyperTraceLbrExamplePerformTrace() +{ + if (LbrStart(LBR_SELECT_WITHOUT_FILTER)) + { + for (volatile int i = 0; i < 50; i++) + { + if (i % 2) + { + INT A = i * 2; + A += 5; + } + else + { + CpuNop(); + CpuNop(); + } + } + + LogInfo("Dumping LBR Buffer...\n"); + + LbrStop(); + LbrPrint(); // This will print the collected LBR branches to the log + } +} + +/** + * @brief Query the state of LBR save and load VM exit and entry controls + * + * @param CoreId The index of the processor core to query + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrQueryStateOfLbrSaveAndLoadVmExitAndEntryControls(UINT32 CoreId) +{ + UNREFERENCED_PARAMETER(CoreId); // Right now there is no core specifc controls for LBR + + return g_LastBranchRecordEnabled; +} + +/** + * @brief Set the kernel status in the HyperTrace LBR operation request structure + * + * @param HyperTraceLbrOperationRequest Pointer to the HyperTrace LBR operation request packet + * @param Status The kernel status code to write into the request + * + * @return VOID + */ +VOID +HyperTraceLbrSetKernelStatus( + HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceLbrOperationRequest, + UINT32 Status) +{ + if (HyperTraceLbrOperationRequest != NULL) + { + HyperTraceLbrOperationRequest->KernelStatus = Status; + } +} + +/** + * @brief Set the kernel status in the HyperTrace LBR dump operation request structure + * + * @param HyperTraceLbrDumpOperationRequest Pointer to the HyperTrace LBR dump operation request packet + * @param Status The kernel status code to write into the request + * + * @return VOID + */ +VOID +HyperTraceLbrDumpSetKernelStatus( + HYPERTRACE_LBR_DUMP_PACKETS * HyperTraceLbrDumpOperationRequest, + UINT32 Status) +{ + if (HyperTraceLbrDumpOperationRequest != NULL) + { + HyperTraceLbrDumpOperationRequest->KernelStatus = Status; + } +} + +/** + * @brief Check if LBR is supported and enabled on the current core + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrCheck() +{ + // + // Only check LBR once it is already initialized + // + if (!g_LastBranchRecordEnabled) + { + return FALSE; + } + + return LbrCheck(); +} + +/** + * @brief Restore (re-enable) LBR collection on the current core with the specified filter options + * @param FilterOptions A bitmask of filter options to apply to the LBR branches + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrRestoreByFilter(UINT64 FilterOptions) +{ + // + // Only restore (re-enable) LBR once it is already initialized + // + if (!g_LastBranchRecordEnabled) + { + return FALSE; + } + + return LbrStart(FilterOptions); +} + +/** + * @brief Restore (re-enable) LBR collection on the current core with previous filter options + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrRestore() +{ + return HyperTraceLbrRestoreByFilter(g_LbrFilterOptions); +} + +/** + * @brief Check if LBR is supported on the current CPU and get its capacity + * + * @param Capacity Pointer to a variable to receive the LBR capacity (number of entries) + * @param IsArchLbr Pointer to a variable to receive whether the supported LBR is architectural LBR or not (legacy LBR) + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrIsSupported(UINT32 * Capacity, BOOLEAN * IsArchLbr) +{ + // + // Check for ARCHITECTURAL LBR support first, if not supported then check for LEGACY LBR support + // + if (!LbrCheckAndReadArchitecturalLbrDetails()) + { + // + // If the CPU does not support architectural LBR, we can check for legacy LBR support as a fallback + // + if (!LbrCheckAndReadLegacyLbrDetails()) + { + return FALSE; + } + } + + // + // Set capacity when the pointer is valid + // + if (Capacity != NULL) + { + *Capacity = (UINT32)g_LbrCapacity; + } + + // + // Set IsArchLbr when the pointer is valid + // + if (IsArchLbr != NULL) + { + *IsArchLbr = g_ArchBasedLastBranchRecord; + } + + return TRUE; +} + +/** + * @brief Enable LBR tracing for HyperTrace + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrEnable(HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + // + // Check if LBR is already enabled or not + // + // We allow re-enabling LBR even if it is already enabled to support scenarios where + // the LBR is deactivated as a result of a #DB and wants to re-enable it again + /* + if (g_LastBranchRecordEnabled) + { + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_ERROR_LBR_ALREADY_ENABLED); + return FALSE; + } + */ + + // + // Check for ARCHITECTURAL LBR support first, if not supported then check for LEGACY LBR support + // + if (!LbrCheckAndReadArchitecturalLbrDetails()) + { + // + // If the CPU does not support architectural LBR, we can check for legacy LBR support as a fallback + // + if (!LbrCheckAndReadLegacyLbrDetails()) + { + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_ERROR_LBR_NOT_SUPPORTED); + return FALSE; + } + } + + // + // Check VMCS support for LBR if the initialization is being done for hypervisor environment + // + if (g_RunningOnHypervisorEnvironment) + { + if ((g_ArchBasedLastBranchRecord && !g_Callbacks.VmFuncCheckCpuSupportForLoadAndClearGuestIa32LbrCtlControls()) || + (!g_ArchBasedLastBranchRecord && !g_Callbacks.VmFuncCheckCpuSupportForSaveAndLoadDebugControls())) + { + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_ERROR_LBR_NOT_SUPPORTED_ON_VMCS); + return FALSE; + } + } + + // + // Broadcast enabling LBR on all cores + // + BroadcastEnableLbrOnAllCores(); + + // + // Check if LBR is enabled or not (for example in VMs, LBR flags are usually masked) + // + if (!LbrCheck()) + { + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_ERROR_LBR_NOT_SUPPORTED); + return FALSE; + } + + // + // Set the flag to indicate that LBR tracing is enabled + // + g_LastBranchRecordEnabled = TRUE; + + // + // Set successful status + // + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_OPERATION_WAS_SUCCESSFUL); + + return TRUE; +} + +/** + * @brief Disable LBR tracing for HyperTrace + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrDisable(HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + // + // Check if LBR is already disabled or not + // + if (!g_LastBranchRecordEnabled) + { + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_ERROR_LBR_ALREADY_DISABLED); + return FALSE; + } + + // + // Disabling LBR + // + g_LastBranchRecordEnabled = FALSE; + + // + // Broadcast disabling LBR on all cores + // + BroadcastDisableLbrOnAllCores(); + + // + // Set successful status + // + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_OPERATION_WAS_SUCCESSFUL); + + return TRUE; +} + +/** + * @brief Flush LBR tracing for HyperTrace + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrFlush(HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + // + // Check if LBR is already disabled or not + // + if (!g_LastBranchRecordEnabled) + { + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_ERROR_LBR_ALREADY_DISABLED); + return FALSE; + } + + // + // Disabling LBR + // + g_LastBranchRecordEnabled = FALSE; + + // + // Broadcast flushing LBR on all cores + // + BroadcastFlushLbrOnAllCores(); + + // + // Set successful status + // + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_OPERATION_WAS_SUCCESSFUL); + + return TRUE; +} + +/** + * @brief Save LBR tracing for HyperTrace + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrSave(HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + // + // Check if LBR is already disabled or not + // + if (!g_LastBranchRecordEnabled) + { + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_ERROR_LBR_ALREADY_DISABLED); + return FALSE; + } + + // LogInfo("Saving LBR Buffer...\n"); + + // + // Save the LBR state + // + LbrSave(); + + // + // The operation was successful + // + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_OPERATION_WAS_SUCCESSFUL); + + return TRUE; +} + +/** + * @brief Print LBR tracing for HyperTrace + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrPrint(HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + // + // Check if LBR is already disabled or not + // + if (!g_LastBranchRecordEnabled) + { + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_ERROR_LBR_ALREADY_DISABLED); + return FALSE; + } + + // LogInfo("Dumping LBR Buffer...\n"); + + // + // Save the LBR state + // + LbrSave(); + + // + // This will print the collected LBR branches to the log + // + LbrPrint(); + + // + // The operation was successful + // + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_OPERATION_WAS_SUCCESSFUL); + + return TRUE; +} + +/** + * @brief Update LBR filter options for HyperTrace + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrUpdateFilterOptions(HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + // + // Check if LBR is already disabled or not + // + if (!g_LastBranchRecordEnabled) + { + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_ERROR_LBR_ALREADY_DISABLED); + return FALSE; + } + + // + // Update the LBR filter options based on the request + // + BroadcastFilterLbrOptionsOnAllCores((UINT64)HyperTraceOperationRequest->LbrFilterOptions); + + // + // The operation was successful + // + HyperTraceLbrSetKernelStatus(HyperTraceOperationRequest, DEBUGGER_OPERATION_WAS_SUCCESSFUL); + + return TRUE; +} + +/** + * @brief Perform actions related to HyperTrace LBR dumping + * + * @param LbrDumpRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrPerformDump(HYPERTRACE_LBR_DUMP_PACKETS * LbrDumpRequest) +{ + ULONG ProcessorsCount; + + // + // Check if LBR is enabled or not before dumping + // + if (!g_LastBranchRecordEnabled) + { + HyperTraceLbrDumpSetKernelStatus(LbrDumpRequest, DEBUGGER_ERROR_LBR_ALREADY_DISABLED); + return FALSE; + } + + // + // Get the number of processors in the system to validate the requested core id for dumping + // + ProcessorsCount = KeQueryActiveProcessorCount(0); + + // + // Check if core id is valid + // + if (LbrDumpRequest->CoreId >= ProcessorsCount) + { + HyperTraceLbrDumpSetKernelStatus(LbrDumpRequest, DEBUGGER_ERROR_INVALID_CORE_ID); + return FALSE; + } + + // + // Check if next core is valid in the case of dumping all cores + // + if (LbrDumpRequest->CoreId == ProcessorsCount - 1) + { + LbrDumpRequest->NextCoreIsValid = FALSE; + } + else + { + LbrDumpRequest->NextCoreIsValid = TRUE; + } + + // + // Set ARCH or LEGACY LBR flag in the dump request structure based on the type of LBR supported by the CPU + // + LbrDumpRequest->ArchBasedLBR = g_ArchBasedLastBranchRecord; + + // + // Set the current LBR capacity in the dump request structure based on the type of LBR supported by the CPU + // + LbrDumpRequest->CurrentLbrCapacity = (UINT8)g_LbrCapacity; + + // + // Copy the LBR stack entries of the requested core into the dump request structure to be sent back to usermode + // + RtlCopyMemory(&LbrDumpRequest->LbrStack, &g_LbrStateList[LbrDumpRequest->CoreId], sizeof(LBR_STACK_ENTRY)); + + // + // Set successful status + // + HyperTraceLbrDumpSetKernelStatus(LbrDumpRequest, DEBUGGER_OPERATION_WAS_SUCCESSFUL); + + return TRUE; +} + +/** + * @brief Perform actions related to HyperTrace LBR operations + * + * @param LbrOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceLbrPerformOperation(HYPERTRACE_LBR_OPERATION_PACKETS * LbrOperationRequest) +{ + BOOLEAN Status = TRUE; + + // + // Check if the hypertrace module is initialized before performing any operation + // + if (!g_HyperTraceCallbacksInitialized) + { + HyperTraceLbrSetKernelStatus(LbrOperationRequest, DEBUGGER_ERROR_HYPERTRACE_NOT_INITIALIZED); + return FALSE; + } + + // + // Perform the requested operation + // + switch (LbrOperationRequest->LbrOperationType) + { + case HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_ENABLE: + + // LogInfo("HyperTrace: Enabling LBR tracing...\n"); + + HyperTraceLbrEnable(LbrOperationRequest); + + break; + + case HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_DISABLE: + + // LogInfo("HyperTrace: Disabling LBR tracing...\n"); + + HyperTraceLbrDisable(LbrOperationRequest); + + break; + + case HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_FLUSH: + + // LogInfo("HyperTrace: Flushing LBR tracing...\n"); + + HyperTraceLbrFlush(LbrOperationRequest); + + break; + + case HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_FILTER: + + // LogInfo("HyperTrace: Updating LBR filter options...\n"); + + HyperTraceLbrUpdateFilterOptions(LbrOperationRequest); + + break; + + default: + + Status = FALSE; + HyperTraceLbrSetKernelStatus(LbrOperationRequest, DEBUGGER_ERROR_INVALID_HYPERTRACE_OPERATION_TYPE); + + break; + } + + return Status; +} diff --git a/hyperdbg/hypertrace/code/api/PtApi.c b/hyperdbg/hypertrace/code/api/PtApi.c new file mode 100644 index 00000000..408848c3 --- /dev/null +++ b/hyperdbg/hypertrace/code/api/PtApi.c @@ -0,0 +1,644 @@ +/** + * @file PtApi.c + * @author Masoud Rahimi Jafari (Masoodrahimy1379@gmail.com) + * @brief Tracing routines for HyperTrace module (Intel Processor Trace) + * @details + * @version 0.19 + * @date 2026-04-29 + * + * @copyright This project is released under the GNU Public License v3. + */ +#include "pch.h" + +/** + * @brief Translate a user-mode HYPERTRACE_PT_OPERATION_PACKETS into a + * kernel-side PT_TRACE_CONFIG, falling back to defaults when the + * caller left fields zero (e.g. a bare `!pt filter`). + * + * The returned config is value-typed; HyperTracePtFilter's slow + * path copies it into every per-CPU slot via + * HyperTracePtSeedConfigOnAllCpus. + * @return VOID + */ +static VOID +HyperTracePtBuildConfig(const HYPERTRACE_PT_OPERATION_PACKETS * Req, + PT_TRACE_CONFIG * OutCfg) +{ + UINT32 Copy; + + // + // Start from defaults; only the fields the user can drive are then + // overridden. + // + PtEngineInitDefaultConfig(OutCfg); + + // + // If the request specifies neither user nor kernel, default to both + // (matches LBR behaviour when filter is empty). + // + if (Req->FilterOptions.TraceUser || Req->FilterOptions.TraceKernel) + { + OutCfg->TraceUser = (Req->FilterOptions.TraceUser != 0) ? TRUE : FALSE; + OutCfg->TraceKernel = (Req->FilterOptions.TraceKernel != 0) ? TRUE : FALSE; + } + + OutCfg->TargetCr3 = Req->EnableOptions.Cr3; + + if (Req->BufferSize != 0) + { + OutCfg->BufferSize = Req->BufferSize; + } + + OutCfg->NumAddrRanges = Req->FilterOptions.NumAddrRanges; + if (OutCfg->NumAddrRanges > PT_MAX_ADDR_RANGES) + OutCfg->NumAddrRanges = PT_MAX_ADDR_RANGES; + + for (Copy = 0; Copy < OutCfg->NumAddrRanges; Copy++) + { + OutCfg->AddrRanges[Copy] = Req->FilterOptions.AddrRanges[Copy]; + } +} + +/** + * @brief Push a fully-formed PT_TRACE_CONFIG into every active per-CPU + * slot. Used by the Enable path so PtAllocateAllCpuBuffers picks up + * the right BufferSize on every core. Runs at PASSIVE_LEVEL — + * does NOT start or stop tracing (callers handle that via DPC) + * @return VOID + */ +static VOID +HyperTracePtSeedConfigOnAllCpus(const PT_TRACE_CONFIG * Cfg) +{ + UINT32 ProcessorsCount; + UINT32 i; + + if (g_PtStateList == NULL || Cfg == NULL) + return; + + ProcessorsCount = KeQueryActiveProcessorCount(0); + + for (i = 0; i < ProcessorsCount; i++) + { + g_PtStateList[i].Config = *Cfg; + } +} + +/** + * @brief Enable PT tracing for HyperTrace + * + * @param PtOperationRequest Pointer to the HyperTrace PT operation request packet + * + * @return BOOLEAN + */ +BOOLEAN +HyperTracePtEnable(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest) +{ + // + // Check if PT is already enabled or not + // + if (g_ProcessorTraceEnabled) + { + PtOperationRequest->KernelStatus = DEBUGGER_ERROR_PT_ALREADY_ENABLED; + return FALSE; + } + + // + // Check PT support on CPU + // + if (!PtCheck()) + { + PtOperationRequest->KernelStatus = DEBUGGER_ERROR_PT_NOT_SUPPORTED; + return FALSE; + } + + // + // Allocate per-CPU ToPA / output / overflow buffers at PASSIVE_LEVEL + // (the contiguous-memory allocator cannot run from a DPC). + // PtAllocateAllCpuBuffers reads Cpu->Config.BufferSize, which was set + // either at module init (default 2MB) or by a prior !pt filter — so + // any pre-enable filter settings are preserved here. + // + if (!PtAllocateAllCpuBuffers()) + { + // + // Roll back any partial allocations so we don't leak on next try. + // + PtFreeAllCpuBuffers(); + PtOperationRequest->KernelStatus = DEBUGGER_ERROR_PT_NOT_SUPPORTED; + return FALSE; + } + + // + // Broadcast enabling PT on all cores + // + BroadcastEnablePtOnAllCores(); + + // + // Set the flag to indicate that PT tracing is enabled + // + g_ProcessorTraceEnabled = TRUE; + + // + // Set successful status + // + PtOperationRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + return TRUE; +} + +/** + * @brief Disable PT tracing for HyperTrace + * + * @param PtOperationRequest Pointer to the HyperTrace PT operation request packet + * + * @return BOOLEAN + */ +BOOLEAN +HyperTracePtDisable(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest) +{ + // + // Check if PT is already disabled or not + // + if (!g_ProcessorTraceEnabled) + { + if (PtOperationRequest != NULL) + { + PtOperationRequest->KernelStatus = DEBUGGER_ERROR_PT_ALREADY_DISABLED; + } + + return FALSE; + } + + // + // Disabling PT + // + g_ProcessorTraceEnabled = FALSE; + + // + // Broadcast disabling PT on all cores (DPC stops tracing per-core) + // + BroadcastDisablePtOnAllCores(); + + // + // Free per-CPU buffers at PASSIVE_LEVEL after the broadcast has stopped + // tracing on every core. + // + PtFreeAllCpuBuffers(); + + // + // Set successful status + // + if (PtOperationRequest != NULL) + { + PtOperationRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + + return TRUE; +} + +/** + * @brief Pause PT tracing on every core. Buffers stay allocated and the + * per-CPU CTL is preserved, so HyperTracePtResume can restart the + * trace exactly where it stopped. + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTracePtPause(HYPERTRACE_PT_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + if (!g_ProcessorTraceEnabled) + { + if (HyperTraceOperationRequest != NULL) + { + HyperTraceOperationRequest->KernelStatus = DEBUGGER_ERROR_PT_ALREADY_DISABLED; + } + return FALSE; + } + + BroadcastPausePtOnAllCores(); + + if (HyperTraceOperationRequest != NULL) + { + HyperTraceOperationRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + + return TRUE; +} + +/** + * @brief Resume PT tracing on every core after a prior HyperTracePtPause. + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTracePtResume(HYPERTRACE_PT_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + if (!g_ProcessorTraceEnabled) + { + if (HyperTraceOperationRequest != NULL) + { + HyperTraceOperationRequest->KernelStatus = DEBUGGER_ERROR_PT_ALREADY_DISABLED; + } + return FALSE; + } + + BroadcastResumePtOnAllCores(); + + if (HyperTraceOperationRequest != NULL) + { + HyperTraceOperationRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + + return TRUE; +} + +/** + * @brief Snapshot the current PT output position on every core and write + * the per-CPU byte counts into HyperTraceOperationRequest->BytesPerCpu. + * The returned counts are the decode window — bytes [0, BytesPerCpu[i]) + * in CPU i's user mapping currently hold valid trace data. + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTracePtSize(HYPERTRACE_PT_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + UINT32 ProcessorsCount; + + if (!g_ProcessorTraceEnabled) + { + if (HyperTraceOperationRequest != NULL) + { + HyperTraceOperationRequest->KernelStatus = DEBUGGER_ERROR_PT_ALREADY_DISABLED; + } + return FALSE; + } + + if (HyperTraceOperationRequest == NULL) + return FALSE; + + ProcessorsCount = KeQueryActiveProcessorCount(0); + + if (ProcessorsCount > PT_MAX_CPUS_FOR_MMAP) + ProcessorsCount = PT_MAX_CPUS_FOR_MMAP; + + RtlZeroMemory(HyperTraceOperationRequest->BytesPerCpu, + sizeof(HyperTraceOperationRequest->BytesPerCpu)); + + BroadcastSizePtOnAllCores(HyperTraceOperationRequest->BytesPerCpu); + + HyperTraceOperationRequest->NumCpus = ProcessorsCount; + HyperTraceOperationRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + return TRUE; +} + +/** + * @brief Dump PT trace state for HyperTrace + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTracePtDump(HYPERTRACE_PT_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + if (!g_ProcessorTraceEnabled) + { + if (HyperTraceOperationRequest != NULL) + { + HyperTraceOperationRequest->KernelStatus = DEBUGGER_ERROR_PT_ALREADY_DISABLED; + } + return FALSE; + } + + LogInfo("Dumping PT trace summary...\n"); + + BroadcastDumpPtOnAllCores(); + + if (HyperTraceOperationRequest != NULL) + { + HyperTraceOperationRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + + return TRUE; +} + +/** + * @brief Flush PT trace state on all cores (free buffers) + * + * @param HyperTraceOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTracePtFlush(HYPERTRACE_PT_OPERATION_PACKETS * HyperTraceOperationRequest) +{ + if (!g_ProcessorTraceEnabled) + { + if (HyperTraceOperationRequest != NULL) + { + HyperTraceOperationRequest->KernelStatus = DEBUGGER_ERROR_PT_ALREADY_DISABLED; + } + return FALSE; + } + + // + // Stop tracing on all cores via DPC (so MSRs are quiesced) + // + BroadcastFlushPtOnAllCores(); + + // + // Then free contiguous buffers at PASSIVE_LEVEL + // + PtFreeAllCpuBuffers(); + + // + // Reallocate buffers so subsequent !pt save / !pt dump / !pt enable + // continue to work — Flush in LBR keeps tracing alive, so we mirror + // that by leaving PT primed for the next !pt enable. + // + if (!PtAllocateAllCpuBuffers()) + { + PtFreeAllCpuBuffers(); + if (HyperTraceOperationRequest != NULL) + { + HyperTraceOperationRequest->KernelStatus = DEBUGGER_ERROR_PT_NOT_SUPPORTED; + } + g_ProcessorTraceEnabled = FALSE; + return FALSE; + } + + // + // Resume tracing on all cores + // + BroadcastEnablePtOnAllCores(); + + if (HyperTraceOperationRequest != NULL) + { + HyperTraceOperationRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + + return TRUE; +} + +/** + * @brief Apply a new PT trace configuration (TraceUser / TraceKernel / + * TargetCr3 / BufferSize / NumAddrRanges + AddrRanges) on all cores. + * + * Mirrors HyperTraceLbrUpdateFilterOptions / LbrFilter: + * + * - If PT is currently enabled, stop tracing on all cores, free + * and reallocate buffers (because BufferSize may have changed), + * push the new config into every per-CPU slot, and resume + * tracing on all cores. + * - If PT is currently disabled, only update the per-CPU config + * so that the next `!pt enable` picks it up. + * + * Must be called at IRQL == PASSIVE_LEVEL because of the + * contiguous-memory allocator. + */ +BOOLEAN +HyperTracePtFilter(HYPERTRACE_PT_OPERATION_PACKETS * Req) +{ + PT_APPLY_CORE_FILTER_REQUEST ApplyCoreFilterReq = {0}; + BOOLEAN WasEnabled = g_ProcessorTraceEnabled; + BOOLEAN BufferChanged = FALSE; + UINT64 ExistingSize = 0; + + // + // Copy the user-mode request into a kernel-mode PT_APPLY_CORE_FILTER_REQUEST + // + memcpy(&ApplyCoreFilterReq.FilterOptions, &Req->FilterOptions, sizeof(PT_FILTER_OPTIONS)); + memcpy(&ApplyCoreFilterReq.EnableOptions, &Req->EnableOptions, sizeof(PT_ENABLE_OPTIONS)); + ApplyCoreFilterReq.BufferSize = Req->BufferSize; + + // + // Translate the user-mode packet into PT_FILTER_OPTIONS - the narrow + // surface PtFilter operates on. Default to user+kernel when the + // caller specified neither (matches LBR's empty-filter behaviour). + // + if (Req->FilterOptions.TraceUser || Req->FilterOptions.TraceKernel) + { + ApplyCoreFilterReq.FilterOptions.TraceUser = (Req->FilterOptions.TraceUser != 0) ? TRUE : FALSE; + ApplyCoreFilterReq.FilterOptions.TraceKernel = (Req->FilterOptions.TraceKernel != 0) ? TRUE : FALSE; + } + else + { + ApplyCoreFilterReq.FilterOptions.TraceUser = TRUE; + ApplyCoreFilterReq.FilterOptions.TraceKernel = TRUE; + } + + if (Req->FilterOptions.NumAddrRanges > PT_MAX_ADDR_RANGES) + ApplyCoreFilterReq.FilterOptions.NumAddrRanges = PT_MAX_ADDR_RANGES; + + // + // Decide between fast (filter-only) and slow (buffer-resize) paths. + // + if (g_PtStateList != NULL) + { + ExistingSize = g_PtStateList[0].Config.BufferSize; + } + + if (ApplyCoreFilterReq.BufferSize != 0 && ApplyCoreFilterReq.BufferSize != ExistingSize) + { + BufferChanged = TRUE; + } + + if (!WasEnabled || BufferChanged) + { + // + // Slow path — PT is off and/or BufferSize changed. We have to + // free + reallocate per-CPU buffers at PASSIVE_LEVEL, so we + // can't go through DPC for the config seeding either. + // + PT_TRACE_CONFIG Cfg; + + if (WasEnabled) + { + BroadcastFlushPtOnAllCores(); + PtFreeAllCpuBuffers(); + } + + // + // Build a full PT_TRACE_CONFIG (defaults + the user-tunable + // fields from the request) and seed it on every CPU so the next + // PtAllocateAllCpuBuffers picks up the right BufferSize and + // PtEngineStart programs the right RTIT_CTL bits. + // + HyperTracePtBuildConfig(Req, &Cfg); + HyperTracePtSeedConfigOnAllCpus(&Cfg); + + if (WasEnabled) + { + if (!PtAllocateAllCpuBuffers()) + { + PtFreeAllCpuBuffers(); + g_ProcessorTraceEnabled = FALSE; + if (Req != NULL) + { + Req->KernelStatus = DEBUGGER_ERROR_PT_NOT_SUPPORTED; + } + return FALSE; + } + + BroadcastEnablePtOnAllCores(); + } + } + else + { + // + // Fast filter-only path: PT is running and BufferSize is + // unchanged. Force FilterOptions.BufferSize=0 so PtFilter on each core + // keeps the buffer that's already allocated, then broadcast. + // + ApplyCoreFilterReq.BufferSize = 0; + BroadcastFilterPtOnAllCores(&ApplyCoreFilterReq); + } + + if (Req != NULL) + { + Req->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + + return TRUE; +} + +/** + * @brief Map every per-CPU PT main output + overflow buffer into the + * calling user-mode process. See HYPERTRACE_PT_MMAP_PACKETS for + * the full lifetime / single-process contract. + */ +BOOLEAN +HyperTracePtMmap(HYPERTRACE_PT_MMAP_PACKETS * Req) +{ + if (Req == NULL) + return FALSE; + + Req->NumCpus = 0; + + if (!g_HyperTraceCallbacksInitialized) + { + Req->KernelStatus = DEBUGGER_ERROR_HYPERTRACE_NOT_INITIALIZED; + return FALSE; + } + + if (!g_ProcessorTraceEnabled) + { + Req->KernelStatus = DEBUGGER_ERROR_PT_ALREADY_DISABLED; + return FALSE; + } + + if (PtMmapAllCpuBuffersToUser(Req->Cpus, PT_MAX_CPUS_FOR_MMAP, &Req->NumCpus) != 0) + { + Req->KernelStatus = DEBUGGER_ERROR_PT_NOT_SUPPORTED; + return FALSE; + } + + Req->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + return TRUE; +} + +/** + * @brief Perform actions related to HyperTrace PT + * + * @param PtOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperTracePtPerformOperation(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest) +{ + BOOLEAN Status = TRUE; + + // + // Check if the hypertrace module is initialized before performing any operation + // + if (!g_HyperTraceCallbacksInitialized) + { + PtOperationRequest->KernelStatus = DEBUGGER_ERROR_HYPERTRACE_NOT_INITIALIZED; + return FALSE; + } + + // + // Perform the requested operation + // + switch (PtOperationRequest->PtOperationType) + { + case HYPERTRACE_PT_OPERATION_REQUEST_TYPE_ENABLE: + + LogInfo("HyperTrace: Enabling PT tracing...\n"); + + HyperTracePtEnable(PtOperationRequest); + + break; + + case HYPERTRACE_PT_OPERATION_REQUEST_TYPE_DISABLE: + + LogInfo("HyperTrace: Disabling PT tracing...\n"); + + HyperTracePtDisable(PtOperationRequest); + + break; + + case HYPERTRACE_PT_OPERATION_REQUEST_TYPE_PAUSE: + + LogInfo("HyperTrace: Pausing PT tracing...\n"); + + HyperTracePtPause(PtOperationRequest); + + break; + + case HYPERTRACE_PT_OPERATION_REQUEST_TYPE_RESUME: + + LogInfo("HyperTrace: Resuming PT tracing...\n"); + + HyperTracePtResume(PtOperationRequest); + + break; + + case HYPERTRACE_PT_OPERATION_REQUEST_TYPE_SIZE: + + LogInfo("HyperTrace: Snapshotting PT buffer sizes...\n"); + + HyperTracePtSize(PtOperationRequest); + + break; + + case HYPERTRACE_PT_OPERATION_REQUEST_TYPE_DUMP: + + LogInfo("HyperTrace: Showing PT tracing...\n"); + + HyperTracePtDump(PtOperationRequest); + + break; + + case HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FLUSH: + + LogInfo("HyperTrace: Flushing PT tracing...\n"); + + HyperTracePtFlush(PtOperationRequest); + + break; + + case HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FILTER: + + LogInfo("HyperTrace: Updating PT filter / config...\n"); + + HyperTracePtFilter(PtOperationRequest); + + break; + + default: + Status = FALSE; + PtOperationRequest->KernelStatus = DEBUGGER_ERROR_INVALID_HYPERTRACE_OPERATION_TYPE; + break; + } + + return Status; +} diff --git a/hyperdbg/hypertrace/code/api/TraceApi.c b/hyperdbg/hypertrace/code/api/TraceApi.c new file mode 100644 index 00000000..94f3e961 --- /dev/null +++ b/hyperdbg/hypertrace/code/api/TraceApi.c @@ -0,0 +1,165 @@ +/** + * @file TraceApi.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Tracing routines for HyperTrace module + * @details + * @version 0.19 + * @date 2026-04-25 + * + * @copyright This project is released under the GNU Public License v3. + */ +#include "pch.h" + +/** + * @brief Initialize the hypertrace module callbacks + * @details This only for callback initialization, not for LBR, PT, etc. initialization + * + * @param HyperTraceCallbacks Pointer to the HyperTrace callbacks structure to be registered + * @param RunningOnHypervisorEnvironment Whether the initialization is being done for hypervisor environment or not, + * it can be used to skip some of the initialization steps if it is not for hypervisor environment and behave differently based on that + * + * @return BOOLEAN + */ +BOOLEAN +HyperTraceInitCallback(HYPERTRACE_CALLBACKS * HyperTraceCallbacks, + BOOLEAN RunningOnHypervisorEnvironment) +{ + UINT32 ProcessorsCount = 0; + + // + // Check if any of the required callbacks are NULL + // + for (UINT32 i = 0; i < sizeof(HYPERTRACE_CALLBACKS) / sizeof(UINT64); i++) + { + if (((PVOID *)HyperTraceCallbacks)[i] == NULL) + { + // + // The callback has null entry, so we cannot proceed + // + return FALSE; + } + } + + // + // Save the callbacks + // + PlatformWriteMemory(&g_Callbacks, HyperTraceCallbacks, sizeof(HYPERTRACE_CALLBACKS)); + + // + // Query the number of processors in the system to initialize the global LBR state list accordingly + // + ProcessorsCount = PlatformCpuGetActiveProcessorCount(); + + // + // Initialize the global LBR state list to hold LBR states for each core + // + g_LbrStateList = (LBR_STACK_ENTRY *)PlatformMemAllocateZeroedNonPagedPool(sizeof(LBR_STACK_ENTRY) * ProcessorsCount); + + // + // Initialize the global PT per-CPU state list. Each entry starts in + // PT_STATE_DISABLED with no buffers allocated; PtStart() will lazily + // allocate ToPA / output / overflow buffers on first use per core. + // + g_PtStateList = (PT_PER_CPU *)PlatformMemAllocateZeroedNonPagedPool(sizeof(PT_PER_CPU) * ProcessorsCount); + + if (g_PtStateList != NULL) + { + UINT32 i; + for (i = 0; i < ProcessorsCount; i++) + { + PtEngineInitDefaultConfig(&g_PtStateList[i].Config); + g_PtStateList[i].State = PT_STATE_DISABLED; + } + } + + // + // Set the flag to indicate whether the initialization is being done for hypervisor environment or not + // + g_RunningOnHypervisorEnvironment = RunningOnHypervisorEnvironment; + + // + // It is initialized, but LBR is disabled at this stage + // + g_LastBranchRecordEnabled = FALSE; + + // + // It is initialized, but Processor Trace is disabled at this stage + // + g_ProcessorTraceEnabled = FALSE; + + // + // Enable callbacks and set the initialized flag + // + g_HyperTraceCallbacksInitialized = TRUE; + + return TRUE; +} + +/** + * @brief Uninitialize the hypertrace module + * + * @return VOID + */ +VOID +HyperTraceUninit() +{ + // + // Check if the callbacks are initialized, if not, we don't need to handle anymore + // + if (!g_HyperTraceCallbacksInitialized) + { + return; + } + + // + // Disable LBR tracing if it is still enabled + // + if (g_LastBranchRecordEnabled) + { + HyperTraceLbrDisable(NULL); + } + + // + // Unallocate the global LBR state list if it is allocated + // + if (g_LbrStateList != NULL) + { + PlatformMemFreePool(g_LbrStateList); + g_LbrStateList = NULL; + } + + // + // Disable Processor Trace if it is still enabled + // + if (g_ProcessorTraceEnabled) + { + HyperTracePtDisable(NULL); + } + + // + // Free PT buffers (if any) and the per-CPU state list + // + if (g_PtStateList != NULL) + { + UINT32 ProcessorsCountLocal = KeQueryActiveProcessorCount(0); + UINT32 i; + + for (i = 0; i < ProcessorsCountLocal; i++) + { + PtEngineFreeBuffers(&g_PtStateList[i]); + } + + PlatformMemFreePool(g_PtStateList); + g_PtStateList = NULL; + } + + // + // Reset the environment flag to default value + // + g_RunningOnHypervisorEnvironment = FALSE; + + // + // Set callbacks to not initialized + // + g_HyperTraceCallbacksInitialized = FALSE; +} diff --git a/hyperdbg/hypertrace/code/broadcast/Broadcast.c b/hyperdbg/hypertrace/code/broadcast/Broadcast.c new file mode 100644 index 00000000..0fd14565 --- /dev/null +++ b/hyperdbg/hypertrace/code/broadcast/Broadcast.c @@ -0,0 +1,164 @@ +/** + * @file Broadcast.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Broadcasting functions + * @details + * @version 0.19 + * @date 2026-04-19 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Routines to enable LBR on all cores + * + * @return VOID + */ +VOID +BroadcastEnableLbrOnAllCores() +{ + // + // Broadcast to all cores + // + KeGenericCallDpc(DpcRoutineEnableLbr, NULL); +} + +/** + * @brief Routines to disable LBR on all cores + * + * @return VOID + */ +VOID +BroadcastDisableLbrOnAllCores() +{ + // + // Broadcast to all cores + // + KeGenericCallDpc(DpcRoutineDisableLbr, NULL); +} + +/** + * @brief Routines to flush LBR on all cores + * + * @return VOID + */ +VOID +BroadcastFlushLbrOnAllCores() +{ + // + // Broadcast to all cores + // + KeGenericCallDpc(DpcRoutineFlushLbr, NULL); +} + +/** + * @brief Routines to filter LBR option on all cores + * + * @param LbrFilterOptions A bitmask of filter options to apply to the LBR branches + * + * @return VOID + */ +VOID +BroadcastFilterLbrOptionsOnAllCores(UINT64 LbrFilterOptions) +{ + // + // Broadcast to all cores + // + KeGenericCallDpc(DpcRoutineFilterLbrOptions, (PVOID)(UINT_PTR)LbrFilterOptions); +} + +/** + * @brief Routines to enable PT on all cores + * + * @return VOID + */ +VOID +BroadcastEnablePtOnAllCores() +{ + KeGenericCallDpc(DpcRoutineEnablePt, NULL); +} + +/** + * @brief Routines to disable PT on all cores + * + * @return VOID + */ +VOID +BroadcastDisablePtOnAllCores() +{ + KeGenericCallDpc(DpcRoutineDisablePt, NULL); +} + +/** + * @brief Routines to pause PT tracing on all cores + * + * @return VOID + */ +VOID +BroadcastPausePtOnAllCores() +{ + KeGenericCallDpc(DpcRoutinePausePt, NULL); +} + +/** + * @brief Routines to resume PT tracing on all cores + * + * @return VOID + */ +VOID +BroadcastResumePtOnAllCores() +{ + KeGenericCallDpc(DpcRoutineResumePt, NULL); +} + +/** + * @brief Routines to snapshot per-CPU PT output positions. The DPC + * writes its own core's byte count into Sizes[CoreId]; the + * caller's UINT64 array must hold at least one slot per CPU. + * + * @return VOID + */ +VOID +BroadcastSizePtOnAllCores(UINT64 * Sizes) +{ + KeGenericCallDpc(DpcRoutineSizePt, (PVOID)Sizes); +} + +/** + * @brief Routines to dump PT state on all cores + * + * @return VOID + */ +VOID +BroadcastDumpPtOnAllCores() +{ + KeGenericCallDpc(DpcRoutineDumpPt, NULL); +} + +/** + * @brief Routines to flush PT state on all cores + * + * @return VOID + */ +VOID +BroadcastFlushPtOnAllCores() +{ + KeGenericCallDpc(DpcRoutineFlushPt, NULL); +} + +/** + * @brief Routines to apply a PT filter on all cores. The same Options + * pointer is passed to every per-core DPC; KeGenericCallDpc is + * synchronous so the caller's storage is valid throughout. + * + * @param FilterRequest Pointer to a PT_APPLY_CORE_FILTER_REQUEST structure containing the filter options to apply on all cores + * + * @return VOID + */ +VOID +BroadcastFilterPtOnAllCores(PT_APPLY_CORE_FILTER_REQUEST * FilterRequest) +{ + KeGenericCallDpc(DpcRoutineFilterPt, (PVOID)FilterRequest); +} diff --git a/hyperdbg/hypertrace/code/broadcast/DpcRoutines.c b/hyperdbg/hypertrace/code/broadcast/DpcRoutines.c new file mode 100644 index 00000000..b17accdd --- /dev/null +++ b/hyperdbg/hypertrace/code/broadcast/DpcRoutines.c @@ -0,0 +1,350 @@ +/** + * @file DpcRoutines.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief DPC routines + * @details + * @version 0.19 + * @date 2026-04-19 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Broadcast enabling LBR + * + * @param Dpc + * @param DeferredContext + * @param SystemArgument1 + * @param SystemArgument2 + * @return BOOLEAN + */ +BOOLEAN +DpcRoutineEnableLbr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); + + // + // Check if the initialization is being done for hypervisor environment or not + // If it is, then we need to perform some additional steps to enable LBR in VMX + // + if (g_RunningOnHypervisorEnvironment) + { + if (g_ArchBasedLastBranchRecord) + { + // + // Perform VMX-root mode specific operations to load and clear guest + // IA32_LBR_CTL MSR (VMCS_GUEST_LBR_CTL) for LBR + // + g_Callbacks.VmFuncSetLoadGuestIa32LbrCtlVmcallOnTargetCore(TRUE); + g_Callbacks.VmFuncSetClearGuestIa32LbrCtlVmcallOnTargetCore(TRUE); + } + else + { + // + // Perform VMX-root mode specific operations to enable load and save + // VM-exit and VM-entry controls for IA32_DEBUGCTL for LBR + // + g_Callbacks.VmFuncSetSaveDebugControlsVmcallOnTargetCore(TRUE); + g_Callbacks.VmFuncSetLoadDebugControlsVmcallOnTargetCore(TRUE); + } + } + + // + // Enable LBR on all cores from VMX-root mode by VMCALL + // By default, all filter options are disabled, which means all branch types will be captured + // + LbrStart(LBR_SELECT_WITHOUT_FILTER); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast disabling LBR + * + * @param Dpc + * @param DeferredContext + * @param SystemArgument1 + * @param SystemArgument2 + * @return BOOLEAN + */ +BOOLEAN +DpcRoutineDisableLbr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); + + // + // Disable LBR on all cores from VMX-root mode by VMCALL + // + LbrStop(); + + // + // Check if the initialization is being done for hypervisor environment or not + // If it is, then we need to perform some additional steps to enable LBR in VMX + // + if (g_RunningOnHypervisorEnvironment) + { + if (g_ArchBasedLastBranchRecord) + { + // + // Perform VMX-root mode specific operations to disable load and clear guest + // IA32_LBR_CTL MSR (VMCS_GUEST_LBR_CTL) for LBR + // + g_Callbacks.VmFuncSetLoadGuestIa32LbrCtlVmcallOnTargetCore(FALSE); + g_Callbacks.VmFuncSetClearGuestIa32LbrCtlVmcallOnTargetCore(FALSE); + } + else + { + // + // Perform VMX-root mode specific operations to disable load and save + // VM-exit and VM-entry controls for IA32_DEBUGCTL for LBR + // + g_Callbacks.VmFuncSetSaveDebugControlsVmcallOnTargetCore(FALSE); + g_Callbacks.VmFuncSetLoadDebugControlsVmcallOnTargetCore(FALSE); + } + } + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast flushing LBR + * + * @param Dpc + * @param DeferredContext + * @param SystemArgument1 + * @param SystemArgument2 + * @return BOOLEAN + */ +BOOLEAN +DpcRoutineFlushLbr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); + + // + // Flush LBR on all cores + // + LbrFlush(); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast updating LBR filter options + * + * @param Dpc + * @param DeferredContext + * @param SystemArgument1 + * @param SystemArgument2 + * @return BOOLEAN + */ +BOOLEAN +DpcRoutineFilterLbrOptions(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + + // + // Flush LBR on all cores + // + LbrFilter((UINT64)DeferredContext); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast enabling PT + * + * @param Dpc + * @param DeferredContext + * @param SystemArgument1 + * @param SystemArgument2 + * @return BOOLEAN + */ +BOOLEAN +DpcRoutineEnablePt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); + + // + // Enable PT on the current core. PT in the current implementation is + // controlled via direct MSR writes from kernel context; if PT is later + // wired into VMCS save/load controls, the corresponding hypervisor + // helpers should be invoked here similar to DpcRoutineEnableLbr. + // + PtStart(); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast disabling PT + */ +BOOLEAN +DpcRoutineDisablePt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); + + PtStop(); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast pausing PT + */ +BOOLEAN +DpcRoutinePausePt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); + + PtPause(); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast resuming PT + */ +BOOLEAN +DpcRoutineResumePt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); + + PtResume(); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast snapshotting per-CPU PT output position. + * + * DeferredContext is a UINT64 array (one slot per active CPU); + * each per-core DPC writes its own core's byte count and never + * touches another slot, so no synchronisation is required. + */ +BOOLEAN +DpcRoutineSizePt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UINT64 * Sizes = (UINT64 *)DeferredContext; + UINT32 Core = KeGetCurrentProcessorNumberEx(NULL); + + UNREFERENCED_PARAMETER(Dpc); + + if (Sizes != NULL && Core < PT_MAX_CPUS_FOR_MMAP) + Sizes[Core] = PtSize(); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast dumping PT state + */ +BOOLEAN +DpcRoutineDumpPt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); + + PtDump(); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast flushing PT state + */ +BOOLEAN +DpcRoutineFlushPt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(DeferredContext); + + PtFlush(); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} + +/** + * @brief Broadcast applying a PT filter to all cores. + * + * DeferredContext carries the PT_APPLY_CORE_FILTER_REQUEST * supplied by the + * broadcaster; PtFilter writes the user-tunable fields into the + * current CPU's per-CPU PT_TRACE_CONFIG and reprograms PT MSRs. + */ +BOOLEAN +DpcRoutineFilterPt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(Dpc); + + PtFilter((const PT_APPLY_CORE_FILTER_REQUEST *)DeferredContext); + + // ------------------------------------------------------------------------------ + // Synchronize the end of this routine with the caller + // + PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2); + + return TRUE; +} diff --git a/hyperdbg/hypertrace/code/common/UnloadDll.c b/hyperdbg/hypertrace/code/common/UnloadDll.c new file mode 100644 index 00000000..17321dbf --- /dev/null +++ b/hyperdbg/hypertrace/code/common/UnloadDll.c @@ -0,0 +1,45 @@ +/** + * @file UnloadDll.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Unloading DLL in the target Windows + * @details + * @version 0.4 + * @date 2023-07-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// We'll add these functions, so whenever HyperDbg's driver is unloaded +// DllUnload will be called to unload this dll from the memory. +// this way we can remove the HyperDbg after unloading as there is no +// 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) +{ + UNREFERENCED_PARAMETER(RegistryPath); + + return STATUS_SUCCESS; +} + +/** + * @brief Routine called on DLL unload + * + * @return NTSTATUS + */ +NTSTATUS +DllUnload(VOID) +{ + return STATUS_SUCCESS; +} diff --git a/hyperdbg/hypertrace/code/lbr/Lbr.c b/hyperdbg/hypertrace/code/lbr/Lbr.c new file mode 100644 index 00000000..de3d8c99 --- /dev/null +++ b/hyperdbg/hypertrace/code/lbr/Lbr.c @@ -0,0 +1,1266 @@ +/** + * @file Lbr.c + * @author Hari Mishal (harimishal6@gmail.com) + * @brief Last Branch Record (LBR) tracing implementation for HyperTrace module + * @details Modified from LIBIHT project (Thomasaon Zhao et al) with Windows style updates. + * @version 0.18 + * @date 2025-12-02 + * + * @copyright This project is released under the GNU Public License v3. + */ +#include "pch.h" + +////////////////////////////////////////////////// +// Global Definitions // +////////////////////////////////////////////////// + +// +// Typical Intel LBR capacities based on CPU model +// This is a subset; you can expand this as needed +// +CPU_LBR_MAP CPU_LBR_MAPS[] = { + {0x5c, 32}, + {0x5f, 32}, + {0x4e, 32}, + {0x5e, 32}, + {0x8e, 32}, + {0x9e, 32}, + {0x55, 32}, + {0x66, 32}, + {0x7a, 32}, + {0x67, 32}, + {0x6a, 32}, + {0x6c, 32}, + {0x7d, 32}, + {0x7e, 32}, + {0x8c, 32}, + {0x8d, 32}, + {0xa5, 32}, + {0xa6, 32}, + {0xa7, 32}, + {0xa8, 32}, + {0x86, 32}, + {0x8a, 32}, + {0x96, 32}, + {0x9c, 32}, + {0x3d, 16}, + {0x47, 16}, + {0x4f, 16}, + {0x56, 16}, + {0x3c, 16}, + {0x45, 16}, + {0x46, 16}, + {0x3f, 16}, + {0x2a, 16}, + {0x2d, 16}, + {0x3a, 16}, + {0x3e, 16}, + {0x1a, 16}, + {0x1e, 16}, + {0x1f, 16}, + {0x2e, 16}, + {0x25, 16}, + {0x2c, 16}, + {0x2f, 16}, + {0x17, 4}, + {0x1d, 4}, + {0x0f, 4}, + {0x37, 8}, + {0x4a, 8}, + {0x4c, 8}, + {0x4d, 8}, + {0x5a, 8}, + {0x5d, 8}, + {0x1c, 8}, + {0x26, 8}, + {0x27, 8}, + {0x35, 8}, + {0x36, 8}}; + +/** + * @brief Check if the current CPU supports architectural LBR + * + * @return BOOLEAN + */ +BOOLEAN +LbrCheckAndReadArchitecturalLbrDetails() +{ + ULONG a, b, c, d; + + CPUID_EAX_07 Edx07 = {0}; + + CPUID28_EAX Eax1c = {0}; + CPUID28_EBX Ebx1c = {0}; + CPUID28_ECX Ecx1c = {0}; + + // + // Check for Architectural LBR support + // + // + xcpuidex(CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, 0x00, &a, &b, &c, &d); + + Edx07.Edx.AsUInt = d; + + // + // CPUID.07H.00H:EDX[19] == 1 means arch LBR is supported + // + if (Edx07.Edx.AsUInt & (1 << 19)) + { + g_ArchBasedLastBranchRecord = TRUE; + } + else + { + // + // Architectural LBR is not supported by the CPU + // + g_ArchBasedLastBranchRecord = FALSE; + + return FALSE; + } + + // + // Being here means the CPU supports architectural LBR, we can read the LBR capabilities from CPUID 0x1c leaf + // + xcpuidex(CPUID_ARCH_LAST_BRANCH_RECORD_INFORMATION, 0x00, &a, &b, &c, &d); + + // + // Assign LBR leafs to structure for easier access + // + Eax1c.AsUInt = a; + Ebx1c.AsUInt = b; + Ecx1c.AsUInt = c; + + // + // Store the CPUID.1CH leaf information in a global structure for later use + // + g_Cpuid28Leafs.Eax = Eax1c; + g_Cpuid28Leafs.Ebx = Ebx1c; + g_Cpuid28Leafs.Ecx = Ecx1c; + g_Cpuid28Leafs.Edx = d; + + // + // Read LBR capacity from CPUID.1CH.00H:EAX[7:0] + // Based on Intel SDM: For each bit n set in this field, the IA32_LBR_DEPTH.DEPTH value 8 * (n + 1) is supported + // + if (Eax1c.LbrDepthMask) + { + // + // Get the highest set bit in LbrDepthMask to determine the maximum supported LBR depth + // + ULONG HighestSetBit = 0; + for (ULONG i = 0; i < 8; i++) + { + if (Eax1c.LbrDepthMask & (1 << i)) + { + HighestSetBit = i; + } + } + g_LbrCapacity = 8 * (HighestSetBit + 1); + } + else + { + // + // If LbrDepthMask is 0, it means the CPU supports architectural LBR but does not specify the depth, we can assume a default value (e.g., 16 or 32) or treat it as unsupported + // + g_LbrCapacity = MAXIMUM_LBR_CAPACITY; // Assuming a default capacity of MAXIMUM_LBR_CAPACITY if not specified + } + + return TRUE; +} + +/** + * @brief Check if the current CPU supports LBR by examining the CPU family and model and looking up the corresponding LBR capacity + * + * @return BOOLEAN + */ +BOOLEAN +LbrCheckAndReadLegacyLbrDetails() +{ + ULONG a, b, c, d; + ULONG Family, Model; + ULONGLONG i; + + xcpuid(1, &a, &b, &c, &d); + + Family = ((a >> 8) & 0xF) + ((a >> 20) & 0xFF); + Model = ((a >> 4) & 0xF) | ((a >> 12) & 0xF0); + + for (i = 0; i < sizeof(CPU_LBR_MAPS) / sizeof(CPU_LBR_MAPS[0]); ++i) + { + if (Model == CPU_LBR_MAPS[i].Model) + { + g_LbrCapacity = CPU_LBR_MAPS[i].LbrCapacity; + break; + } + } + + if (g_LbrCapacity == 0) + { + return FALSE; + } + + return TRUE; +} + +/** + * @brief Check and adjust compatibility of LBR filterings for ARCH based LBR + * + * @return VOID + */ +VOID +LbrAdjustArchBasedFilteringCompatibility(IA32_LBR_CTL_REGISTER * Ia32LbrCtl) +{ + // + // Check capabilities and apply necessary adjustments based on CPU support + // + if (!g_Cpuid28Leafs.Ebx.LbrCpl) + { + // + // If CPL filtering is not supported + // we cannot filter kernel vs user mode branches, so we clear those filter bits to avoid confusion + // + Ia32LbrCtl->Bits.OS = 0; + Ia32LbrCtl->Bits.USR = 0; + } + + if (!g_Cpuid28Leafs.Ebx.LbrFilter) + { + // + // If branch filtering is not supported, we cannot filter by branch type, so we clear all the specific branch type filter bits + // + Ia32LbrCtl->Bits.JCC = 0; + Ia32LbrCtl->Bits.NearRelJmp = 0; + Ia32LbrCtl->Bits.NearIndJmp = 0; + Ia32LbrCtl->Bits.NearRelCall = 0; + Ia32LbrCtl->Bits.NearIndCall = 0; + Ia32LbrCtl->Bits.NearRet = 0; + Ia32LbrCtl->Bits.OtherBranch = 0; + } + + if (!g_Cpuid28Leafs.Ebx.LbrCallStack) + { + // + // If call-stack mode is not supported, we cannot filter by call stack, so we clear that filter bit + // + Ia32LbrCtl->Bits.CallStack = 0; + } +} + +/** + * @brief Convert a filter options bitmask into IA32_LBR_CTL format for architectural LBR + * + * @param FilterOptions A bitmask of filter options (e.g., LBR_KERNEL, LBR_USER, LBR_JCC, etc.) + * @param Ia32LbrCtl Pointer to the IA32_LBR_CTL_REGISTER to populate with the converted filter bits + * @return VOID + */ +VOID +LbrBuildArchBasedFilterOptions(UINT64 FilterOptions, IA32_LBR_CTL_REGISTER * Ia32LbrCtl) +{ + // + // By default, we are enabling all of them + // + Ia32LbrCtl->Bits.OS = 1; + Ia32LbrCtl->Bits.USR = 1; + Ia32LbrCtl->Bits.JCC = 1; + Ia32LbrCtl->Bits.NearRelCall = 1; + Ia32LbrCtl->Bits.NearIndCall = 1; + Ia32LbrCtl->Bits.NearRet = 1; + Ia32LbrCtl->Bits.NearIndJmp = 1; + Ia32LbrCtl->Bits.NearRelJmp = 1; + Ia32LbrCtl->Bits.OtherBranch = 1; + Ia32LbrCtl->Bits.CallStack = 1; + + // + // Perform filtering the results + // + if (FilterOptions & LBR_KERNEL) + { + Ia32LbrCtl->Bits.OS = 0; + } + + if (FilterOptions & LBR_USER) + { + Ia32LbrCtl->Bits.USR = 0; + } + + if (FilterOptions & LBR_JCC) + { + Ia32LbrCtl->Bits.JCC = 0; + } + + if (FilterOptions & LBR_REL_CALL) + { + Ia32LbrCtl->Bits.NearRelCall = 0; + } + + if (FilterOptions & LBR_IND_CALL) + { + Ia32LbrCtl->Bits.NearIndCall = 0; + } + + if (FilterOptions & LBR_RETURN) + { + Ia32LbrCtl->Bits.NearRet = 0; + } + + if (FilterOptions & LBR_IND_JMP) + { + Ia32LbrCtl->Bits.NearIndJmp = 0; + } + + if (FilterOptions & LBR_REL_JMP) + { + Ia32LbrCtl->Bits.NearRelJmp = 0; + } + + if (FilterOptions & LBR_FAR_OTHER_BRANCHES) + { + Ia32LbrCtl->Bits.OtherBranch = 0; + } + + if (FilterOptions & LBR_CALL_STACK) + { + Ia32LbrCtl->Bits.CallStack = 0; + } + + // + // Adjust LBR fitlering options based on the CPU capabilities to ensure we are not setting unsupported filter bits + // + LbrAdjustArchBasedFilteringCompatibility(Ia32LbrCtl); +} +/** + * @brief Set the LBR select filter MSR (MSR_LEGACY_LBR_SELECT) for legacy LBR, + * dispatching via VMCALL when in VMX non-root mode + * + * @details This function is only relevant for legacy LBR. Architectural LBR encodes + * filter options directly in IA32_LBR_CTL and does not use MSR_LEGACY_LBR_SELECT. + * Note: Even though MSR_LEGACY_LBR_SELECT is a plain MSR (not a VMCS field), it + * must be set from VMX-root mode for the LBR MSRs to work correctly. + * + * @param FilterOptions The raw filter options bitmask to write into MSR_LEGACY_LBR_SELECT + * @return VOID + */ +VOID +LbrSetLbrSelectFilter(UINT64 FilterOptions) +{ + BOOLEAN IsOnVmxRootMode; + + if (g_RunningOnHypervisorEnvironment) + { + IsOnVmxRootMode = g_Callbacks.VmFuncVmxGetCurrentExecutionMode(); + + // + // If we don't set it on VMX-root mode, the LBR MSRs won't work based on our tests + // even though it is just a plain MSR (and not a VMCS field) + // + if (IsOnVmxRootMode) + { + // + // It is on VMX-root mode, run it directly to set the MSR_LEGACY_LBR_SELECT MSR value + // + g_Callbacks.VmFuncSetLbrSelect(FilterOptions); + } + else + { + // + // It is not on VMX-root mode, so we need to perform a VMCALL to set the MSR_LEGACY_LBR_SELECT MSR value on the target core + // + g_Callbacks.VmFuncSetLbrSelectVmcallOnTargetCore(FilterOptions); + } + } + else + { + xwrmsr(MSR_LEGACY_LBR_SELECT, FilterOptions); + } +} + +/** + * @brief Zero out the LBR hardware state (TOS and all from/to MSR pairs) + * + * @details For architectural LBR the TOS index is not maintained by software and the CPU + * shifts entries automatically, so MSR_LBR_TOS is skipped in that case. + * + * @return VOID + */ +VOID +LbrClearHardwareState() +{ + // + // For architectural LBR, the TOS is not used; the CPU shifts LBR entries automatically + // and does not update the TOS index + // + if (!g_ArchBasedLastBranchRecord) + { + xwrmsr(MSR_LBR_TOS, 0); + } + + // + // Clearing LBR TO and FROM MSRs + // + for (ULONG i = 0; i < (ULONG)g_LbrCapacity; i++) + { + if (g_ArchBasedLastBranchRecord) + { + xwrmsr(IA32_LBR_0_FROM_IP + i, 0); + xwrmsr(IA32_LBR_0_TO_IP + i, 0); + } + else + { + xwrmsr(MSR_LASTBRANCH_0_FROM_IP + i, 0); + xwrmsr(MSR_LASTBRANCH_0_TO_IP + i, 0); + } + } +} + +/** + * @brief Enable LBR collection on architectural (ARCH) based LBR + * + * @param Ia32LbrCtl Pointer to the IA32_LBR_CTL_REGISTER whose LBREn bit will be set + * @return VOID + */ +VOID +LbrEnableArchBased(IA32_LBR_CTL_REGISTER * Ia32LbrCtl) +{ + Ia32LbrCtl->Bits.LBREn = 1; +} + +/** + * @brief Enable LBR collection on legacy based LBR + * + * @param DbgCtlMsr Pointer to the IA32_DEBUGCTL MSR value to be modified + * @return VOID + */ +VOID +LbrEnableLegacyBased(ULONGLONG * DbgCtlMsr) +{ + // + // Enable LBR and CLEAR 'Freeze LBRs on PMI' (Bit 11) + // If Bit 11 is set, the LBR stops recording as soon as a single PMI interrupt fires + // + *DbgCtlMsr |= IA32_DEBUGCTL_LBR_FLAG; // Bit 0 = 1 + *DbgCtlMsr &= ~(1ULL << IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI_BIT); // Bit 11 = 0 +} + +/** + * @brief Start LBR collection when running natively (outside any hypervisor environment) + * + * @param Ia32LbrCtl The pre-built IA32_LBR_CTL_REGISTER value carrying the filter bits (arch LBR) + * @return VOID + */ +VOID +LbrStartOnNativeMode(IA32_LBR_CTL_REGISTER Ia32LbrCtl) +{ + ULONGLONG DbgCtlMsr = 0; + + if (g_ArchBasedLastBranchRecord) + { + // + // No need to read the existing control since we are replacing it entirely for ARCH LBR + // + LbrEnableArchBased(&Ia32LbrCtl); + xwrmsr(IA32_LBR_CTL, Ia32LbrCtl.AsUInt); + } + else + { + xrdmsr(IA32_DEBUGCTL, &DbgCtlMsr); + LbrEnableLegacyBased(&DbgCtlMsr); + xwrmsr(IA32_DEBUGCTL, DbgCtlMsr); + } +} + +/** + * @brief Read current LBR control register values while in VMX root-mode + * + * @param DbgCtlMsr Pointer to receive the IA32_DEBUGCTL MSR value (legacy LBR) + * @param Ia32LbrCtl Pointer to receive the IA32_LBR_CTL register value (arch LBR) + * @return VOID + */ +VOID +LbrGetValuesOnVmxRootMode(ULONGLONG * DbgCtlMsr, IA32_LBR_CTL_REGISTER * Ia32LbrCtl) +{ + if (g_ArchBasedLastBranchRecord) + { + // + // It is on VMX-root mode, run it directly to get the IA32_LBR_CTL value in VMCS + // + Ia32LbrCtl->AsUInt = g_Callbacks.VmFuncGetGuestIa32LbrCtl(); + } + else + { + // + // It is on VMX-root mode, run it directly to get the IA32_DEBUGCTL MSR value in VMCS + // + *DbgCtlMsr = g_Callbacks.VmFuncGetDebugctl(); + } +} + +/** + * @brief Read current LBR control register values while in VMX non-root mode (via VMCALL) + * + * @param DbgCtlMsr Pointer to receive the IA32_DEBUGCTL MSR value (legacy LBR) + * @param Ia32LbrCtl Pointer to receive the IA32_LBR_CTL register value (arch LBR) + * @return VOID + */ +VOID +LbrGetValuesOnVmxNonRootMode(ULONGLONG * DbgCtlMsr, IA32_LBR_CTL_REGISTER * Ia32LbrCtl) +{ + if (g_ArchBasedLastBranchRecord) + { + // + // It is not on VMX-root mode, so we need to perform a VMCALL to get the IA32_LBR_CTL value on the target core + // + Ia32LbrCtl->AsUInt = g_Callbacks.VmFuncGetGuestIa32LbrCtlVmcallOnTargetCore(); + } + else + { + // + // It is not on VMX-root mode, so we need to perform a VMCALL to get the IA32_DEBUGCTL MSR value on the target core + // + *DbgCtlMsr = g_Callbacks.VmFuncGetDebugctlVmcallOnTargetCore(); + } +} + +/** + * @brief Disable LBR collection on architectural (ARCH) based LBR + * + * @param Ia32LbrCtl Pointer to the IA32_LBR_CTL register whose LBREn bit will be cleared + * @return VOID + */ +VOID +LbrDisableArchBased(IA32_LBR_CTL_REGISTER * Ia32LbrCtl) +{ + Ia32LbrCtl->Bits.LBREn = 0; +} + +/** + * @brief Disable LBR collection on legacy based LBR + * + * @param DbgCtlMsr Pointer to the IA32_DEBUGCTL MSR value whose LBR flag will be cleared + * @return VOID + */ +VOID +LbrDisableLegacyBased(ULONGLONG * DbgCtlMsr) +{ + *DbgCtlMsr &= ~IA32_DEBUGCTL_LBR_FLAG; +} + +/** + * @brief Write back modified LBR control register values while in VMX root-mode + * + * @param DbgCtlMsr The updated IA32_DEBUGCTL MSR value to apply (legacy LBR) + * @param Ia32LbrCtl The updated IA32_LBR_CTL register value to apply (arch LBR) + * @return VOID + */ +VOID +LbrSetValuesOnVmxRootMode(ULONGLONG DbgCtlMsr, IA32_LBR_CTL_REGISTER Ia32LbrCtl) +{ + if (g_ArchBasedLastBranchRecord) + { + // + // It is on VMX-root mode, run it directly to set the IA32_LBR_CTL value in VMCS + // + g_Callbacks.VmFuncSetGuestIa32LbrCtl(Ia32LbrCtl.AsUInt); + } + else + { + // + // It is on VMX-root mode, run it directly to set the IA32_DEBUGCTL MSR value in VMCS + // + g_Callbacks.VmFuncSetDebugctl(DbgCtlMsr); + } +} + +/** + * @brief Write back modified LBR control register values while in VMX non-root mode (via VMCALL) + * + * @param DbgCtlMsr The updated IA32_DEBUGCTL MSR value to apply (legacy LBR) + * @param Ia32LbrCtl The updated IA32_LBR_CTL register value to apply (arch LBR) + * @return VOID + */ +VOID +LbrSetValuesOnVmxNonRootMode(ULONGLONG DbgCtlMsr, IA32_LBR_CTL_REGISTER Ia32LbrCtl) +{ + if (g_ArchBasedLastBranchRecord) + { + // + // It is not on VMX-root mode, so we need to perform a VMCALL to set the IA32_LBR_CTL value on the target core + // + g_Callbacks.VmFuncSetGuestIa32LbrCtlVmcallOnTargetCore(Ia32LbrCtl.AsUInt); + } + else + { + // + // It is not on VMX-root mode, so we need to perform a VMCALL to set the IA32_DEBUGCTL MSR value on the target core + // + g_Callbacks.VmFuncSetDebugctlVmcallOnTargetCore(DbgCtlMsr); + } +} + +/** + * @brief Stop LBR collection when running natively (outside any hypervisor environment) + * + * @return VOID + */ +VOID +LbrStopOnNativeMode() +{ + ULONGLONG DbgCtlMsr = NULL64_ZERO; + IA32_LBR_CTL_REGISTER Ia32LbrCtl = {0}; + + if (g_ArchBasedLastBranchRecord) + { + xrdmsr(IA32_LBR_CTL, &Ia32LbrCtl.AsUInt); + LbrDisableArchBased(&Ia32LbrCtl); + xwrmsr(IA32_LBR_CTL, Ia32LbrCtl); + } + else + { + xrdmsr(IA32_DEBUGCTL, &DbgCtlMsr); + LbrDisableLegacyBased(&DbgCtlMsr); + xwrmsr(IA32_DEBUGCTL, DbgCtlMsr); + } +} + +/** + * @brief Zero the ARCH LBR control register while in VMX root-mode + * + * @details Setting IA32_LBR_CTL to 0 simultaneously clears all filter bits and + * disables collection (LBREn = 0), which is the correct flush state. + * + * @return VOID + */ +VOID +LbrResetArchControlOnVmxRootMode() +{ + // + // It is on VMX-root mode, set the entire IA32_LBR_CTL to 0 directly in VMCS + // (this also disables LBR since LBREn is cleared) + // + g_Callbacks.VmFuncSetGuestIa32LbrCtl(0); +} + +/** + * @brief Zero the ARCH LBR control register while in VMX non-root mode (via VMCALL) + * + * @details Setting IA32_LBR_CTL to 0 simultaneously clears all filter bits and + * disables collection (LBREn = 0), which is the correct flush state. + * + * @return VOID + */ +VOID +LbrResetArchControlOnVmxNonRootMode() +{ + // + // It is not on VMX-root mode, perform a VMCALL to set the entire IA32_LBR_CTL to 0 on the target core + // (this also disables LBR since LBREn is cleared) + // + g_Callbacks.VmFuncSetGuestIa32LbrCtlVmcallOnTargetCore(0); +} + +/** + * @brief Reset the LBR control registers to zero, covering both ARCH and legacy LBR + * across all execution environments (native, VMX root-mode, VMX non-root mode) + * + * @details For architectural LBR, IA32_LBR_CTL is zeroed entirely (clearing filter bits + * and disabling collection in one write). For legacy LBR, MSR_LEGACY_LBR_SELECT + * is zeroed to reset the branch filter to its default capture-all state. + * Note: Even though MSR_LEGACY_LBR_SELECT is a plain MSR (not a VMCS field), + * it must be written from VMX-root mode for the change to take effect. + * + * @return VOID + */ +VOID +LbrResetControlRegisters() +{ + BOOLEAN IsOnVmxRootMode; + + if (g_RunningOnHypervisorEnvironment) + { + IsOnVmxRootMode = g_Callbacks.VmFuncVmxGetCurrentExecutionMode(); + + // + // If we don't set it on VMX-root mode, the LBR MSRs won't work based on our tests + // even though it is just a plain MSR (and not a VMCS field) + // + if (IsOnVmxRootMode) + { + if (g_ArchBasedLastBranchRecord) + { + LbrResetArchControlOnVmxRootMode(); + } + else + { + // + // Reuse LbrSetLbrSelectFilter: writing 0 resets MSR_LEGACY_LBR_SELECT to + // its default state (capture all branch types) from VMX-root mode + // + g_Callbacks.VmFuncSetLbrSelect(0); + } + } + else + { + if (g_ArchBasedLastBranchRecord) + { + LbrResetArchControlOnVmxNonRootMode(); + } + else + { + // + // Reuse LbrSetLbrSelectFilter: writing 0 resets MSR_LEGACY_LBR_SELECT to + // its default state (capture all branch types) via VMCALL on the target core + // + g_Callbacks.VmFuncSetLbrSelectVmcallOnTargetCore(0); + } + } + } + else + { + if (g_ArchBasedLastBranchRecord) + { + xwrmsr(IA32_LBR_CTL, 0); + } + else + { + xwrmsr(MSR_LEGACY_LBR_SELECT, 0); + } + } +} + +/** + * @brief Adjust filter options for call stack + * + * @param FilterOptions A bitmask of filter options + * @return VOID + */ +VOID +LbrAdjustFilterOptionsForCallStack(UINT64 * FilterOptions) +{ + // + // Call-stack mode should be used with branch type enabling configured to capture only CALLs (NEAR_REL_CALL and + // NEAR_IND_CALL) and RETs (NEAR_RET). When configured in this manner, the LBR array emulates a call stack, + // where CALLs are "pushed" and RETs "pop" them off the stack. If other branch types (JCC, NEAR_*_JMP, or + // OTHER_BRANCH) are enabled for recording with call-stack mode, LBR behavior may be undefined, so we will + // mask out any branch type filters that are not CALLs or RETs when call-stack mode is requested to ensure + // we are correctly emulating a call stack and avoiding undefined behavior + // + + // + // If it is call_stack then we only keep the user and kernel bit and filter all branch types + // except calls and rets to ensure we are only capturing call stack profile + // + if (*FilterOptions & LBR_CALL_STACK) + { + // + // Preserve only the user/kernel privilege bits from the original options, + // then apply the mandatory call stack base flags + // + *FilterOptions = LBR_CALL_STACK_BASE_FLAGS | (*FilterOptions & (LBR_KERNEL | LBR_USER)); + } +} + +/** + * @brief Adjust filter options + * + * @param FilterOptions A bitmask of filter options + * @param Ia32LbrCtl Pointer to the IA32_LBR_CTL_REGISTER to adjust based on the filter options and CPU capabilities + * + * @return VOID + */ +VOID +LbrAdjustFilterOptions(UINT64 FilterOptions, IA32_LBR_CTL_REGISTER * Ia32LbrCtl) +{ + // + // Adjust filter options in case of call_stack + // + LbrAdjustFilterOptionsForCallStack(&FilterOptions); + + // + // Save the LBR filter options to a global variable for later use + // + g_LbrFilterOptions = FilterOptions; + + // + // For architectural LBR, convert filter options into IA32_LBR_CTL bit fields + // + if (g_ArchBasedLastBranchRecord) + { + LbrBuildArchBasedFilterOptions(FilterOptions, Ia32LbrCtl); + } + + // + // For legacy LBR, write the raw filter options to MSR_LEGACY_LBR_SELECT + // Architectural LBR encodes its filters in IA32_LBR_CTL and does not use this MSR + // + if (!g_ArchBasedLastBranchRecord) + { + LbrSetLbrSelectFilter(FilterOptions); + } +} + +/** + * @brief Check if architectural LBR is enabled based on the IA32_LBR_CTL register value + * + * @param Ia32LbrCtl The IA32_LBR_CTL register value to inspect + * @return BOOLEAN + */ +BOOLEAN +LbrCheckArchBased(IA32_LBR_CTL_REGISTER Ia32LbrCtl) +{ + return Ia32LbrCtl.Bits.LBREn ? TRUE : FALSE; +} + +/** + * @brief Check if legacy LBR is enabled based on the IA32_DEBUGCTL MSR value + * + * @param DbgCtlMsr The IA32_DEBUGCTL MSR value to inspect + * @return BOOLEAN + */ +BOOLEAN +LbrCheckLegacyBased(ULONGLONG DbgCtlMsr) +{ + return (DbgCtlMsr & IA32_DEBUGCTL_LBR_FLAG) ? TRUE : FALSE; +} + +/** + * @brief Check if LBR is enabled while in VMX root-mode + * + * @return BOOLEAN + */ +BOOLEAN +LbrCheckOnVmxRootMode() +{ + ULONGLONG DbgCtlMsr = 0; + IA32_LBR_CTL_REGISTER Ia32LbrCtl = {0}; + + if (g_ArchBasedLastBranchRecord) + { + Ia32LbrCtl.AsUInt = g_Callbacks.VmFuncGetGuestIa32LbrCtl(); + return LbrCheckArchBased(Ia32LbrCtl); + } + else + { + DbgCtlMsr = g_Callbacks.VmFuncGetDebugctl(); + return LbrCheckLegacyBased(DbgCtlMsr); + } +} + +/** + * @brief Check if LBR is enabled while in native mode or VMX non-root mode + * + * @return BOOLEAN + */ +BOOLEAN +LbrCheckOnNativeOrVmxNonRootMode() +{ + ULONGLONG DbgCtlMsr = 0; + IA32_LBR_CTL_REGISTER Ia32LbrCtl = {0}; + + if (g_ArchBasedLastBranchRecord) + { + xrdmsr(IA32_LBR_CTL, &Ia32LbrCtl.AsUInt); + return LbrCheckArchBased(Ia32LbrCtl); + } + else + { + xrdmsr(IA32_DEBUGCTL, &DbgCtlMsr); + return LbrCheckLegacyBased(DbgCtlMsr); + } +} + +/** + * @brief Check if LBR is enabled or not + * + * @return BOOLEAN + */ +BOOLEAN +LbrCheck() +{ + BOOLEAN IsOnVmxRootMode = FALSE; + + if (g_RunningOnHypervisorEnvironment) + { + IsOnVmxRootMode = g_Callbacks.VmFuncVmxGetCurrentExecutionMode(); + } + + if (IsOnVmxRootMode) + { + return LbrCheckOnVmxRootMode(); + } + else + { + return LbrCheckOnNativeOrVmxNonRootMode(); + } +} + +/** + * @brief Start collecting LBR branches + * + * @param FilterOptions A bitmask of filter options to apply to the LBR branches (e.g., filtering by branch type, privilege level, etc.) + * + * @return BOOLEAN + */ +BOOLEAN +LbrStart(UINT64 FilterOptions) +{ + BOOLEAN IsOnVmxRootMode; + IA32_LBR_CTL_REGISTER Ia32LbrCtl = {0}; + ULONGLONG DbgCtlMsr = 0; + + if (g_LbrCapacity == 0) + { + LogInfo("Err, LBR aborting, CPU model not supported\n"); + return FALSE; + } + + // + // Adjust and set filter options + // + LbrAdjustFilterOptions(FilterOptions, &Ia32LbrCtl); + + // + // Clear hardware state before enabling LBR + // + LbrClearHardwareState(); + + if (g_RunningOnHypervisorEnvironment) + { + IsOnVmxRootMode = g_Callbacks.VmFuncVmxGetCurrentExecutionMode(); + + // + // DEBUGCTL is not involved in ARCH LBR - it has its own dedicated control register + // So for ARCH LBR we skip reading the previous value and build the register from scratch (replacing it) + // + if (!g_ArchBasedLastBranchRecord) + { + if (IsOnVmxRootMode) + { + LbrGetValuesOnVmxRootMode(&DbgCtlMsr, &Ia32LbrCtl); + } + else + { + LbrGetValuesOnVmxNonRootMode(&DbgCtlMsr, &Ia32LbrCtl); + } + } + + // + // Apply the appropriate bit to enable LBR based on whether it is architectural LBR or legacy LBR + // + if (g_ArchBasedLastBranchRecord) + { + LbrEnableArchBased(&Ia32LbrCtl); + } + else + { + LbrEnableLegacyBased(&DbgCtlMsr); + } + + // + // Write the updated LBR control register values back based on the current VMX execution mode + // + if (IsOnVmxRootMode) + { + LbrSetValuesOnVmxRootMode(DbgCtlMsr, Ia32LbrCtl); + } + else + { + LbrSetValuesOnVmxNonRootMode(DbgCtlMsr, Ia32LbrCtl); + } + } + else + { + LbrStartOnNativeMode(Ia32LbrCtl); + } + + return TRUE; +} + +/** + * @brief Stop collecting LBR branches + * + * @return VOID + */ +VOID +LbrStop() +{ + BOOLEAN IsOnVmxRootMode; + ULONGLONG DbgCtlMsr = NULL64_ZERO; + IA32_LBR_CTL_REGISTER Ia32LbrCtl = {0}; + + if (g_RunningOnHypervisorEnvironment) + { + IsOnVmxRootMode = g_Callbacks.VmFuncVmxGetCurrentExecutionMode(); + + // + // Read the current LBR control register values based on the current VMX execution mode + // + if (IsOnVmxRootMode) + { + LbrGetValuesOnVmxRootMode(&DbgCtlMsr, &Ia32LbrCtl); + } + else + { + LbrGetValuesOnVmxNonRootMode(&DbgCtlMsr, &Ia32LbrCtl); + } + + // + // Apply the appropriate bit to disable LBR based on whether it is architectural LBR or legacy LBR + // + if (g_ArchBasedLastBranchRecord) + { + LbrDisableArchBased(&Ia32LbrCtl); + } + else + { + LbrDisableLegacyBased(&DbgCtlMsr); + } + + // + // Write the updated LBR control register values back based on the current VMX execution mode + // + if (IsOnVmxRootMode) + { + LbrSetValuesOnVmxRootMode(DbgCtlMsr, Ia32LbrCtl); + } + else + { + LbrSetValuesOnVmxNonRootMode(DbgCtlMsr, Ia32LbrCtl); + } + } + else + { + LbrStopOnNativeMode(); + } +} + +/** + * @brief Flush LBR MSRs by disabling LBR and clearing all LBR entries + * + * @return VOID + */ +VOID +LbrFlush() +{ + // LogInfo("Flush LBR on cpu core: %d\n", KeGetCurrentProcessorNumberEx(NULL)); + + // + // Stop LBR collection and save any remaining entries + // + LbrStop(); + + // + // Reset the LBR control registers to zero: + // - ARCH LBR: zeroes IA32_LBR_CTL entirely (clears filters and disables collection) + // - Legacy LBR: zeroes MSR_LEGACY_LBR_SELECT (resets branch filter to capture-all) + // + LbrResetControlRegisters(); + + // + // Clear all remaining hardware state (TOS for legacy LBR, and all from/to MSR pairs) + // + LbrClearHardwareState(); +} + +/** + * @brief Filter LBR branches based on the provided options + * @param FilterOptions A bitmask of filter options to apply to the LBR branches + * + * @return VOID + */ +VOID +LbrFilter(UINT64 FilterOptions) +{ + // LogInfo("Updating LBR filter options: 0x%llx\n", FilterOptions); + + // + // First, we flush the LBR to clear out any existing entries that may not meet the new filter criteria + // + LbrFlush(); + + // + // Then we apply the new filter options and re-enable LBR with the updated filter settings + // + LbrStart(FilterOptions); +} + +/** + * @brief Save LBR branches + * + * @return VOID + */ +VOID +LbrSave() +{ + UINT64 LbrTos; + LBR_STACK_ENTRY * State; + UINT32 CurrentCore = 0; + + // + // Get the current core id + // + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + + // + // Get the current processor LBR stack + // + State = &g_LbrStateList[CurrentCore]; + + // + // Read and store the current TOS index to know where the most recent branch is stored + // Note that there is no TOS index in ARCH LBR since everything is in order + // + if (!g_ArchBasedLastBranchRecord) + { + xrdmsr(MSR_LBR_TOS, &LbrTos); + State->Tos = (UINT8)LbrTos; + } + + // + // Dump LBR entries into the current core's state structure + // + for (ULONG i = 0; i < (ULONG)g_LbrCapacity; i++) + { + if (g_ArchBasedLastBranchRecord) + { + xrdmsr(IA32_LBR_0_FROM_IP + i, &State->BranchEntry[i].From); + xrdmsr(IA32_LBR_0_TO_IP + i, &State->BranchEntry[i].To); + xrdmsr(IA32_LBR_0_INFO + i, &State->LastBranchInfo[i].AsUInt); + } + else + { + xrdmsr(MSR_LASTBRANCH_0_FROM_IP + i, &State->BranchEntry[i].From); + xrdmsr(MSR_LASTBRANCH_0_TO_IP + i, &State->BranchEntry[i].To); + xrdmsr(MSR_LASTBRANCH_INFO_0 + i, &State->LastBranchInfo[i].AsUInt); + } + } +} + +/** + * @brief Get the branch type name based on the LBR branch type value (only applicable for architectural LBR) + * + * @details THIS FUNCTION IS ALSO IMPLEMENTED IN THE USER MODE + * + * @param BrType The raw branch type value from the LBR info MSR + * @param BrTypeName A character buffer to receive the branch type name string + * + * @return VOID + */ +VOID +LbrGetArchBranchType(UINT32 BrType, CHAR * BrTypeName) +{ + if (BrType == LBR_BR_TYPE_COND) + { + strncpy(BrTypeName, "COND ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType == LBR_BR_TYPE_JMP_INDIRECT) + { + strncpy(BrTypeName, "JMP Indirect ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType == LBR_BR_TYPE_JMP_DIRECT) + { + strncpy(BrTypeName, "JMP Direct ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType == LBR_BR_TYPE_CALL_INDIRECT) + { + strncpy(BrTypeName, "CALL Indirect", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType == LBR_BR_TYPE_CALL_DIRECT) + { + strncpy(BrTypeName, "CALL Direct ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType == LBR_BR_TYPE_RET) + { + strncpy(BrTypeName, "RET ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType >= LBR_BR_TYPE_RESERVED_MIN && BrType <= LBR_BR_TYPE_RESERVED_MAX) + { + strncpy(BrTypeName, "Reserved ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType >= LBR_BR_TYPE_OTHER_MIN && BrType <= LBR_BR_TYPE_OTHER_MAX) + { + strncpy(BrTypeName, "Other Branch ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else + { + strncpy(BrTypeName, "Unknown ", LBR_BR_TYPE_NAME_MAX_LEN); + } +} + +/** + * @brief Print collected LBR branches + * + * @return VOID + */ +VOID +LbrPrint() +{ + ULONG CurrentIdx; + LBR_STACK_ENTRY * State; + UINT32 CurrentCore = 0; + CHAR BrTypeName[LBR_BR_TYPE_NAME_MAX_LEN] = {0}; + UINT32 BrType = 0; + // + // Get the current core id + // + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + + // + // Get the current processor LBR stack + // + State = &g_LbrStateList[CurrentCore]; + + Log("LBR Chronological Trace on core : 0x%x\n\n", CurrentCore); + + for (ULONG i = 1; i <= g_LbrCapacity; i++) + { + if (g_ArchBasedLastBranchRecord) + { + // + // In ARCH LBR, there is not TOS index and everything is in order + // + CurrentIdx = i - 1; + } + else + { + CurrentIdx = (ULONG)(State->Tos + i) % (ULONG)g_LbrCapacity; + } + + if (State->BranchEntry[CurrentIdx].From == 0) + { + continue; + } + + if (g_ArchBasedLastBranchRecord) + { + BrType = (UINT32)State->LastBranchInfo[CurrentIdx].BrType_OnlyArchLbr; + + // + // Get the branch type name for better readability when printing + // + LbrGetArchBranchType(BrType, BrTypeName); + + // + // Architectural LBR + // + Log("\t [%2u] Branch Mispredicted: %s, Branch type: %s, Cycle Count (Decimal): %04d (is valid? %s) - From: %016llx To: %016llx\n", + CurrentIdx, + State->LastBranchInfo[CurrentIdx].Mispred ? "true " : "false", + BrTypeName, + State->LastBranchInfo[CurrentIdx].CycleCount, + State->LastBranchInfo[CurrentIdx].CycCntValid_OnlyArchLbr ? "true " : "false", + State->BranchEntry[CurrentIdx].From, + State->BranchEntry[CurrentIdx].To); + } + else + { + // + // Legacy LBR + // + Log("\t [%2u] Branch Mispredicted: %s, Cycle Count (Decimal): %04d - From: %016llx To: %016llx\n", + CurrentIdx, + State->LastBranchInfo[CurrentIdx].Mispred ? "true " : "false", + State->LastBranchInfo[CurrentIdx].CycleCount, + State->BranchEntry[CurrentIdx].From, + State->BranchEntry[CurrentIdx].To); + } + } +} diff --git a/hyperdbg/hypertrace/code/pt/Pt.c b/hyperdbg/hypertrace/code/pt/Pt.c new file mode 100644 index 00000000..2dfe7ce5 --- /dev/null +++ b/hyperdbg/hypertrace/code/pt/Pt.c @@ -0,0 +1,1510 @@ +/** + * @file Pt.c + * @author Masoud Rahimi Jafari (Masoodrahimy1379@gmail.com) + * @brief Processor Trace (PT) tracing implementation for HyperTrace module + * @details Programs Intel PT MSRs and manages per-CPU ToPA / output buffers. + * The engine half (PtEngine*) deals with a single PT_PER_CPU at a + * time and is OS-agnostic. The HyperDbg wrappers (PtCheck, PtStart, + * PtStop, PtPause, PtResume, PtSize, PtDump, PtFlush) operate on the + * global per-CPU state list (g_PtStateList) and mirror the LBR API + * surface. + * @version 0.19 + * @date 2026-04-29 + * + * @copyright This project is released under the GNU Public License v3. + */ +#include "pch.h" + +////////////////////////////////////////////////// +// Internal allocation helpers // +////////////////////////////////////////////////// + +/** + * @brief Allocate physically contiguous memory for ToPA / output buffers. + * + * Intel PT requires the output region's physical address to be aligned to + * its own size. We use MmAllocateContiguousMemorySpecifyCache with a + * BoundaryAddressMultipleOf equal to the requested size — the allocator + * then picks a base that does not cross any size-aligned boundary, which + * for a power-of-two size means the base is a multiple of that size. + * + * @param Size Bytes to allocate. Must be a power of two for size + * alignment. + * @param Alignment Requested alignment in bytes. Pass `Size` for the + * ToPA output region; pass PT_PAGE_SIZE for the ToPA + * table itself and the overflow page. + * + * @return PVOID Virtual address of the allocation, or NULL on failure. + */ +static PVOID +PtAllocateContiguousAligned(UINT64 Size, UINT64 Alignment) +{ + PHYSICAL_ADDRESS Lo = {0}; + PHYSICAL_ADDRESS Hi = {0}; + PHYSICAL_ADDRESS Boundary = {0}; + PVOID Result; + + Hi.QuadPart = MAXULONG64; + Boundary.QuadPart = (LONGLONG)Alignment; + + Result = MmAllocateContiguousMemorySpecifyCache( + (SIZE_T)Size, + Lo, + Hi, + Boundary, + MmCached); + + if (Result != NULL) + { + RtlSecureZeroMemory(Result, (SIZE_T)Size); + } + + return Result; +} + +/** + * @brief Free a physically contiguous allocation made by PtAllocateContiguousAligned. + */ +static VOID +PtFreeContiguous(PVOID Va) +{ + if (Va != NULL) + { + MmFreeContiguousMemory(Va); + } +} + +/** + * @brief Translate a kernel virtual address to a physical address. + */ +static UINT64 +PtVaToPa(PVOID Va) +{ + PHYSICAL_ADDRESS Pa = MmGetPhysicalAddress(Va); + return (UINT64)Pa.QuadPart; +} + +////////////////////////////////////////////////// +// User-mode mmap helpers // +////////////////////////////////////////////////// + +/** + * @brief Build an MDL whose PFN list concatenates the main output + * buffer and the overflow page, then map the combined region + * into the current user process as one virtually contiguous + * range. + * + * Main and overflow come from separate + * MmAllocateContiguousMemorySpecifyCache calls so they are each + * physically contiguous but not contiguous with each other. By + * constructing one MDL whose PFN array is [main pfns | overflow + * pfns], MmMapLockedPagesSpecifyCache produces a single user VA + * range of MainSize + OverflowSize bytes that the consumer reads + * as one stream (main first, overflow second). Pages are + * non-paged so MDL_PAGES_LOCKED is enough to satisfy the mapper. + * + * Wrapped in SEH because MmMapLockedPagesSpecifyCache raises on + * quota / VAD failures rather than returning NULL. + * + * @return INT32 0 on success, -1 on failure (outputs untouched). + */ +static INT32 +PtMmapCpuRegionToUser(PVOID MainVa, + UINT64 MainPhysical, + SIZE_T MainSize, + UINT64 OverflowPhysical, + SIZE_T OverflowSize, + PMDL * OutMdl, + PVOID * OutUserVa) +{ + SIZE_T TotalSize = MainSize + OverflowSize; + ULONG MainPages; + ULONG OverflowPages; + ULONG i; + PFN_NUMBER * Pfns; + PFN_NUMBER MainPfnBase; + PFN_NUMBER OverflowPfnBase; + PMDL Mdl; + PVOID UserVa = NULL; + + if (MainVa == NULL || MainSize == 0 || OverflowSize == 0 || TotalSize == 0) + return -1; + + // + // Sizes must be whole pages — ToPA-backed buffers always are. + // + if ((MainSize & (PT_PAGE_SIZE - 1)) != 0 || (OverflowSize & (PT_PAGE_SIZE - 1)) != 0) + return -1; + + // + // IoAllocateMdl sizes the embedded PFN array from the byte range we + // pass in. The seed VA only sets the byte-offset within the first + // page (0 for our page-aligned contiguous allocations); we overwrite + // the PFN list below so it stops describing MainVa past its own end. + // + Mdl = IoAllocateMdl(MainVa, (ULONG)TotalSize, FALSE, FALSE, NULL); + if (Mdl == NULL) + return -1; + + MainPages = (ULONG)(MainSize >> PAGE_SHIFT); + OverflowPages = (ULONG)(OverflowSize >> PAGE_SHIFT); + MainPfnBase = (PFN_NUMBER)(MainPhysical >> PAGE_SHIFT); + OverflowPfnBase = (PFN_NUMBER)(OverflowPhysical >> PAGE_SHIFT); + + Pfns = MmGetMdlPfnArray(Mdl); + for (i = 0; i < MainPages; i++) + Pfns[i] = MainPfnBase + i; + for (i = 0; i < OverflowPages; i++) + Pfns[MainPages + i] = OverflowPfnBase + i; + + // + // Pages are physically present and non-pageable (contiguous memory); + // tag the MDL so MmMapLockedPagesSpecifyCache accepts it. + // + Mdl->MdlFlags |= MDL_PAGES_LOCKED; + + __try + { + UserVa = MmMapLockedPagesSpecifyCache( + Mdl, + UserMode, + MmCached, + NULL, + FALSE, + NormalPagePriority); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + UserVa = NULL; + } + + if (UserVa == NULL) + { + IoFreeMdl(Mdl); + return -1; + } + + *OutMdl = Mdl; + *OutUserVa = UserVa; + return 0; +} + +/** + * @brief Tear down the combined user mapping produced by + * PtMmapCpuRegionToUser. Caller must be in the mapping process; + * see the cooperative single-process contract. + */ +static VOID +PtUnmapCpuRegionFromUser(PMDL Mdl, PVOID UserVa) +{ + if (UserVa != NULL && Mdl != NULL) + { + __try + { + MmUnmapLockedPages(UserVa, Mdl); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + // + // Mapping process may have already exited. + // + } + } + + if (Mdl != NULL) + { + IoFreeMdl(Mdl); + } +} + +////////////////////////////////////////////////// +// Engine routines // +////////////////////////////////////////////////// + +/** + * @brief Convert a buffer size in bytes to the ToPA Size field encoding. + * Valid sizes are 4KB * 2^N for N = 0..15. + * + * @param SizeInBytes + * @return INT32 Encoding 0..15, or -1 if the size is not supported. + */ +INT32 +PtEngineSizeToTopaEncoding(UINT64 SizeInBytes) +{ + UINT64 Pages; + INT32 N; + + if (SizeInBytes < PT_PAGE_SIZE) + return -1; + + Pages = SizeInBytes / PT_PAGE_SIZE; + + // + // Must be an exact power-of-two number of pages + // + if ((Pages & (Pages - 1)) != 0) + return -1; + + N = 0; + while ((Pages >> N) != 1) + N++; + + if (N > 15) + return -1; + + return N; +} + +/** + * @brief Probe Intel PT capabilities via CPUID leaf 7 / leaf 0x14. + * + * @param OutCaps Optional. If non-NULL, populated with detailed capabilities. + * + * @return INT32 0 on success (PT supported), -1 if PT is not supported. + */ +INT32 +PtEngineQueryCapabilities(PT_CAPABILITIES * OutCaps) +{ + int Info[4] = {0}; + int MaxSubleaf = 0; + UINT64 VmxMisc; + + // + // Check PT support: CPUID.(EAX=07H,ECX=0):EBX[25] + // + __cpuidex(Info, 0x07, 0); + if ((Info[1] & (1 << 25)) == 0) + return -1; + + if (OutCaps == NULL) + return 0; + + RtlZeroMemory(OutCaps, sizeof(*OutCaps)); + + // + // Leaf 0x14, sub-leaf 0: capability flags + // + Info[0] = Info[1] = Info[2] = Info[3] = 0; + __cpuidex(Info, 0x14, 0); + + MaxSubleaf = Info[0]; /* EAX: max valid sub-leaf */ + + // + // EBX capabilities + // + OutCaps->Cr3Filtering = (Info[1] >> 0) & 1; + OutCaps->PsbCycConfigurable = (Info[1] >> 1) & 1; + OutCaps->IpFiltering = (Info[1] >> 2) & 1; + OutCaps->MtcSupport = (Info[1] >> 3) & 1; + OutCaps->PtwriteSupport = (Info[1] >> 4) & 1; + OutCaps->PowerEventTrace = (Info[1] >> 5) & 1; + + // + // ECX capabilities + // + OutCaps->TopaOutput = (Info[2] >> 0) & 1; + OutCaps->TopaMultiEntry = (Info[2] >> 1) & 1; + OutCaps->SingleRangeOutput = (Info[2] >> 2) & 1; + OutCaps->TransportOutput = (Info[2] >> 3) & 1; + OutCaps->IpPayloadsAreLip = (Info[2] >> 31) & 1; + + // + // Sub-leaf 1: detailed numerics + // + if (MaxSubleaf >= 1) + { + Info[0] = Info[1] = Info[2] = Info[3] = 0; + __cpuidex(Info, 0x14, 1); + + OutCaps->NumAddrRanges = (UINT32)(Info[0] & 0x7); + OutCaps->MtcPeriodBitmap = (UINT16)((Info[0] >> 16) & 0xFFFF); + OutCaps->CycThresholdBitmap = (UINT16)(Info[1] & 0xFFFF); + OutCaps->PsbFreqBitmap = (UINT16)((Info[1] >> 16) & 0xFFFF); + } + + // + // VMX support: IA32_VMX_MISC[14] indicates Intel PT may be used in VMX + // operation. Reading IA32_VMX_MISC is unconditional on a VMX-capable + // CPU; if the CPU isn't VMX-capable the bit is meaningless and the + // value falls through as 0. + // + VmxMisc = __readmsr(0x00000485 /* IA32_VMX_MISC */); + OutCaps->VmxSupport = (VmxMisc >> 14) & 1; + + return 0; +} + +/** + * @brief Initialize a PT_TRACE_CONFIG with sensible defaults. + * Trace user + kernel, branch + TSC packets, 2 MB output buffer. + */ +VOID +PtEngineInitDefaultConfig(PT_TRACE_CONFIG * Config) +{ + UINT32 i; + + Config->TraceUser = TRUE; + Config->TraceKernel = TRUE; + Config->TargetCr3 = 0; + Config->NumAddrRanges = 0; + Config->EnableBranch = TRUE; + Config->EnableTsc = FALSE; + Config->EnableMtc = FALSE; + Config->EnableCyc = FALSE; + Config->EnableRetCompression = FALSE; + Config->MtcFreq = 0; + Config->CycThresh = 0; + Config->PsbFreq = 0; + Config->BufferSize = PT_DEFAULT_BUFFER_SIZE; + + for (i = 0; i < PT_MAX_ADDR_RANGES; i++) + { + Config->AddrRanges[i].Start = 0; + Config->AddrRanges[i].End = 0; + Config->AddrRanges[i].IsStopRange = FALSE; + } +} + +/** + * @brief Allocate the ToPA table, output buffer, and overflow zone for one + * per-CPU PT context, then build the ToPA entries. + * + * ToPA layout: + * [0] main output buffer (Config->BufferSize), INT=1 + * [1] overflow page (4 KB), INT=0 + * [2] END, wraps back to ToPA table (circular) + * + * @return INT32 0 on success, -1 on allocation failure, -2 on bad config. + */ +INT32 +PtEngineAllocateBuffers(PT_PER_CPU * Cpu, const PT_TRACE_CONFIG * Config) +{ + INT32 SizeEncoding; + UINT64 BufSize; + PT_TOPA_ENTRY * Topa; + + if (Cpu == NULL || Config == NULL) + return -2; + + BufSize = Config->BufferSize; + if (BufSize == 0) + BufSize = PT_DEFAULT_BUFFER_SIZE; + + // + // Validate buffer size is a valid ToPA encoding + // + SizeEncoding = PtEngineSizeToTopaEncoding(BufSize); + if (SizeEncoding < 0) + return -2; + + // + // 1. ToPA table — one 4KB page, must be 4KB-aligned + // + Cpu->Buffer.TopaVa = (PT_TOPA_ENTRY *)PtAllocateContiguousAligned(PT_PAGE_SIZE, PT_PAGE_SIZE); + if (Cpu->Buffer.TopaVa == NULL) + return -1; + Cpu->Buffer.TopaPhysical = PtVaToPa(Cpu->Buffer.TopaVa); + + // + // 2. Main output buffer — must be aligned to its own size + // + Cpu->Buffer.OutputVa = PtAllocateContiguousAligned(BufSize, BufSize); + if (Cpu->Buffer.OutputVa == NULL) + { + PtFreeContiguous(Cpu->Buffer.TopaVa); + Cpu->Buffer.TopaVa = NULL; + return -1; + } + Cpu->Buffer.OutputPhysical = PtVaToPa(Cpu->Buffer.OutputVa); + Cpu->Buffer.OutputSize = BufSize; + + // + // 3. Overflow landing zone — 4KB + // + Cpu->Buffer.OverflowVa = PtAllocateContiguousAligned(PT_OVERFLOW_SIZE, PT_PAGE_SIZE); + if (Cpu->Buffer.OverflowVa == NULL) + { + PtFreeContiguous(Cpu->Buffer.OutputVa); + Cpu->Buffer.OutputVa = NULL; + PtFreeContiguous(Cpu->Buffer.TopaVa); + Cpu->Buffer.TopaVa = NULL; + return -1; + } + Cpu->Buffer.OverflowPhysical = PtVaToPa(Cpu->Buffer.OverflowVa); + + // + // 4. Build the ToPA table — 3 entries + // + Topa = Cpu->Buffer.TopaVa; + + // + // Entry 0: main data buffer, INT=1 (trigger PMI when full) + // + Topa[0].Value = 0; + Topa[0].BaseAddr = Cpu->Buffer.OutputPhysical >> 12; + Topa[0].Size = (UINT64)SizeEncoding; + Topa[0].Int = 1; + Topa[0].Stop = 0; + + // + // Entry 1: overflow landing zone (4 KB), no interrupt + // + Topa[1].Value = 0; + Topa[1].BaseAddr = Cpu->Buffer.OverflowPhysical >> 12; + Topa[1].Size = PT_TOPA_SIZE_4K; + Topa[1].Int = 0; + Topa[1].Stop = 0; + + // + // Entry 2: END — circular, points back to this ToPA table + // + Topa[2].Value = 0; + Topa[2].End = 1; + Topa[2].BaseAddr = Cpu->Buffer.TopaPhysical >> 12; + + // + // Copy config and initialize state + // + Cpu->Config = *Config; + Cpu->Config.BufferSize = BufSize; + Cpu->SavedCtl.Value = 0; + Cpu->State = PT_STATE_READY; + Cpu->TotalBytesCaptured = 0; + + return 0; +} + +/** + * @brief Free all PT buffers belonging to one per-CPU context. + * Must not be called while State == PT_STATE_TRACING. + */ +VOID +PtEngineFreeBuffers(PT_PER_CPU * Cpu) +{ + if (Cpu == NULL) + return; + + // + // Refuse to free while tracing — caller must stop first + // + if (Cpu->State == PT_STATE_TRACING) + return; + + if (Cpu->Buffer.OverflowVa) + { + PtFreeContiguous(Cpu->Buffer.OverflowVa); + Cpu->Buffer.OverflowVa = NULL; + Cpu->Buffer.OverflowPhysical = 0; + } + if (Cpu->Buffer.OutputVa) + { + PtFreeContiguous(Cpu->Buffer.OutputVa); + Cpu->Buffer.OutputVa = NULL; + Cpu->Buffer.OutputPhysical = 0; + Cpu->Buffer.OutputSize = 0; + } + if (Cpu->Buffer.TopaVa) + { + PtFreeContiguous(Cpu->Buffer.TopaVa); + Cpu->Buffer.TopaVa = NULL; + Cpu->Buffer.TopaPhysical = 0; + } + + Cpu->State = PT_STATE_DISABLED; + Cpu->TotalBytesCaptured = 0; + Cpu->SavedCtl.Value = 0; +} + +/** + * @brief Build IA32_RTIT_CTL from a config + capabilities. + * Does not set TraceEn; caller is responsible for enabling last. + */ +static PT_RTIT_CTL_REGISTER +PtEngineBuildCtlFromConfig(const PT_TRACE_CONFIG * Cfg, + const PT_CAPABILITIES * Caps) +{ + PT_RTIT_CTL_REGISTER Ctl; + Ctl.Value = 0; + + // + // Core settings + // + Ctl.TraceEn = 0; /* enabled last, after everything is set */ + Ctl.ToPA = 1; /* always use ToPA output */ + Ctl.FabricEn = 0; /* always output to memory */ + + // + // Privilege filter + // + Ctl.Os = Cfg->TraceKernel ? 1 : 0; + Ctl.User = Cfg->TraceUser ? 1 : 0; + + // + // CR3 filtering + // + Ctl.Cr3Filter = (Cfg->TargetCr3 != 0) ? 1 : 0; + + // + // Branch tracing — the core functionality + // + Ctl.BranchEn = Cfg->EnableBranch ? 1 : 0; + + // + // Timing packets + // + Ctl.TscEn = Cfg->EnableTsc ? 1 : 0; + + if (Caps->MtcSupport) + { + Ctl.MtcEn = Cfg->EnableMtc ? 1 : 0; + if (Cfg->EnableMtc && ((1 << Cfg->MtcFreq) & Caps->MtcPeriodBitmap)) + Ctl.MtcFreq = Cfg->MtcFreq; + } + + if (Caps->PsbCycConfigurable) + { + Ctl.CycEn = Cfg->EnableCyc ? 1 : 0; + if (Cfg->EnableCyc && ((1 << Cfg->CycThresh) & Caps->CycThresholdBitmap)) + Ctl.CycThresh = Cfg->CycThresh; + if ((1 << Cfg->PsbFreq) & Caps->PsbFreqBitmap) + Ctl.PsbFreq = Cfg->PsbFreq; + } + + // + // RET compression + // + Ctl.DisRetc = Cfg->EnableRetCompression ? 0 : 1; + + // + // IP filter range configuration + // + Ctl.Addr0Cfg = 0; + Ctl.Addr1Cfg = 0; + Ctl.Addr2Cfg = 0; + Ctl.Addr3Cfg = 0; + + if (Cfg->NumAddrRanges > 0 && Caps->IpFiltering) + { + if (Cfg->NumAddrRanges >= 1 && Caps->NumAddrRanges >= 1) + Ctl.Addr0Cfg = Cfg->AddrRanges[0].IsStopRange ? 2 : 1; + if (Cfg->NumAddrRanges >= 2 && Caps->NumAddrRanges >= 2) + Ctl.Addr1Cfg = Cfg->AddrRanges[1].IsStopRange ? 2 : 1; + if (Cfg->NumAddrRanges >= 3 && Caps->NumAddrRanges >= 3) + Ctl.Addr2Cfg = Cfg->AddrRanges[2].IsStopRange ? 2 : 1; + if (Cfg->NumAddrRanges >= 4 && Caps->NumAddrRanges >= 4) + Ctl.Addr3Cfg = Cfg->AddrRanges[3].IsStopRange ? 2 : 1; + } + + return Ctl; +} + +/** + * @brief Start tracing on the CURRENT CPU using the passed PT_PER_CPU. + * Programs all PT MSRs and sets TraceEn=1. + * + * Must be called from the target CPU (DPC or VMX root). + * + * @return INT32 0 on success, -1 on error. + */ +INT32 +PtEngineStart(PT_PER_CPU * Cpu) +{ + PT_RTIT_CTL_REGISTER Ctl; + PT_CAPABILITIES Caps; + UINT32 i; + BOOLEAN IsOnVmxRootMode = FALSE; + + if (Cpu == NULL) + return -1; + if (Cpu->State != PT_STATE_READY && Cpu->State != PT_STATE_STOPPED) + return -1; + if (Cpu->Buffer.TopaVa == NULL || Cpu->Buffer.OutputVa == NULL) + return -1; + + if (PtEngineQueryCapabilities(&Caps) != 0) + return -1; + + // + // Detect VMX-root context if running under HyperDbg's hypervisor. + // + // Intel PT MSRs (IA32_RTIT_*) are NOT in the default MSR bitmap, so a + // direct WRMSR to them in either VMX root or VMX non-root passes + // through to hardware without trapping. This means the same MSR + // sequence below works correctly from a DPC running in the guest as + // well as from a VMX-root packet handler. We still read the mode for + // logging and for any future hypervisor-only code (e.g. setting the + // "Clear IA32_RTIT_CTL on VM-exit" VMCS control or saving guest-side + // RTIT state across VM transitions). + // + if (g_RunningOnHypervisorEnvironment) + { + IsOnVmxRootMode = g_Callbacks.VmFuncVmxGetCurrentExecutionMode(); + // LogInfo("PT: PtEngineStart on core %u (vmx-root=%u)\n", + // KeGetCurrentProcessorNumberEx(NULL), + // (UINT32)IsOnVmxRootMode); + } + + // + // Don't request more IP ranges or features than the CPU supports + // + if (Cpu->Config.NumAddrRanges > Caps.NumAddrRanges) + return -1; + if (Cpu->Config.NumAddrRanges > 0 && !Caps.IpFiltering) + return -1; + if (Cpu->Config.TargetCr3 != 0 && !Caps.Cr3Filtering) + return -1; + + // + // Step 1: Ensure tracing is off and clear status + // + { + PT_RTIT_CTL_REGISTER Cur; + Cur.Value = __readmsr(MSR_IA32_RTIT_CTL); + if (Cur.TraceEn) + { + Cur.TraceEn = 0; + __writemsr(MSR_IA32_RTIT_CTL, Cur.Value); + } + } + + __writemsr(MSR_IA32_RTIT_STATUS, 0); + + // + // Step 2: Set output base and reset output position + // + __writemsr(MSR_IA32_RTIT_OUTPUT_BASE, Cpu->Buffer.TopaPhysical); + { + PT_OUTPUT_MASK_PTRS_REGISTER InitMask; + InitMask.Value = 0; + InitMask.LowerMask = 0x7F; + InitMask.MaskOrTableOffset = 0; + InitMask.OutputOffset = 0; + __writemsr(MSR_IA32_RTIT_OUTPUT_MASK_PTRS, InitMask.Value); + } + + // + // Step 3: Set CR3 filter + // + __writemsr(MSR_IA32_RTIT_CR3_MATCH, Cpu->Config.TargetCr3); + + // + // Step 4: Set IP address ranges. IMPORTANT: only touch ADDRn MSRs the + // CPU actually supports; writing to non-existent ADDRn MSRs causes #GP. + // + for (i = 0; i < Caps.NumAddrRanges; i++) + { + UINT32 MsrA = MSR_IA32_RTIT_ADDR0_A + (i * 2); + UINT32 MsrB = MSR_IA32_RTIT_ADDR0_B + (i * 2); + + if (i < Cpu->Config.NumAddrRanges) + { + __writemsr(MsrA, Cpu->Config.AddrRanges[i].Start); + __writemsr(MsrB, Cpu->Config.AddrRanges[i].End); + } + else + { + __writemsr(MsrA, 0); + __writemsr(MsrB, 0); + } + } + + // + // Step 5: Build IA32_RTIT_CTL and enable + // + Ctl = PtEngineBuildCtlFromConfig(&Cpu->Config, &Caps); + + // + // Save the CTL value for resume + // + Cpu->SavedCtl = Ctl; + + // + // Enable tracing — MUST be the last MSR write + // + Ctl.TraceEn = 1; + Cpu->SavedCtl.TraceEn = 1; + __writemsr(MSR_IA32_RTIT_CTL, Ctl.Value); + + // + // Step 6: Verify tracing started + // + { + PT_RTIT_STATUS_REGISTER Status; + Status.Value = __readmsr(MSR_IA32_RTIT_STATUS); + if (Status.Error) + { + Ctl.TraceEn = 0; + __writemsr(MSR_IA32_RTIT_CTL, Ctl.Value); + Cpu->State = PT_STATE_ERROR; + return -1; + } + } + + Cpu->State = PT_STATE_TRACING; + return 0; +} + +/** + * @brief Read current output position, calculate bytes written, and + * optionally copy trace data into Out starting at Out->WriteOffset, + * then advance WriteOffset. + */ +static UINT64 +PtEngineReadBytesWritten(const PT_BUFFER * Buf, PT_OUTPUT_BUFFER * Out) +{ + PT_OUTPUT_MASK_PTRS_REGISTER Mask; + UINT32 TopaIndex; + UINT32 BytesInEntry; + UINT64 Total = 0; + + Mask.Value = __readmsr(MSR_IA32_RTIT_OUTPUT_MASK_PTRS); + + TopaIndex = (UINT32)(Mask.MaskOrTableOffset >> 0); + BytesInEntry = (UINT32)Mask.OutputOffset; + + // + // ToPA layout: + // Entry[0] = main buffer (OutputSize bytes) + // Entry[1] = overflow (4KB) + // Entry[2] = END + // + if (TopaIndex == 0) + { + Total = BytesInEntry; + } + else if (TopaIndex >= 1) + { + Total = Buf->OutputSize + BytesInEntry; + } + + // + // Copy trace data if the caller provided a buffer with enough room + // + if (Out != NULL && Out->Buffer != NULL && Total > 0) + { + if (Out->WriteOffset + Total <= Out->Length) + { + UINT8 * Dest = (UINT8 *)Out->Buffer + Out->WriteOffset; + UINT64 MainBytes = (Total < Buf->OutputSize) ? Total : Buf->OutputSize; + UINT64 SpillBytes = (Total > Buf->OutputSize) ? (Total - Buf->OutputSize) : 0; + + RtlCopyMemory(Dest, Buf->OutputVa, (SIZE_T)MainBytes); + + if (SpillBytes > 0) + RtlCopyMemory(Dest + MainBytes, Buf->OverflowVa, (SIZE_T)SpillBytes); + + Out->WriteOffset += Total; + } + // else: not enough space — skip copy, WriteOffset unchanged + } + + return Total; +} + +/** + * @brief Stop tracing on the CURRENT CPU. Reads final output position, + * copies trace data if requested, resets PT MSRs. + * + * @return UINT64 Total bytes captured (across all PMIs + final), or 0 on error. + */ +UINT64 +PtEngineStop(PT_PER_CPU * Cpu, PT_OUTPUT_BUFFER * Out) +{ + UINT64 BytesThisRun; + UINT32 i; + BOOLEAN IsOnVmxRootMode = FALSE; + + if (Cpu == NULL) + return 0; + if (Cpu->State != PT_STATE_TRACING && Cpu->State != PT_STATE_PAUSED) + return 0; + + // + // Detect VMX-root context for symmetry with PtEngineStart. Direct WRMSR + // works in both modes for PT MSRs (not in MSR bitmap by default). + // + if (g_RunningOnHypervisorEnvironment) + { + IsOnVmxRootMode = g_Callbacks.VmFuncVmxGetCurrentExecutionMode(); + // LogInfo("PT: PtEngineStop on core %u (vmx-root=%u)\n", + // KeGetCurrentProcessorNumberEx(NULL), + // (UINT32)IsOnVmxRootMode); + } + + // + // Disable tracing + // + { + PT_RTIT_CTL_REGISTER Ctl; + Ctl.Value = __readmsr(MSR_IA32_RTIT_CTL); + Ctl.TraceEn = 0; + __writemsr(MSR_IA32_RTIT_CTL, Ctl.Value); + } + + // + // Read final output position and copy data if requested + // + BytesThisRun = PtEngineReadBytesWritten(&Cpu->Buffer, Out); + Cpu->TotalBytesCaptured += BytesThisRun; + + // + // Check for hardware error + // + { + PT_RTIT_STATUS_REGISTER Status; + Status.Value = __readmsr(MSR_IA32_RTIT_STATUS); + if (Status.Error) + { + Cpu->State = PT_STATE_ERROR; + return 0; + } + } + + // + // Reset all PT MSRs + // + __writemsr(MSR_IA32_RTIT_CTL, 0); + __writemsr(MSR_IA32_RTIT_STATUS, 0); + __writemsr(MSR_IA32_RTIT_OUTPUT_BASE, 0); + __writemsr(MSR_IA32_RTIT_OUTPUT_MASK_PTRS, 0); + __writemsr(MSR_IA32_RTIT_CR3_MATCH, 0); + + // + // Clear all ADDRn MSRs that this CPU supports. + // NumAddrRanges was validated against caps in PtEngineStart. + // + for (i = 0; i < Cpu->Config.NumAddrRanges; i++) + { + __writemsr(MSR_IA32_RTIT_ADDR0_A + (i * 2), 0); + __writemsr(MSR_IA32_RTIT_ADDR0_B + (i * 2), 0); + } + + Cpu->State = PT_STATE_STOPPED; + return Cpu->TotalBytesCaptured; +} + +/** + * @brief Pause tracing on the CURRENT CPU. Preserves buffer state. + */ +INT32 +PtEnginePause(PT_PER_CPU * Cpu) +{ + PT_RTIT_CTL_REGISTER Ctl; + + if (Cpu == NULL || Cpu->State != PT_STATE_TRACING) + return -1; + + Ctl.Value = __readmsr(MSR_IA32_RTIT_CTL); + Ctl.TraceEn = 0; + __writemsr(MSR_IA32_RTIT_CTL, Ctl.Value); + + Cpu->State = PT_STATE_PAUSED; + return 0; +} + +/** + * @brief Resume tracing on the CURRENT CPU after pause. + */ +INT32 +PtEngineResume(PT_PER_CPU * Cpu) +{ + PT_RTIT_CTL_REGISTER Ctl; + + if (Cpu == NULL || Cpu->State != PT_STATE_PAUSED) + return -1; + + Ctl = Cpu->SavedCtl; + Ctl.TraceEn = 1; + __writemsr(MSR_IA32_RTIT_CTL, Ctl.Value); + + Cpu->State = PT_STATE_TRACING; + return 0; +} + +/** + * @brief Check whether the latest PMI was raised by Intel PT + * (IA32_PERF_GLOBAL_STATUS bit 55). + */ +BOOLEAN +PtEngineIsPtPmi() +{ + UINT64 GlobalStatus = __readmsr(MSR_IA32_PERF_GLOBAL_STATUS); + return (GlobalStatus & PERF_GLOBAL_STATUS_TOPA_PMI) ? TRUE : FALSE; +} + +/** + * @brief Handle a ToPA PMI on the CURRENT CPU. Caller is responsible for + * having already disabled tracing (e.g. via VMCS clear of RTIT_CTL). + * + * @return UINT64 number of bytes captured in this PMI event. + */ +UINT64 +PtEngineHandlePmi(PT_PER_CPU * Cpu, PT_OUTPUT_BUFFER * Out) +{ + UINT64 BytesThisEvent; + + if (Cpu == NULL) + return 0; + + // + // 1. Read how many bytes were written and copy them out + // + BytesThisEvent = PtEngineReadBytesWritten(&Cpu->Buffer, Out); + Cpu->TotalBytesCaptured += BytesThisEvent; + + // + // 2. Reset output position to start of buffer BEFORE acknowledging the + // PMI. PT keeps tracing during the handler (TraceEn stays 1) and the + // hardware is free to raise another ToPA PMI as soon as PendTopaPmi / + // PERF_GLOBAL_STATUS.TopaPmi are cleared. If MASK_PTRS still points + // deep into the overflow page (or past wrap) at that moment, a + // back-to-back PMI would observe stale state. + // + { + PT_OUTPUT_MASK_PTRS_REGISTER ResetMask; + ResetMask.Value = 0; + ResetMask.LowerMask = 0x7F; + ResetMask.MaskOrTableOffset = 0; + ResetMask.OutputOffset = 0; + __writemsr(MSR_IA32_RTIT_OUTPUT_MASK_PTRS, ResetMask.Value); + } + + // + // 3. Clear PT pending PMI bits in IA32_RTIT_STATUS + // + { + PT_RTIT_STATUS_REGISTER Status; + Status.Value = __readmsr(MSR_IA32_RTIT_STATUS); + Status.PendTopaPmi = 0; + Status.PendPsbPmi = 0; + Status.Error = 0; + Status.Stopped = 0; + __writemsr(MSR_IA32_RTIT_STATUS, Status.Value); + } + + // + // 4. Acknowledge the global PMI bit + // + __writemsr(MSR_IA32_PERF_GLOBAL_OVF_CTRL, PERF_GLOBAL_STATUS_TOPA_PMI); + + return BytesThisEvent; +} + +////////////////////////////////////////////////// +// HyperDbg-style wrappers // +// (mirror of Lbr.c API surface) // +////////////////////////////////////////////////// + +/** + * @brief Check whether Intel PT is supported on the current CPU. + * Mirrors LbrCheck — must be called once before any Pt* operation. + * + * If running under HyperDbg's hypervisor we also verify that the + * platform's IA32_VMX_MISC MSR advertises PT-in-VMX support, since + * without that bit set we may not be able to keep PT alive across + * VM transitions in a future VMCS-controlled implementation. This + * is a soft check — the current direct-MSR path still works because + * PT MSRs aren't trapped — but it surfaces the situation in the log. + * + * @return BOOLEAN TRUE if Intel PT is available. + */ +BOOLEAN +PtCheck() +{ + PT_CAPABILITIES Caps = {0}; + + if (PtEngineQueryCapabilities(&Caps) != 0) + return FALSE; + + // + // We require ToPA output for our buffer scheme + // + if (!Caps.TopaOutput) + { + LogInfo("PT: CPU does not support ToPA output; PT cannot be used here.\n"); + return FALSE; + } + + if (g_RunningOnHypervisorEnvironment && !Caps.VmxSupport) + { + // LogInfo("PT: IA32_VMX_MISC[14] is clear - Intel PT in VMX is not " + // "advertised on this CPU. Direct MSR programming still works " + // "from VMX non-root because PT MSRs are not trapped.\n"); + } + + return TRUE; +} + +/** + * @brief Allocate ToPA / output / overflow buffers for every active CPU. + * + * Must be called at IRQL == PASSIVE_LEVEL (before broadcasting the + * per-core enable DPC), because MmAllocateContiguousMemorySpecifyCache + * is paged. + * + * Idempotent: cores that already have buffers (State != DISABLED) + * are skipped. + * + * @return BOOLEAN TRUE if every core ended up with a usable buffer set. + */ +BOOLEAN +PtAllocateAllCpuBuffers() +{ + UINT32 ProcessorsCount; + UINT32 i; + + if (g_PtStateList == NULL) + return FALSE; + + ProcessorsCount = KeQueryActiveProcessorCount(0); + + for (i = 0; i < ProcessorsCount; i++) + { + PT_PER_CPU * Cpu = &g_PtStateList[i]; + PT_TRACE_CONFIG Cfg = Cpu->Config; + + if (Cpu->State != PT_STATE_DISABLED) + continue; + + if (Cfg.BufferSize == 0) + PtEngineInitDefaultConfig(&Cfg); + + if (PtEngineAllocateBuffers(Cpu, &Cfg) != 0) + { + // LogInfo("PT: buffer allocation failed on core %u\n", i); + return FALSE; + } + } + + return TRUE; +} + +/** + * @brief Free ToPA / output / overflow buffers for every active CPU. + * + * Must be called at IRQL == PASSIVE_LEVEL (after broadcasting any + * per-core disable DPC), because MmFreeContiguousMemory is paged. + */ +VOID +PtFreeAllCpuBuffers() +{ + UINT32 ProcessorsCount; + UINT32 i; + + if (g_PtStateList == NULL) + return; + + // + // Drop any live user mappings before the underlying contiguous + // memory goes away. Must run in the same process that called the + // mmap IOCTL — see HYPERTRACE_PT_MMAP_PACKETS for the contract. + // + PtUnmapAllCpuBuffersFromUser(); + + ProcessorsCount = KeQueryActiveProcessorCount(0); + + for (i = 0; i < ProcessorsCount; i++) + { + PtEngineFreeBuffers(&g_PtStateList[i]); + } +} + +/** + * @brief Map every per-CPU PT main output buffer and 4 KB overflow page + * into the current user process as a single virtually contiguous + * region per CPU, and fill OutDescs[i] with the base UserVa and + * the total Size (main + overflow) for that CPU. + * + * PT buffers must already exist (PtAllocateAllCpuBuffers must + * have run, i.e. PT is enabled). Idempotent within an enable + * cycle: a second call returns the already-cached mappings. On + * any per-CPU failure the partial work is rolled back and the + * function returns -1. + * + * @return INT32 0 on success, -1 on failure. + */ +INT32 +PtMmapAllCpuBuffersToUser(PT_USER_BUFFER_DESC * OutDescs, UINT32 MaxDescs, UINT32 * OutNumCpus) +{ + UINT32 ProcessorsCount; + UINT32 i; + + if (OutDescs == NULL || OutNumCpus == NULL || g_PtStateList == NULL) + return -1; + + ProcessorsCount = KeQueryActiveProcessorCount(0); + if (ProcessorsCount == 0 || ProcessorsCount > MaxDescs || ProcessorsCount > PT_MAX_CPUS_FOR_MMAP) + return -1; + + if (!g_PtUserMappingsActive) + { + for (i = 0; i < ProcessorsCount; i++) + { + PT_PER_CPU * Cpu = &g_PtStateList[i]; + + if (Cpu->Buffer.OutputVa == NULL || Cpu->Buffer.OverflowVa == NULL) + { + PtUnmapAllCpuBuffersFromUser(); + return -1; + } + + if (PtMmapCpuRegionToUser(Cpu->Buffer.OutputVa, + Cpu->Buffer.OutputPhysical, + (SIZE_T)Cpu->Buffer.OutputSize, + Cpu->Buffer.OverflowPhysical, + (SIZE_T)PT_OVERFLOW_SIZE, + &g_PtUserMappings[i].Mdl, + &g_PtUserMappings[i].UserVa) != 0) + { + PtUnmapAllCpuBuffersFromUser(); + return -1; + } + } + + g_PtUserMappingsActive = TRUE; + } + + for (i = 0; i < ProcessorsCount; i++) + { + OutDescs[i].CpuId = i; + OutDescs[i].Reserved = 0; + OutDescs[i].UserVa = (UINT64)(ULONG_PTR)g_PtUserMappings[i].UserVa; + OutDescs[i].Size = g_PtStateList[i].Buffer.OutputSize + PT_OVERFLOW_SIZE; + } + + *OutNumCpus = ProcessorsCount; + return 0; +} + +/** + * @brief Release every user mapping created by PtMmapAllCpuBuffersToUser. + * Called by PtFreeAllCpuBuffers (i.e. on PT disable / flush) so + * user VAs stop being usable before the backing memory is freed. + * Also used as a rollback path on partial mmap failure. + * + * Always walks the full table (PtUnmapCpuRegionFromUser is + * NULL-safe) so rollback after a half-finished mapping still + * cleans up the CPUs that were mapped before the failure. + */ +VOID +PtUnmapAllCpuBuffersFromUser() +{ + UINT32 i; + + for (i = 0; i < PT_MAX_CPUS_FOR_MMAP; i++) + { + PtUnmapCpuRegionFromUser(g_PtUserMappings[i].Mdl, + g_PtUserMappings[i].UserVa); + g_PtUserMappings[i].Mdl = NULL; + g_PtUserMappings[i].UserVa = NULL; + } + + g_PtUserMappingsActive = FALSE; +} + +/** + * @brief Start PT tracing on the CURRENT CPU. Buffers must already be + * allocated by PtAllocateAllCpuBuffers (called at PASSIVE_LEVEL). + * + * Mirrors LbrStart but takes no parameters: per-CPU configuration is + * sourced from g_PtStateList[core].Config (defaulted at init time). + * + * @return BOOLEAN TRUE on success. + */ +BOOLEAN +PtStart() +{ + UINT32 CurrentCore; + PT_PER_CPU * Cpu; + + if (g_PtStateList == NULL) + { + LogInfo("PT: per-CPU state not initialized.\n"); + return FALSE; + } + + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + Cpu = &g_PtStateList[CurrentCore]; + + if (Cpu->State == PT_STATE_DISABLED) + { + // + // Buffers should have been allocated at PASSIVE_LEVEL beforehand. + // Allocating from a DPC is unsafe (MmAllocateContiguousMemory* is + // a paged routine) so just bail out. + // + // LogInfo("PT: buffers not allocated for core %u\n", CurrentCore); + return FALSE; + } + + if (PtEngineStart(Cpu) != 0) + { + // LogInfo("PT: PtEngineStart failed on core %u (state=%d)\n", CurrentCore, Cpu->State); + return FALSE; + } + + return TRUE; +} + +/** + * @brief Stop PT tracing on the CURRENT CPU. + * Trace data accumulated in the per-CPU output buffer is left in + * place; PtSize / PtDump can read it later. + */ +VOID +PtStop() +{ + UINT32 CurrentCore; + PT_PER_CPU * Cpu; + + if (g_PtStateList == NULL) + return; + + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + Cpu = &g_PtStateList[CurrentCore]; + + // LogInfo("PT: stopping trace on core %d\n", CurrentCore); + + PtEngineStop(Cpu, NULL); +} + +/** + * @brief Pause PT tracing on the CURRENT CPU. Buffer state is preserved + * so a subsequent PtResume picks up where this left off. + */ +VOID +PtPause() +{ + UINT32 CurrentCore; + PT_PER_CPU * Cpu; + + if (g_PtStateList == NULL) + return; + + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + Cpu = &g_PtStateList[CurrentCore]; + + // LogInfo("PT: pausing trace on core %u\n", CurrentCore); + + PtEnginePause(Cpu); +} + +/** + * @brief Resume PT tracing on the CURRENT CPU after a prior PtPause. + */ +VOID +PtResume() +{ + UINT32 CurrentCore; + PT_PER_CPU * Cpu; + + if (g_PtStateList == NULL) + return; + + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + Cpu = &g_PtStateList[CurrentCore]; + + // LogInfo("PT: resuming trace on core %u\n", CurrentCore); + + PtEngineResume(Cpu); +} + +/** + * @brief Snapshot the current PT output position on the CURRENT CPU + * without disturbing tracing state. The returned value is the + * number of bytes of valid trace data sitting in this CPU's + * main + overflow buffer, i.e. the offset a decoder should stop + * at when reading from the user mapping. + */ +UINT64 +PtSize() +{ + UINT32 CurrentCore; + PT_PER_CPU * Cpu; + PT_OUTPUT_MASK_PTRS_REGISTER Mask; + UINT32 TopaIndex; + UINT32 BytesInEntry; + + if (g_PtStateList == NULL) + return 0; + + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + Cpu = &g_PtStateList[CurrentCore]; + + if (Cpu->State != PT_STATE_TRACING && Cpu->State != PT_STATE_PAUSED && Cpu->State != PT_STATE_STOPPED) + return 0; + + // + // Read MASK_PTRS without touching MSRs that would disturb tracing. + // For an active trace this gives the live byte count; for stopped + // traces it returns the position at the moment tracing was disabled. + // + Mask.Value = __readmsr(MSR_IA32_RTIT_OUTPUT_MASK_PTRS); + TopaIndex = (UINT32)Mask.MaskOrTableOffset; + BytesInEntry = (UINT32)Mask.OutputOffset; + + if (TopaIndex == 0) + return BytesInEntry; + + return Cpu->Buffer.OutputSize + BytesInEntry; +} + +/** + * @brief Print PT trace summary for the CURRENT CPU. + * + * PT packets are a compressed binary stream that requires a decoder + * (libipt or similar) to be human-readable, so this only emits the + * per-CPU statistics; bulk packet data is preserved in the output + * buffer for offline retrieval. + */ +VOID +PtDump() +{ + UINT32 CurrentCore; + PT_PER_CPU * Cpu; + + if (g_PtStateList == NULL) + return; + + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + Cpu = &g_PtStateList[CurrentCore]; + + Log("PT trace summary for core %u\n", CurrentCore); + Log(" State : %d\n", Cpu->State); + Log(" TotalBytesCaptured : 0x%llx\n", Cpu->TotalBytesCaptured); + Log(" OutputBufferSize : 0x%llx\n", Cpu->Buffer.OutputSize); + Log(" TopaPhysical : 0x%llx\n", Cpu->Buffer.TopaPhysical); + Log(" OutputPhysical : 0x%llx\n", Cpu->Buffer.OutputPhysical); + Log(" TraceUser/Kernel : %u / %u\n", Cpu->Config.TraceUser, Cpu->Config.TraceKernel); + Log(" TargetCr3 : 0x%llx\n", Cpu->Config.TargetCr3); +} + +/** + * @brief LBR-style filter wrapper: refresh tracing on the CURRENT CPU with + * a fresh PT_FILTER_OPTIONS. + * + * Mirrors LbrFilter — the caller hands in only the fields a user is + * allowed to drive (TraceUser, TraceKernel, TargetCr3, BufferSize, + * NumAddrRanges, AddrRanges) and PtFilter writes them into the + * per-CPU PT_TRACE_CONFIG one at a time. Engine-managed options + * (BranchEn, TscEn, MtcEn, CycEn, RetCompression, *Freq) are left + * alone, so a filter call can never accidentally turn off the + * packet types the engine relies on. + * + * BufferSize == 0 keeps the per-CPU value already in place, so + * pure filter changes (privilege bits, CR3, IP ranges) skip any + * reallocation of the ToPA / output / overflow buffers and can + * run entirely from a DPC. Genuine buffer-size changes still need + * a PASSIVE_LEVEL caller to free + reallocate; HyperTracePtFilter + * handles that case before broadcasting. + */ +VOID +PtFilter(const PT_APPLY_CORE_FILTER_REQUEST * FilterRequest) +{ + UINT32 CurrentCore; + PT_PER_CPU * Cpu; + UINT32 i; + PT_CAPABILITIES Caps = {0}; + + if (g_PtStateList == NULL || FilterRequest == NULL) + return; + + if (PtEngineQueryCapabilities(&Caps) != 0) + return; + + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + Cpu = &g_PtStateList[CurrentCore]; + + // LogInfo("PT: applying filter on core %u\n", CurrentCore); + + // + // Stop tracing on this CPU first so we can safely mutate Cpu->Config + // and reprogram the RTIT_CTL bits. + // + if (Cpu->State == PT_STATE_TRACING || Cpu->State == PT_STATE_PAUSED) + { + PtEngineStop(Cpu, NULL); + } + + // + // Apply only the user-tunable fields to this CPU's per-CPU config. + // + Cpu->Config.TraceUser = (BOOLEAN)FilterRequest->FilterOptions.TraceUser; + Cpu->Config.TraceKernel = (BOOLEAN)FilterRequest->FilterOptions.TraceKernel; + + if (FilterRequest->EnableOptions.Cr3 != 0 && !Caps.Cr3Filtering) + { + // LogInfo("PT: CR3 filtering requested but not supported by CPU\n"); + Cpu->Config.TargetCr3 = 0; + } + else + { + Cpu->Config.TargetCr3 = FilterRequest->EnableOptions.Cr3; + } + + if (FilterRequest->FilterOptions.NumAddrRanges > Caps.NumAddrRanges) + { + // LogInfo("PT: requested %u IP filter ranges, but CPU only supports %u\n", FilterRequest->FilterOptions.NumAddrRanges, Caps.NumAddrRanges); + Cpu->Config.NumAddrRanges = Caps.NumAddrRanges; + } + else if (FilterRequest->FilterOptions.NumAddrRanges > 0 && !Caps.IpFiltering) + { + // LogInfo("PT: IP filtering requested but not supported by CPU\n"); + Cpu->Config.NumAddrRanges = 0; + } + else + { + Cpu->Config.NumAddrRanges = FilterRequest->FilterOptions.NumAddrRanges; + } + + if (FilterRequest->BufferSize != 0) + { + Cpu->Config.BufferSize = FilterRequest->BufferSize; + } + + for (i = 0; i < PT_MAX_ADDR_RANGES; i++) + { + Cpu->Config.AddrRanges[i] = FilterRequest->FilterOptions.AddrRanges[i]; + } + + // + // If the per-CPU buffers haven't been allocated yet, leave the slot + // configured so the next PtStart picks it up — skip starting here + // because PtEngineStart needs ToPA / output / overflow already + // allocated at PASSIVE_LEVEL. + // + if (Cpu->State == PT_STATE_DISABLED) + return; + + PtEngineStart(Cpu); +} + +/** + * @brief Flush PT trace state on the CURRENT CPU — disables tracing and + * clears the bytes-captured counter so the next PtStart begins from + * a fresh baseline. Buffer freeing happens at PASSIVE_LEVEL via + * PtFreeAllCpuBuffers; this is safe to call from a DPC. + * + * Mirrors LbrFlush. + */ +VOID +PtFlush() +{ + UINT32 CurrentCore; + PT_PER_CPU * Cpu; + + if (g_PtStateList == NULL) + return; + + CurrentCore = KeGetCurrentProcessorNumberEx(NULL); + Cpu = &g_PtStateList[CurrentCore]; + + // LogInfo("PT: flush on core %u\n", CurrentCore); + + if (Cpu->State == PT_STATE_TRACING || Cpu->State == PT_STATE_PAUSED) + { + PtEngineStop(Cpu, NULL); + } + + Cpu->TotalBytesCaptured = 0; +} diff --git a/hyperdbg/hypertrace/header/api/LbrApi.h b/hyperdbg/hypertrace/header/api/LbrApi.h new file mode 100644 index 00000000..7569fe2e --- /dev/null +++ b/hyperdbg/hypertrace/header/api/LbrApi.h @@ -0,0 +1,21 @@ +/** + * @file LbrApi.h + * @author Hari Mishal (harimishal6@gmail.com) + * @brief Header for LBR tracing routines for HyperTrace module (Intel Last Branch Record) + * @details + * @version 0.18 + * @date 2025-12-02 + * + * @copyright This project is released under the GNU Public License v3. + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +HyperTraceLbrExamplePerformTrace(); + +BOOLEAN +HyperTraceLbrDisable(HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceOperationRequest); diff --git a/hyperdbg/hypertrace/header/api/PtApi.h b/hyperdbg/hypertrace/header/api/PtApi.h new file mode 100644 index 00000000..d75ea2b0 --- /dev/null +++ b/hyperdbg/hypertrace/header/api/PtApi.h @@ -0,0 +1,21 @@ +/** + * @file PtApi.h + * @author Masoud Rahimi Jafari (Masoodrahimy1379@gmail.com) + * @brief Header for PT tracing routines for HyperTrace module (Intel Processor Trace) + * @details + * @version 0.19 + * @date 2026-04-29 + * + * @copyright This project is released under the GNU Public License v3. + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +// +// The exported HyperTracePt* API is declared in +// SDK/imports/kernel/HyperDbgHyperTrace.h (with the dllexport / dllimport +// decoration). Internal-only PT helpers should be declared here. +// diff --git a/hyperdbg/hypertrace/header/api/TraceApi.h b/hyperdbg/hypertrace/header/api/TraceApi.h new file mode 100644 index 00000000..1dff92cf --- /dev/null +++ b/hyperdbg/hypertrace/header/api/TraceApi.h @@ -0,0 +1,47 @@ +/** + * @file TraceApi.h + * @author + * @brief Header for general tracing routines for HyperTrace module + * @details + * @version 0.19 + * @date 2026-04-25 + * + * @copyright This project is released under the GNU Public License v3. + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +// +// Most of the functions are defined and exported +// + +////////////////////////////////////////////////// +// Platform Wrappers // +////////////////////////////////////////////////// + +#define xrdmsr(msr, pval) (*(pval) = CpuReadMsr(msr)) +#define xwrmsr(msr, val) (msr, val) + +// CPUID (Fixed C6001: initialized CpuInfo) +#define xcpuid(code, a, b, c, d) \ + { \ + int CpuInfo[4] = {0}; \ + CpuCpuId(CpuInfo, code); \ + *a = CpuInfo[0]; \ + *b = CpuInfo[1]; \ + *c = CpuInfo[2]; \ + *d = CpuInfo[3]; \ + } + +#define xcpuidex(code, subleaf, a, b, c, d) \ + { \ + int CpuInfo[4] = {0}; \ + CpuCpuIdEx(CpuInfo, code, subleaf); \ + *a = CpuInfo[0]; \ + *b = CpuInfo[1]; \ + *c = CpuInfo[2]; \ + *d = CpuInfo[3]; \ + } diff --git a/hyperdbg/hypertrace/header/broadcast/Broadcast.h b/hyperdbg/hypertrace/header/broadcast/Broadcast.h new file mode 100644 index 00000000..eb857072 --- /dev/null +++ b/hyperdbg/hypertrace/header/broadcast/Broadcast.h @@ -0,0 +1,53 @@ + +/** + * @file Broadcast.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for broadcasting functions + * @details + * @version 0.19 + * @date 2026-04-19 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +BroadcastEnableLbrOnAllCores(); + +VOID +BroadcastDisableLbrOnAllCores(); + +VOID +BroadcastFlushLbrOnAllCores(); + +VOID +BroadcastFilterLbrOptionsOnAllCores(UINT64 LbrFilterOptions); + +VOID +BroadcastEnablePtOnAllCores(); + +VOID +BroadcastDisablePtOnAllCores(); + +VOID +BroadcastPausePtOnAllCores(); + +VOID +BroadcastResumePtOnAllCores(); + +VOID +BroadcastSizePtOnAllCores(UINT64 * Sizes); + +VOID +BroadcastDumpPtOnAllCores(); + +VOID +BroadcastFlushPtOnAllCores(); + +VOID +BroadcastFilterPtOnAllCores(PT_APPLY_CORE_FILTER_REQUEST * FilterRequest); diff --git a/hyperdbg/hypertrace/header/broadcast/DpcRoutines.h b/hyperdbg/hypertrace/header/broadcast/DpcRoutines.h new file mode 100644 index 00000000..da4c94b5 --- /dev/null +++ b/hyperdbg/hypertrace/header/broadcast/DpcRoutines.h @@ -0,0 +1,53 @@ + +/** + * @file DpcRoutines.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Definition for DPC functions + * @details + * @version 0.19 + * @date 2026-04-19 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +DpcRoutineEnableLbr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineDisableLbr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineFlushLbr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineFilterLbrOptions(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineEnablePt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineDisablePt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutinePausePt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineResumePt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineSizePt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineDumpPt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineFlushPt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); + +BOOLEAN +DpcRoutineFilterPt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2); diff --git a/hyperdbg/hypertrace/header/common/UnloadDll.h b/hyperdbg/hypertrace/header/common/UnloadDll.h new file mode 100644 index 00000000..9bb252d2 --- /dev/null +++ b/hyperdbg/hypertrace/header/common/UnloadDll.h @@ -0,0 +1,22 @@ +/** + * @file UnloadDll.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for unloading DLL in the target Windows + * + * @version 0.4 + * @date 2023-07-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Exported Functions // +////////////////////////////////////////////////// + +__declspec(dllexport) NTSTATUS +DllInitialize(_In_ PUNICODE_STRING RegistryPath); + +__declspec(dllexport) NTSTATUS + DllUnload(VOID); diff --git a/hyperdbg/hypertrace/header/globals/GlobalVariables.h b/hyperdbg/hypertrace/header/globals/GlobalVariables.h new file mode 100644 index 00000000..7e50072c --- /dev/null +++ b/hyperdbg/hypertrace/header/globals/GlobalVariables.h @@ -0,0 +1,101 @@ + +/** + * @file GlobalVariables.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Definition for global variables + * @details + * @version 0.19 + * @date 2026-04-19 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Global Variables // +////////////////////////////////////////////////// + +/** + * @brief List of callbacks + * + */ +HYPERTRACE_CALLBACKS g_Callbacks; + +/** + * @brief The flag indicating whether the hypertrace module callbacks is initialized or not + * + */ +BOOLEAN g_HyperTraceCallbacksInitialized; + +/** + * @brief The flag indicating whether the initialization is being done for hypervisor environment or not + * + */ +BOOLEAN g_RunningOnHypervisorEnvironment; + +/** + * @brief The flag indicating whether the architectural LBR is supported by the CPU or not + * if false it means the legacy LBR is supported + * + */ +BOOLEAN g_ArchBasedLastBranchRecord; + +/** + * @brief The flag indicating whether the hypertrace LBR tracing is initialized or not + * + */ +BOOLEAN g_LastBranchRecordEnabled; + +/** + * @brief This will be a dynamically allocated array to hold LBR states for each core + * + */ +LBR_STACK_ENTRY * g_LbrStateList; + +/** + * @brief The global variable to hold the LBR capacity of the current CPU + * + */ +ULONGLONG g_LbrCapacity; + +/** + * @brief The global variable to hold CPUID leaf 0x28 information (Architectural LBR Enumeration Leaf) + * + */ +CPUID28_LEAFS g_Cpuid28Leafs; + +/** + * @brief The global variable to hold the current LBR filter options bitmask (for both architectural and legacy LBR) + * + */ +UINT64 g_LbrFilterOptions; + +/** + * @brief The flag indicating whether the hypertrace Processor Trace is initialized or not + * + */ +BOOLEAN g_ProcessorTraceEnabled; + +/** + * @brief Dynamically allocated array of per-CPU Intel PT state. + * Sized to KeQueryActiveProcessorCount(0) at hypertrace init. + */ +PT_PER_CPU * g_PtStateList; + +/** + * @brief Per-CPU MDL + user-mode VA for the PT mmap surface (main + * output buffer concatenated with the 4 KB overflow page in a + * single contiguous user mapping). Populated by + * PtMmapAllCpuBuffersToUser, torn down by + * PtUnmapAllCpuBuffersFromUser. The user VAs are only valid in + * the address space of the process that called the mmap IOCTL — + * see HYPERTRACE_PT_MMAP_PACKETS for the contract. + */ +PT_USER_MAPPING g_PtUserMappings[PT_MAX_CPUS_FOR_MMAP]; + +/** + * @brief Set while g_PtUserMappings holds live user mappings; cleared + * by PtUnmapAllCpuBuffersFromUser. + */ +BOOLEAN g_PtUserMappingsActive; diff --git a/hyperdbg/hypertrace/header/lbr/Lbr.h b/hyperdbg/hypertrace/header/lbr/Lbr.h new file mode 100644 index 00000000..a9293850 --- /dev/null +++ b/hyperdbg/hypertrace/header/lbr/Lbr.h @@ -0,0 +1,188 @@ +/** + * @file Lbr.h + * @author Hari Mishal (harimishal6@gmail.com) + * @brief Message logging and tracing implementation + * @details Modified from LIBIHT project (Thomasaon Zhao et al) with Windows style updates. + * @version 0.18 + * @date 2025-12-02 + * + * @copyright This project is released under the GNU Public License v3. + */ +#pragma once + +////////////////////////////////////////////////// +// Constants // +////////////////////////////////////////////////// + +// +// Legacy LBR MSRs +// +#ifndef MSR_LEGACY_LBR_SELECT +# define MSR_LEGACY_LBR_SELECT 0x000001C8 // originally defined in SDK to be used by other module like HyperHV +#endif // !MSR_LEGACY_LBR_SELECT +#define MSR_LBR_TOS 0x000001C9 +#define MSR_LASTBRANCH_0_FROM_IP 0x00000680 +#define MSR_LASTBRANCH_0_TO_IP 0x000006C0 +#define MSR_LASTBRANCH_INFO_0 0x00000DC0 +#define LBR_SELECT_WITHOUT_FILTER 0x00000000 + +// +// Arch LBR MSRs +// +#define IA32_LBR_0_FROM_IP 0x1500 +#define IA32_LBR_0_TO_IP 0x1600 +#define IA32_LBR_0_INFO 0x1200 + +#define CPUID_ARCH_LAST_BRANCH_RECORD_INFORMATION 0x1c + +// +// This MSR could be used as an alternative to MSR_LBR_SELECT and IA32_DEBUGCTL for enabling and configuring LBR +// For using that in hypervisor Load Guest IA32_LBR_CTL Entry Control and Clear IA32_LBR_CTL Exit Control should +// be configured, plus host could control it over Guest IA32_LBR_CTL on VMCS +// +#define IA32_LBR_CTL 0x000014CE + +////////////////////////////////////////////////// +// CPUID Structures // +////////////////////////////////////////////////// + +/* + * @brief Intel Architectural LBR CPUID detection/enumeration details: + */ +typedef union _CPUID28_EAX +{ + struct + { + /* Supported LBR depth values */ + UINT32 LbrDepthMask : 8; + UINT32 Reserved : 22; + /* Deep C-state Reset */ + UINT32 LbrDeepCReset : 1; + /* IP values contain LIP */ + UINT32 LbrLip : 1; + }; + UINT32 AsUInt; +} CPUID28_EAX, *PCPUID28_EAX; + +typedef union _CPUID28_EBX +{ + struct + { + /* CPL Filtering Supported */ + UINT32 LbrCpl : 1; + /* Branch Filtering Supported */ + UINT32 LbrFilter : 1; + /* Call-stack Mode Supported */ + UINT32 LbrCallStack : 1; + UINT32 Reserved : 29; + }; + UINT32 AsUInt; +} CPUID28_EBX, *PCPUID28_EBX; + +typedef union _CPUID28_ECX +{ + struct + { + /* Mispredict Bit Supported */ + UINT32 LbrMispred : 1; + /* Timed LBRs Supported */ + UINT32 LbrTimedLbr : 1; + /* Branch Type Field Supported */ + UINT32 LbrBrType : 1; + UINT32 Reserved : 29; + }; + UINT32 AsUInt; +} CPUID28_ECX, *PCPUID28_ECX; + +/* + * @brief The structure to hold the CPUID leaf 0x28 details for Architectural LBRs + */ +typedef struct _CPUID28_LEAFS +{ + CPUID28_EAX Eax; + CPUID28_EBX Ebx; + CPUID28_ECX Ecx; + UINT32 Edx; +} CPUID28_LEAFS, *PCPUID28_LEAFS; + +////////////////////////////////////////////////// +// MSR Structures // +////////////////////////////////////////////////// + +/** + * @brief The structure to hold the IA32_LBR_CTL MSR, which is used to enable and configure the LBR feature + * @details MSR Address: 0x14CEH (Hex) / 5326 (Dec) + */ +typedef union _IA32_LBR_CTL_REGISTER +{ + ULONG64 AsUInt; + + struct + { + ULONG64 LBREn : 1; // [0] When set, enables LBR recording + ULONG64 OS : 1; // [1] When set, allows LBR recording when CPL == 0 + ULONG64 USR : 1; // [2] When set, allows LBR recording when CPL != 0 + ULONG64 CallStack : 1; // [3] When set, records branches in call-stack mode (See Section 7.1.2.4) + ULONG64 Reserved0 : 12; // [15:4] Reserved (must be zero) + ULONG64 JCC : 1; // [16] When set, records taken conditional branches (See Section 7.1.2.3) + ULONG64 NearRelJmp : 1; // [17] When set, records near relative JMPs (See Section 7.1.2.3) + ULONG64 NearIndJmp : 1; // [18] When set, records near indirect JMPs (See Section 7.1.2.3) + ULONG64 NearRelCall : 1; // [19] When set, records near relative CALLs (See Section 7.1.2.3) + ULONG64 NearIndCall : 1; // [20] When set, records near indirect CALLs (See Section 7.1.2.3) + ULONG64 NearRet : 1; // [21] When set, records near RETs (See Section 7.1.2.3) + ULONG64 OtherBranch : 1; // [22] When set, records other branches (See Section 7.1.2.3) + ULONG64 Reserved1 : 41; // [63:23] Reserved (must be zero) + } Bits; + +} IA32_LBR_CTL_REGISTER, *PIA32_LBR_CTL_REGISTER; + +////////////////////////////////////////////////// +// Global Variables // +////////////////////////////////////////////////// + +/** + * @brief The structure to hold the mapping of CPU model to its LBR capacity + * + */ +typedef struct _CPU_LBR_MAP +{ + ULONG Model; + ULONG LbrCapacity; +} CPU_LBR_MAP, *PCPU_LBR_MAP; + +/** + * @brief The global variable to hold the mapping of CPU model to its LBR capacity + * + */ +extern CPU_LBR_MAP CPU_LBR_MAPS[]; + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +LbrCheckAndReadLegacyLbrDetails(); + +BOOLEAN +LbrCheckAndReadArchitecturalLbrDetails(); + +BOOLEAN +LbrStart(UINT64 FilterOptions); + +BOOLEAN +LbrCheck(); + +VOID +LbrFilter(UINT64 FilterOptions); + +VOID +LbrStop(); + +VOID +LbrFlush(); + +VOID +LbrSave(); + +VOID +LbrPrint(); diff --git a/hyperdbg/hypertrace/header/pch.h b/hyperdbg/hypertrace/header/pch.h new file mode 100644 index 00000000..4e591600 --- /dev/null +++ b/hyperdbg/hypertrace/header/pch.h @@ -0,0 +1,124 @@ +/** + * @file pch.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers of Message logging and tracing + * @details + * @version 0.2 + * @date 2023-01-23 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#define _NO_CRT_STDIO_INLINE + +#pragma warning(disable : 4201) // Suppress nameless struct/union warning + +// +// Environment headers +// +#include "platform/general/header/Environment.h" + +#ifdef HYPERDBG_ENV_WINDOWS + +// +// Windows defined functions +// +# include +# include +# include + +#endif // HYPERDBG_ENV_WINDOWS + +// +// Scope definitions +// +#define HYPERDBG_KERNEL_MODE +#define HYPERDBG_HYPERTRACE + +// +// Add ia32-doc +// +#include "ia32-doc/out/ia32.h" + +// +// SDK headers +// +#include "SDK/HyperDbgSdk.h" + +// +// Configuration +// +#include "config/Configuration.h" + +// +// Platform independent headers +// +#include "platform/kernel/header/PlatformMem.h" +#include "platform/kernel/header/PlatformIntrinsics.h" +#include "platform/kernel/header/PlatformBroadcast.h" +#include "platform/kernel/header/PlatformCpu.h" +#include "platform/kernel/header/PlatformSpinlock.h" +#include "platform/kernel/header/PlatformIrql.h" +#include "platform/kernel/header/PlatformDpc.h" +#include "platform/kernel/header/PlatformTime.h" +#include "platform/kernel/header/PlatformDbg.h" +#include "platform/kernel/header/PlatformIo.h" +#include "platform/kernel/header/PlatformEvent.h" + +// +// Unload function (to be called when the driver is unloaded) +// +#include "common/UnloadDll.h" + +// +// Hyperlog headers +// +#include "components/callback/header/HyperLogCallback.h" +#include "SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h" + +// +// Spinlock headers +// +#include "components/spinlock/header/Spinlock.h" + +// +// Hypertrace Callbacks +// +#include "SDK/modules/HyperTrace.h" + +// +// Definition of general tracing types +// +#include "api/TraceApi.h" + +// +// Definition of tracing types and structures (Last Branch Record) +// +#include "lbr/Lbr.h" +#include "api/LbrApi.h" + +// +// Definition of tracing types and structures (Processor Trace). +// Pt.h must come before broadcast/Broadcast.h because Broadcast.h +// references PT_FILTER_OPTIONS in its function signatures. +// +#include "pt/Pt.h" +#include "api/PtApi.h" + +// +// DPC and broadcasting function headers +// +#include "broadcast/DpcRoutines.h" +#include "broadcast/Broadcast.h" + +// +// Export functions +// +#include "SDK/imports/kernel/HyperDbgHyperTrace.h" + +// +// Global variables +// +#include "globals/GlobalVariables.h" diff --git a/hyperdbg/hypertrace/header/pt/Pt.h b/hyperdbg/hypertrace/header/pt/Pt.h new file mode 100644 index 00000000..f7801bbb --- /dev/null +++ b/hyperdbg/hypertrace/header/pt/Pt.h @@ -0,0 +1,146 @@ +/** + * @file Pt.h + * @author Masoud Rahimi Jafari (Masoodrahimy1379@gmail.com) + * @brief Header for Processor Trace (PT) tracing routines for HyperTrace module + * @details Engine that programs Intel PT MSRs from VMX root or kernel context. + * Buffer / ToPA management is kept here; user-visible PT structures + * live in the SDK header [PtDefinitions.h]. + * @version 0.19 + * @date 2026-04-29 + * + * @copyright This project is released under the GNU Public License v3. + */ +#pragma once + +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +/** + * @brief Per-CPU bookkeeping for the user-mode mmap surface. + * + * One MDL + user VA per CPU describes the main output buffer + * immediately followed by the 4 KB overflow page as a single + * virtually contiguous region in the mapping process. Lives in + * g_PtUserMappings; lifetime tied to the PT enable cycle. + */ +typedef struct _PT_USER_MAPPING +{ + PMDL Mdl; + PVOID UserVa; + +} PT_USER_MAPPING, *PPT_USER_MAPPING; + +/** + * @brief PT apply core filter requests. + */ +typedef struct _PT_APPLY_CORE_FILTER_REQUEST +{ + PT_FILTER_OPTIONS FilterOptions; + PT_ENABLE_OPTIONS EnableOptions; + UINT64 BufferSize; /* Output buffer size (0 = default / PT_DEFAULT_BUFFER_SIZE) */ + +} PT_APPLY_CORE_FILTER_REQUEST, *PPT_APPLY_CORE_FILTER_REQUEST; + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +// +// HyperDbg-style wrappers (mirroring Lbr*) +// + +BOOLEAN +PtCheck(); + +BOOLEAN +PtStart(); + +VOID +PtStop(); + +VOID +PtPause(); + +VOID +PtResume(); + +UINT64 +PtSize(); + +VOID +PtDump(); + +VOID +PtFlush(); + +// +// LBR-style filter wrapper, one CPU at a time. Mirrors LbrFilter in shape: +// caller passes a PT_APPLY_CORE_FILTER_REQUEST describing only the user-tunable bits +// (TraceUser, TraceKernel, TargetCr3, BufferSize, NumAddrRanges, AddrRanges), +// and PtFilter handles the stop / config-update / start sequence on the +// CURRENT CPU. Engine-internal config (BranchEn, TscEn, etc.) is left +// untouched in the per-CPU PT_TRACE_CONFIG. +// +VOID +PtFilter(const PT_APPLY_CORE_FILTER_REQUEST * FilterRequest); + +// +// PASSIVE_LEVEL helpers — call before / after the per-core DPC broadcasts. +// Required because MmAllocateContiguousMemorySpecifyCache and +// MmFreeContiguousMemory must run at IRQL == PASSIVE_LEVEL. +// + +BOOLEAN +PtAllocateAllCpuBuffers(); + +VOID +PtFreeAllCpuBuffers(); + +// +// User-mode mmap surface: map every per-CPU main output + overflow +// buffer into the calling user process. Idempotent within an enable +// cycle; torn down by PtFreeAllCpuBuffers (i.e. PT disable / flush). +// +INT32 +PtMmapAllCpuBuffersToUser(PT_USER_BUFFER_DESC * OutDescs, UINT32 MaxDescs, UINT32 * OutNumCpus); + +VOID +PtUnmapAllCpuBuffersFromUser(); + +// +// Engine routines (operate on a specific PT_PER_CPU instance) +// + +INT32 +PtEngineQueryCapabilities(PT_CAPABILITIES * OutCaps); + +VOID +PtEngineInitDefaultConfig(PT_TRACE_CONFIG * Config); + +INT32 +PtEngineAllocateBuffers(PT_PER_CPU * Cpu, const PT_TRACE_CONFIG * Config); + +VOID +PtEngineFreeBuffers(PT_PER_CPU * Cpu); + +INT32 +PtEngineStart(PT_PER_CPU * Cpu); + +UINT64 +PtEngineStop(PT_PER_CPU * Cpu, PT_OUTPUT_BUFFER * Out); + +INT32 +PtEnginePause(PT_PER_CPU * Cpu); + +INT32 +PtEngineResume(PT_PER_CPU * Cpu); + +UINT64 +PtEngineHandlePmi(PT_PER_CPU * Cpu, PT_OUTPUT_BUFFER * Out); + +BOOLEAN +PtEngineIsPtPmi(); + +INT32 +PtEngineSizeToTopaEncoding(UINT64 SizeInBytes); diff --git a/hyperdbg/hypertrace/hypertrace.def b/hyperdbg/hypertrace/hypertrace.def new file mode 100644 index 00000000..54a2d6b2 --- /dev/null +++ b/hyperdbg/hypertrace/hypertrace.def @@ -0,0 +1,6 @@ +LIBRARY hypertrace + +EXPORTS + + DllInitialize PRIVATE + DllUnload PRIVATE \ No newline at end of file diff --git a/hyperdbg/hypertrace/hypertrace.vcxproj b/hyperdbg/hypertrace/hypertrace.vcxproj new file mode 100644 index 00000000..1b0d38f2 --- /dev/null +++ b/hyperdbg/hypertrace/hypertrace.vcxproj @@ -0,0 +1,153 @@ + + + + + + + + debug + x64 + + + release + x64 + + + + {9FA45E25-DAEB-4C2D-806C-7908A180195D} + {1bc93793-694f-48fe-9372-81e2b05556fd} + v4.5 + 12.0 + Debug + x64 + hypertrace + $(LatestTargetPlatformVersion) + + + + Windows10 + true + WindowsKernelModeDriver10.0 + DynamicLibrary + KMDF + Desktop + false + + + Windows10 + false + WindowsKernelModeDriver10.0 + DynamicLibrary + KMDF + Desktop + false + + + + + + + + + + + DbgengKernelDebugger + $(SolutionDir)build\bin\$(Configuration)\ + $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + false + + + DbgengKernelDebugger + $(SolutionDir)build\bin\$(Configuration)\ + $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + false + + + + sha256 + + + $(SolutionDir)\include;$(ProjectDir)header;$(SolutionDir)dependencies;%(AdditionalIncludeDirectories) + true + Create + pch.h + stdcpp20 + + + true + + true + hypertrace.def + + + + + sha256 + + + $(SolutionDir)\include;$(ProjectDir)header;$(SolutionDir)dependencies;%(AdditionalIncludeDirectories) + true + Create + pch.h + stdcpp20 + Full + + + true + + true + hypertrace.def + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + \ No newline at end of file diff --git a/hyperdbg/hypertrace/hypertrace.vcxproj.filters b/hyperdbg/hypertrace/hypertrace.vcxproj.filters new file mode 100644 index 00000000..32ace76c --- /dev/null +++ b/hyperdbg/hypertrace/hypertrace.vcxproj.filters @@ -0,0 +1,155 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {1ab177b4-9e6c-460e-834a-8fced04b42a3} + + + {21f0281e-fc2a-4e13-97ac-e4b35a05a31e} + + + {09d5457a-bade-4a3f-a171-641110492d57} + + + {b8b32a09-61fb-433a-ad79-eb7cfc5f3437} + + + {32ea8333-847b-443d-8992-4140d54dc1d3} + + + {2271439b-db98-4351-9457-77225ccee301} + + + {d2eb3e6f-49d6-49c6-a255-a0158414ff54} + + + {df6eb164-34b2-4f2a-9530-b88443662fb7} + + + {cb4e742a-6e43-4798-af4a-72bcb11089c9} + + + {ab21116d-5f5b-4ef8-82bb-6585ac3dec95} + + + {57d56081-eede-41a3-b9f0-e7019d32c986} + + + {a59b8bf9-45ee-49c9-bbac-9b065f41f1a2} + + + {7d49a3f4-a2eb-48b1-8f41-220b9ccf30dc} + + + {4f62540b-d186-479e-83a0-1b550134f487} + + + {9fe877a7-e261-4579-9752-a3156b6e69d9} + + + {8bc2336a-b1c5-4e93-9793-23a5cfdc741d} + + + {fc73555b-2be3-4898-bcdb-df83fa3e1388} + + + + + code\platform + + + code\api + + + code\api + + + code\broadcast + + + code\broadcast + + + code\common + + + code\lbr + + + code\pt + + + code\api + + + code\platform + + + code\broadcast + + + code\platform + + + code\components\callback + + + + + header + + + header\platform + + + header\api + + + header\broadcast + + + header\broadcast + + + header\common + + + header\globals + + + header\lbr + + + header\pt + + + header\api + + + header\api + + + header\platform + + + header\platform + + + header\platform + + + header\components\callback + + + + + + \ No newline at end of file diff --git a/hyperdbg/hypertrace/packages.config b/hyperdbg/hypertrace/packages.config new file mode 100644 index 00000000..eb276766 --- /dev/null +++ b/hyperdbg/hypertrace/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/hyperdbg/include/Definition.h b/hyperdbg/include/Definition.h deleted file mode 100644 index f7733598..00000000 --- a/hyperdbg/include/Definition.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file Definition.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Header files for global definitions - * @details This file contains definitions that are use in both user mode and - * kernel mode Means that if you change the following files, structures or - * enums, then these settings apply to both usermode and kernel mode - * @version 0.1 - * @date 2020-04-10 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Config File // -////////////////////////////////////////////////// - -/** - * @brief Config file name for HyperDbg - * - */ -#define CONFIG_FILE_NAME L"config.ini" - -////////////////////////////////////////////////// -// Installer // -////////////////////////////////////////////////// - -/** - * @brief name of HyperDbg's VMM driver - * - */ -#define VMM_DRIVER_NAME "hprdbghv" - -/** - * @brief name of HyperDbg's VMM driver - * - */ -#define KERNEL_DEBUGGER_DRIVER_NAME "hprdbgkd" - -////////////////////////////////////////////////// -// Test Cases // -////////////////////////////////////////////////// - -/** - * @brief Test cases file name - */ -#define TEST_CASE_FILE_NAME "test-cases.txt" - -/** - * @brief Test cases file name - */ -#define SCRIPT_ENGINE_TEST_CASES_DIRECTORY "script-test-cases" - -/** - * @brief Maximum test cases to communicate between debugger and debuggee process - */ -#define TEST_CASE_MAXIMUM_NUMBER_OF_KERNEL_TEST_CASES 200 - -/** - * @brief Maximum buffer to communicate between debugger and debuggee process - */ -#define TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE sizeof(DEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION) * TEST_CASE_MAXIMUM_NUMBER_OF_KERNEL_TEST_CASES - -////////////////////////////////////////////////// -// Delay Speeds // -////////////////////////////////////////////////// - -/** - * @brief The speed delay for showing messages from kernel-mode - * to user-mode in VMI-mode, using a lower value causes the - * HyperDbg to show messages faster but you should keep in mind, - * not to eat all of the CPU - */ -#define DefaultSpeedOfReadingKernelMessages 30 diff --git a/hyperdbg/include/SDK/Examples/hyperdbg_app/code/hyperdbg-app.cpp b/hyperdbg/include/SDK/Examples/hyperdbg_app/code/hyperdbg-app.cpp deleted file mode 100644 index dd2aa152..00000000 --- a/hyperdbg/include/SDK/Examples/hyperdbg_app/code/hyperdbg-app.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/** - * @file hyperdbg-app.cpp - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Controller of the reversing machine's module - * @details - * - * @version 0.2 - * @date 2023-02-01 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#include "pch.h" - -/** - * @brief Holds the global handle of device which is used - * to send the request to the kernel by IOCTL, this - * handle is not used for IRP Pending of message tracing - * this handle used in reversing machine - * - */ -HANDLE g_DeviceHandleReversingMachine; - -/** - * @brief Handle to show that if the debugger is loaded successfully - * - */ -HANDLE g_IsDriverLoadedSuccessfully = NULL; - -/** - * @brief Holds the global handle of device which is used - * to send the request to the kernel by IOCTL, this - * handle is not used for IRP Pending of message tracing - * this handle is used in KD VMM - * - */ -HANDLE g_DeviceHandle; - -/** - * @brief Checks whether the RM module is loaded or not - * - */ -BOOLEAN g_IsReversingMachineModulesLoaded; - -/** - * @brief Shows whether the vmxoff process start or not - * - */ -BOOLEAN g_IsVmxOffProcessStart; - -/* -#ifdef __cplusplus -extern "C" { -#endif - -__declspec(dllexport) int ReversingMachineStart(); -__declspec(dllexport) int ReversingMachineStop(); - -#ifdef __cplusplus -} -#endif -*/ - -/** - * @brief Show messages - * - * @param Fmt format string message - */ -VOID -ShowMessages(const char * Fmt, ...) -{ - va_list ArgList; - - va_start(ArgList, Fmt); - vprintf(Fmt, ArgList); - va_end(ArgList); -} - -/** - * @brief Read kernel buffers using IRP Pending - * - * @param Device Driver handle - */ -void -ReadIrpBasedBuffer() -{ - BOOL Status; - ULONG ReturnedLength; - REGISTER_NOTIFY_BUFFER RegisterEvent; - UINT32 OperationCode; - DWORD ErrorNum; - HANDLE Handle; - - RegisterEvent.hEvent = NULL; - RegisterEvent.Type = IRP_BASED; - - // - // Create another handle to be used in for reading kernel messages, - // it is because I noticed that if I use a same handle for IRP Pending - // and other IOCTLs then if I complete that IOCTL then both of the current - // IOCTL and the Pending IRP are completed and return to user mode, - // even if it's odd but that what happens, so this way we can solve it - // if you know why this problem happens, then contact me ! - // - Handle = CreateFileA( - "\\\\.\\HyperDbgReversingMachineDevice", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, /// lpSecurityAttirbutes - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - NULL); /// lpTemplateFile - - if (Handle == INVALID_HANDLE_VALUE) - { - ErrorNum = GetLastError(); - if (ErrorNum == ERROR_ACCESS_DENIED) - { - ShowMessages("err, access denied\nare you sure you have administrator " - "rights?\n"); - } - else if (ErrorNum == ERROR_GEN_FAILURE) - { - ShowMessages("err, a device attached to the system is not functioning\n" - "vmx feature might be disabled from BIOS or VBS/HVCI is active\n"); - } - else - { - ShowMessages("err, CreateFile failed with (%x)\n", ErrorNum); - } - - g_DeviceHandle = NULL; - Handle = NULL; - - return; - } - - // - // allocate buffer for transferring messages - // - char * OutputBuffer = (char *)malloc(UsermodeBufferSize); - - try - { - while (TRUE) - { - // - // Clear the buffer - // - ZeroMemory(OutputBuffer, UsermodeBufferSize); - - Sleep(DefaultSpeedOfReadingKernelMessages); // we're not trying to eat all of the CPU ;) - - Status = DeviceIoControl( - Handle, // Handle to device - IOCTL_REGISTER_EVENT, // IO Control Code (IOCTL) - &RegisterEvent, // Input Buffer to driver. - SIZEOF_REGISTER_EVENT * 2, // Length of input buffer in bytes. (x 2 is bcuz as the - // driver is x64 and has 64 bit values) - OutputBuffer, // Output Buffer from driver. - UsermodeBufferSize, // Length of output buffer in bytes. - &ReturnedLength, // Bytes placed in buffer. - NULL // synchronous call - ); - - if (!Status) - { - // - // Error occurred for second time, and we show the error message - // - // ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); - - // - // if we reach here, the packet is probably failed, it might - // be because of using flush command - // - continue; - } - - // - // Compute the received buffer's operation code - // - OperationCode = 0; - memcpy(&OperationCode, OutputBuffer, sizeof(UINT32)); - - switch (OperationCode) - { - case OPERATION_LOG_NON_IMMEDIATE_MESSAGE: - - ShowMessages("%s", OutputBuffer + sizeof(UINT32)); - - break; - case OPERATION_LOG_INFO_MESSAGE: - - ShowMessages("%s", OutputBuffer + sizeof(UINT32)); - - break; - case OPERATION_LOG_ERROR_MESSAGE: - - ShowMessages("%s", OutputBuffer + sizeof(UINT32)); - - break; - case OPERATION_LOG_WARNING_MESSAGE: - - ShowMessages("%s", OutputBuffer + sizeof(UINT32)); - - break; - - case OPERATION_HYPERVISOR_DRIVER_IS_SUCCESSFULLY_LOADED: - - // - // Indicate that driver (Hypervisor) is loaded successfully - // - SetEvent(g_IsDriverLoadedSuccessfully); - - break; - - default: - - ShowMessages("err, unknown message is received in rev module\n"); - - break; - } - } - } - catch (const std::exception &) - { - ShowMessages("err, exception occurred in creating handle or parsing buffer\n"); - } - free(OutputBuffer); - - // - // closeHandle - // - if (!CloseHandle(Handle)) - { - ShowMessages("err, closing handle 0x%x\n", GetLastError()); - }; -} - -/** - * @brief Create a thread for pending buffers - * - * @param Data - * @return DWORD Device Handle - */ -DWORD WINAPI -IrpBasedBufferThread(void * data) -{ - // - // Do stuff. This will be the first function called on the new - // thread. When this function returns, the thread goes away. See - // MSDN for more details. Test Irp Based Notifications - // - ReadIrpBasedBuffer(); - - return 0; -} - -/** - * @brief Unload the reversing machine driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -int -ReversingMachineStop() -{ - // - // Not implemented - // - return 0; -} - -/** - * @brief Load the reversing machine driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -int -ReversingMachineStart() -{ - DWORD ErrorNum; - DWORD ThreadId; - - if (g_DeviceHandle) - { - ShowMessages("handle of the driver found, if you use 'load' before, please " - "unload it using 'unload'\n"); - return 1; - } - - // - // Make sure that this variable is false, because it might be set to - // true as the result of a previous load - // - g_IsVmxOffProcessStart = FALSE; - - // - // Init entering vmx - // - g_DeviceHandle = CreateFileA( - "\\\\.\\HyperDbgReversingMachineDevice", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, /// lpSecurityAttirbutes - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - NULL); /// lpTemplateFile - - if (g_DeviceHandle == INVALID_HANDLE_VALUE) - { - ErrorNum = GetLastError(); - - if (ErrorNum == ERROR_ACCESS_DENIED) - { - ShowMessages("err, access denied\nare you sure you have administrator " - "rights?\n"); - } - else if (ErrorNum == ERROR_GEN_FAILURE) - { - ShowMessages("err, a device attached to the system is not functioning\n" - "vmx feature might be disabled from BIOS or VBS/HVCI is active\n"); - } - else - { - ShowMessages("err, CreateFile failed (%x)\n", ErrorNum); - } - - g_DeviceHandle = NULL; - return 1; - } - // - // Create event to show if the hypervisor is loaded or not - // - g_IsDriverLoadedSuccessfully = CreateEvent(NULL, FALSE, FALSE, NULL); - - HANDLE Thread = CreateThread(NULL, 0, IrpBasedBufferThread, NULL, 0, &ThreadId); - - // if (Thread) - // { - // ShowMessages("thread Created successfully\n"); - // } - - // - // We wait for the first message from the kernel debugger to continue - // - WaitForSingleObject( - g_IsDriverLoadedSuccessfully, - INFINITE); - - // - // No need to handle anymore - // - CloseHandle(g_IsDriverLoadedSuccessfully); - - // - // Operation was successful - // - return 0; -} - -/** - * @brief Unload the reversing machine driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -int -HyperDbgUnloadReversingMachine() -{ - // - // Check if driver is loaded - // - if (!g_IsReversingMachineModulesLoaded) - { - ShowMessages("handle of the driver not found, probably the driver is not loaded. Did you use 'load' command?\n"); - return 1; - } - - ShowMessages("start terminating...\n"); - - // - // Call the unloader of the hprdbgrev module - // - ReversingMachineStop(); - - ShowMessages("you're not on reversing machine's hypervisor anymore!\n"); - - return 0; -} - -/** - * @brief Load the reversing machine driver - * - * @return int return zero if it was successful or non-zero if there - * was error - */ -int -HyperDbgLoadReversingMachine() -{ - char CpuId[13] = {0}; - - if (g_DeviceHandle) - { - ShowMessages("handle of the driver found, if you use 'load' before, please " - "unload it using 'unload'\n"); - return 1; - } - - // - // Read the vendor string - // - HyperDbgReadVendorString(CpuId); - - ShowMessages("current processor vendor is : %s\n", CpuId); - - if (strcmp(CpuId, "GenuineIntel") == 0) - { - ShowMessages("virtualization technology is vt-x\n"); - } - else - { - ShowMessages("this program is not designed to run in a non-VT-x " - "environment !\n"); - return 1; - } - - if (HyperDbgVmxSupportDetection()) - { - ShowMessages("vmx operation is supported by your processor\n"); - } - else - { - ShowMessages("vmx operation is not supported by your processor\n"); - return 1; - } - - // - // Call hprdbgrev start function - // - ReversingMachineStart(); - - return 0; -} - -/** - * @brief main function - * - * @return int - */ -int -main() -{ - if (HyperDbgLoadReversingMachine() == 0) - { - // - // HyperDbg driver loaded successfully - // - HyperDbgUnloadReversingMachine(); - } - else - { - ShowMessages("err, in loading HyperDbg\n"); - } -} diff --git a/hyperdbg/include/SDK/Headers/BasicTypes.h b/hyperdbg/include/SDK/Headers/BasicTypes.h deleted file mode 100644 index 7c426390..00000000 --- a/hyperdbg/include/SDK/Headers/BasicTypes.h +++ /dev/null @@ -1,144 +0,0 @@ -/** - * @file BasicTypes.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief HyperDbg's SDK Headers For Basic Datatypes - * @details This file contains definitions of basic datatypes - * @version 0.2 - * @date 2022-06-28 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -#pragma warning(disable : 4201) // Suppress nameless struct/union warning - -////////////////////////////////////////////////// -// Basic Datatypes // -////////////////////////////////////////////////// - -typedef unsigned long long QWORD; -typedef unsigned __int64 UINT64, *PUINT64; -typedef unsigned long DWORD; -typedef int BOOL; -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef int INT; -typedef unsigned int UINT; -typedef unsigned int * PUINT; -typedef unsigned __int64 ULONG64, *PULONG64; -typedef unsigned __int64 DWORD64, *PDWORD64; -typedef char CHAR; -typedef wchar_t WCHAR; -#define VOID void - -typedef unsigned char UCHAR; -typedef unsigned short USHORT; -typedef unsigned long ULONG; - -typedef UCHAR BOOLEAN; // winnt -typedef BOOLEAN * PBOOLEAN; // winnt - -typedef signed char INT8, *PINT8; -typedef signed short INT16, *PINT16; -typedef signed int INT32, *PINT32; -typedef signed __int64 INT64, *PINT64; -typedef unsigned char UINT8, *PUINT8; -typedef unsigned short UINT16, *PUINT16; -typedef unsigned int UINT32, *PUINT32; -typedef unsigned __int64 UINT64, *PUINT64; - -#define NULL_ZERO 0 -#define NULL64_ZERO 0ull - -#define FALSE 0 -#define TRUE 1 - -#define UPPER_56_BITS 0xffffffffffffff00 -#define UPPER_48_BITS 0xffffffffffff0000 -#define UPPER_32_BITS 0xffffffff00000000 -#define LOWER_32_BITS 0x00000000ffffffff -#define LOWER_16_BITS 0x000000000000ffff -#define LOWER_8_BITS 0x00000000000000ff -#define SECOND_LOWER_8_BITS 0x000000000000ff00 -#define UPPER_48_BITS_AND_LOWER_8_BITS 0xffffffffffff00ff - -// -// DO NOT FUCKING TOUCH THIS STRUCTURE WITHOUT COORDINATION WITH SINA -// -typedef struct GUEST_REGS -{ - // - // DO NOT FUCKING TOUCH THIS STRUCTURE WITHOUT COORDINATION WITH SINA - // - - UINT64 rax; // 0x00 - UINT64 rcx; // 0x08 - UINT64 rdx; // 0x10 - UINT64 rbx; // 0x18 - UINT64 rsp; // 0x20 - UINT64 rbp; // 0x28 - UINT64 rsi; // 0x30 - UINT64 rdi; // 0x38 - UINT64 r8; // 0x40 - UINT64 r9; // 0x48 - UINT64 r10; // 0x50 - UINT64 r11; // 0x58 - UINT64 r12; // 0x60 - UINT64 r13; // 0x68 - UINT64 r14; // 0x70 - UINT64 r15; // 0x78 - - // - // DO NOT FUCKING TOUCH THIS STRUCTURE WITHOUT COORDINATION WITH SINA - // - -} GUEST_REGS, *PGUEST_REGS; - -/** - * @brief struct for extra registers - * - */ -typedef struct GUEST_EXTRA_REGISTERS -{ - UINT16 CS; - UINT16 DS; - UINT16 FS; - UINT16 GS; - UINT16 ES; - UINT16 SS; - UINT64 RFLAGS; - UINT64 RIP; -} GUEST_EXTRA_REGISTERS, *PGUEST_EXTRA_REGISTERS; - -/** - * @brief List of different variables - */ -typedef struct _SCRIPT_ENGINE_VARIABLES_LIST -{ - UINT64 * TempList; - UINT64 * GlobalVariablesList; - UINT64 * LocalVariablesList; - -} SCRIPT_ENGINE_VARIABLES_LIST, *PSCRIPT_ENGINE_VARIABLES_LIST; - -/** - * @brief CR3 Structure - * - */ -typedef struct _CR3_TYPE -{ - union - { - UINT64 Flags; - - struct - { - UINT64 Pcid : 12; - UINT64 PageFrameNumber : 36; - UINT64 Reserved1 : 12; - UINT64 Reserved_2 : 3; - UINT64 PcidInvalidate : 1; - } Fields; - }; -} CR3_TYPE, *PCR3_TYPE; diff --git a/hyperdbg/include/SDK/Headers/HardwareDebugger.h b/hyperdbg/include/SDK/Headers/HardwareDebugger.h deleted file mode 100644 index 4a62700f..00000000 --- a/hyperdbg/include/SDK/Headers/HardwareDebugger.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @file HardwareDebugger.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief HyperDbg's Hardware Debugger (hwdbg) types and constants - * @details This file contains definitions of hwdbg elements - * used in HyperDbg - * @version 0.9 - * @date 2024-04-28 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -/** - * @brief Different action of hwdbg - * @warning This file should be changed along with hwdbg files - * - */ -typedef enum _HWDBG_ACTION_ENUMS -{ - hwdbgActionSendVersion = 0, - hwdbgActionSendPinInformation = 1, - hwdbgActionConfigureScriptBuffer = 2, - -} HWDBG_ACTION_ENUMS; - -/** - * @brief Different responses come from hwdbg - * @warning This file should be changed along with hwdbg files - * - */ -typedef enum _HWDBG_RESPONSE_ENUMS -{ - hwdbgResponseVersion = 0, - hwdbgResponsePinInformation = 1, - hwdbgResponseScriptBufferConfigurationResult = 2, - -} HWDBG_RESPONSE_ENUMS; diff --git a/hyperdbg/include/SDK/Headers/Ioctls.h b/hyperdbg/include/SDK/Headers/Ioctls.h deleted file mode 100644 index 62ea34a1..00000000 --- a/hyperdbg/include/SDK/Headers/Ioctls.h +++ /dev/null @@ -1,297 +0,0 @@ -/** - * @file Ioctls.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief HyperDbg's SDK IOCTL codes - * @details This file contains definitions of IOCTLs used in HyperDbg - * @version 0.2 - * @date 2022-06-24 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -////////////////////////////////////////////////// -// Definitions // -////////////////////////////////////////////////// - -// -// The following controls are mainly defined in -// - -// -// Macro definition for defining IOCTL and FSCTL function control codes. Note -// that function codes 0-2047 are reserved for Microsoft Corporation, and -// 2048-4095 are reserved for customers. -// -#ifndef CTL_CODE - -# define CTL_CODE(DeviceType, Function, Method, Access) ( \ - ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) - -#endif // ! CTL_CODE - -#ifndef FILE_ANY_ACCESS - -# define FILE_ANY_ACCESS 0 - -#endif // !FILE_ANY_ACCESS - -// -// Define the method codes for how buffers are passed for I/O and FS controls -// - -#ifndef METHOD_BUFFERED - -# define METHOD_BUFFERED 0 - -#endif // !METHOD_BUFFERED - -#ifndef FILE_DEVICE_UNKNOWN - -# define FILE_DEVICE_UNKNOWN 0x00000022 - -#endif // !FILE_DEVICE_UNKNOWN - -////////////////////////////////////////////////// -// IOCTLs // -////////////////////////////////////////////////// - -/** - * @brief ioctl, register a new event - * - */ -#define IOCTL_REGISTER_EVENT \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, irp pending mechanism for reading from message tracing buffers - * - */ -#define IOCTL_RETURN_IRP_PENDING_PACKETS_AND_DISALLOW_IOCTL \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, to terminate vmx and exit form debugger - * - */ -#define IOCTL_TERMINATE_VMX \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, request to read memory - * - */ -#define IOCTL_DEBUGGER_READ_MEMORY \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, request to read or write on a special MSR - * - */ -#define IOCTL_DEBUGGER_READ_OR_WRITE_MSR \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, request to read page table entries - * - */ -#define IOCTL_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, register an event - * - */ -#define IOCTL_DEBUGGER_REGISTER_EVENT \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, add action to event - * - */ -#define IOCTL_DEBUGGER_ADD_ACTION_TO_EVENT \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, request to enable or disable transparent-mode - * - */ -#define IOCTL_DEBUGGER_HIDE_AND_UNHIDE_TO_TRANSPARENT_THE_DEBUGGER \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, for !va2pa and !pa2va commands - * - */ -#define IOCTL_DEBUGGER_VA2PA_AND_PA2VA_COMMANDS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, request to edit virtual and physical memory - * - */ -#define IOCTL_DEBUGGER_EDIT_MEMORY \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80a, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, request to search virtual and physical memory - * - */ -#define IOCTL_DEBUGGER_SEARCH_MEMORY \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80b, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, request to modify an event (enable/disable/clear) - * - */ -#define IOCTL_DEBUGGER_MODIFY_EVENTS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80c, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, flush the kernel buffers - * - */ -#define IOCTL_DEBUGGER_FLUSH_LOGGING_BUFFERS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80d, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, attach or detach user-mode processes - * - */ -#define IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80e, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, print states (Deprecated) - * - * - */ -#define IOCTL_DEBUGGER_PRINT \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80f, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, prepare debuggee - * - */ -#define IOCTL_PREPARE_DEBUGGEE \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, pause and halt the system - * - */ -#define IOCTL_PAUSE_PACKET_RECEIVED \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x811, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, send a signal that execution of command finished - * - */ -#define IOCTL_SEND_SIGNAL_EXECUTION_IN_DEBUGGEE_FINISHED \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x812, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, send user-mode messages to the debugger - * - */ -#define IOCTL_SEND_USERMODE_MESSAGES_TO_DEBUGGER \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x813, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, send general buffer from debuggee to debugger - * - */ -#define IOCTL_SEND_GENERAL_BUFFER_FROM_DEBUGGEE_TO_DEBUGGER \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x814, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, collects a buffer from kernel-side testing information - * - */ -#define IOCTL_SEND_GET_KERNEL_SIDE_TEST_INFORMATION \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x815, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, to perform kernel-side tests - * - */ -#define IOCTL_PERFROM_KERNEL_SIDE_TESTS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x816, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, to reserve pre-allocated pools - * - */ -#define IOCTL_RESERVE_PRE_ALLOCATED_POOLS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x817, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, to send user debugger commands - * - */ -#define IOCTL_SEND_USER_DEBUGGER_COMMANDS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x818, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, to get active threads/processes that are debugging - * - */ -#define IOCTL_GET_DETAIL_OF_ACTIVE_THREADS_AND_PROCESSES \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x819, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, to get user mode modules details - * - */ -#define IOCTL_GET_USER_MODE_MODULE_DETAILS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x81a, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, query count of active threads or processes - * - */ -#define IOCTL_QUERY_COUNT_OF_ACTIVE_PROCESSES_OR_THREADS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x81b, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, to get list threads/processes - * - */ -#define IOCTL_GET_LIST_OF_THREADS_AND_PROCESSES \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x81c, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, query the current process details - * - */ -#define IOCTL_QUERY_CURRENT_PROCESS \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x81d, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, query the current thread details - * - */ -#define IOCTL_QUERY_CURRENT_THREAD \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x81e, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, request service from the reversing machine - * - */ -#define IOCTL_REQUEST_REV_MACHINE_SERVICE \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x81f, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, request to bring pages in - * - */ -#define IOCTL_DEBUGGER_BRING_PAGES_IN \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x820, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/** - * @brief ioctl, to preactivate a functionality - * - */ -#define IOCTL_PREACTIVATE_FUNCTIONALITY \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS) diff --git a/hyperdbg/include/SDK/HyperDbgSdk.h b/hyperdbg/include/SDK/HyperDbgSdk.h index 9fcaa386..fc53dd57 100644 --- a/hyperdbg/include/SDK/HyperDbgSdk.h +++ b/hyperdbg/include/SDK/HyperDbgSdk.h @@ -1,11 +1,44 @@ #pragma once -#include "SDK/Headers/Constants.h" -#include "SDK/Headers/BasicTypes.h" -#include "SDK/Headers/ErrorCodes.h" -#include "SDK/Headers/Connection.h" -#include "SDK/Headers/DataTypes.h" -#include "SDK/Headers/Ioctls.h" -#include "SDK/Headers/Events.h" -#include "SDK/Headers/RequestStructures.h" -#include "SDK/Headers/Symbols.h" +// +// General SDK Headers +// +#include "SDK/headers/BasicTypes.h" +#include "SDK/headers/Constants.h" +#include "SDK/headers/ErrorCodes.h" +#include "SDK/headers/Connection.h" +#include "SDK/headers/DataTypes.h" +#include "SDK/headers/Ioctls.h" +#include "SDK/headers/Events.h" +#include "SDK/headers/Symbols.h" +#include "SDK/headers/HardwareDebugger.h" + +// +// Devices +// +#include "SDK/headers/Pcie.h" + +// +// Last Branch Records +// +#include "SDK/headers/LbrDefinitions.h" + +// +// Intel Processor Trace +// +#include "SDK/headers/PtDefinitions.h" + +// +// Request Packets +// +#include "SDK/headers/RequestStructures.h" + +// +// Asserts +// +#include "SDK/headers/Assertions.h" + +// +// Script Engine +// +#include "SDK/headers/ScriptEngineCommonDefinitions.h" diff --git a/hyperdbg/include/SDK/Imports/HyperDbgCtrlImports.h b/hyperdbg/include/SDK/Imports/HyperDbgCtrlImports.h deleted file mode 100644 index 0664cead..00000000 --- a/hyperdbg/include/SDK/Imports/HyperDbgCtrlImports.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @file HyperDbgCtrlImports.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Headers relating exported functions from controller interface - * @version 0.2 - * @date 2023-02-02 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -#ifdef HYPERDBG_HPRDBGCTRL -# define IMPORT_EXPORT_CTRL __declspec(dllexport) -#else -# define IMPORT_EXPORT_CTRL __declspec(dllimport) -#endif - -// -// Header file of HPRDBGCTRL -// Imports -// -#ifdef __cplusplus -extern "C" { -#endif - -// -// Support Detection -// -IMPORT_EXPORT_CTRL bool HyperDbgVmxSupportDetection(); -IMPORT_EXPORT_CTRL void HyperDbgReadVendorString(char *); - -// -// VMM Module -// -IMPORT_EXPORT_CTRL int HyperDbgLoadVmm(); -IMPORT_EXPORT_CTRL int HyperDbgUnloadVmm(); -IMPORT_EXPORT_CTRL int HyperDbgInstallVmmDriver(); -IMPORT_EXPORT_CTRL int HyperDbgUninstallVmmDriver(); -IMPORT_EXPORT_CTRL int HyperDbgStopVmmDriver(); - -// -// General imports -// -IMPORT_EXPORT_CTRL int HyperDbgInterpreter(char * Command); -IMPORT_EXPORT_CTRL void HyperDbgShowSignature(); -IMPORT_EXPORT_CTRL void HyperDbgSetTextMessageCallback(Callback handler); -IMPORT_EXPORT_CTRL int HyperDbgScriptReadFileAndExecuteCommandline(int argc, char * argv[]); -IMPORT_EXPORT_CTRL bool HyperDbgContinuePreviousCommand(); -IMPORT_EXPORT_CTRL bool HyperDbgCheckMultilineCommand(char * CurrentCommand, bool Reset); - -#ifdef __cplusplus -} -#endif diff --git a/hyperdbg/include/SDK/Imports/HyperDbgRevImports.h b/hyperdbg/include/SDK/Imports/HyperDbgRevImports.h deleted file mode 100644 index 25a90cb2..00000000 --- a/hyperdbg/include/SDK/Imports/HyperDbgRevImports.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file HyperDbgRevImports.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Headers relating exported functions from reversing machine interface - * @version 0.2 - * @date 2023-02-02 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -// -// Header file of hpr -// Imports -// -#ifdef __cplusplus -extern "C" { -#endif - -// -// Reversing Machine Module -// -__declspec(dllimport) int ReversingMachineStart(); -__declspec(dllimport) int ReversingMachineStop(); - -#ifdef __cplusplus -} -#endif diff --git a/hyperdbg/include/SDK/Imports/HyperDbgScriptImports.h b/hyperdbg/include/SDK/Imports/HyperDbgScriptImports.h deleted file mode 100644 index f677985b..00000000 --- a/hyperdbg/include/SDK/Imports/HyperDbgScriptImports.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file HyperDbgScriptImports.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Headers relating exported functions from script engine - * @version 0.2 - * @date 2023-02-02 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -// -// Header file of script-engine -// Imports -// -#ifdef __cplusplus -extern "C" { -#endif - -__declspec(dllimport) PSYMBOL_BUFFER ScriptEngineParse(char * str); -__declspec(dllimport) PSYMBOL_BUFFER GetStackBuffer(); -__declspec(dllimport) void PrintSymbolBuffer(const PSYMBOL_BUFFER SymbolBuffer); -__declspec(dllimport) void PrintSymbol(PSYMBOL Symbol); -__declspec(dllimport) void RemoveSymbolBuffer(PSYMBOL_BUFFER SymbolBuffer); - -// -// pdb parser -// -__declspec(dllimport) VOID - ScriptEngineSetTextMessageCallback(PVOID Handler); -__declspec(dllimport) VOID - ScriptEngineSymbolAbortLoading(); -__declspec(dllimport) UINT64 - ScriptEngineConvertNameToAddress(const char * FunctionOrVariableName, PBOOLEAN WasFound); -__declspec(dllimport) UINT32 - ScriptEngineLoadFileSymbol(UINT64 BaseAddress, const char * PdbFileName, const char * CustomModuleName); -__declspec(dllimport) UINT32 - ScriptEngineUnloadAllSymbols(); -__declspec(dllimport) UINT32 - ScriptEngineUnloadModuleSymbol(char * ModuleName); -__declspec(dllimport) UINT32 - ScriptEngineSearchSymbolForMask(const char * SearchMask); -__declspec(dllimport) BOOLEAN - ScriptEngineGetFieldOffset(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset); -__declspec(dllimport) BOOLEAN - ScriptEngineGetDataTypeSize(CHAR * TypeName, UINT64 * TypeSize); -__declspec(dllimport) BOOLEAN - ScriptEngineCreateSymbolTableForDisassembler(void * CallbackFunction); -__declspec(dllimport) BOOLEAN - ScriptEngineConvertFileToPdbPath(const char * LocalFilePath, char * ResultPath); -__declspec(dllimport) BOOLEAN - ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetails(const char * LocalFilePath, char * PdbFilePath, char * GuidAndAgeDetails, BOOLEAN Is32BitModule); -__declspec(dllimport) BOOLEAN - ScriptEngineSymbolInitLoad(PVOID BufferToStoreDetails, UINT32 StoredLength, BOOLEAN DownloadIfAvailable, const char * SymbolPath, BOOLEAN IsSilentLoad); -__declspec(dllimport) BOOLEAN - ScriptEngineShowDataBasedOnSymbolTypes(const char * TypeName, UINT64 Address, BOOLEAN IsStruct, PVOID BufferAddress, const char * AdditionalParameters); - -#ifdef __cplusplus -} -#endif diff --git a/hyperdbg/include/SDK/Imports/HyperDbgSymImports.h b/hyperdbg/include/SDK/Imports/HyperDbgSymImports.h deleted file mode 100644 index 2985523f..00000000 --- a/hyperdbg/include/SDK/Imports/HyperDbgSymImports.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file HyperDbgSymImports.h - * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Headers relating exported functions from symbol parser - * @version 0.2 - * @date 2023-02-02 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -// -// Header file of symbol-parser -// Imports -// -#ifdef __cplusplus -extern "C" { -#endif - -__declspec(dllimport) VOID - SymSetTextMessageCallback(PVOID Handler); -__declspec(dllimport) VOID - SymbolAbortLoading(); -__declspec(dllimport) UINT64 - SymConvertNameToAddress(const char * FunctionOrVariableName, PBOOLEAN WasFound); -__declspec(dllimport) UINT32 - SymLoadFileSymbol(UINT64 BaseAddress, const char * PdbFileName, const char * CustomModuleName); -__declspec(dllimport) UINT32 - SymUnloadAllSymbols(); -__declspec(dllimport) UINT32 - SymUnloadModuleSymbol(char * ModuleName); -__declspec(dllimport) UINT32 - SymSearchSymbolForMask(const char * SearchMask); -__declspec(dllimport) BOOLEAN - SymGetFieldOffset(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset); -__declspec(dllimport) BOOLEAN - SymGetDataTypeSize(CHAR * TypeName, UINT64 * TypeSize); -__declspec(dllimport) BOOLEAN - SymCreateSymbolTableForDisassembler(void * CallbackFunction); -__declspec(dllimport) BOOLEAN - SymConvertFileToPdbPath(const char * LocalFilePath, char * ResultPath); -__declspec(dllimport) BOOLEAN - SymConvertFileToPdbFileAndGuidAndAgeDetails(const char * LocalFilePath, - char * PdbFilePath, - char * GuidAndAgeDetails, - BOOLEAN Is32BitModule); -__declspec(dllimport) BOOLEAN - SymbolInitLoad(PVOID BufferToStoreDetails, - UINT32 StoredLength, - BOOLEAN DownloadIfAvailable, - const char * SymbolPath, - BOOLEAN IsSilentLoad); -__declspec(dllimport) BOOLEAN - SymShowDataBasedOnSymbolTypes(const char * TypeName, - UINT64 Address, - BOOLEAN IsStruct, - PVOID BufferAddress, - const char * AdditionalParameters); -__declspec(dllimport) BOOLEAN - SymQuerySizeof(_In_ const char * StructNameOrTypeName, _Out_ UINT32 * SizeOfField); -__declspec(dllimport) BOOLEAN - SymCastingQueryForFiledsAndTypes(_In_ const char * StructName, - _In_ const char * FiledOfStructName, - _Out_ PBOOLEAN IsStructNamePointerOrNot, - _Out_ PBOOLEAN IsFiledOfStructNamePointerOrNot, - _Out_ char ** NewStructOrTypeName, - _Out_ UINT32 * OffsetOfFieldFromTop, - _Out_ UINT32 * SizeOfField); - -#ifdef __cplusplus -} -#endif diff --git a/hyperdbg/include/SDK/headers/Assertions.h b/hyperdbg/include/SDK/headers/Assertions.h new file mode 100644 index 00000000..6f5ea32e --- /dev/null +++ b/hyperdbg/include/SDK/headers/Assertions.h @@ -0,0 +1,31 @@ +/** + * @file Assertions.h + * @author ddkwork + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief HyperDbg's assertions + * @details This file contains asserts and static asserts + * @version 0.10 + * @date 2024-06-21 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Asserts // +////////////////////////////////////////////////// + +/** + * @brief check so the DEBUGGEE_UD_PAUSED_PACKET should be smaller than packet size + * + */ +static_assert(sizeof(DEBUGGEE_UD_PAUSED_PACKET) < PacketChunkSize, + "err (static_assert), size of PacketChunkSize should be bigger than DEBUGGEE_UD_PAUSED_PACKET"); + +/** + * @brief check so the DEBUGGER_UPDATE_SYMBOL_TABLE should be smaller than packet size + * + */ +static_assert(sizeof(DEBUGGER_UPDATE_SYMBOL_TABLE) < PacketChunkSize, + "err (static_assert), size of PacketChunkSize should be bigger than DEBUGGER_UPDATE_SYMBOL_TABLE (MODULE_SYMBOL_DETAIL)"); diff --git a/hyperdbg/include/SDK/headers/BasicTypes.h b/hyperdbg/include/SDK/headers/BasicTypes.h new file mode 100644 index 00000000..17e5c84a --- /dev/null +++ b/hyperdbg/include/SDK/headers/BasicTypes.h @@ -0,0 +1,250 @@ +/** + * @file BasicTypes.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief HyperDbg's SDK Headers For Basic Datatypes + * @details This file contains definitions of basic datatypes + * @version 0.2 + * @date 2022-06-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#ifdef _WIN32 // Windows + +# pragma warning(disable : 4201) // Suppress nameless struct/union warning + +#endif + +////////////////////////////////////////////////// +// Basic Datatypes // +////////////////////////////////////////////////// + +typedef unsigned long long QWORD; +typedef int BOOL; + +typedef short SHORT; +typedef long LONG; + +typedef unsigned short USHORT; +typedef unsigned long ULONG; + +typedef char CHAR; +typedef unsigned char UCHAR; +typedef UCHAR BOOLEAN; +typedef BOOLEAN * PBOOLEAN; + +typedef unsigned long DWORD; +typedef unsigned long ULONG; +typedef unsigned char BYTE; +typedef unsigned short USHORT; +typedef unsigned short WORD; +typedef int INT; +typedef unsigned int UINT; +typedef unsigned int * PUINT; + +typedef int INT; +typedef signed char INT8, *PINT8; +typedef signed short INT16, *PINT16; +typedef signed int INT32, *PINT32; + +typedef unsigned char UINT8, *PUINT8; +typedef unsigned short UINT16, *PUINT16; +typedef unsigned int UINT32, *PUINT32; + +typedef void * PVOID; + +#ifdef _WIN32 // Windows + +typedef signed __int64 INT64, *PINT64; +typedef unsigned __int64 UINT64, *PUINT64; + +typedef unsigned __int64 ULONG64, *PULONG64; +typedef unsigned __int64 DWORD64, *PDWORD64; + +typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; +typedef unsigned __int64 ULONGLONG; + +typedef wchar_t WCHAR; + +#elif defined(__linux__) // Linux + +typedef void VOID; + +typedef size_t SIZE_T; +typedef SIZE_T * PSIZE_T; + +typedef signed long long INT64, *PINT64; +typedef unsigned long long UINT64, *PUINT64; + +typedef unsigned long long ULONG64, *PULONG64; +typedef unsigned long long DWORD64, *PDWORD64; + +typedef unsigned long long ULONGLONG; +typedef unsigned long long ULONG_PTR, *PULONG_PTR; + +typedef INT64 LONGLONG; + +typedef union _LARGE_INTEGER { + struct { DWORD LowPart; LONG HighPart; }; + LONGLONG QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +// +// To be fixed later, linux wchar_t is 4 bytes, but windows wchar_t is 2 bytes +// +// typedef UINT16 wchar_t; +typedef UINT16 WCHAR; +// typedef wchar_t WCHAR; + +typedef PVOID HANDLE; +typedef HANDLE * PHANDLE; + +// Windows pointer-style aliases (used by the cross-platform driver/IOCTL wrappers) +typedef PVOID LPVOID; +typedef DWORD * LPDWORD; + +#endif + +#define NULL_ZERO 0 +#define NULL64_ZERO 0ull + +#define FALSE 0 +#define TRUE 1 + +#define UPPER_56_BITS 0xffffffffffffff00 +#define UPPER_48_BITS 0xffffffffffff0000 +#define UPPER_32_BITS 0xffffffff00000000 +#define LOWER_32_BITS 0x00000000ffffffff +#define LOWER_16_BITS 0x000000000000ffff +#define LOWER_8_BITS 0x00000000000000ff +#define SECOND_LOWER_8_BITS 0x000000000000ff00 +#define UPPER_48_BITS_AND_LOWER_8_BITS 0xffffffffffff00ff + +#if defined(__linux__) // Linux + +# define MAX_PATH 260 + +#endif + +// +// DO NOT FUCKING TOUCH THIS STRUCTURE WITHOUT COORDINATION WITH SINA +// +#pragma pack(push, 1) // Ensure no padding +typedef struct GUEST_REGS +{ + // + // DO NOT FUCKING TOUCH THIS STRUCTURE WITHOUT COORDINATION WITH SINA + // + + UINT64 rax; // 0x00 + UINT64 rcx; // 0x08 + UINT64 rdx; // 0x10 + UINT64 rbx; // 0x18 + UINT64 rsp; // 0x20 + UINT64 rbp; // 0x28 + UINT64 rsi; // 0x30 + UINT64 rdi; // 0x38 + UINT64 r8; // 0x40 + UINT64 r9; // 0x48 + UINT64 r10; // 0x50 + UINT64 r11; // 0x58 + UINT64 r12; // 0x60 + UINT64 r13; // 0x68 + UINT64 r14; // 0x70 + UINT64 r15; // 0x78 + + // + // DO NOT FUCKING TOUCH THIS STRUCTURE WITHOUT COORDINATION WITH SINA + // + +} GUEST_REGS, *PGUEST_REGS; +#pragma pack(pop) + +typedef struct XMM_REG +{ + UINT64 XmmLow; // Low 64 bits + UINT64 XmmHigh; // High 64 bits + +} XMM_REG; + +#pragma pack(push, 1) // Ensure no padding +typedef struct GUEST_XMM_REGS +{ + XMM_REG xmm0; // 0x00 + XMM_REG xmm1; // 0x10 + XMM_REG xmm2; // 0x20 + XMM_REG xmm3; // 0x30 + XMM_REG xmm4; // 0x40 + XMM_REG xmm5; // 0x50 + + // + // As per Microsoft ABI documentation, the following registers are nonvolatile + // So, MSVC compiler will save them on the stack if they are used in the function + // Thus, for the sake of performance, we comment them out + // + XMM_REG xmm6_not_saved; // 0x60 + XMM_REG xmm7_not_saved; // 0x70 + XMM_REG xmm8_not_saved; // 0x80 + XMM_REG xmm9_not_saved; // 0x90 + XMM_REG xmm10_not_saved; // 0xA0 + XMM_REG xmm11_not_saved; // 0xB0 + XMM_REG xmm12_not_saved; // 0xC0 + XMM_REG xmm13_not_saved; // 0xD0 + XMM_REG xmm14_not_saved; // 0xE0 + XMM_REG xmm15_not_saved; // 0xF0 + + UINT32 mxcsr; // 0x100 + +} GUEST_XMM_REGS, *PGUEST_XMM_REGS; +#pragma pack(pop) + +/** + * @brief struct for extra registers + * + */ +typedef struct GUEST_EXTRA_REGISTERS +{ + UINT16 CS; + UINT16 DS; + UINT16 FS; + UINT16 GS; + UINT16 ES; + UINT16 SS; + UINT64 RFLAGS; + UINT64 RIP; +} GUEST_EXTRA_REGISTERS, *PGUEST_EXTRA_REGISTERS; + +/** + * @brief List of different variables + */ +typedef struct _SCRIPT_ENGINE_GENERAL_REGISTERS +{ + UINT64 * StackBuffer; + UINT64 * GlobalVariablesList; + UINT64 StackIndx; + UINT64 StackBaseIndx; + UINT64 ReturnValue; +} SCRIPT_ENGINE_GENERAL_REGISTERS, *PSCRIPT_ENGINE_GENERAL_REGISTERS; + +/** + * @brief CR3 Structure + * + */ +typedef struct _CR3_TYPE +{ + union + { + UINT64 Flags; + + struct + { + UINT64 Pcid : 12; + UINT64 PageFrameNumber : 36; + UINT64 Reserved1 : 12; + UINT64 Reserved_2 : 3; + UINT64 PcidInvalidate : 1; + } Fields; + }; +} CR3_TYPE, *PCR3_TYPE; diff --git a/hyperdbg/include/SDK/Headers/Connection.h b/hyperdbg/include/SDK/headers/Connection.h similarity index 85% rename from hyperdbg/include/SDK/Headers/Connection.h rename to hyperdbg/include/SDK/headers/Connection.h index f416eb38..aac62f47 100644 --- a/hyperdbg/include/SDK/Headers/Connection.h +++ b/hyperdbg/include/SDK/headers/Connection.h @@ -95,6 +95,14 @@ typedef enum _DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_SYMBOL_QUERY_PTE, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_SET_SHORT_CIRCUITING_STATE, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_INJECT_PAGE_FAULT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_WRITE_REGISTER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_QUERY_PCITREE, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_ACTIONS_ON_APIC, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_QUERY_PCIDEVINFO, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_READ_IDT_ENTRIES, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_SMI_OPERATION, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_HYPERTRACE_LBR_DUMP, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_HYPERTRACE_PT_OPERATION, // // Debuggee to debugger @@ -127,6 +135,14 @@ typedef enum _DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_PTE, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_VA2PA_AND_PA2VA, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_BRINGING_PAGES_IN, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_WRITE_REGISTER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_PCITREE, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_APIC_REQUESTS, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_PCIDEVINFO, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_QUERY_IDT_ENTRIES_REQUESTS, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_SMI_OPERATION_REQUESTS, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_HYPERTRACE_LBR_DUMP_REQUESTS, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_HYPERTRACE_PT_OPERATION_REQUESTS, // // hardware debuggee to debugger diff --git a/hyperdbg/include/SDK/Headers/Constants.h b/hyperdbg/include/SDK/headers/Constants.h similarity index 72% rename from hyperdbg/include/SDK/Headers/Constants.h rename to hyperdbg/include/SDK/headers/Constants.h index ef6cb31f..dae3aa47 100644 --- a/hyperdbg/include/SDK/Headers/Constants.h +++ b/hyperdbg/include/SDK/headers/Constants.h @@ -1,6 +1,7 @@ /** * @file Constants.h * @author Sina Karvandi (sina@hyperdbg.org) + * @author jtaw5649 * @brief HyperDbg's SDK constants * @details This file contains definitions of constants * used in HyperDbg @@ -17,9 +18,11 @@ ////////////////////////////////////////////////// #define VERSION_MAJOR 0 -#define VERSION_MINOR 9 +#define VERSION_MINOR 21 #define VERSION_PATCH 0 +#define BETA_VERSION FALSE + // // Example of __DATE__ string: "Jul 27 2012" // 01234567890 @@ -76,69 +79,9 @@ #define BUILD_SEC_CH0 (__TIME__[6]) #define BUILD_SEC_CH1 (__TIME__[7]) -#if VERSION_MAJOR > 100 +#ifdef __cplusplus // because it's not valid in C -# define VERSION_MAJOR_INIT \ - ((VERSION_MAJOR / 100) + '0'), \ - (((VERSION_MAJOR % 100) / 10) + '0'), \ - ((VERSION_MAJOR % 10) + '0') - -#elif VERSION_MAJOR > 10 - -# define VERSION_MAJOR_INIT \ - ((VERSION_MAJOR / 10) + '0'), \ - ((VERSION_MAJOR % 10) + '0') - -#else - -# define VERSION_MAJOR_INIT \ - (VERSION_MAJOR + '0') - -#endif - -#if VERSION_MINOR > 100 - -# define VERSION_MINOR_INIT \ - ((VERSION_MINOR / 100) + '0'), \ - (((VERSION_MINOR % 100) / 10) + '0'), \ - ((VERSION_MINOR % 10) + '0') - -#elif VERSION_MINOR > 10 - -# define VERSION_MINOR_INIT \ - ((VERSION_MINOR / 10) + '0'), \ - ((VERSION_MINOR % 10) + '0') - -#else - -# define VERSION_MINOR_INIT \ - (VERSION_MINOR + '0') - -#endif - -#if VERSION_PATCH > 100 - -# define VERSION_PATCH_INIT \ - ((VERSION_PATCH / 100) + '0'), \ - (((VERSION_PATCH % 100) / 10) + '0'), \ - ((VERSION_PATCH % 10) + '0') - -#elif VERSION_PATCH > 10 - -# define VERSION_PATCH_INIT \ - ((VERSION_PATCH / 10) + '0'), \ - ((VERSION_PATCH % 10) + '0') - -#else - -# define VERSION_PATCH_INIT \ - (VERSION_PATCH + '0') - -#endif - -#ifndef HYPERDBG_KERNEL_MODE - -const unsigned char BuildDateTime[] = { +const UCHAR BuildDateTime[] = { BUILD_YEAR_CH0, BUILD_YEAR_CH1, BUILD_YEAR_CH2, @@ -161,16 +104,21 @@ const unsigned char BuildDateTime[] = { '\0'}; -const unsigned char CompleteVersion[] = { - 'v', - VERSION_MAJOR_INIT, - '.', - VERSION_MINOR_INIT, - '.', - VERSION_PATCH_INIT, - '\0'}; +// Macro to convert a number to a string +# define STRINGIFY(x) #x +# define TOSTRING(x) STRINGIFY(x) -const unsigned char BuildVersion[] = { +// Complete version as a string + +# if BETA_VERSION == FALSE +# define HYPERDBG_COMPLETE_VERSION "v" TOSTRING(VERSION_MAJOR) "." TOSTRING(VERSION_MINOR) "." TOSTRING(VERSION_PATCH) "\0" +# else +# define HYPERDBG_COMPLETE_VERSION "v" TOSTRING(VERSION_MAJOR) "." TOSTRING(VERSION_MINOR) "." TOSTRING(VERSION_PATCH) "-beta\0" +# endif + +const UCHAR CompleteVersion[] = HYPERDBG_COMPLETE_VERSION; + +const UCHAR BuildVersion[] = { BUILD_YEAR_CH0, BUILD_YEAR_CH1, BUILD_YEAR_CH2, @@ -187,12 +135,12 @@ const unsigned char BuildVersion[] = { '\0'}; -const unsigned char BuildSignature[] = { - VERSION_MAJOR_INIT, +const UCHAR BuildSignature[] = { + TOSTRING(VERSION_MAJOR)[0], '.', - VERSION_MINOR_INIT, + TOSTRING(VERSION_MINOR)[0], '.', - VERSION_PATCH_INIT, + TOSTRING(VERSION_PATCH)[0], '-', BUILD_YEAR_CH0, BUILD_YEAR_CH1, @@ -210,7 +158,7 @@ const unsigned char BuildSignature[] = { '\0'}; -#endif // SCRIPT_ENGINE_KERNEL_MODE +#endif ////////////////////////////////////////////////// // Message Tracing // @@ -251,7 +199,7 @@ const unsigned char BuildSignature[] = { * @details the maximum packet size for sending over serial * */ -#define MaxSerialPacketSize 10 * NORMAL_PAGE_SIZE +#define MaxSerialPacketSize 20 * NORMAL_PAGE_SIZE /** * @brief Final storage size of message tracing @@ -429,23 +377,17 @@ const unsigned char BuildSignature[] = { #define OPERATION_LOG_NON_IMMEDIATE_MESSAGE 4U #define OPERATION_LOG_WITH_TAG 5U -#define OPERATION_COMMAND_FROM_DEBUGGER_CLOSE_AND_UNLOAD_VMM \ - 6U | OPERATION_MANDATORY_DEBUGGEE_BIT -#define OPERATION_DEBUGGEE_USER_INPUT 7U | OPERATION_MANDATORY_DEBUGGEE_BIT -#define OPERATION_DEBUGGEE_REGISTER_EVENT 8U | OPERATION_MANDATORY_DEBUGGEE_BIT -#define OPERATION_DEBUGGEE_ADD_ACTION_TO_EVENT \ - 9 | OPERATION_MANDATORY_DEBUGGEE_BIT -#define OPERATION_DEBUGGEE_CLEAR_EVENTS 10U | OPERATION_MANDATORY_DEBUGGEE_BIT -#define OPERATION_DEBUGGEE_CLEAR_EVENTS_WITHOUT_NOTIFYING_DEBUGGER 11U | OPERATION_MANDATORY_DEBUGGEE_BIT -#define OPERATION_HYPERVISOR_DRIVER_IS_SUCCESSFULLY_LOADED \ - 12U | OPERATION_MANDATORY_DEBUGGEE_BIT -#define OPERATION_HYPERVISOR_DRIVER_END_OF_IRPS \ - 13U | OPERATION_MANDATORY_DEBUGGEE_BIT -#define OPERATION_COMMAND_FROM_DEBUGGER_RELOAD_SYMBOL \ - 14U | OPERATION_MANDATORY_DEBUGGEE_BIT - -#define OPERATION_NOTIFICATION_FROM_USER_DEBUGGER_PAUSE \ - 15U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_LOG_MESSAGE_MANDATORY 6U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_COMMAND_FROM_DEBUGGER_CLOSE_AND_UNLOAD_VMM 7U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_DEBUGGEE_USER_INPUT 8U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_DEBUGGEE_REGISTER_EVENT 9U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_DEBUGGEE_ADD_ACTION_TO_EVENT 10U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_DEBUGGEE_CLEAR_EVENTS 11U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_DEBUGGEE_CLEAR_EVENTS_WITHOUT_NOTIFYING_DEBUGGER 12U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_HYPERVISOR_DRIVER_IS_SUCCESSFULLY_LOADED 13U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_HYPERVISOR_DRIVER_END_OF_IRPS 14U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_COMMAND_FROM_DEBUGGER_RELOAD_SYMBOL 15U | OPERATION_MANDATORY_DEBUGGEE_BIT +#define OPERATION_NOTIFICATION_FROM_USER_DEBUGGER_PAUSE 16U | OPERATION_MANDATORY_DEBUGGEE_BIT ////////////////////////////////////////////////// // Breakpoints & Debug Breakpoints // @@ -623,7 +565,15 @@ const unsigned char BuildSignature[] = { # define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) #endif // !HIBYTE -#define MAX_TEMP_COUNT 128 +/** + * @brief Maximum number of stack buffer count in the script engine + */ +#define MAX_STACK_BUFFER_COUNT 256 + +/** + * @brief Maximum number of variables that can be used in the script engine + */ +#define MAX_EXECUTION_COUNT 1000000 // TODO: Extract number of variables from input of ScriptEngine // and allocate variableList Dynamically. @@ -635,6 +585,128 @@ const unsigned char BuildSignature[] = { // Debugger // ////////////////////////////////////////////////// +/** + * @brief Segment selector registers in x86 + * + */ +typedef enum _SEGMENT_REGISTERS +{ + ES = 0, + CS, + SS, + DS, + FS, + GS, + LDTR, + TR +} SEGMENT_REGISTERS; + +/* + * @brief Windows IRQ Levels + */ +#define PASSIVE_LEVEL 0 // Passive release level +#define LOW_LEVEL 0 // Lowest interrupt level +#define APC_LEVEL 1 // APC interrupt level +#define DISPATCH_LEVEL 2 // Dispatcher level +#define CMCI_LEVEL 5 // CMCI handler level +#define CLOCK_LEVEL 13 // Interval clock level +#define IPI_LEVEL 14 // Interprocessor interrupt level +#define DRS_LEVEL 14 // Deferred Recovery Service level +#define POWER_LEVEL 14 // Power failure level +#define PROFILE_LEVEL 15 // timer used for profiling. +#define HIGH_LEVEL 15 // Highest interrupt level + +/** + * @brief Intel CPU flags in CR0 + */ +#define REG_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */ +#define REG_CR0_MP 0x00000002 /* Monitor Coprocessor (RW) */ +#define REG_CR0_EM 0x00000004 /* Require FPU Emulation (RO) */ +#define REG_CR0_TS 0x00000008 /* Task Switched (RW) */ +#define REG_CR0_ET 0x00000010 /* Extension type (RO) */ +#define REG_CR0_NE 0x00000020 /* Numeric Error Reporting (RW) */ +#define REG_CR0_WP 0x00010000 /* Supervisor Write Protect (RW) */ +#define REG_CR0_AM 0x00040000 /* Alignment Checking (RW) */ +#define REG_CR0_NW 0x20000000 /* Not Write-Through (RW) */ +#define REG_CR0_CD 0x40000000 /* Cache Disable (RW) */ +#define REG_CR0_PG 0x80000000 /* Paging */ + +/** + * @brief Intel CPU features in CR4 + * + */ +#define REG_CR4_VME 0x0001 /* enable vm86 extensions */ +#define REG_CR4_PVI 0x0002 /* virtual interrupts flag enable */ +#define REG_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ +#define REG_CR4_DE 0x0008 /* enable debugging extensions */ +#define REG_CR4_PSE 0x0010 /* enable page size extensions */ +#define REG_CR4_PAE 0x0020 /* enable physical address extensions */ +#define REG_CR4_MCE 0x0040 /* Machine check enable */ +#define REG_CR4_PGE 0x0080 /* enable global pages */ +#define REG_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ +#define REG_CR4_OSFXSR 0x0200 /* enable fast FPU save and restore */ +#define REG_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */ +#define REG_CR4_VMXE 0x2000 /* enable VMX */ + +/* + * @brief Segment register and corresponding GDT meaning in Windows + */ +#define KGDT64_NULL (0 * 16) // NULL descriptor +#define KGDT64_R0_CODE (1 * 16) // kernel mode 64-bit code +#define KGDT64_R0_DATA (1 * 16) + 8 // kernel mode 64-bit data (stack) +#define KGDT64_R3_CMCODE (2 * 16) // user mode 32-bit code +#define KGDT64_R3_DATA (2 * 16) + 8 // user mode 32-bit data +#define KGDT64_R3_CODE (3 * 16) // user mode 64-bit code +#define KGDT64_SYS_TSS (4 * 16) // kernel mode system task state +#define KGDT64_R3_CMTEB (5 * 16) // user mode 32-bit TEB +#define KGDT64_R0_CMCODE (6 * 16) // kernel mode 32-bit code +#define KGDT64_LAST (7 * 16) // last entry + +/** + * @brief PCID Flags + * + */ +#define PCID_NONE 0x000 +#define PCID_MASK 0x003 + +/** + * @brief The Microsoft Hypervisor interface defined constants + * + */ +#define CPUID_HV_VENDOR_AND_MAX_FUNCTIONS 0x40000000 +#define CPUID_HV_INTERFACE 0x40000001 + +/** + * @brief Transparent-mode feature mask + * + */ +#define TRANSPARENT_EVADE_MASK_SYSCALL_HOOK 0x00000001 +#define TRANSPARENT_EVADE_MASK_CPUID 0x00000002 +#define TRANSPARENT_EVADE_MASK_MSR 0x00000004 +#define TRANSPARENT_EVADE_MASK_TRAP_FLAG 0x00000008 +#define TRANSPARENT_EVADE_MASK_ALL \ + (TRANSPARENT_EVADE_MASK_SYSCALL_HOOK | TRANSPARENT_EVADE_MASK_CPUID | TRANSPARENT_EVADE_MASK_MSR | TRANSPARENT_EVADE_MASK_TRAP_FLAG) +#define TRANSPARENT_EVADE_MASK_DEFAULT TRANSPARENT_EVADE_MASK_ALL + +/** + * @brief Cpuid to get virtual address width + * + */ +#define CPUID_ADDR_WIDTH 0x80000008 + +/** + * @brief CPUID Features + * + */ +#define CPUID_PROCESSOR_AND_PROCESSOR_FEATURE_IDENTIFIERS 0x00000001 + +/** + * @brief Hypervisor reserved range for RDMSR and WRMSR + * + */ +#define RESERVED_MSR_RANGE_LOW 0x40000000 +#define RESERVED_MSR_RANGE_HI 0x400000F0 + /** * @brief Apply event modifications to all tags * diff --git a/hyperdbg/include/SDK/Headers/DataTypes.h b/hyperdbg/include/SDK/headers/DataTypes.h similarity index 84% rename from hyperdbg/include/SDK/Headers/DataTypes.h rename to hyperdbg/include/SDK/headers/DataTypes.h index 2935acdd..0c03ca5a 100644 --- a/hyperdbg/include/SDK/Headers/DataTypes.h +++ b/hyperdbg/include/SDK/headers/DataTypes.h @@ -28,6 +28,39 @@ typedef enum _PAGING_LEVEL PagingLevelPageMapLevel4 } PAGING_LEVEL; +////////////////////////////////////////////////// +// CPU Information // +////////////////////////////////////////////////// + +/** + * @brief Different processor vendors + * + */ +typedef enum _GENERIC_PROCESSOR_VENDOR +{ + GENERIC_PROCESSOR_VENDOR_INTEL, + GENERIC_PROCESSOR_VENDOR_AMD, + GENERIC_PROCESSOR_VENDOR_OTHERS, +} GENERIC_PROCESSOR_VENDOR; + +////////////////////////////////////////////////// +// List Entries // +////////////////////////////////////////////////// + +// +// Doubly linked list structure. Can be used as either a list head, or +// as link words. +// +#if defined(__linux__) + +typedef struct _LIST_ENTRY +{ + struct _LIST_ENTRY * Flink; + struct _LIST_ENTRY * Blink; +} LIST_ENTRY, *PLIST_ENTRY; + +#endif // defined(__linux__) + ////////////////////////////////////////////////// // Pool Manager // ////////////////////////////////////////////////// @@ -116,10 +149,17 @@ typedef enum _DEBUGGER_THREAD_PROCESS_TRACING /** * @brief Callback type that can be used to be used - * as a custom ShowMessages function + * as a custom ShowMessages function (by passing message as a parameter) * */ -typedef int (*Callback)(const char * Text); +typedef int (*SendMessageWithParamCallback)(const char * Text); + +/** + * @brief Callback type that can be used to be used + * as a custom ShowMessages function (using shared buffer) + * + */ +typedef int (*SendMessageWithSharedBufferCallback)(VOID); ////////////////////////////////////////////////// // Communications // @@ -231,17 +271,9 @@ typedef struct _DEBUGGEE_UD_PAUSED_PACKET VMM_CALLBACK_EVENT_CALLING_STAGE_TYPE EventCallingStage; BYTE InstructionBytesOnRip[MAXIMUM_INSTR_SIZE]; UINT16 ReadInstructionLen; - GUEST_REGS GuestRegs; } DEBUGGEE_UD_PAUSED_PACKET, *PDEBUGGEE_UD_PAUSED_PACKET; -/** - * @brief check so the DEBUGGEE_UD_PAUSED_PACKET should be smaller than packet size - * - */ -static_assert(sizeof(DEBUGGEE_UD_PAUSED_PACKET) < PacketChunkSize, - "err (static_assert), size of PacketChunkSize should be bigger than DEBUGGEE_UD_PAUSED_PACKET"); - ////////////////////////////////////////////////// // Message Tracing Enums // ////////////////////////////////////////////////// @@ -298,10 +330,37 @@ typedef struct _DIRECT_VMCALL_PARAMETERS } DIRECT_VMCALL_PARAMETERS, *PDIRECT_VMCALL_PARAMETERS; +////////////////////////////////////////////////// +// Syscall Callbacks // +////////////////////////////////////////////////// + +/** + * @brief The (optional) context parameters for the transparent-mode + * + */ +typedef struct _SYSCALL_CALLBACK_CONTEXT_PARAMS +{ + UINT64 OptionalParam1; // Optional parameter + UINT64 OptionalParam2; // Optional parameter + UINT64 OptionalParam3; // Optional parameter + UINT64 OptionalParam4; // Optional parameter + +} SYSCALL_CALLBACK_CONTEXT_PARAMS, *PSYSCALL_CALLBACK_CONTEXT_PARAMS; + ////////////////////////////////////////////////// // EPT Hook // ////////////////////////////////////////////////// +/** + * @brief different type of memory addresses + * + */ +typedef enum _DEBUGGER_HOOK_MEMORY_TYPE +{ + DEBUGGER_MEMORY_HOOK_VIRTUAL_ADDRESS, + DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS +} DEBUGGER_HOOK_MEMORY_TYPE; + /** * @brief Temporary $context used in some EPT hook commands * @@ -319,12 +378,13 @@ typedef struct _EPT_HOOKS_CONTEXT */ typedef struct _EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR { - UINT64 StartAddress; - UINT64 EndAddress; - BOOLEAN SetHookForRead; - BOOLEAN SetHookForWrite; - BOOLEAN SetHookForExec; - UINT64 Tag; + UINT64 StartAddress; + UINT64 EndAddress; + BOOLEAN SetHookForRead; + BOOLEAN SetHookForWrite; + BOOLEAN SetHookForExec; + DEBUGGER_HOOK_MEMORY_TYPE MemoryType; + UINT64 Tag; } EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR, *PEPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR; diff --git a/hyperdbg/include/SDK/Headers/ErrorCodes.h b/hyperdbg/include/SDK/headers/ErrorCodes.h similarity index 80% rename from hyperdbg/include/SDK/Headers/ErrorCodes.h rename to hyperdbg/include/SDK/headers/ErrorCodes.h index 3447c8f0..bf31a55c 100644 --- a/hyperdbg/include/SDK/Headers/ErrorCodes.h +++ b/hyperdbg/include/SDK/headers/ErrorCodes.h @@ -90,7 +90,7 @@ * @brief error, the debugger is already in transparent-mode * */ -#define DEBUGGER_ERROR_DEBUGGER_ALREADY_UHIDE 0xc000000a +#define DEBUGGER_ERROR_DEBUGGER_ALREADY_HIDE 0xc000000a /** * @brief error, invalid parameters in !e* e* commands @@ -107,7 +107,7 @@ 0xc000000c /** - * @brief error, an invalid address is specified based on anotehr process's cr3 + * @brief error, an invalid address is specified based on another process's cr3 * in !e* or e* commands * */ @@ -519,6 +519,140 @@ */ #define DEBUGGER_ERROR_THE_TARGET_EVENT_IS_DISABLED_BUT_CANNOT_BE_CLEARED_PRIRITY_BUFFER_IS_FULL 0xc000004f +/** + * @brief error, not all cores are locked (probably due to a race condition in HyperDbg) in + * instant-event mechanism + * + */ +#define DEBUGGER_ERROR_NOT_ALL_CORES_ARE_LOCKED_FOR_APPLYING_INSTANT_EVENT 0xc0000050 + +/** + * @brief error, switching to the target core is not possible because core is not locked + * (probably due to a race condition in HyperDbg) + * + */ +#define DEBUGGER_ERROR_TARGET_SWITCHING_CORE_IS_NOT_LOCKED 0xc0000051 + +/** + * @brief error, invalid physical address + * + */ +#define DEBUGGER_ERROR_INVALID_PHYSICAL_ADDRESS 0xc0000052 + +/** + * @brief error, could not perform APIC actions + * + */ +#define DEBUGGER_ERROR_APIC_ACTIONS_ERROR 0xc0000053 + +/** + * @brief error, debugger is already not in the transparent-mode + * + */ +#define DEBUGGER_ERROR_DEBUGGER_ALREADY_UNHIDE 0xc0000054 + +/** + * @brief error, the user debugger cannot be initialized + * + */ +#define DEBUGGER_ERROR_DEBUGGER_NOT_INITIALIZED 0xc0000055 + +/** + * @brief error, cannot put EPT hooks on addresses above 512 GB + * + */ +#define DEBUGGER_ERROR_CANNOT_PUT_EPT_HOOKS_ON_PHYSICAL_ADDRESS_ABOVE_512_GB 0xc0000056 + +/** + * @brief error, invalid parameters for SMI operation request + * + */ +#define DEBUGGER_ERROR_INVALID_SMI_OPERATION_PARAMETERS 0xc0000057 + +/** + * @brief error, unable to trigger SMI + * + */ +#define DEBUGGER_ERROR_UNABLE_TO_TRIGGER_SMI 0xc0000058 + +/** + * @brief error, unable to apply the command to the target thread + * + */ +#define DEBUGGER_ERROR_UNABLE_TO_APPLY_COMMAND_TO_THE_TARGET_THREAD 0xc0000059 + +/** + * @brief error, HyperTrace is not initialized + * + */ +#define DEBUGGER_ERROR_HYPERTRACE_NOT_INITIALIZED 0xc000005a + +/** + * @brief error, invalid HyperTrace operation type is specified in the request + * + */ +#define DEBUGGER_ERROR_INVALID_HYPERTRACE_OPERATION_TYPE 0xc000005b + +/** + * @brief error, LBR is already enabled + * + */ +#define DEBUGGER_ERROR_LBR_ALREADY_ENABLED 0xc000005c + +/** + * @brief error, LBR is already disabled + * + */ +#define DEBUGGER_ERROR_LBR_ALREADY_DISABLED 0xc000005d + +/** + * @brief error, LBR is not supported by the processor + * + */ +#define DEBUGGER_ERROR_LBR_NOT_SUPPORTED 0xc000005e + +/** + * @brief error, LBR not supported on VMCS + * + */ +#define DEBUGGER_ERROR_LBR_NOT_SUPPORTED_ON_VMCS 0xc000005f + +/** + * @brief error, PT is already enabled + * + */ +#define DEBUGGER_ERROR_PT_ALREADY_ENABLED 0xc0000060 + +/** + * @brief error, PT is already disabled + * + */ +#define DEBUGGER_ERROR_PT_ALREADY_DISABLED 0xc0000061 + +/** + * @brief error, PT is not supported by the processor + * + */ +#define DEBUGGER_ERROR_PT_NOT_SUPPORTED 0xc0000062 + +/** + * @brief error, VMM cannot be initialized while HyperTrace module is already loaded + * + */ +#define DEBUGGER_ERROR_VMM_CANNOT_BE_INITIALIZED_IF_HYPERTRACE_IS_LOADED 0xc0000063 + +/** + * @brief error, VMM cannot be initialized if the debugger is not loaded + * + */ +#define DEBUGGER_ERROR_VMM_CANNOT_BE_INITIALIZED_IF_DEBUGGER_IS_NOT_LOADED 0xc0000064 + +/** + * @brief error, cannot initialize the debugger + * + */ +#define DEBUGGER_ERROR_CANNOT_INITIALIZE_DEBUGGER 0xc0000065 + // // WHEN YOU ADD ANYTHING TO THIS LIST OF ERRORS, THEN // MAKE SURE TO ADD AN ERROR MESSAGE TO ShowErrorMessage(UINT32 Error) diff --git a/hyperdbg/include/SDK/Headers/Events.h b/hyperdbg/include/SDK/headers/Events.h similarity index 96% rename from hyperdbg/include/SDK/Headers/Events.h rename to hyperdbg/include/SDK/headers/Events.h index ce4e5678..0af4052a 100644 --- a/hyperdbg/include/SDK/Headers/Events.h +++ b/hyperdbg/include/SDK/headers/Events.h @@ -169,6 +169,11 @@ typedef enum _VMM_EVENT_TYPE_ENUM TRAP_EXECUTION_MODE_CHANGED, TRAP_EXECUTION_INSTRUCTION_TRACE, + // + // XSETBV Instruction Execution Events + // + XSETBV_INSTRUCTION_EXECUTION + } VMM_EVENT_TYPE_ENUM; /** @@ -194,8 +199,6 @@ typedef enum _DEBUGGER_EVENT_SYSCALL_SYSRET_TYPE } DEBUGGER_EVENT_SYSCALL_SYSRET_TYPE; -#define SIZEOF_DEBUGGER_MODIFY_EVENTS sizeof(DEBUGGER_MODIFY_EVENTS) - /** * @brief Type of mode change traps * @@ -248,6 +251,8 @@ typedef struct _DEBUGGER_MODIFY_EVENTS } DEBUGGER_MODIFY_EVENTS, *PDEBUGGER_MODIFY_EVENTS; +#define SIZEOF_DEBUGGER_MODIFY_EVENTS sizeof(DEBUGGER_MODIFY_EVENTS) + /** * @brief request for performing a short-circuiting event * @@ -273,6 +278,8 @@ typedef struct _DEBUGGER_EVENT_OPTIONS UINT64 OptionalParam2; // Optional parameter UINT64 OptionalParam3; // Optional parameter UINT64 OptionalParam4; // Optional parameter + UINT64 OptionalParam5; // Optional parameter + UINT64 OptionalParam6; // Optional parameter } DEBUGGER_EVENT_OPTIONS, *PDEBUGGER_EVENT_OPTIONS; @@ -333,6 +340,8 @@ typedef enum _PROTECTED_HV_RESOURCES_TYPE PROTECTED_HV_RESOURCES_MOV_TO_CR3_EXITING, + PROTECTED_HV_RESOURCES_SAVE_AND_LOAD_DEBUG_CONTROLS, + } PROTECTED_HV_RESOURCES_TYPE; ////////////////////////////////////////////////// @@ -350,8 +359,6 @@ typedef struct _DEBUGGER_GENERAL_EVENT_DETAIL CommandsEventList; // Linked-list of commands list (used for tracing purpose // in user mode) - time_t CreationTime; // Date of creating this event - UINT32 CoreId; // determines the core index to apply this event to, if it's // 0xffffffff means that we have to apply it to all cores @@ -394,6 +401,8 @@ typedef struct _DEBUGGER_GENERAL_EVENT_DETAIL } DEBUGGER_GENERAL_EVENT_DETAIL, *PDEBUGGER_GENERAL_EVENT_DETAIL; +#define SIZEOF_DEBUGGER_GENERAL_EVENT_DETAIL sizeof(DEBUGGER_GENERAL_EVENT_DETAIL) + /** * @brief Each event can have multiple actions * @details THIS STRUCTURE IS ONLY USED IN USER MODE @@ -413,6 +422,8 @@ typedef struct _DEBUGGER_GENERAL_ACTION } DEBUGGER_GENERAL_ACTION, *PDEBUGGER_GENERAL_ACTION; +#define SIZEOF_DEBUGGER_GENERAL_ACTION sizeof(DEBUGGER_GENERAL_ACTION) + /** * @brief Status of register buffers * diff --git a/hyperdbg/include/SDK/headers/HardwareDebugger.h b/hyperdbg/include/SDK/headers/HardwareDebugger.h new file mode 100644 index 00000000..d80122e3 --- /dev/null +++ b/hyperdbg/include/SDK/headers/HardwareDebugger.h @@ -0,0 +1,204 @@ +/** + * @file HardwareDebugger.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief HyperDbg's Hardware Debugger (hwdbg) types and constants + * @details This file contains definitions of hwdbg elements + * used in HyperDbg + * @version 0.9 + * @date 2024-04-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Definitions // +////////////////////////////////////////////////// + +/** + * @brief Initial debuggee to debugger offset + * + */ +#define DEFAULT_INITIAL_DEBUGGEE_TO_DEBUGGER_OFFSET 0x200 + +/** + * @brief Initial debugger to debuggee offset + * + */ +#define DEFAULT_INITIAL_DEBUGGER_TO_DEBUGGEE_OFFSET 0x0 + +/** + * @brief Initial default buffer size (BRAN Size) + * @details Number of 4-Byte integers (256 * 4 Byte * 8 bits = 8-kilobits) + * + */ +#define DEFAULT_INITIAL_BRAM_BUFFER_SIZE 256 + +/** + * @brief Path to read the sample of the instance info + * + */ +#define HWDBG_TEST_READ_INSTANCE_INFO_PATH "..\\..\\..\\..\\hwdbg\\sim\\hwdbg\\DebuggerModuleTestingBRAM\\bram_instance_info.txt" + +/** + * @brief Path to write the sample of the script buffer + * + */ +#define HWDBG_TEST_WRITE_SCRIPT_BUFFER_PATH "..\\..\\..\\..\\hwdbg\\src\\test\\bram\\script_buffer.hex.txt" + +/** + * @brief Path to write the sample of the instance info requests + * + */ +#define HWDBG_TEST_WRITE_INSTANCE_INFO_PATH "..\\..\\..\\..\\hwdbg\\src\\test\\bram\\instance_info.hex.txt" + +////////////////////////////////////////////////// +// Enums // +////////////////////////////////////////////////// + +/** + * @brief Different action of hwdbg + * @warning This file should be changed along with hwdbg files + * + */ +typedef enum _HWDBG_ACTION_ENUMS +{ + hwdbgActionSendInstanceInfo = 1, + hwdbgActionConfigureScriptBuffer = 2, + +} HWDBG_ACTION_ENUMS; + +/** + * @brief Different responses come from hwdbg + * @warning This file should be changed along with hwdbg files + * + */ +typedef enum _HWDBG_RESPONSE_ENUMS +{ + hwdbgResponseSuccessOrErrorMessage = 1, + hwdbgResponseInstanceInfo = 2, + +} HWDBG_RESPONSE_ENUMS; + +/** + * @brief Different success or error codes in hwdbg + * @warning This file should be changed along with hwdbg files + * + */ +typedef enum _HWDBG_SUCCESS_OR_ERROR_ENUMS +{ + hwdbgOperationWasSuccessful = 0x7FFFFFFF, + hwdbgErrorInvalidPacket = 1, + +} HWDBG_SUCCESS_OR_ERROR_ENUMS; + +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +/** + * @brief The structure of port information (each item) in hwdbg + * + */ +typedef struct _HWDBG_PORT_INFORMATION_ITEMS +{ + UINT32 PortSize; + +} HWDBG_PORT_INFORMATION_ITEMS, *PHWDBG_PORT_INFORMATION_ITEMS; + +/** + * @brief The structure of script capabilities information in hwdbg + * + */ +#pragma pack(push, 4) // This is to make sure the structure is packed (without padding alignment) +typedef struct _HWDBG_INSTANCE_INFORMATION +{ + // + // ANY ADDITION TO THIS STRUCTURE SHOULD BE SYNCHRONIZED WITH SCALA AND INSTANCE INFO SENDER MODULE + // + UINT32 version; // Target version of HyperDbg (same as hwdbg) + UINT32 maximumNumberOfStages; // Number of stages that this instance of hwdbg supports (NumberOfSupportedStages == 0 means script engine is disabled) + UINT32 scriptVariableLength; // Maximum length of variables (and other script elements) + UINT32 numberOfSupportedLocalAndGlobalVariables; // Number of supported local (and global) variables + UINT32 numberOfSupportedTemporaryVariables; // Number of supported temporary variables + UINT32 maximumNumberOfSupportedGetScriptOperators; // Maximum supported GET operators in a single func + UINT32 maximumNumberOfSupportedSetScriptOperators; // Maximum supported SET operators in a single func + UINT32 sharedMemorySize; // Size of shared memory + UINT32 debuggerAreaOffset; // The memory offset of debugger + UINT32 debuggeeAreaOffset; // The memory offset of debuggee + UINT32 numberOfPins; // Number of pins + UINT32 numberOfPorts; // Number of ports + + // + // ANY ADDITION TO THIS STRUCTURE SHOULD BE SYNCHRONIZED WITH SCALA AND INSTANCE INFO SENDER MODULE + // + + struct _HWDBG_SCRIPT_CAPABILITIES + { + // + // ANY ADDITION TO THIS MASK SHOULD BE ADDED TO HwdbgInterpreterShowScriptCapabilities + // and HwdbgInterpreterCheckScriptBufferWithScriptCapabilities as well Scala file + // + UINT64 assign_local_global_var : 1; + UINT64 assign_registers : 1; + UINT64 assign_pseudo_registers : 1; + UINT64 conditional_statements_and_comparison_operators : 1; + UINT64 stack_assignments : 1; + + UINT64 func_or : 1; + UINT64 func_xor : 1; + UINT64 func_and : 1; + UINT64 func_asr : 1; + UINT64 func_asl : 1; + UINT64 func_add : 1; + UINT64 func_sub : 1; + UINT64 func_mul : 1; + UINT64 func_div : 1; + UINT64 func_mod : 1; + UINT64 func_gt : 1; + UINT64 func_lt : 1; + UINT64 func_egt : 1; + UINT64 func_elt : 1; + UINT64 func_equal : 1; + UINT64 func_neq : 1; + UINT64 func_jmp : 1; + UINT64 func_jz : 1; + UINT64 func_jnz : 1; + UINT64 func_mov : 1; + UINT64 func_printf : 1; + + // + // ANY ADDITION TO THIS MASK SHOULD BE ADDED TO HwdbgInterpreterShowScriptCapabilities + // and HwdbgInterpreterCheckScriptBufferWithScriptCapabilities as well Scala file + // + + } scriptCapabilities; + + UINT32 bramAddrWidth; // BRAM address width + UINT32 bramDataWidth; // BRAM data width + + // + // Here the details of port arrangements are located (HWDBG_PORT_INFORMATION_ITEMS) + // As the following type: + // HWDBG_PORT_INFORMATION_ITEMS portsConfiguration[numberOfPorts] ; Port arrangement + // + +} HWDBG_INSTANCE_INFORMATION, *PHWDBG_INSTANCE_INFORMATION; +#pragma pack(pop) // This is to make sure the structure is packed (without padding alignment) + +/** + * @brief The structure of script buffer in hwdbg + * + */ +typedef struct _HWDBG_SCRIPT_BUFFER +{ + UINT32 scriptNumberOfSymbols; // Number of symbols in the script + + // + // Here the script buffer is located + // + // UINT8 scriptBuffer[scriptNumberOfSymbols]; // The script buffer + // + +} HWDBG_SCRIPT_BUFFER, *PHWDBG_SCRIPT_BUFFER; diff --git a/hyperdbg/include/SDK/headers/Ioctls.h b/hyperdbg/include/SDK/headers/Ioctls.h new file mode 100644 index 00000000..20a2057a --- /dev/null +++ b/hyperdbg/include/SDK/headers/Ioctls.h @@ -0,0 +1,430 @@ +/** + * @file Ioctls.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief HyperDbg's SDK IOCTL codes + * @details This file contains definitions of IOCTLs used in HyperDbg + * @version 0.2 + * @date 2022-06-24 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Definitions // +////////////////////////////////////////////////// + +// +// The following controls are mainly defined in +// + +// +// Macro definition for defining IOCTL and FSCTL function control codes. Note +// that function codes 0-2047 are reserved for Microsoft Corporation, and +// 2048-4095 are reserved for customers. +// +#ifndef CTL_CODE + +# define CTL_CODE(DeviceType, Function, Method, Access) ( \ + ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) + +#endif // ! CTL_CODE + +#ifndef FILE_ANY_ACCESS + +# define FILE_ANY_ACCESS 0 + +#endif // !FILE_ANY_ACCESS + +// +// Define the method codes for how buffers are passed for I/O and FS controls +// + +#ifndef METHOD_BUFFERED + +# define METHOD_BUFFERED 0 + +#endif // !METHOD_BUFFERED + +#ifndef FILE_DEVICE_UNKNOWN + +# define FILE_DEVICE_UNKNOWN 0x00000022 + +#endif // !FILE_DEVICE_UNKNOWN + +/** + * @brief Extract the function from an IOCTL code + * + */ +#define CTL_CODE_FUNCTION(Code) (((Code) >> 2) & 0xFFF) + +/** + * @brief Base code for IOCTLs + * + */ +#define IOCTL_START_CODE 0x800 + +/** + * @brief ioctl, for basic communication between user-mode and kernel-mode, and for loading and initializing the driver and its components + * + */ +#define IOCTL_BASIC_IOCTL IOCTL_START_CODE + 0x00 + +/** + * @brief ioctl, for KD (Kernel Debugger) related functionalities + * + */ +#define IOCTL_KD_IOCTL IOCTL_START_CODE + 0x100 + +/** + * @brief ioctl, for VMM and debugger related functionalities + * + */ +#define IOCTL_VMM_IOCTL IOCTL_START_CODE + 0x200 + +/** + * @brief ioctl, for HyperTrace related functionalities + * + */ +#define IOCTL_HYPERTRACE_IOCTL IOCTL_START_CODE + 0x300 + +////////////////////////////////////////////////// +// Basic IOCTLs // +////////////////////////////////////////////////// + +/** + * @brief ioctl, initialize the VMM module + * + */ +#define IOCTL_INIT_VMM \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASIC_IOCTL + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, initialize the HyperTrace module + * + */ +#define IOCTL_INIT_HYPERTRACE \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASIC_IOCTL + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, register a new event + * + */ +#define IOCTL_REGISTER_EVENT \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASIC_IOCTL + 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, irp pending mechanism for reading from message tracing buffers + * + */ +#define IOCTL_RETURN_IRP_PENDING_PACKETS_AND_DISALLOW_IOCTL \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASIC_IOCTL + 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS) + +////////////////////////////////////////////////// +// KD IOCTLs // +////////////////////////////////////////////////// + +////////////////////////////////////////////////// +// VMM IOCTLs // +////////////////////////////////////////////////// + +/** + * @brief ioctl, to terminate vmx and exit form debugger + * + */ +#define IOCTL_TERMINATE_VMX \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, request to read memory + * + */ +#define IOCTL_DEBUGGER_READ_MEMORY \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, request to read or write on a special MSR + * + */ +#define IOCTL_DEBUGGER_READ_OR_WRITE_MSR \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, request to read page table entries + * + */ +#define IOCTL_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, register an event + * + */ +#define IOCTL_DEBUGGER_REGISTER_EVENT \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, add action to event + * + */ +#define IOCTL_DEBUGGER_ADD_ACTION_TO_EVENT \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, request to enable or disable transparent-mode + * + */ +#define IOCTL_DEBUGGER_HIDE_AND_UNHIDE_TO_TRANSPARENT_THE_DEBUGGER \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, for !va2pa and !pa2va commands + * + */ +#define IOCTL_DEBUGGER_VA2PA_AND_PA2VA_COMMANDS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, request to edit virtual and physical memory + * + */ +#define IOCTL_DEBUGGER_EDIT_MEMORY \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, request to search virtual and physical memory + * + */ +#define IOCTL_DEBUGGER_SEARCH_MEMORY \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x0a, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, request to modify an event (enable/disable/clear) + * + */ +#define IOCTL_DEBUGGER_MODIFY_EVENTS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x0b, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, flush the kernel buffers + * + */ +#define IOCTL_DEBUGGER_FLUSH_LOGGING_BUFFERS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x0c, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, attach or detach user-mode processes + * + */ +#define IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x0d, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, print states (Deprecated) + * + * + */ +#define IOCTL_DEBUGGER_PRINT \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x0e, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, prepare debuggee + * + */ +#define IOCTL_PREPARE_DEBUGGEE \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x0f, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, pause and halt the system + * + */ +#define IOCTL_PAUSE_PACKET_RECEIVED \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x10, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, send a signal that execution of command finished + * + */ +#define IOCTL_SEND_SIGNAL_EXECUTION_IN_DEBUGGEE_FINISHED \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x11, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, send user-mode messages to the debugger + * + */ +#define IOCTL_SEND_USERMODE_MESSAGES_TO_DEBUGGER \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x12, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, send general buffer from debuggee to debugger + * + */ +#define IOCTL_SEND_GENERAL_BUFFER_FROM_DEBUGGEE_TO_DEBUGGER \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x13, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to perform kernel-side tests + * + */ +#define IOCTL_PERFORM_KERNEL_SIDE_TESTS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x14, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to reserve pre-allocated pools + * + */ +#define IOCTL_RESERVE_PRE_ALLOCATED_POOLS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x15, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to send user debugger commands + * + */ +#define IOCTL_SEND_USER_DEBUGGER_COMMANDS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x16, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to get active threads/processes that are debugging + * + */ +#define IOCTL_GET_DETAIL_OF_ACTIVE_THREADS_AND_PROCESSES \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x17, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to get user mode modules details + * + */ +#define IOCTL_GET_USER_MODE_MODULE_DETAILS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x18, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, query count of active threads or processes + * + */ +#define IOCTL_QUERY_COUNT_OF_ACTIVE_PROCESSES_OR_THREADS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x19, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to get list threads/processes + * + */ +#define IOCTL_GET_LIST_OF_THREADS_AND_PROCESSES \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x1a, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, query the current process details + * + */ +#define IOCTL_QUERY_CURRENT_PROCESS \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x1b, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, query the current thread details + * + */ +#define IOCTL_QUERY_CURRENT_THREAD \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x1c, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, request service from the reversing machine + * + */ +#define IOCTL_REQUEST_REV_MACHINE_SERVICE \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x1d, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, request to bring pages in + * + */ +#define IOCTL_DEBUGGER_BRING_PAGES_IN \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x1e, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to preactivate a functionality + * + */ +#define IOCTL_PREACTIVATE_FUNCTIONALITY \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x1f, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to enumerate PCIe endpoints + * + */ +#define IOCTL_PCIE_ENDPOINT_ENUM \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x20, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to perform actions related to APIC + * + */ +#define IOCTL_PERFORM_ACTIONS_ON_APIC \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x21, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to query for PCI endpoint info + * + */ +#define IOCTL_PCIDEVINFO_ENUM \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x22, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to query the IDT entries + * + */ +#define IOCTL_QUERY_IDT_ENTRY \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x24, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to set breakpoint for the user debugger + * + */ +#define IOCTL_SET_BREAKPOINT_USER_DEBUGGER \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x25, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to perform SMI operations + * + */ +#define IOCTL_PERFORM_SMI_OPERATION \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x26, METHOD_BUFFERED, FILE_ANY_ACCESS) + +////////////////////////////////////////////////// +// HyperTrace IOCTLs // +////////////////////////////////////////////////// + +/** + * @brief ioctl, to unload HyperTrace module + * + */ +#define IOCTL_PERFORM_HYPERTRACE_UNLOAD \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_HYPERTRACE_IOCTL + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to perform HyperTrace LBR operations + * + */ +#define IOCTL_PERFORM_HYPERTRACE_LBR_OPERATION \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_HYPERTRACE_IOCTL + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to perform HyperTrace LBR dump + * + */ +#define IOCTL_PERFORM_HYPERTRACE_LBR_DUMP \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_HYPERTRACE_IOCTL + 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to perform HyperTrace PT operations + * + */ +#define IOCTL_PERFORM_HYPERTRACE_PT_OPERATION \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_HYPERTRACE_IOCTL + 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to map per-CPU HyperTrace PT output buffers into the + * calling user-mode process. See HYPERTRACE_PT_MMAP_PACKETS. + * + */ +#define IOCTL_PERFORM_HYPERTRACE_PT_MMAP \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_HYPERTRACE_IOCTL + 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS) diff --git a/hyperdbg/include/SDK/headers/LbrDefinitions.h b/hyperdbg/include/SDK/headers/LbrDefinitions.h new file mode 100644 index 00000000..49e634d3 --- /dev/null +++ b/hyperdbg/include/SDK/headers/LbrDefinitions.h @@ -0,0 +1,171 @@ +/** + * @file LbrDefinitions.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Last Branch Record (LBR) related data structures + * @details + * @version 0.19 + * @date 2026-04-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Constants // +////////////////////////////////////////////////// + +/** + * @brief MSR address of LBR_SELECT, which is used to configure the LBR filtering options + */ +#define MSR_LEGACY_LBR_SELECT 0x000001C8 + +/** + * @brief Maximum LBR capacity that is supported by processors + * + */ +#define MAXIMUM_LBR_CAPACITY 0x20 // 32 entries, which is the maximum supported by modern Intel CPUs + +/* + * Intel LBR_SELECT bits + * + * Hardware branch filter (not available on all CPUs) + */ +#define LBR_KERNEL_BIT 0 /* do not capture at ring0 */ +#define LBR_USER_BIT 1 /* do not capture at ring > 0 */ +#define LBR_JCC_BIT 2 /* do not capture conditional branches */ +#define LBR_REL_CALL_BIT 3 /* do not capture relative calls */ +#define LBR_IND_CALL_BIT 4 /* do not capture indirect calls */ +#define LBR_RETURN_BIT 5 /* do not capture near returns */ +#define LBR_IND_JMP_BIT 6 /* do not capture indirect jumps */ +#define LBR_REL_JMP_BIT 7 /* do not capture relative jumps */ +#define LBR_FAR_BIT 8 /* do not capture far branches */ +#define LBR_CALL_STACK_BIT 9 /* enable call stack: not available on all CPUs */ + +/* + * We mask it out before writing it to + * the actual MSR. But it helps the constraint code to understand + * that this is a separate configuration. + */ +#define LBR_KERNEL (1 << LBR_KERNEL_BIT) +#define LBR_USER (1 << LBR_USER_BIT) +#define LBR_JCC (1 << LBR_JCC_BIT) +#define LBR_REL_CALL (1 << LBR_REL_CALL_BIT) +#define LBR_IND_CALL (1 << LBR_IND_CALL_BIT) +#define LBR_RETURN (1 << LBR_RETURN_BIT) +#define LBR_IND_JMP (1 << LBR_IND_JMP_BIT) +#define LBR_REL_JMP (1 << LBR_REL_JMP_BIT) +#define LBR_FAR_OTHER_BRANCHES (1 << LBR_FAR_BIT) // It is used for OTHER BRANCHES in ARCH LBR +#define LBR_CALL_STACK (1 << LBR_CALL_STACK_BIT) + +/** + * @brief For call-stack mode, only CALLs and RETs should be captured + * Capturing other branch types may lead to undefined behavior + */ +#define LBR_CALL_STACK_BASE_FLAGS (LBR_CALL_STACK | (LBR_JCC | LBR_IND_JMP | LBR_REL_JMP | LBR_FAR_OTHER_BRANCHES)) + +/** + * @brief Branch Type Encodings (Only on Architectural LBR, not available in Legacy LBR) + */ +#define LBR_BR_TYPE_COND 0x0 +#define LBR_BR_TYPE_JMP_INDIRECT 0x1 +#define LBR_BR_TYPE_JMP_DIRECT 0x2 +#define LBR_BR_TYPE_CALL_INDIRECT 0x3 +#define LBR_BR_TYPE_CALL_DIRECT 0x4 +#define LBR_BR_TYPE_RET 0x5 +#define LBR_BR_TYPE_RESERVED_MIN 0x6 /* 011xb */ +#define LBR_BR_TYPE_RESERVED_MAX 0x7 /* 011xb */ +#define LBR_BR_TYPE_OTHER_MIN 0x8 /* 1xxxb */ +#define LBR_BR_TYPE_OTHER_MAX 0xF /* 1xxxb */ + +#define LBR_BR_TYPE_NAME_MAX_LEN 16 /* longest string is "CALL Indirect\0" = 14 chars, rounded up */ + +////////////////////////////////////////////////// +// MSR Structures // +////////////////////////////////////////////////// +/** + * MSR_LBR_INFO_x - Last Branch Record Info Register + * Register Address: 1200H-121FH, 4608-4639 + */ +typedef union +{ + struct + { + /** Bits 15:0 - Elapsed core clocks since last update to the LBR stack (saturating) */ + UINT64 CycleCount : 16; + + /** Bits 55:16 - Undefined. May be zero or non-zero. + * Writes of non-zero values do not fault, but reads may return a different value. */ + UINT64 Reserved : 40; + + /** + * Bits 59:56 - Branch type recorded by this LBR entry. + * Encodings: + * 0000b = COND + * 0001b = JMP Indirect + * 0010b = JMP Direct + * 0011b = CALL Indirect + * 0100b = CALL Direct + * 0101b = RET + * 011xb = Reserved + * 1xxxb = Other Branch + */ + UINT64 BrType_OnlyArchLbr : 4; + + /** Bit 60 - When set, the CycleCount field contains a valid elapsed cycle count */ + UINT64 CycCntValid_OnlyArchLbr : 1; + + /** + * Bit 61 - TSX Abort indicator. + * When set: + * LBR_FROM = EIP at the time of the TSX Abort + * LBR_TO = EIP of the start of HLE region OR EIP of the RTM Abort Handler + * Undefined on processors that do not support Intel TSX + * (CPUID.07H.00H:EBX.HLE[4] = 0 and CPUID.07H.00H:EBX.RTM[11] = 0). + */ + UINT64 TsxAbort : 1; + + /** + * Bit 62 - When set, indicates the branch retired during a TSX transaction. + * Undefined on processors that do not support Intel TSX + * (CPUID.07H.00H:EBX.HLE[4] = 0 and CPUID.07H.00H:EBX.RTM[11] = 0). + */ + UINT64 InTsx : 1; + + /** + * Bit 63 - Branch misprediction flag. + * When set, the target of the branch was mispredicted and/or the + * direction (taken/non-taken) was mispredicted. + * When clear, the branch target/direction was correctly predicted. + */ + UINT64 Mispred : 1; + }; + UINT64 AsUInt; +} MSR_LBR_INFO, *PMSR_LBR_INFO; + +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +/** + * @brief The structure to hold a single LBR entry (from and to addresses) + * + */ +typedef struct _LBR_BRANCH_ENTRY +{ + ULONGLONG From; + ULONGLONG To; + +} LBR_BRANCH_ENTRY, PLBR_BRANCH_ENTRY; + +/** + * @brief The structure to hold the LBR stack for a single processor core, including the branch entries and the TOS index + * + */ +typedef struct _LBR_STACK_ENTRY +{ + LBR_BRANCH_ENTRY BranchEntry[MAXIMUM_LBR_CAPACITY]; + MSR_LBR_INFO LastBranchInfo[MAXIMUM_LBR_CAPACITY]; + UINT8 Tos; + +} LBR_STACK_ENTRY, PLBR_STACK_ENTRY; diff --git a/hyperdbg/include/SDK/headers/Pcie.h b/hyperdbg/include/SDK/headers/Pcie.h new file mode 100644 index 00000000..dabfdfbe --- /dev/null +++ b/hyperdbg/include/SDK/headers/Pcie.h @@ -0,0 +1,176 @@ +/** + * @file Pcie.h + * @author Bjrn Ruytenberg (bjorn@bjornweb.nl) + * @brief PCIe-related data structures + * @details + * @version 0.10.3 + * @date 2024-10-30 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once +#pragma pack(1) + +////////////////////////////////////////////////// +// Headers // +////////////////////////////////////////////////// + +// +// TODO +// - Add support for domains beyond 0000 +// - Add ECAM support +// +// PCIe Base Specification, Rev. 4.0, Version 1.0, Table 7-59: Link Address for Link Type 1 +// Bus: 0-255 (8 bit) +// Device: 0-31 (5 bit) +// Function: 0-7 (3 bit) +// +#define BUS_BIT_WIDTH 8 +#define DEVICE_BIT_WIDTH 5 +#define FUNCTION_BIT_WIDTH 3 + +// +// NOTE +// On real-world systems, the number of endpoints will likely not exceed 255. +// If increasing DEV_MAX_NUM is necessary, ensure PCI_DEV_MINIMAL[DEV_MAX_NUM] does not result in exceeding MaxSerialPacketSize. +// +#define DOMAIN_MAX_NUM 0 +#define BUS_MAX_NUM 255 +#define DEVICE_MAX_NUM 32 +#define FUNCTION_MAX_NUM 8 +#define DEV_MAX_NUM 255 +#define CAM_CONFIG_SPACE_LENGTH 255 + +/** + * @brief PCI Common Header + * + */ +typedef struct _PORTABLE_PCI_COMMON_HEADER +{ + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Command; + UINT16 Status; + UINT8 RevisionId; + UINT8 ClassCode[3]; + UINT8 CacheLineSize; + UINT8 PrimaryLatencyTimer; + UINT8 HeaderType; + UINT8 Bist; +} PORTABLE_PCI_COMMON_HEADER, *PPORTABLE_PCI_COMMON_HEADER; + +/** + * @brief PCI Device Header + * + */ +typedef union _PORTABLE_PCI_DEVICE_HEADER +{ + struct _PORTABLE_PCI_EP_HEADER + { + UINT32 Bar[6]; // Base Address Registers + UINT32 CardBusCISPtr; // CardBus CIS Pointer + UINT16 SubVendorId; // Subsystem Vendor ID + UINT16 SubSystemId; // Subsystem ID + UINT32 ROMBar; // Expansion ROM Base Address + UINT8 CapabilitiesPtr; // Capabilities Pointer + UINT8 Reserved[3]; + UINT32 Reserved1; + UINT8 InterruptLine; // Interrupt Line + UINT8 InterruptPin; // Interrupt Pin + UINT8 MinGnt; // Min_Gnt + UINT8 MaxLat; // Max_Lat + } ConfigSpaceEp; + + struct _PORTABLE_PCI_BRIDGE_HEADER + { + UINT32 Bar[2]; + UINT8 PrimaryBusNumber; + UINT8 SecondaryBusNumber; + UINT8 SubordinateBusNumber; + UINT8 SecondaryLatencyTimer; + UINT8 IoBase; + UINT8 IoLimit; + UINT16 SecondaryStatus; + UINT16 MemoryBase; + UINT16 MemoryLimit; + UINT16 PrefetchableMemoryBase; + UINT16 PrefetchableMemoryLimit; + UINT32 PrefetchableBaseUpper32b; + UINT32 PrefetchableLimitUpper32b; + UINT16 IoBaseUpper16b; + UINT16 IoLimitUpper16b; + UINT8 CapabilityPtr; + UINT8 Reserved[3]; + UINT32 ROMBar; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT16 BridgeControl; + } ConfigSpacePtpBridge; + + // TODO: Add support for HeaderType 0x2 (PCI-to-CardBus bridge) +} PORTABLE_PCI_DEVICE_HEADER, *PPORTABLE_PCI_DEVICE_HEADER; + +/** + * @brief PCI Configuration Space Minimal Header for !pcitree + * + */ +typedef struct _PORTABLE_PCI_CONFIG_SPACE_HEADER_MINIMAL +{ + // + // Common header + // + UINT16 VendorId; + UINT16 DeviceId; + UINT8 ClassCode[3]; +} PORTABLE_PCI_CONFIG_SPACE_HEADER_MINIMAL, *PPORTABLE_PCI_CONFIG_SPACE_HEADER_MINIMAL; + +/** + * @brief PCI Device Minimal Data Structure for !pcitree + * + */ +typedef struct _PCI_DEV_MINIMAL +{ + UINT8 Bus : BUS_BIT_WIDTH; + UINT8 Device : DEVICE_BIT_WIDTH; + UINT8 Function : FUNCTION_BIT_WIDTH; + PORTABLE_PCI_CONFIG_SPACE_HEADER_MINIMAL ConfigSpace; +} PCI_DEV_MINIMAL, *PPCI_DEV_MINIMAL; + +/** + * @brief PCI Device MMIO BAR Metadata + * + */ +typedef struct _PCI_DEV_MMIOBAR_INFO +{ + BOOL Is64Bit; + BOOL IsEnabled; + UINT64 BarOffsetEnd; + UINT64 BarSize; +} PCI_DEV_MMIOBAR_INFO, *PPCI_DEV_MMIOBAR_INFO; + +/** + * @brief PCI Configuration Space Header + * + */ +typedef struct _PORTABLE_PCI_CONFIG_SPACE_HEADER +{ + PORTABLE_PCI_COMMON_HEADER CommonHeader; + PORTABLE_PCI_DEVICE_HEADER DeviceHeader; +} PORTABLE_PCI_CONFIG_SPACE_HEADER, *PPORTABLE_PCI_CONFIG_SPACE_HEADER; + +/** + * @brief PCI Device Data Structure + * + */ +typedef struct _PCI_DEV +{ + UINT8 Bus : BUS_BIT_WIDTH; + UINT8 Device : DEVICE_BIT_WIDTH; + UINT8 Function : FUNCTION_BIT_WIDTH; + PORTABLE_PCI_CONFIG_SPACE_HEADER ConfigSpace; + BYTE ConfigSpaceAdditional[CAM_CONFIG_SPACE_LENGTH - sizeof(PORTABLE_PCI_CONFIG_SPACE_HEADER)]; + PCI_DEV_MMIOBAR_INFO MmioBarInfo[6]; +} PCI_DEV, *PPCI_DEV; + +#pragma pack() diff --git a/hyperdbg/include/SDK/headers/PtDefinitions.h b/hyperdbg/include/SDK/headers/PtDefinitions.h new file mode 100644 index 00000000..cb827378 --- /dev/null +++ b/hyperdbg/include/SDK/headers/PtDefinitions.h @@ -0,0 +1,369 @@ +/** + * @file PtDefinitions.h + * @author Masoud Rahimi Jafari (Masoodrahimy1379@gmail.com) + * @brief Intel Processor Trace (PT) related data structures and hardware + * definitions shared between the kernel and user-mode components. + * @details + * @version 0.19 + * @date 2026-04-29 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// MSR Addresses // +// (Intel SDM Vol. 3, Chapter 32) // +////////////////////////////////////////////////// + +#define MSR_IA32_RTIT_OUTPUT_BASE 0x00000560 +#define MSR_IA32_RTIT_OUTPUT_MASK_PTRS 0x00000561 +#define MSR_IA32_RTIT_CTL 0x00000570 +#define MSR_IA32_RTIT_STATUS 0x00000571 +#define MSR_IA32_RTIT_CR3_MATCH 0x00000572 + +#define MSR_IA32_RTIT_ADDR0_A 0x00000580 +#define MSR_IA32_RTIT_ADDR0_B 0x00000581 +#define MSR_IA32_RTIT_ADDR1_A 0x00000582 +#define MSR_IA32_RTIT_ADDR1_B 0x00000583 +#define MSR_IA32_RTIT_ADDR2_A 0x00000584 +#define MSR_IA32_RTIT_ADDR2_B 0x00000585 +#define MSR_IA32_RTIT_ADDR3_A 0x00000586 +#define MSR_IA32_RTIT_ADDR3_B 0x00000587 + +// +// Used in PMI acknowledgment +// +#define MSR_IA32_PERF_GLOBAL_STATUS 0x0000038E +#define MSR_IA32_PERF_GLOBAL_OVF_CTRL 0x00000390 + +// +// Bit 55 of IA32_PERF_GLOBAL_STATUS: ToPA PMI pending +// +#define PERF_GLOBAL_STATUS_TOPA_PMI (1ULL << 55) + +////////////////////////////////////////////////// +// Constants // +////////////////////////////////////////////////// + +#define PT_PAGE_SIZE 0x1000ULL /* 4 KB */ +#define PT_OVERFLOW_SIZE PT_PAGE_SIZE /* 4 KB overflow landing zone */ +#define PT_MAX_ADDR_RANGES 4 + +// +// Maximum CPUs that the PT user-mode mmap surface can describe in a +// single request. Sized to fit one HYPERTRACE_PT_MMAP_PACKETS within a +// typical IOCTL buffer and to cover realistic host topologies. +// +#define PT_MAX_CPUS_FOR_MMAP 64 + +// +// ToPA entry Size field encoding: value N = 4KB * 2^N +// +#define PT_TOPA_SIZE_4K 0 +#define PT_TOPA_SIZE_8K 1 +#define PT_TOPA_SIZE_16K 2 +#define PT_TOPA_SIZE_32K 3 +#define PT_TOPA_SIZE_64K 4 +#define PT_TOPA_SIZE_128K 5 +#define PT_TOPA_SIZE_256K 6 +#define PT_TOPA_SIZE_512K 7 +#define PT_TOPA_SIZE_1M 8 +#define PT_TOPA_SIZE_2M 9 +#define PT_TOPA_SIZE_4M 10 +#define PT_TOPA_SIZE_8M 11 +#define PT_TOPA_SIZE_16M 12 +#define PT_TOPA_SIZE_32M 13 +#define PT_TOPA_SIZE_64M 14 +#define PT_TOPA_SIZE_128M 15 + +////////////////////////////////////////////////// +// MSR Structures // +////////////////////////////////////////////////// + +/** + * @brief IA32_RTIT_CTL — PT master control register + * @details Intel SDM Vol. 3, Section 32.2.7.2 + */ +typedef union _PT_RTIT_CTL_REGISTER +{ + struct + { + UINT64 TraceEn : 1; /* [0] Enable tracing */ + UINT64 CycEn : 1; /* [1] CYC packets */ + UINT64 Os : 1; /* [2] Trace CPL 0 */ + UINT64 User : 1; /* [3] Trace CPL > 0 */ + UINT64 PwrEvtEn : 1; /* [4] Power event trace */ + UINT64 FupOnPtw : 1; /* [5] FUP on PTWRITE */ + UINT64 FabricEn : 1; /* [6] Trace to fabric (must be 0) */ + UINT64 Cr3Filter : 1; /* [7] Filter by CR3 */ + UINT64 ToPA : 1; /* [8] Use ToPA output scheme */ + UINT64 MtcEn : 1; /* [9] MTC packets */ + UINT64 TscEn : 1; /* [10] TSC packets */ + UINT64 DisRetc : 1; /* [11] Disable RET compression */ + UINT64 PtwEn : 1; /* [12] PTWRITE packets */ + UINT64 BranchEn : 1; /* [13] Branch trace (TNT, TIP, FUP) */ + UINT64 MtcFreq : 4; /* [14:17] MTC frequency */ + UINT64 Reserved0 : 1; /* [18] Must be 0 */ + UINT64 CycThresh : 4; /* [19:22] CYC threshold */ + UINT64 Reserved1 : 1; /* [23] Must be 0 */ + UINT64 PsbFreq : 4; /* [24:27] PSB frequency */ + UINT64 Reserved2 : 4; /* [28:31] Must be 0 */ + UINT64 Addr0Cfg : 4; /* [32:35] Range 0 mode (1=filter / 2=stop) */ + UINT64 Addr1Cfg : 4; /* [36:39] Range 1 mode */ + UINT64 Addr2Cfg : 4; /* [40:43] Range 2 mode */ + UINT64 Addr3Cfg : 4; /* [44:47] Range 3 mode */ + UINT64 Reserved3 : 16; /* [48:63] Must be 0 */ + }; + UINT64 Value; +} PT_RTIT_CTL_REGISTER, *PPT_RTIT_CTL_REGISTER; + +/** + * @brief IA32_RTIT_STATUS — PT status / error register + * @details Intel SDM Vol. 3, Section 32.2.7.4 + */ +typedef union _PT_RTIT_STATUS_REGISTER +{ + struct + { + UINT64 FilterEn : 1; /* [0] RO: IP filter allowing trace */ + UINT64 ContextEn : 1; /* [1] RO: Context (CR3) allowing trace */ + UINT64 TriggerEn : 1; /* [2] RO: Trigger conditions met */ + UINT64 Reserved0 : 1; /* [3] Must be 0 */ + UINT64 Error : 1; /* [4] RO/Sticky: Operational error */ + UINT64 Stopped : 1; /* [5] RO: TraceStop hit */ + UINT64 PendTopaPmi : 1; /* [6] RW: ToPA PMI pending — clear this */ + UINT64 PendPsbPmi : 1; /* [7] RW: PSB+ PMI pending — clear this */ + UINT64 Reserved1 : 24; /* [8:31] Must be 0 */ + UINT64 PacketByteCnt : 17; /* [32:48] Bytes since last PSB */ + UINT64 Reserved2 : 15; /* [49:63] Must be 0 */ + }; + UINT64 Value; +} PT_RTIT_STATUS_REGISTER, *PPT_RTIT_STATUS_REGISTER; + +/** + * @brief IA32_RTIT_OUTPUT_MASK_PTRS — Output position tracker + * @details Intel SDM Vol. 3, Section 32.2.7.8 + */ +typedef union _PT_OUTPUT_MASK_PTRS_REGISTER +{ + struct + { + UINT64 LowerMask : 7; /* [0:6] Forced to 0x7F */ + UINT64 MaskOrTableOffset : 25; /* [7:31] ToPA: table entry index */ + UINT64 OutputOffset : 32; /* [32:63] Byte offset in current entry */ + }; + UINT64 Value; +} PT_OUTPUT_MASK_PTRS_REGISTER, *PPT_OUTPUT_MASK_PTRS_REGISTER; + +/** + * @brief ToPA Table Entry + * @details Intel SDM Vol. 3, Section 32.2.7.2 (Table of Physical Addresses) + */ +typedef union _PT_TOPA_ENTRY +{ + struct + { + UINT64 End : 1; /* [0] Last entry — wraps to next table */ + UINT64 Reserved0 : 1; /* [1] Must be 0 */ + UINT64 Int : 1; /* [2] Generate PMI when region fills */ + UINT64 Reserved1 : 1; /* [3] Must be 0 */ + UINT64 Stop : 1; /* [4] Stop tracing when region fills */ + UINT64 Reserved2 : 1; /* [5] Must be 0 */ + UINT64 Size : 4; /* [6:9] Region size (4K*2^N) */ + UINT64 Reserved3 : 2; /* [10:11] Must be 0 */ + UINT64 BaseAddr : 36; /* [12:47] Physical address >> 12 */ + UINT64 Reserved4 : 16; /* [48:63] Must be 0 */ + }; + UINT64 Value; +} PT_TOPA_ENTRY, *PPT_TOPA_ENTRY; + +////////////////////////////////////////////////// +// Capability / Config // +////////////////////////////////////////////////// + +/** + * @brief Discovered Intel PT capabilities (populated from CPUID leaf 0x14). + */ +typedef struct _PT_CAPABILITIES +{ + UINT32 Cr3Filtering : 1; /* Can filter by process CR3 */ + UINT32 PsbCycConfigurable : 1; /* PSBFreq and CYC configurable */ + UINT32 IpFiltering : 1; /* IP filtering and TraceStop supported */ + UINT32 MtcSupport : 1; /* MTC packets supported */ + UINT32 PtwriteSupport : 1; /* PTWRITE instruction supported */ + UINT32 PowerEventTrace : 1; /* Power event trace supported */ + UINT32 VmxSupport : 1; /* PT works in VMX operations */ + UINT32 TopaOutput : 1; /* ToPA output scheme supported */ + UINT32 TopaMultiEntry : 1; /* ToPA tables can have >1 entry */ + UINT32 SingleRangeOutput : 1; /* Single contiguous range output */ + UINT32 TransportOutput : 1; /* Trace transport subsystem output */ + UINT32 IpPayloadsAreLip : 1; /* IP payloads are LIP (not RIP) */ + UINT32 Reserved : 20; + + UINT32 NumAddrRanges; /* Number of ADDRn_CFG pairs (0-4) */ + UINT16 MtcPeriodBitmap; /* Supported MTC period values */ + UINT16 CycThresholdBitmap; /* Supported CYC threshold values */ + UINT16 PsbFreqBitmap; /* Supported PSB frequency values */ + +} PT_CAPABILITIES, *PPT_CAPABILITIES; + +/** + * @brief Intel PT trace state machine. + */ +typedef enum _PT_STATE +{ + PT_STATE_DISABLED = 0, /* No buffers allocated, PT off */ + PT_STATE_READY, /* Buffers allocated, MSRs not yet programmed */ + PT_STATE_TRACING, /* TraceEn=1, actively generating packets */ + PT_STATE_PAUSED, /* TraceEn=0 temporarily (PMI or user pause) */ + PT_STATE_STOPPED, /* Tracing done, buffer has valid data */ + PT_STATE_ERROR /* Hardware error (check IA32_RTIT_STATUS) */ +} PT_STATE; + +/** + * @brief Intel PT IP filter range. + */ +typedef struct _PT_ADDR_RANGE +{ + UINT64 Start; /* Start virtual address — written to ADDRn_A */ + UINT64 End; /* End virtual address — written to ADDRn_B */ + BOOLEAN IsStopRange; /* FALSE = filter (only trace inside range) + TRUE = trace-stop (stop when entering range) */ +} PT_ADDR_RANGE, *PPT_ADDR_RANGE; + +/** + * @brief Intel PT trace configuration — what the user specifies. + */ +typedef struct _PT_TRACE_CONFIG +{ + // + // What to trace + // + BOOLEAN TraceUser; /* Trace CPL 3 (user mode) */ + BOOLEAN TraceKernel; /* Trace CPL 0 (kernel mode) */ + UINT64 TargetCr3; /* Process to trace (0 = trace all) */ + + // + // IP filtering + // + UINT32 NumAddrRanges; /* 0-4 active ranges */ + PT_ADDR_RANGE AddrRanges[PT_MAX_ADDR_RANGES]; + + // + // Packet options + // + BOOLEAN EnableBranch; /* BranchEn — must be TRUE for useful traces */ + BOOLEAN EnableTsc; /* TscEn — timestamps at PSB boundaries */ + BOOLEAN EnableMtc; /* MtcEn — wall-clock timing packets */ + BOOLEAN EnableCyc; /* CycEn — cycle-accurate packets */ + BOOLEAN EnableRetCompression; /* TRUE keeps RET compression */ + UINT8 MtcFreq; /* 0-15: MTC period (must be in capabilities) */ + UINT8 CycThresh; /* 0-15: CYC threshold */ + UINT8 PsbFreq; /* 0-15: PSB frequency (0 = every 2KB) */ + + // + // Buffer size + // + UINT64 BufferSize; /* Main output buffer size in bytes + Must be 4KB * 2^N (4KB, 8KB, ..., 128MB) + Default: PT_DEFAULT_BUFFER_SIZE (2MB) */ +} PT_TRACE_CONFIG, *PPT_TRACE_CONFIG; + +////////////////////////////////////////////////// +// Per-CPU Trace State // +////////////////////////////////////////////////// + +/** + * @brief Per-CPU PT buffer layout + * + * ToPA Table (one 4KB page, 3 entries used): + * Entry[0] — Main data buffer (BufferSize), INT=1 + * Entry[1] — Overflow zone (4KB), INT=0 + * Entry[2] — END, points back to ToPA table (circular) + */ +typedef struct _PT_BUFFER +{ + // + // ToPA table + // + PT_TOPA_ENTRY * TopaVa; /* Virtual addr of the ToPA table */ + UINT64 TopaPhysical; /* Physical addr — IA32_RTIT_OUTPUT_BASE */ + + // + // Main output buffer + // + PVOID OutputVa; /* Virtual addr — read trace data from here */ + UINT64 OutputPhysical; /* Physical addr — goes into ToPA entry[0] */ + UINT64 OutputSize; /* Bytes (e.g., 0x200000 for 2MB) */ + + // + // Overflow landing zone (4KB) + // + PVOID OverflowVa; /* Virtual addr of overflow page */ + UINT64 OverflowPhysical; /* Physical addr — ToPA entry[1] */ + +} PT_BUFFER, *PPT_BUFFER; + +/** + * @brief Per-CPU Intel PT state — one of these per logical processor. + */ +typedef struct _PT_PER_CPU +{ + PT_BUFFER Buffer; /* ToPA + output buffers */ + PT_RTIT_CTL_REGISTER SavedCtl; /* Last written IA32_RTIT_CTL */ + PT_TRACE_CONFIG Config; /* Current trace configuration */ + PT_STATE State; /* Current state machine position */ + UINT64 TotalBytesCaptured; /* Accumulated across PMI events */ + +} PT_PER_CPU, *PPT_PER_CPU; + +////////////////////////////////////////////////// +// Trace Output Descriptor // +////////////////////////////////////////////////// + +/** + * @brief Trace output descriptor + * + * Passed to the engine to receive trace data. WriteOffset serves dual purpose: + * - Input: where in Buffer to start writing new data. + * - Output: updated to Buffer[0..WriteOffset) = valid data after the call. + * + * If the remaining space (Length - WriteOffset) is smaller than the new data, + * the copy is skipped and WriteOffset is not updated. + * Pass NULL instead of a PT_OUTPUT_BUFFER * to skip copying entirely. + */ +typedef struct _PT_OUTPUT_BUFFER +{ + PVOID Buffer; /* Destination buffer for trace data */ + UINT64 Length; /* Total size of Buffer in bytes */ + UINT64 WriteOffset; /* Next write position; valid data is [0..WriteOffset) */ + +} PT_OUTPUT_BUFFER, *PPT_OUTPUT_BUFFER; + +////////////////////////////////////////////////// +// User-mode mmap descriptor // +////////////////////////////////////////////////// + +/** + * @brief One per-CPU descriptor returned by the PT mmap surface. + * + * The main output buffer and the 4 KB overflow page are stitched + * into a single virtually contiguous region in the calling user + * process — main first, then overflow, matching the order PT + * writes them on a ToPA PMI. Consumers read the whole stream + * as Size bytes starting at UserVa. + * + * UserVa is valid only in the address space of the process that + * issued the mmap IOCTL, and only until PT is disabled / flushed + * (at which point the underlying kernel buffers are torn down). + */ +typedef struct _PT_USER_BUFFER_DESC +{ + UINT32 CpuId; + UINT32 Reserved; + UINT64 UserVa; /* base of the combined main + overflow mapping */ + UINT64 Size; /* total bytes in the mapping (main + overflow) */ + +} PT_USER_BUFFER_DESC, *PPT_USER_BUFFER_DESC; diff --git a/hyperdbg/include/SDK/Headers/RequestStructures.h b/hyperdbg/include/SDK/headers/RequestStructures.h similarity index 58% rename from hyperdbg/include/SDK/Headers/RequestStructures.h rename to hyperdbg/include/SDK/headers/RequestStructures.h index 64e04cbe..5e5b66b4 100644 --- a/hyperdbg/include/SDK/Headers/RequestStructures.h +++ b/hyperdbg/include/SDK/headers/RequestStructures.h @@ -1,6 +1,7 @@ /** * @file RequestStructures.h * @author Sina Karvandi (sina@hyperdbg.org) + * @author jtaw5649 * @brief HyperDbg's SDK Headers Request Packets * @details This file contains definitions of request packets (enums, structs) * @version 0.2 @@ -10,6 +11,37 @@ * */ #pragma once +#include "Pcie.h" + +#define SIZEOF_DEBUGGER_INIT_VMM_PACKET \ + sizeof(DEBUGGER_INIT_VMM_PACKET) + +/** + * @brief request for initializing VMM + * + */ +typedef struct _DEBUGGER_INIT_VMM_PACKET +{ + UINT32 KernelStatus; + +} DEBUGGER_INIT_VMM_PACKET, *PDEBUGGER_INIT_VMM_PACKET; + +// ============================================================================================== + +#define SIZEOF_DEBUGGER_INIT_HYPERTRACE_PACKET \ + sizeof(DEBUGGER_INIT_HYPERTRACE_PACKET) + +/** + * @brief request for initializing HyperTrace + * + */ +typedef struct _DEBUGGER_INIT_HYPERTRACE_PACKET +{ + UINT32 KernelStatus; + +} DEBUGGER_INIT_HYPERTRACE_PACKET, *PDEBUGGER_INIT_HYPERTRACE_PACKET; + +// ============================================================================================== #define SIZEOF_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS \ sizeof(DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS) @@ -40,8 +72,7 @@ typedef struct _DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS } DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS, *PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_VA2PA_AND_PA2VA_COMMANDS \ sizeof(DEBUGGER_VA2PA_AND_PA2VA_COMMANDS) @@ -60,8 +91,8 @@ typedef struct _DEBUGGER_VA2PA_AND_PA2VA_COMMANDS } DEBUGGER_VA2PA_AND_PA2VA_COMMANDS, *PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS; -/* ============================================================================================== - */ +// ============================================================================================== + #define SIZEOF_DEBUGGER_PAGE_IN_REQUEST \ sizeof(DEBUGGER_PAGE_IN_REQUEST) @@ -79,8 +110,7 @@ typedef struct _DEBUGGER_PAGE_IN_REQUEST } DEBUGGER_PAGE_IN_REQUEST, *PDEBUGGER_PAGE_IN_REQUEST; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief different modes of reconstruct requests @@ -121,8 +151,7 @@ typedef struct _REVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST } REVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST, *PREVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_DT_COMMAND_OPTIONS \ sizeof(DEBUGGER_DT_COMMAND_OPTIONS) @@ -133,18 +162,17 @@ typedef struct _REVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST */ typedef struct _DEBUGGER_DT_COMMAND_OPTIONS { - const char * TypeName; + const CHAR * TypeName; UINT64 SizeOfTypeName; UINT64 Address; BOOLEAN IsStruct; PVOID BufferAddress; UINT32 TargetPid; - const char * AdditionalParameters; + const CHAR * AdditionalParameters; } DEBUGGER_DT_COMMAND_OPTIONS, *PDEBUGGER_DT_COMMAND_OPTIONS; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief different types of prealloc requests @@ -178,8 +206,7 @@ typedef struct _DEBUGGER_PREALLOC_COMMAND } DEBUGGER_PREALLOC_COMMAND, *PDEBUGGER_PREALLOC_COMMAND; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief different types of preactivate requests @@ -205,8 +232,7 @@ typedef struct _DEBUGGER_PREACTIVATE_COMMAND } DEBUGGER_PREACTIVATE_COMMAND, *PDEBUGGER_PREACTIVATE_COMMAND; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_READ_MEMORY sizeof(DEBUGGER_READ_MEMORY) @@ -230,6 +256,17 @@ typedef enum _DEBUGGER_READ_MEMORY_TYPE DEBUGGER_READ_VIRTUAL_ADDRESS } DEBUGGER_READ_MEMORY_TYPE; +/** + * @brief different address mode + * + */ +typedef enum _DEBUGGER_READ_MEMORY_ADDRESS_MODE +{ + DEBUGGER_READ_ADDRESS_MODE_32_BIT, + DEBUGGER_READ_ADDRESS_MODE_64_BIT + +} DEBUGGER_READ_MEMORY_ADDRESS_MODE; + /** * @brief the way that debugger should show * the details of memory or disassemble them @@ -253,17 +290,15 @@ typedef enum _DEBUGGER_SHOW_MEMORY_STYLE */ typedef struct _DEBUGGER_READ_MEMORY { - UINT32 Pid; // Read from cr3 of what process - UINT64 Address; - UINT32 Size; - BOOLEAN IsForDisasm; // Debugger sets whether the read memory is for diassembler or not - BOOLEAN Is32BitAddress; // Debuggee sets the status of address - DEBUGGER_READ_MEMORY_TYPE MemoryType; - DEBUGGER_READ_READING_TYPE ReadingType; - PDEBUGGER_DT_COMMAND_OPTIONS DtDetails; - DEBUGGER_SHOW_MEMORY_STYLE Style; // not used in local debugging - UINT32 ReturnLength; // not used in local debugging - UINT32 KernelStatus; // not used in local debugging + UINT32 Pid; // Read from cr3 of what process + UINT64 Address; + UINT32 Size; + BOOLEAN GetAddressMode; // Debugger sets whether the read memory is for diassembler or not + DEBUGGER_READ_MEMORY_ADDRESS_MODE AddressMode; // Debuggee sets the mode of address + DEBUGGER_READ_MEMORY_TYPE MemoryType; + DEBUGGER_READ_READING_TYPE ReadingType; + UINT32 ReturnLength; // not used in local debugging + UINT32 KernelStatus; // not used in local debugging // // Here is the target buffer (actual memory) @@ -271,8 +306,7 @@ typedef struct _DEBUGGER_READ_MEMORY } DEBUGGER_READ_MEMORY, *PDEBUGGER_READ_MEMORY; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_FLUSH_LOGGING_BUFFERS \ sizeof(DEBUGGER_FLUSH_LOGGING_BUFFERS) @@ -289,8 +323,7 @@ typedef struct _DEBUGGER_FLUSH_LOGGING_BUFFERS } DEBUGGER_FLUSH_LOGGING_BUFFERS, *PDEBUGGER_FLUSH_LOGGING_BUFFERS; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_TEST_QUERY_BUFFER \ sizeof(DEBUGGER_TEST_QUERY_BUFFER) @@ -328,8 +361,7 @@ typedef struct _DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER } DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER, *PDEBUGGER_DEBUGGER_TEST_QUERY_BUFFER; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_PERFORM_KERNEL_TESTS \ sizeof(DEBUGGER_PERFORM_KERNEL_TESTS) @@ -344,8 +376,7 @@ typedef struct _DEBUGGER_PERFORM_KERNEL_TESTS } DEBUGGER_PERFORM_KERNEL_TESTS, *PDEBUGGER_PERFORM_KERNEL_TESTS; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL \ sizeof(DEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL) @@ -361,26 +392,7 @@ typedef struct _DEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL } DEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL, *PDEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL; -/* ============================================================================================== - */ - -#define SIZEOF_DEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION \ - sizeof(DEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION) - -/** - * @brief request for collecting debuggee's kernel-side test information - * - */ -typedef struct _DEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION -{ - UINT64 Value; - char Tag[32]; - -} DEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION, - *PDEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION; - -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER \ sizeof(DEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER) @@ -403,8 +415,7 @@ typedef struct _DEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER } DEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER, *PDEBUGGEE_SEND_GENERAL_PACKET_FROM_DEBUGGEE_TO_DEBUGGER; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER \ sizeof(DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER) @@ -425,8 +436,7 @@ typedef struct _DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER } DEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER, *PDEBUGGER_SEND_USERMODE_MESSAGES_TO_DEBUGGER; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_READ_AND_WRITE_ON_MSR \ sizeof(DEBUGGER_READ_AND_WRITE_ON_MSR) @@ -447,18 +457,19 @@ typedef enum _DEBUGGER_MSR_ACTION_TYPE */ typedef struct _DEBUGGER_READ_AND_WRITE_ON_MSR { - UINT64 Msr; // It's actually a 32-Bit value but let's not mess with a register - UINT32 CoreNumber; // specifies the core to execute wrmsr or read the msr - // (DEBUGGER_READ_AND_WRITE_ON_MSR_APPLY_ALL_CORES mean all - // the cores) - DEBUGGER_MSR_ACTION_TYPE - ActionType; // Detects whether user needs wrmsr or rdmsr - UINT64 Value; + UINT64 Msr; // It's actually a 32-Bit value but let's not mess with a register + UINT32 CoreNumber; // specifies the core to execute wrmsr or read the msr + // (DEBUGGER_READ_AND_WRITE_ON_MSR_APPLY_ALL_CORES mean all + // the cores) + DEBUGGER_MSR_ACTION_TYPE ActionType; // Detects whether user needs wrmsr or rdmsr + UINT64 Value; } DEBUGGER_READ_AND_WRITE_ON_MSR, *PDEBUGGER_READ_AND_WRITE_ON_MSR; -/* ============================================================================================== - */ +#define SIZEOF_DEBUGGER_READ_AND_WRITE_ON_MSR \ + sizeof(DEBUGGER_READ_AND_WRITE_ON_MSR) + +// ============================================================================================== #define SIZEOF_DEBUGGER_EDIT_MEMORY sizeof(DEBUGGER_EDIT_MEMORY) @@ -468,8 +479,8 @@ typedef struct _DEBUGGER_READ_AND_WRITE_ON_MSR */ typedef enum _DEBUGGER_EDIT_MEMORY_TYPE { - EDIT_PHYSICAL_MEMORY, - EDIT_VIRTUAL_MEMORY + EDIT_VIRTUAL_MEMORY, + EDIT_PHYSICAL_MEMORY } DEBUGGER_EDIT_MEMORY_TYPE; /** @@ -489,19 +500,17 @@ typedef enum _DEBUGGER_EDIT_MEMORY_BYTE_SIZE */ typedef struct _DEBUGGER_EDIT_MEMORY { - UINT32 Result; // Result from kernel + UINT32 Result; UINT64 Address; // Target address to modify UINT32 ProcessId; // specifies the process id DEBUGGER_EDIT_MEMORY_TYPE MemoryType; // Type of memory DEBUGGER_EDIT_MEMORY_BYTE_SIZE ByteSize; // Modification size UINT32 CountOf64Chunks; UINT32 FinalStructureSize; - UINT32 KernelStatus; // not used in local debugging } DEBUGGER_EDIT_MEMORY, *PDEBUGGER_EDIT_MEMORY; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_SEARCH_MEMORY sizeof(DEBUGGER_SEARCH_MEMORY) @@ -545,8 +554,36 @@ typedef struct _DEBUGGER_SEARCH_MEMORY } DEBUGGER_SEARCH_MEMORY, *PDEBUGGER_SEARCH_MEMORY; -/* ============================================================================================== +// ============================================================================================== + +/** + * @brief Windows System call values that are intercepted by transparency mode + * + * NOTE: Windows system calls can change values on each version + * This structure is used to keep track of the system call numbers + * based on the current running Windows version + * */ +typedef struct _SYSTEM_CALL_NUMBERS_INFORMATION +{ + UINT32 SysNtQuerySystemInformation; + UINT32 SysNtQuerySystemInformationEx; // On 24H2, changes on each windows version + + UINT32 SysNtSystemDebugControl; // On 24H2, changes on each windows version + UINT32 SysNtQueryAttributesFile; + UINT32 SysNtOpenDirectoryObject; + UINT32 SysNtQueryDirectoryObject; // On 24H2, changes on each windows version + UINT32 SysNtQueryInformationProcess; + UINT32 SysNtSetInformationProcess; + UINT32 SysNtQueryInformationThread; + UINT32 SysNtSetInformationThread; + UINT32 SysNtOpenFile; + UINT32 SysNtOpenKey; + UINT32 SysNtOpenKeyEx; // On 24H2, changes on each windows version + UINT32 SysNtQueryValueKey; + UINT32 SysNtEnumerateKey; + +} SYSTEM_CALL_NUMBERS_INFORMATION, *PSYSTEM_CALL_NUMBERS_INFORMATION; #define SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE \ sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE) @@ -559,28 +596,30 @@ typedef struct _DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE { BOOLEAN IsHide; - UINT64 CpuidAverage; - UINT64 CpuidStandardDeviation; - UINT64 CpuidMedian; + // UINT64 CpuidAverage; + // UINT64 CpuidStandardDeviation; + // UINT64 CpuidMedian; - UINT64 RdtscAverage; - UINT64 RdtscStandardDeviation; - UINT64 RdtscMedian; + // UINT64 RdtscAverage; + // UINT64 RdtscStandardDeviation; + // UINT64 RdtscMedian; BOOLEAN TrueIfProcessIdAndFalseIfProcessName; UINT32 ProcId; - UINT32 LengthOfProcessName; // in the case of !hide name xxx, this parameter - // shows the length of xxx + UINT32 LengthOfProcessName; - UINT64 KernelStatus; /* DEBUGGER_OPERATION_WAS_SUCCESSFUL , + SYSTEM_CALL_NUMBERS_INFORMATION SystemCallNumbersInformation; // System call numbers information + + UINT32 KernelStatus; /* DEBUGGER_OPERATION_WAS_SUCCESSFUL , DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER */ + UINT32 EvadeMask; // zero means TRANSPARENT_EVADE_MASK_DEFAULT + } DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE, *PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE; -/* ============================================================================================== - */ +// ============================================================================================== #define SIZEOF_DEBUGGER_PREPARE_DEBUGGEE sizeof(DEBUGGER_PREPARE_DEBUGGEE) @@ -592,14 +631,13 @@ typedef struct _DEBUGGER_PREPARE_DEBUGGEE { UINT32 PortAddress; UINT32 Baudrate; - UINT64 NtoskrnlBaseAddress; + UINT64 KernelBaseAddress; UINT32 Result; // Result from the kernel CHAR OsName[MAXIMUM_CHARACTER_FOR_OS_NAME]; } DEBUGGER_PREPARE_DEBUGGEE, *PDEBUGGER_PREPARE_DEBUGGEE; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief The structure of changing core packet in HyperDbg @@ -612,8 +650,8 @@ typedef struct _DEBUGGEE_CHANGE_CORE_PACKET } DEBUGGEE_CHANGE_CORE_PACKET, *PDEBUGGEE_CHANGE_CORE_PACKET; -/* ============================================================================================== - */ +// ============================================================================================== + #define SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS \ sizeof(DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS) @@ -627,6 +665,7 @@ typedef enum _DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_TYPE DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_DETACH, DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_REMOVE_HOOKS, DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_KILL_PROCESS, + DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_CONTINUE_PROCESS, DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_PAUSE_PROCESS, DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_SWITCH_BY_PROCESS_OR_THREAD, DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_QUERY_COUNT_OF_ACTIVE_DEBUGGING_THREADS, @@ -644,7 +683,10 @@ typedef struct _DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS UINT32 ThreadId; BOOLEAN CheckCallbackAtFirstInstruction; BOOLEAN Is32Bit; - BOOLEAN IsPaused; // used in switching to threads + UINT64 Rip; // used in switching threads + BYTE InstructionBytesOnRip[MAXIMUM_INSTR_SIZE]; // used in switching threads + UINT32 SizeOfInstruction; // used in switching threads + BOOLEAN IsPaused; // used in switching to threads DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_TYPE Action; UINT32 CountOfActiveDebuggingThreadsAndProcesses; // used in showing the list of active threads/processes UINT64 Token; @@ -653,8 +695,8 @@ typedef struct _DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS } DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, *PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS; -/* ============================================================================================== - */ +// ============================================================================================== + #define SIZEOF_DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS \ sizeof(DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS) @@ -760,8 +802,10 @@ typedef struct _DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS } DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS, *PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS; -/* ============================================================================================== - */ +#define SIZEOF_DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS \ + sizeof(DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS) + +// ============================================================================================== /** * @brief The structure for saving the callstack frame of one parameter @@ -811,8 +855,8 @@ typedef struct _DEBUGGER_CALLSTACK_REQUEST } DEBUGGER_CALLSTACK_REQUEST, *PDEBUGGER_CALLSTACK_REQUEST; -/* ============================================================================================== - */ +// ============================================================================================== + #define SIZEOF_USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS \ sizeof(USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS) @@ -820,12 +864,12 @@ typedef struct _USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS { UINT32 ProcessId; UINT32 ThreadId; + UINT64 NumberOfBlockedContextSwitches; BOOLEAN IsProcess; } USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS, *PUSERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief Used for run the script @@ -865,8 +909,7 @@ typedef struct _DEBUGGER_EVENT_REQUEST_CUSTOM_CODE } DEBUGGER_EVENT_REQUEST_CUSTOM_CODE, *PDEBUGGER_EVENT_REQUEST_CUSTOM_CODE; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief User-mode debugging actions @@ -876,8 +919,9 @@ typedef enum _DEBUGGER_UD_COMMAND_ACTION_TYPE { DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE = 0, DEBUGGER_UD_COMMAND_ACTION_TYPE_PAUSE, - DEBUGGER_UD_COMMAND_ACTION_TYPE_CONTINUE, DEBUGGER_UD_COMMAND_ACTION_TYPE_REGULAR_STEP, + DEBUGGER_UD_COMMAND_ACTION_TYPE_READ_REGISTERS, + DEBUGGER_UD_COMMAND_ACTION_TYPE_EXECUTE_SCRIPT_BUFFER, } DEBUGGER_UD_COMMAND_ACTION_TYPE; @@ -905,12 +949,14 @@ typedef struct _DEBUGGER_UD_COMMAND_PACKET UINT64 ProcessDebuggingDetailToken; UINT32 TargetThreadId; BOOLEAN ApplyToAllPausedThreads; + BOOLEAN WaitForEventCompletion; UINT32 Result; } DEBUGGER_UD_COMMAND_PACKET, *PDEBUGGER_UD_COMMAND_PACKET; -/* ============================================================================================== - */ +#define SIZEOF_DEBUGGER_UD_COMMAND_PACKET sizeof(DEBUGGER_UD_COMMAND_PACKET) + +// ============================================================================================== /** * @brief Debugger process switch and process details @@ -942,8 +988,7 @@ typedef struct _DEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET } DEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET, *PDEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief Debugger size of DEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET @@ -990,8 +1035,7 @@ typedef struct _DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET #define SIZEOF_DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET \ sizeof(DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET) -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief stepping and tracking types @@ -1032,8 +1076,466 @@ typedef struct _DEBUGGEE_STEP_PACKET */ #define DEBUGGER_REMOTE_TRACKING_DEFAULT_COUNT_OF_STEPPING 0xffffffff -/* ============================================================================================== +// ============================================================================================== + +/** + * @brief Perform actions related to APIC + * */ +typedef enum _DEBUGGER_APIC_REQUEST_TYPE +{ + DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC, + DEBUGGER_APIC_REQUEST_TYPE_READ_IO_APIC, + +} DEBUGGER_APIC_REQUEST_TYPE; + +/** + * @brief The structure of actions for APIC + * + */ +typedef struct _DEBUGGER_APIC_REQUEST +{ + DEBUGGER_APIC_REQUEST_TYPE ApicType; + BOOLEAN IsUsingX2APIC; + UINT32 KernelStatus; + +} DEBUGGER_APIC_REQUEST, *PDEBUGGER_APIC_REQUEST; + +/** + * @brief Debugger size of DEBUGGER_APIC_REQUEST + * + */ +#define SIZEOF_DEBUGGER_APIC_REQUEST \ + sizeof(DEBUGGER_APIC_REQUEST) + +/** + * @brief LAPIC structure size + */ +#define LAPIC_SIZE 0x400 + +#define LAPIC_LVT_FLAG_ENTRY_MASKED (1UL << 16) +#define LAPIC_LVT_DELIVERY_MODE_EXT_INT (7UL << 8) +#define LAPIC_SVR_FLAG_SW_ENABLE (1UL << 8) + +/** + * @brief LAPIC structure and offsets + */ +typedef struct _LAPIC_PAGE +{ + UINT8 Reserved000[0x10]; + UINT8 Reserved010[0x10]; + + UINT32 Id; // offset 0x020 + UINT8 Reserved024[0x0C]; + + UINT32 Version; // offset 0x030 + UINT8 Reserved034[0x0C]; + + UINT8 Reserved040[0x40]; + + UINT32 TPR; // offset 0x080 + UINT8 Reserved084[0x0C]; + + UINT32 ArbitrationPriority; // offset 0x090 + UINT8 Reserved094[0x0C]; + + UINT32 ProcessorPriority; // offset 0x0A0 + UINT8 Reserved0A4[0x0C]; + + UINT32 EOI; // offset 0x0B0 + UINT8 Reserved0B4[0x0C]; + + UINT32 RemoteRead; // offset 0x0C0 + UINT8 Reserved0C4[0x0C]; + + UINT32 LogicalDestination; // offset 0x0D0 + UINT8 Reserved0D4[0x0C]; + + UINT32 DestinationFormat; // offset 0x0E0 + UINT8 Reserved0E4[0x0C]; + + UINT32 SpuriousInterruptVector; // offset 0x0F0 + UINT8 Reserved0F4[0x0C]; + + UINT32 ISR[32]; // offset 0x100 + + UINT32 TMR[32]; // offset 0x180 + + UINT32 IRR[32]; // offset 0x200 + + UINT32 ErrorStatus; // offset 0x280 + UINT8 Reserved284[0x0C]; + + UINT8 Reserved290[0x60]; + + UINT32 LvtCmci; // offset 0x2F0 + UINT8 Reserved2F4[0x0C]; + + UINT32 IcrLow; // offset 0x300 + UINT8 Reserved304[0x0C]; + + UINT32 IcrHigh; // offset 0x310 + UINT8 Reserved314[0x0C]; + + UINT32 LvtTimer; // offset 0x320 + UINT8 Reserved324[0x0C]; + + UINT32 LvtThermalSensor; // offset 0x330 + UINT8 Reserved334[0x0C]; + + UINT32 LvtPerfMonCounters; // offset 0x340 + UINT8 Reserved344[0x0C]; + + UINT32 LvtLINT0; // offset 0x350 + UINT8 Reserved354[0x0C]; + + UINT32 LvtLINT1; // offset 0x360 + UINT8 Reserved364[0x0C]; + + UINT32 LvtError; // offset 0x370 + UINT8 Reserved374[0x0C]; + + UINT32 InitialCount; // offset 0x380 + UINT8 Reserved384[0x0C]; + + UINT32 CurrentCount; // offset 0x390 + UINT8 Reserved394[0x0C]; + + UINT8 Reserved3A0[0x40]; // offset 0x3A0 + + UINT32 DivideConfiguration; // offset 0x3E0 + UINT8 Reserved3E4[0x0C]; + + UINT32 SelfIpi; // offset 0x3F0 + UINT8 Reserved3F4[0x0C]; // valid only for X2APIC +} LAPIC_PAGE, *PLAPIC_PAGE; + +// ============================================================================================== + +/** + * @brief Maximum number of I/O APIC entries + * @details Usually 256 entries are enough (but we allocate 400 for systems with more + * I/O APIC entries) + * We're not gonna make the packet bigger than it's needed + * + */ +#define MAX_NUMBER_OF_IO_APIC_ENTRIES 400 + +/** + * @brief The structure of I/O APIC result packet in HyperDbg + * + */ +typedef struct _IO_APIC_ENTRY_PACKETS +{ + UINT64 ApicBasePa; + UINT64 ApicBaseVa; + UINT32 IoIdReg; + UINT32 IoLl; + UINT32 IoArbIdReg; + UINT64 LlLhData[MAX_NUMBER_OF_IO_APIC_ENTRIES]; + +} IO_APIC_ENTRY_PACKETS, *PIO_APIC_ENTRY_PACKETS; + +/** + * @brief check so the IO_APIC_ENTRY_PACKETS should be smaller than packet size + * + */ +static_assert(sizeof(IO_APIC_ENTRY_PACKETS) < PacketChunkSize, + "err (static_assert), size of PacketChunkSize should be bigger than IO_APIC_ENTRY_PACKETS"); + +// ============================================================================================== + +/** + * @brief Perform actions related to SMIs + * + */ +typedef enum _SMI_OPERATION_REQUEST_TYPE +{ + SMI_OPERATION_REQUEST_TYPE_READ_COUNT, + SMI_OPERATION_REQUEST_TYPE_TRIGGER_POWER_SMI, + +} SMI_OPERATION_REQUEST_TYPE; + +/** + * @brief The structure of I/O APIC result packet in HyperDbg + * + */ +typedef struct _SMI_OPERATION_PACKETS +{ + SMI_OPERATION_REQUEST_TYPE SmiOperationType; + UINT64 SmiCount; + UINT32 KernelStatus; + +} SMI_OPERATION_PACKETS, *PSMI_OPERATION_PACKETS; + +/** + * @brief Debugger size of SMI_OPERATION_PACKETS + * + */ +#define SIZEOF_SMI_OPERATION_PACKETS \ + sizeof(SMI_OPERATION_PACKETS) + +// ============================================================================================== + +/** + * @brief Perform actions related to HyperTrace for LBR + * + */ +typedef enum _HYPERTRACE_LBR_OPERATION_REQUEST_TYPE +{ + HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_ENABLE, + HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_DISABLE, + HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_FLUSH, + + HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_FILTER, + + // HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_QUERY, + // HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_DUMP, + +} HYPERTRACE_LBR_OPERATION_REQUEST_TYPE; + +/** + * @brief The structure of HyperTrace LBR result packet in HyperDbg + * + */ +typedef struct _HYPERTRACE_LBR_OPERATION_PACKETS +{ + HYPERTRACE_LBR_OPERATION_REQUEST_TYPE LbrOperationType; + UINT32 LbrFilterOptions; + UINT32 KernelStatus; + +} HYPERTRACE_LBR_OPERATION_PACKETS, *PHYPERTRACE_LBR_OPERATION_PACKETS; + +/** + * @brief Debugger size of HYPERTRACE_LBR_OPERATION_PACKETS + * + */ +#define SIZEOF_HYPERTRACE_LBR_OPERATION_PACKETS \ + sizeof(HYPERTRACE_LBR_OPERATION_PACKETS) + +// ============================================================================================== + +/** + * @brief The structure of HyperTrace LBR dump result packet in HyperDbg + * + */ +typedef struct _HYPERTRACE_LBR_DUMP_PACKETS +{ + UINT32 CoreId; + BOOLEAN NextCoreIsValid; // In the case of dumping all cores, this flag indicates whether the next core number is valid + BOOLEAN ArchBasedLBR; // Whether the LBR is architecture-based + LBR_STACK_ENTRY LbrStack; + UINT8 CurrentLbrCapacity; + UINT32 KernelStatus; + +} HYPERTRACE_LBR_DUMP_PACKETS, *PHYPERTRACE_LBR_DUMP_PACKETS; + +/** + * @brief In the case of dumping all cores, this value is used to specify that all cores should be dumped + * + */ +#define HYPERTRACE_LBR_DUMP_ALL_CORES 0xffffffff + +/** + * @brief Debugger size of HYPERTRACE_LBR_DUMP_PACKETS + * + */ +#define SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS \ + sizeof(HYPERTRACE_LBR_DUMP_PACKETS) + +// ============================================================================================== + +/** + * @brief Perform actions related to HyperTrace for PT + * + */ +typedef enum _HYPERTRACE_PT_OPERATION_REQUEST_TYPE +{ + HYPERTRACE_PT_OPERATION_REQUEST_TYPE_ENABLE, + HYPERTRACE_PT_OPERATION_REQUEST_TYPE_DISABLE, + HYPERTRACE_PT_OPERATION_REQUEST_TYPE_PAUSE, + HYPERTRACE_PT_OPERATION_REQUEST_TYPE_RESUME, + HYPERTRACE_PT_OPERATION_REQUEST_TYPE_SIZE, + HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FLUSH, + HYPERTRACE_PT_OPERATION_REQUEST_TYPE_DUMP, + HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FILTER, + HYPERTRACE_PT_OPERATION_REQUEST_TYPE_PACKET, + +} HYPERTRACE_PT_OPERATION_REQUEST_TYPE; + +/** + * @brief The maximum buffer size for PT + * + */ +#define PT_DEFAULT_BUFFER_SIZE 0x200000 // 2 MB + +/** + * @brief The default core for PT + * + */ +#define PT_DEFAULT_PINNING_CORE 0x0 // 0th core + +/** + * @brief PT enable options structure + * + */ +typedef struct _PT_ENABLE_OPTIONS +{ + UINT32 EnableByCr3 : 1; // Enable by CR3 + UINT32 EnableByPid : 1; // Enable by PID + UINT32 EnableByTid : 1; // Enable by TID + UINT32 EnableByPname : 1; // Enable by process name + + UINT32 Pid; + UINT32 Tid; + UINT64 Cr3; + CHAR ProcessName[256]; + +} PT_ENABLE_OPTIONS, *PPT_ENABLE_OPTIONS; + +/** + * @brief PT filter options structure + * + */ +typedef struct _PT_FILTER_OPTIONS +{ + UINT32 TraceUser : 1; // Trace user mode + UINT32 TraceKernel : 1; // Trace kernel mode + + UINT8 NumAddrRanges; /* Number of valid AddrRanges entries */ + PT_ADDR_RANGE AddrRanges[PT_MAX_ADDR_RANGES]; // Address ranges to filter by + +} PT_FILTER_OPTIONS, *PPT_FILTER_OPTIONS; + +/** + * @brief PT packet options structure + * + */ +typedef struct _PT_PACKET_OPTIONS +{ + UINT32 PSB : 1; // PSB packet + UINT32 PIP : 1; // PIP packet + UINT32 TSC : 1; // TSC packet + UINT32 MTC : 1; // MTC packet + UINT32 CYC : 1; // CYC packet + UINT32 TNT : 1; // TNT packet + UINT32 TIP : 1; // TIP packet + UINT32 FUP : 1; // FUP packet + UINT32 MODE : 1; // MODE packet + +} PT_PACKET_OPTIONS, *PPT_PACKET_OPTIONS; + +/** + * @brief The structure of HyperTrace PT result packet in HyperDbg + * + */ +typedef struct _HYPERTRACE_PT_OPERATION_PACKETS +{ + HYPERTRACE_PT_OPERATION_REQUEST_TYPE PtOperationType; + UINT32 KernelStatus; + + // + // Enable + // + UINT64 BufferSize; /* Output buffer size (0 = default / PT_DEFAULT_BUFFER_SIZE) */ + PT_ENABLE_OPTIONS EnableOptions; /* Options for enabling PT (CPL, CR3, PID, TID, Pname) */ + UINT32 CoreId; /* Core ID for running (pinning) process/thread */ + + // + // Filter + // + PT_FILTER_OPTIONS FilterOptions; /* Options for filtering PT (CPL, AddrRanges) */ + + // + // Packet + // + PT_PACKET_OPTIONS PacketOptions; /* Options for PT packets */ + + // + // Size + // + UINT32 NumCpus; /* CPUs populated in BytesPerCpu */ + UINT64 BytesPerCpu[PT_MAX_CPUS_FOR_MMAP]; + +} HYPERTRACE_PT_OPERATION_PACKETS, *PHYPERTRACE_PT_OPERATION_PACKETS; + +/** + * @brief Debugger size of HYPERTRACE_PT_OPERATION_PACKETS + * + */ +#define SIZEOF_HYPERTRACE_PT_OPERATION_PACKETS \ + sizeof(HYPERTRACE_PT_OPERATION_PACKETS) + +// ============================================================================================== + +/** + * @brief Result packet for the HyperTrace PT mmap surface. + * + * On success KernelStatus is DEBUGGER_OPERATION_WAS_SUCCESSFUL, + * NumCpus gives the number of CPUs that were mapped, and + * Cpus[0..NumCpus) hand back a single { UserVa, Size } per CPU. + * Each Size covers the main output buffer immediately followed + * by the 4 KB overflow page as one contiguous byte stream. + * + * Mapping contract (cooperative single-process): + * - The IOCTL maps into the address space of the process that + * calls DeviceIoControl. The returned user VAs are not + * portable across processes. + * - Mapping is tied to the PT enable cycle. PT disable / flush + * tears the mapping down; the caller must not touch the + * user VAs afterwards. + * - Calling the IOCTL twice within the same enable cycle + * returns the existing mapping (idempotent). + */ +typedef struct _HYPERTRACE_PT_MMAP_PACKETS +{ + UINT32 KernelStatus; + UINT32 NumCpus; + PT_USER_BUFFER_DESC Cpus[PT_MAX_CPUS_FOR_MMAP]; + +} HYPERTRACE_PT_MMAP_PACKETS, *PHYPERTRACE_PT_MMAP_PACKETS; + +/** + * @brief Debugger size of HYPERTRACE_PT_MMAP_PACKETS + * + */ +#define SIZEOF_HYPERTRACE_PT_MMAP_PACKETS \ + sizeof(HYPERTRACE_PT_MMAP_PACKETS) + +// ============================================================================================== + +/** + * @brief Maximum number of IDT entries + * + */ +#define MAX_NUMBER_OF_IDT_ENTRIES 256 + +/** + * @brief The structure of IDT entries result packet in HyperDbg + * + */ +typedef struct _INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS +{ + UINT32 KernelStatus; + UINT64 IdtEntry[MAX_NUMBER_OF_IDT_ENTRIES]; + +} INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS, *PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS; + +/** + * @brief Debugger size of INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS + * + */ +#define SIZEOF_INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS \ + sizeof(INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS) + +/** + * @brief check so the INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS should be smaller than packet size + * + */ +static_assert(sizeof(INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS) < PacketChunkSize, + "err (static_assert), size of PacketChunkSize should be bigger than INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS"); + +// ============================================================================================== /** * @brief The structure of .formats result packet in HyperDbg @@ -1046,8 +1548,7 @@ typedef struct _DEBUGGEE_FORMATS_PACKET } DEBUGGEE_FORMATS_PACKET, *PDEBUGGEE_FORMATS_PACKET; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief The structure of .sym reload packet in HyperDbg @@ -1059,8 +1560,7 @@ typedef struct _DEBUGGEE_SYMBOL_REQUEST_PACKET } DEBUGGEE_SYMBOL_REQUEST_PACKET, *PDEBUGGEE_SYMBOL_REQUEST_PACKET; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief The structure of bp command packet in HyperDbg @@ -1078,6 +1578,13 @@ typedef struct _DEBUGGEE_BP_PACKET } DEBUGGEE_BP_PACKET, *PDEBUGGEE_BP_PACKET; +/** + * @brief Debugger size of DEBUGGEE_BP_PACKET + * + */ +#define SIZEOF_DEBUGGEE_BP_PACKET \ + sizeof(DEBUGGEE_BP_PACKET) + /** * @brief breakpoint modification types * @@ -1104,8 +1611,7 @@ typedef struct _DEBUGGEE_BP_LIST_OR_MODIFY_PACKET } DEBUGGEE_BP_LIST_OR_MODIFY_PACKET, *PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief Whether a jump is taken or not taken @@ -1121,8 +1627,7 @@ typedef enum _DEBUGGER_CONDITIONAL_JUMP_STATUS } DEBUGGER_CONDITIONAL_JUMP_STATUS; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief The structure of script packet in HyperDbg @@ -1133,6 +1638,7 @@ typedef struct _DEBUGGEE_SCRIPT_PACKET UINT32 ScriptBufferSize; UINT32 ScriptBufferPointer; BOOLEAN IsFormat; + UINT64 FormatValue; UINT32 Result; // @@ -1141,8 +1647,7 @@ typedef struct _DEBUGGEE_SCRIPT_PACKET } DEBUGGEE_SCRIPT_PACKET, *PDEBUGGEE_SCRIPT_PACKET; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief The structure of result of search packet in HyperDbg @@ -1155,8 +1660,7 @@ typedef struct _DEBUGGEE_RESULT_OF_SEARCH_PACKET } DEBUGGEE_RESULT_OF_SEARCH_PACKET, *PDEBUGGEE_RESULT_OF_SEARCH_PACKET; -/* ============================================================================================== - */ +// ============================================================================================== /** * @brief Register Descriptor Structure to use in r command. @@ -1164,11 +1668,72 @@ typedef struct _DEBUGGEE_RESULT_OF_SEARCH_PACKET */ typedef struct _DEBUGGEE_REGISTER_READ_DESCRIPTION { - UINT32 RegisterID; // the number is from REGS_ENUM + UINT32 RegisterId; UINT64 Value; UINT32 KernelStatus; } DEBUGGEE_REGISTER_READ_DESCRIPTION, *PDEBUGGEE_REGISTER_READ_DESCRIPTION; -/* ============================================================================================== +// ============================================================================================== + +/** + * @brief Register Descriptor Structure to write on registers. + * */ +typedef struct _DEBUGGEE_REGISTER_WRITE_DESCRIPTION +{ + UINT32 RegisterId; + UINT64 Value; + UINT32 KernelStatus; + +} DEBUGGEE_REGISTER_WRITE_DESCRIPTION, *PDEBUGGEE_REGISTER_WRITE_DESCRIPTION; + +// ============================================================================================== + +#define SIZEOF_DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET \ + sizeof(DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET) + +/** + * @brief Pcitree Request-Response Packet. Represents PCI device tree. + * + */ +typedef struct _DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET +{ + UINT32 KernelStatus; + UINT8 DeviceInfoListNum; + PCI_DEV_MINIMAL DeviceInfoList[DEV_MAX_NUM]; + +} DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET, *PDEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET; + +/** + * @brief check so the DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET should be smaller than packet size + * + */ +static_assert(sizeof(DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET) < PacketChunkSize, + "err (static_assert), size of PacketChunkSize should be bigger than DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET"); + +// ============================================================================================== + +#define SIZEOF_DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET \ + sizeof(DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET) + +/** + * @brief PCI device info Request-Response Packet, used by !pcicam and future PCI-related commands. Represents a PCI device. + * + */ +typedef struct _DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET +{ + UINT32 KernelStatus; + BOOL PrintRaw; + PCI_DEV DeviceInfo; + +} DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET, *PDEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET; + +/** + * @brief check so the DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET should be smaller than packet size + * + */ +static_assert(sizeof(DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET) < PacketChunkSize, + "err (static_assert), size of PacketChunkSize should be bigger than DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET"); + +// ============================================================================================== diff --git a/hyperdbg/include/SDK/headers/ScriptEngineCommonDefinitions.h b/hyperdbg/include/SDK/headers/ScriptEngineCommonDefinitions.h new file mode 100644 index 00000000..2a8f16fb --- /dev/null +++ b/hyperdbg/include/SDK/headers/ScriptEngineCommonDefinitions.h @@ -0,0 +1,474 @@ +#pragma once +#ifndef SCRIPT_ENGINE_COMMON_DEFINITIONS_H +#define SCRIPT_ENGINE_COMMON_DEFINITIONS_H + +typedef struct SYMBOL +{ + long long unsigned Type; + long long unsigned Len; + long long unsigned Value; + +} SYMBOL, *PSYMBOL; + +#define SIZE_SYMBOL_WITHOUT_LEN sizeof(long long unsigned) * 2 + +typedef struct HWDBG_SHORT_SYMBOL +{ + long long unsigned Type; + long long unsigned Value; + +} HWDBG_SHORT_SYMBOL, *PHWDBG_SHORT_SYMBOL; + +typedef struct SYMBOL_BUFFER { + PSYMBOL Head; + unsigned int Pointer; + unsigned int Size; + char* Message; +} SYMBOL_BUFFER, * PSYMBOL_BUFFER; + +typedef struct SYMBOL_MAP +{ + char* Name; + long long unsigned Type; +} SYMBOL_MAP, * PSYMBOL_MAP; + +typedef struct ACTION_BUFFER { + long long unsigned Tag; + long long unsigned CurrentAction; + char ImmediatelySendTheResults; + long long unsigned Context; + char CallingStage; +} ACTION_BUFFER, *PACTION_BUFFER; + +#define SYMBOL_UNDEFINED 0 +#define SYMBOL_GLOBAL_ID_TYPE 1 +#define SYMBOL_LOCAL_ID_TYPE 2 +#define SYMBOL_NUM_TYPE 3 +#define SYMBOL_REGISTER_TYPE 4 +#define SYMBOL_PSEUDO_REG_TYPE 5 +#define SYMBOL_SEMANTIC_RULE_TYPE 6 +#define SYMBOL_TEMP_TYPE 7 +#define SYMBOL_STRING_TYPE 8 +#define SYMBOL_VARIABLE_COUNT_TYPE 9 +#define SYMBOL_INVALID 10 +#define SYMBOL_WSTRING_TYPE 11 +#define SYMBOL_FUNCTION_PARAMETER_ID_TYPE 12 +#define SYMBOL_RETURN_ADDRESS_TYPE 13 +#define SYMBOL_FUNCTION_PARAMETER_TYPE 14 +#define SYMBOL_STACK_INDEX_TYPE 15 +#define SYMBOL_STACK_BASE_INDEX_TYPE 16 +#define SYMBOL_RETURN_VALUE_TYPE 17 +#define SYMBOL_REFERENCE_LOCAL_ID_TYPE 18 +#define SYMBOL_REFERENCE_TEMP_TYPE 19 +#define SYMBOL_DEREFERENCE_LOCAL_ID_TYPE 20 +#define SYMBOL_DEREFERENCE_TEMP_TYPE 21 + +static const char *const SymbolTypeNames[] = { +"SYMBOL_UNDEFINED", +"SYMBOL_GLOBAL_ID_TYPE", +"SYMBOL_LOCAL_ID_TYPE", +"SYMBOL_NUM_TYPE", +"SYMBOL_REGISTER_TYPE", +"SYMBOL_PSEUDO_REG_TYPE", +"SYMBOL_SEMANTIC_RULE_TYPE", +"SYMBOL_TEMP_TYPE", +"SYMBOL_STRING_TYPE", +"SYMBOL_VARIABLE_COUNT_TYPE", +"SYMBOL_INVALID", +"SYMBOL_WSTRING_TYPE", +"SYMBOL_FUNCTION_PARAMETER_ID_TYPE", +"SYMBOL_RETURN_ADDRESS_TYPE", +"SYMBOL_FUNCTION_PARAMETER_TYPE", +"SYMBOL_STACK_INDEX_TYPE", +"SYMBOL_STACK_BASE_INDEX_TYPE", +"SYMBOL_RETURN_VALUE_TYPE", +"SYMBOL_REFERENCE_LOCAL_ID_TYPE", +"SYMBOL_REFERENCE_TEMP_TYPE", +"SYMBOL_DEREFERENCE_LOCAL_ID_TYPE", +"SYMBOL_DEREFERENCE_TEMP_TYPE" +}; + +#define SYMBOL_MEM_VALID_CHECK_MASK (1 << 31) +#define INVALID 0x80000000 +#define LALR_ACCEPT 0x7fffffff + + + +#define FUNC_UNDEFINED 0 +#define FUNC_INC 1 +#define FUNC_DEC 2 +#define FUNC_REFERENCE 3 +#define FUNC_OR 4 +#define FUNC_XOR 5 +#define FUNC_AND 6 +#define FUNC_ASR 7 +#define FUNC_ASL 8 +#define FUNC_ADD 9 +#define FUNC_SUB 10 +#define FUNC_MUL 11 +#define FUNC_DIV 12 +#define FUNC_MOD 13 +#define FUNC_GT 14 +#define FUNC_LT 15 +#define FUNC_EGT 16 +#define FUNC_ELT 17 +#define FUNC_EQUAL 18 +#define FUNC_NEQ 19 +#define FUNC_JMP 20 +#define FUNC_JZ 21 +#define FUNC_JNZ 22 +#define FUNC_MOV 23 +#define FUNC_START_OF_DO_WHILE 24 +#define FUNC_START_OF_DO_WHILE_COMMANDS 25 +#define FUNC_END_OF_DO_WHILE 26 +#define FUNC_START_OF_FOR 27 +#define FUNC_FOR_INC_DEC 28 +#define FUNC_START_OF_FOR_OMMANDS 29 +#define FUNC_END_OF_IF 30 +#define FUNC_IGNORE_LVALUE 31 +#define FUNC_PUSH 32 +#define FUNC_POP 33 +#define FUNC_CALL 34 +#define FUNC_RET 35 +#define FUNC_PRINT 36 +#define FUNC_FORMATS 37 +#define FUNC_EVENT_ENABLE 38 +#define FUNC_EVENT_DISABLE 39 +#define FUNC_EVENT_CLEAR 40 +#define FUNC_TEST_STATEMENT 41 +#define FUNC_SPINLOCK_LOCK 42 +#define FUNC_SPINLOCK_UNLOCK 43 +#define FUNC_EVENT_SC 44 +#define FUNC_MICROSLEEP 45 +#define FUNC_PRINTF 46 +#define FUNC_PAUSE 47 +#define FUNC_FLUSH 48 +#define FUNC_EVENT_TRACE_STEP 49 +#define FUNC_EVENT_TRACE_STEP_IN 50 +#define FUNC_EVENT_TRACE_STEP_OUT 51 +#define FUNC_EVENT_TRACE_INSTRUMENTATION_STEP 52 +#define FUNC_EVENT_TRACE_INSTRUMENTATION_STEP_IN 53 +#define FUNC_RDTSC 54 +#define FUNC_RDTSCP 55 +#define FUNC_LBR_SAVE 56 +#define FUNC_LBR_DUMP 57 +#define FUNC_LBR_PRINT 58 +#define FUNC_LBR_RESTORE 59 +#define FUNC_LBR_CHECK 60 +#define FUNC_SPINLOCK_LOCK_CUSTOM_WAIT 61 +#define FUNC_EVENT_INJECT 62 +#define FUNC_POI 63 +#define FUNC_DB 64 +#define FUNC_DD 65 +#define FUNC_DW 66 +#define FUNC_DQ 67 +#define FUNC_NEG 68 +#define FUNC_HI 69 +#define FUNC_LOW 70 +#define FUNC_NOT 71 +#define FUNC_CHECK_ADDRESS 72 +#define FUNC_DISASSEMBLE_LEN 73 +#define FUNC_DISASSEMBLE_LEN32 74 +#define FUNC_DISASSEMBLE_LEN64 75 +#define FUNC_INTERLOCKED_INCREMENT 76 +#define FUNC_INTERLOCKED_DECREMENT 77 +#define FUNC_PHYSICAL_TO_VIRTUAL 78 +#define FUNC_VIRTUAL_TO_PHYSICAL 79 +#define FUNC_POI_PA 80 +#define FUNC_HI_PA 81 +#define FUNC_LOW_PA 82 +#define FUNC_DB_PA 83 +#define FUNC_DD_PA 84 +#define FUNC_DW_PA 85 +#define FUNC_DQ_PA 86 +#define FUNC_LBR_RESTORE_BY_FILTER 87 +#define FUNC_ED 88 +#define FUNC_EB 89 +#define FUNC_EQ 90 +#define FUNC_INTERLOCKED_EXCHANGE 91 +#define FUNC_INTERLOCKED_EXCHANGE_ADD 92 +#define FUNC_EB_PA 93 +#define FUNC_ED_PA 94 +#define FUNC_EQ_PA 95 +#define FUNC_INTERLOCKED_COMPARE_EXCHANGE 96 +#define FUNC_STRLEN 97 +#define FUNC_STRCMP 98 +#define FUNC_MEMCMP 99 +#define FUNC_STRNCMP 100 +#define FUNC_WCSLEN 101 +#define FUNC_WCSCMP 102 +#define FUNC_EVENT_INJECT_ERROR_CODE 103 +#define FUNC_MEMCPY 104 +#define FUNC_MEMCPY_PA 105 +#define FUNC_WCSNCMP 106 + +static const char *const FunctionNames[] = { +"FUNC_UNDEFINED", +"FUNC_INC", +"FUNC_DEC", +"FUNC_REFERENCE", +"FUNC_OR", +"FUNC_XOR", +"FUNC_AND", +"FUNC_ASR", +"FUNC_ASL", +"FUNC_ADD", +"FUNC_SUB", +"FUNC_MUL", +"FUNC_DIV", +"FUNC_MOD", +"FUNC_GT", +"FUNC_LT", +"FUNC_EGT", +"FUNC_ELT", +"FUNC_EQUAL", +"FUNC_NEQ", +"FUNC_JMP", +"FUNC_JZ", +"FUNC_JNZ", +"FUNC_MOV", +"FUNC_START_OF_DO_WHILE", +"FUNC_START_OF_DO_WHILE_COMMANDS", +"FUNC_END_OF_DO_WHILE", +"FUNC_START_OF_FOR", +"FUNC_FOR_INC_DEC", +"FUNC_START_OF_FOR_OMMANDS", +"FUNC_END_OF_IF", +"FUNC_IGNORE_LVALUE", +"FUNC_PUSH", +"FUNC_POP", +"FUNC_CALL", +"FUNC_RET", +"FUNC_PRINT", +"FUNC_FORMATS", +"FUNC_EVENT_ENABLE", +"FUNC_EVENT_DISABLE", +"FUNC_EVENT_CLEAR", +"FUNC_TEST_STATEMENT", +"FUNC_SPINLOCK_LOCK", +"FUNC_SPINLOCK_UNLOCK", +"FUNC_EVENT_SC", +"FUNC_MICROSLEEP", +"FUNC_PRINTF", +"FUNC_PAUSE", +"FUNC_FLUSH", +"FUNC_EVENT_TRACE_STEP", +"FUNC_EVENT_TRACE_STEP_IN", +"FUNC_EVENT_TRACE_STEP_OUT", +"FUNC_EVENT_TRACE_INSTRUMENTATION_STEP", +"FUNC_EVENT_TRACE_INSTRUMENTATION_STEP_IN", +"FUNC_RDTSC", +"FUNC_RDTSCP", +"FUNC_LBR_SAVE", +"FUNC_LBR_DUMP", +"FUNC_LBR_PRINT", +"FUNC_LBR_RESTORE", +"FUNC_LBR_CHECK", +"FUNC_SPINLOCK_LOCK_CUSTOM_WAIT", +"FUNC_EVENT_INJECT", +"FUNC_POI", +"FUNC_DB", +"FUNC_DD", +"FUNC_DW", +"FUNC_DQ", +"FUNC_NEG", +"FUNC_HI", +"FUNC_LOW", +"FUNC_NOT", +"FUNC_CHECK_ADDRESS", +"FUNC_DISASSEMBLE_LEN", +"FUNC_DISASSEMBLE_LEN32", +"FUNC_DISASSEMBLE_LEN64", +"FUNC_INTERLOCKED_INCREMENT", +"FUNC_INTERLOCKED_DECREMENT", +"FUNC_PHYSICAL_TO_VIRTUAL", +"FUNC_VIRTUAL_TO_PHYSICAL", +"FUNC_POI_PA", +"FUNC_HI_PA", +"FUNC_LOW_PA", +"FUNC_DB_PA", +"FUNC_DD_PA", +"FUNC_DW_PA", +"FUNC_DQ_PA", +"FUNC_LBR_RESTORE_BY_FILTER", +"FUNC_ED", +"FUNC_EB", +"FUNC_EQ", +"FUNC_INTERLOCKED_EXCHANGE", +"FUNC_INTERLOCKED_EXCHANGE_ADD", +"FUNC_EB_PA", +"FUNC_ED_PA", +"FUNC_EQ_PA", +"FUNC_INTERLOCKED_COMPARE_EXCHANGE", +"FUNC_STRLEN", +"FUNC_STRCMP", +"FUNC_MEMCMP", +"FUNC_STRNCMP", +"FUNC_WCSLEN", +"FUNC_WCSCMP", +"FUNC_EVENT_INJECT_ERROR_CODE", +"FUNC_MEMCPY", +"FUNC_MEMCPY_PA", +"FUNC_WCSNCMP", +}; + +typedef enum REGS_ENUM { + REGISTER_RAX = 0, + REGISTER_EAX = 1, + REGISTER_AX = 2, + REGISTER_AH = 3, + REGISTER_AL = 4, + REGISTER_RCX = 5, + REGISTER_ECX = 6, + REGISTER_CX = 7, + REGISTER_CH = 8, + REGISTER_CL = 9, + REGISTER_RDX = 10, + REGISTER_EDX = 11, + REGISTER_DX = 12, + REGISTER_DH = 13, + REGISTER_DL = 14, + REGISTER_RBX = 15, + REGISTER_EBX = 16, + REGISTER_BX = 17, + REGISTER_BH = 18, + REGISTER_BL = 19, + REGISTER_RSP = 20, + REGISTER_ESP = 21, + REGISTER_SP = 22, + REGISTER_SPL = 23, + REGISTER_RBP = 24, + REGISTER_EBP = 25, + REGISTER_BP = 26, + REGISTER_BPL = 27, + REGISTER_RSI = 28, + REGISTER_ESI = 29, + REGISTER_SI = 30, + REGISTER_SIL = 31, + REGISTER_RDI = 32, + REGISTER_EDI = 33, + REGISTER_DI = 34, + REGISTER_DIL = 35, + REGISTER_R8 = 36, + REGISTER_R8D = 37, + REGISTER_R8W = 38, + REGISTER_R8H = 39, + REGISTER_R8L = 40, + REGISTER_R9 = 41, + REGISTER_R9D = 42, + REGISTER_R9W = 43, + REGISTER_R9H = 44, + REGISTER_R9L = 45, + REGISTER_R10 = 46, + REGISTER_R10D = 47, + REGISTER_R10W = 48, + REGISTER_R10H = 49, + REGISTER_R10L = 50, + REGISTER_R11 = 51, + REGISTER_R11D = 52, + REGISTER_R11W = 53, + REGISTER_R11H = 54, + REGISTER_R11L = 55, + REGISTER_R12 = 56, + REGISTER_R12D = 57, + REGISTER_R12W = 58, + REGISTER_R12H = 59, + REGISTER_R12L = 60, + REGISTER_R13 = 61, + REGISTER_R13D = 62, + REGISTER_R13W = 63, + REGISTER_R13H = 64, + REGISTER_R13L = 65, + REGISTER_R14 = 66, + REGISTER_R14D = 67, + REGISTER_R14W = 68, + REGISTER_R14H = 69, + REGISTER_R14L = 70, + REGISTER_R15 = 71, + REGISTER_R15D = 72, + REGISTER_R15W = 73, + REGISTER_R15H = 74, + REGISTER_R15L = 75, + REGISTER_DS = 76, + REGISTER_ES = 77, + REGISTER_FS = 78, + REGISTER_GS = 79, + REGISTER_CS = 80, + REGISTER_SS = 81, + REGISTER_RFLAGS = 82, + REGISTER_EFLAGS = 83, + REGISTER_FLAGS = 84, + REGISTER_CF = 85, + REGISTER_PF = 86, + REGISTER_AF = 87, + REGISTER_ZF = 88, + REGISTER_SF = 89, + REGISTER_TF = 90, + REGISTER_IF = 91, + REGISTER_DF = 92, + REGISTER_OF = 93, + REGISTER_IOPL = 94, + REGISTER_NT = 95, + REGISTER_RF = 96, + REGISTER_VM = 97, + REGISTER_AC = 98, + REGISTER_VIF = 99, + REGISTER_VIP = 100, + REGISTER_ID = 101, + REGISTER_RIP = 102, + REGISTER_EIP = 103, + REGISTER_IP = 104, + REGISTER_IDTR = 105, + REGISTER_LDTR = 106, + REGISTER_GDTR = 107, + REGISTER_TR = 108, + REGISTER_CR0 = 109, + REGISTER_CR2 = 110, + REGISTER_CR3 = 111, + REGISTER_CR4 = 112, + REGISTER_CR8 = 113, + REGISTER_DR0 = 114, + REGISTER_DR1 = 115, + REGISTER_DR2 = 116, + REGISTER_DR3 = 117, + REGISTER_DR6 = 118, + REGISTER_DR7 = 119 + +} REGS_ENUM; + +static const char *const RegistersNames[] = { +"rax", "eax", "ax", "ah", "al", "rcx", "ecx", "cx", +"ch", "cl", "rdx", "edx", "dx", "dh", "dl", "rbx", +"ebx", "bx", "bh", "bl", "rsp", "esp", "sp", "spl", +"rbp", "ebp", "bp", "bpl", "rsi", "esi", "si", "sil", +"rdi", "edi", "di", "dil", "r8", "r8d", "r8w", "r8h", +"r8l", "r9", "r9d", "r9w", "r9h", "r9l", "r10", "r10d", +"r10w", "r10h", "r10l", "r11", "r11d", "r11w", "r11h", "r11l", +"r12", "r12d", "r12w", "r12h", "r12l", "r13", "r13d", "r13w", +"r13h", "r13l", "r14", "r14d", "r14w", "r14h", "r14l", "r15", +"r15d", "r15w", "r15h", "r15l", "ds", "es", "fs", "gs", +"cs", "ss", "rflags", "eflags", "flags", "cf", "pf", "af", +"zf", "sf", "tf", "if", "df", "of", "iopl", "nt", +"rf", "vm", "ac", "vif", "vip", "id", "rip", "eip", +"ip", "idtr", "ldtr", "gdtr", "tr", "cr0", "cr2", "cr3", +"cr4", "cr8", "dr0", "dr1", "dr2", "dr3", "dr6", "dr7" +}; + +#define PSEUDO_REGISTER_PID 0 +#define PSEUDO_REGISTER_TID 1 +#define PSEUDO_REGISTER_PNAME 2 +#define PSEUDO_REGISTER_CORE 3 +#define PSEUDO_REGISTER_PROC 4 +#define PSEUDO_REGISTER_THREAD 5 +#define PSEUDO_REGISTER_PEB 6 +#define PSEUDO_REGISTER_TEB 7 +#define PSEUDO_REGISTER_IP 8 +#define PSEUDO_REGISTER_BUFFER 9 +#define PSEUDO_REGISTER_CONTEXT 10 +#define PSEUDO_REGISTER_EVENT_TAG 11 +#define PSEUDO_REGISTER_EVENT_ID 12 +#define PSEUDO_REGISTER_EVENT_STAGE 13 +#define PSEUDO_REGISTER_DATE 14 +#define PSEUDO_REGISTER_TIME 15 + +#endif diff --git a/hyperdbg/include/SDK/Headers/Symbols.h b/hyperdbg/include/SDK/headers/Symbols.h similarity index 89% rename from hyperdbg/include/SDK/Headers/Symbols.h rename to hyperdbg/include/SDK/headers/Symbols.h index c67f3c45..960b5e78 100644 --- a/hyperdbg/include/SDK/Headers/Symbols.h +++ b/hyperdbg/include/SDK/headers/Symbols.h @@ -39,7 +39,7 @@ typedef struct _USERMODE_LOADED_MODULE_SYMBOLS { UINT64 BaseAddress; UINT64 Entrypoint; - wchar_t FilePath[MAX_PATH]; + WCHAR FilePath[MAX_PATH]; } USERMODE_LOADED_MODULE_SYMBOLS, *PUSERMODE_LOADED_MODULE_SYMBOLS; @@ -57,6 +57,8 @@ typedef struct _USERMODE_LOADED_MODULE_DETAILS } USERMODE_LOADED_MODULE_DETAILS, *PUSERMODE_LOADED_MODULE_DETAILS; +#define SIZEOF_USERMODE_LOADED_MODULE_DETAILS sizeof(USERMODE_LOADED_MODULE_DETAILS) + /** * @brief Callback type that should be used to add * list of Addresses to ObjectNames @@ -77,13 +79,6 @@ typedef struct _DEBUGGER_UPDATE_SYMBOL_TABLE } DEBUGGER_UPDATE_SYMBOL_TABLE, *PDEBUGGER_UPDATE_SYMBOL_TABLE; -/** - * @brief check so the DEBUGGER_UPDATE_SYMBOL_TABLE should be smaller than packet size - * - */ -static_assert(sizeof(DEBUGGER_UPDATE_SYMBOL_TABLE) < PacketChunkSize, - "err (static_assert), size of PacketChunkSize should be bigger than DEBUGGER_UPDATE_SYMBOL_TABLE (MODULE_SYMBOL_DETAIL)"); - /* ============================================================================================== */ diff --git a/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperEvade.h b/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperEvade.h new file mode 100644 index 00000000..168167fb --- /dev/null +++ b/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperEvade.h @@ -0,0 +1,59 @@ +/** + * @file HyperDbgHyperEvade.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers relating exported functions from hyperevade (transparency) module + * @version 0.14 + * @date 2025-06-07 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#ifdef HYPERDBG_HYPEREVADE +# define IMPORT_EXPORT_HYPEREVADE __declspec(dllexport) +#else +# define IMPORT_EXPORT_HYPEREVADE __declspec(dllimport) +#endif + +////////////////////////////////////////////////// +// hyperevade functions // +////////////////////////////////////////////////// + +// +// Initializing and uninitializing routines +// +IMPORT_EXPORT_HYPEREVADE BOOLEAN +TransparentHideDebugger(HYPEREVADE_CALLBACKS * HyperevadeCallbacks, + DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE * TransparentModeRequest); + +IMPORT_EXPORT_HYPEREVADE BOOLEAN +TransparentUnhideDebugger(); + +// +// VMX footprint routines +// +IMPORT_EXPORT_HYPEREVADE VOID +TransparentCheckAndModifyCpuid(PGUEST_REGS Regs, INT32 CpuInfo[]); + +IMPORT_EXPORT_HYPEREVADE VOID +TransparentCheckAndTrapFlagAfterVmexit(); + +IMPORT_EXPORT_HYPEREVADE BOOLEAN +TransparentCheckAndModifyMsrRead(PGUEST_REGS Regs, UINT32 TargetMsr); + +IMPORT_EXPORT_HYPEREVADE BOOLEAN +TransparentCheckAndModifyMsrWrite(PGUEST_REGS Regs, UINT32 TargetMsr); + +// +// Syscall footprint routines +// +IMPORT_EXPORT_HYPEREVADE VOID +TransparentHandleSystemCallHook(GUEST_REGS * Regs); + +IMPORT_EXPORT_HYPEREVADE VOID +TransparentCallbackHandleAfterSyscall(GUEST_REGS * Regs, + UINT32 ProcessId, + UINT32 ThreadId, + UINT64 Context, + SYSCALL_CALLBACK_CONTEXT_PARAMS * Params); diff --git a/hyperdbg/include/SDK/Imports/HyperDbgHyperLogImports.h b/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperLogImports.h similarity index 86% rename from hyperdbg/include/SDK/Imports/HyperDbgHyperLogImports.h rename to hyperdbg/include/SDK/imports/kernel/HyperDbgHyperLogImports.h index ca9741c6..f3a388a3 100644 --- a/hyperdbg/include/SDK/Imports/HyperDbgHyperLogImports.h +++ b/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperLogImports.h @@ -34,7 +34,7 @@ LogCallbackPrepareAndSendMessageToQueue(UINT32 OperationCode, BOOLEAN IsImmediateMessage, BOOLEAN ShowCurrentSystemTime, BOOLEAN Priority, - const char * Fmt, + const CHAR * Fmt, ...); IMPORT_EXPORT_HYPERLOG BOOLEAN @@ -42,7 +42,7 @@ LogCallbackPrepareAndSendMessageToQueueWrapper(UINT32 OperationCode, BOOLEAN IsImmediateMessage, BOOLEAN ShowCurrentSystemTime, BOOLEAN Priority, - const char * Fmt, + const CHAR * Fmt, va_list ArgList); IMPORT_EXPORT_HYPERLOG BOOLEAN @@ -57,8 +57,8 @@ LogCallbackCheckIfBufferIsFull(BOOLEAN Priority); IMPORT_EXPORT_HYPERLOG BOOLEAN LogCallbackSendMessageToQueue(UINT32 OperationCode, BOOLEAN IsImmediateMessage, CHAR * LogMessage, UINT32 BufferLen, BOOLEAN Priority); -IMPORT_EXPORT_HYPERLOG NTSTATUS -LogRegisterEventBasedNotification(PDEVICE_OBJECT DeviceObject, PIRP Irp); +IMPORT_EXPORT_HYPERLOG BOOLEAN +LogRegisterEventBasedNotification(PVOID TargetIrp); -IMPORT_EXPORT_HYPERLOG NTSTATUS -LogRegisterIrpBasedNotification(PDEVICE_OBJECT DeviceObject, PIRP Irp); +IMPORT_EXPORT_HYPERLOG BOOLEAN +LogRegisterIrpBasedNotification(PVOID TargetIrp, LONG * Status); diff --git a/hyperdbg/include/SDK/Imports/HyperDbgHyperLogIntrinsics.h b/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h similarity index 92% rename from hyperdbg/include/SDK/Imports/HyperDbgHyperLogIntrinsics.h rename to hyperdbg/include/SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h index 0605fefc..837fb661 100644 --- a/hyperdbg/include/SDK/Imports/HyperDbgHyperLogIntrinsics.h +++ b/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h @@ -40,19 +40,19 @@ typedef enum _LOG_TYPE DbgPrint("[+] Information (%s:%d) | " format "\n", \ __func__, \ __LINE__, \ - __VA_ARGS__) + ##__VA_ARGS__) # define LogWarning(format, ...) \ DbgPrint("[-] Warning (%s:%d) | " format "\n", \ __func__, \ __LINE__, \ - __VA_ARGS__) + ##__VA_ARGS__) # define LogError(format, ...) \ DbgPrint("[!] Error (%s:%d) | " format "\n", \ __func__, \ __LINE__, \ - __VA_ARGS__); \ + ##__VA_ARGS__); \ DbgBreakPoint() /** @@ -60,7 +60,7 @@ typedef enum _LOG_TYPE * */ # define Log(format, ...) \ - DbgPrint(format, __VA_ARGS__) + DbgPrint(format, ##__VA_ARGS__) #else @@ -76,7 +76,7 @@ typedef enum _LOG_TYPE "[+] Information (%s:%d) | " format "\n", \ __func__, \ __LINE__, \ - __VA_ARGS__) + ##__VA_ARGS__) /** * @brief Log in the case of priority message @@ -90,7 +90,7 @@ typedef enum _LOG_TYPE "[+] Information (%s:%d) | " format "\n", \ __func__, \ __LINE__, \ - __VA_ARGS__) + ##__VA_ARGS__) /** * @brief Log in the case of warning @@ -104,7 +104,7 @@ typedef enum _LOG_TYPE "[-] Warning (%s:%d) | " format "\n", \ __func__, \ __LINE__, \ - __VA_ARGS__) + ##__VA_ARGS__) /** * @brief Log in the case of error @@ -118,7 +118,7 @@ typedef enum _LOG_TYPE "[!] Error (%s:%d) | " format "\n", \ __func__, \ __LINE__, \ - __VA_ARGS__); \ + ##__VA_ARGS__); \ if (DebugMode) \ DbgBreakPoint() @@ -132,7 +132,7 @@ typedef enum _LOG_TYPE FALSE, \ FALSE, \ format, \ - __VA_ARGS__) + ##__VA_ARGS__) /** * @brief Log without any prefix and bypass the stack @@ -161,4 +161,4 @@ typedef enum _LOG_TYPE "[+] Information (%s:%d) | " format "\n", \ __func__, \ __LINE__, \ - __VA_ARGS__) + ##__VA_ARGS__) diff --git a/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperPerf.h b/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperPerf.h new file mode 100644 index 00000000..f6997795 --- /dev/null +++ b/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperPerf.h @@ -0,0 +1,33 @@ +/** + * @file HyperDbgHyperPerf.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers relating exported functions from hyperperf (pmu) module + * @version 0.21 + * @date 2026-06-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#ifdef HYPERDBG_HYPERPERF +# define IMPORT_EXPORT_HYPERPERF __declspec(dllexport) +#else +# define IMPORT_EXPORT_HYPERPERF __declspec(dllimport) +#endif + +////////////////////////////////////////////////// +// HyperPerf Functions // +////////////////////////////////////////////////// + +// +// Initialize the hyperperf module with the provided callbacks +// +IMPORT_EXPORT_HYPERPERF BOOLEAN +HyperPerfInitCallback(HYPERPERF_CALLBACKS * HyperPerfCallbacks, BOOLEAN RunningOnHypervisorEnvironment); + +// +// Uninitialize the HyperPerf module +// +IMPORT_EXPORT_HYPERPERF VOID +HyperPerfUninit(); diff --git a/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperTrace.h b/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperTrace.h new file mode 100644 index 00000000..5da661de --- /dev/null +++ b/hyperdbg/include/SDK/imports/kernel/HyperDbgHyperTrace.h @@ -0,0 +1,114 @@ +/** + * @file HyperDbgHyperTrace.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers relating exported functions from hypertrace (tracing) module + * @version 0.18 + * @date 2026-02-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#ifdef HYPERDBG_HYPERTRACE +# define IMPORT_EXPORT_HYPERTRACE __declspec(dllexport) +#else +# define IMPORT_EXPORT_HYPERTRACE __declspec(dllimport) +#endif + +////////////////////////////////////////////////// +// HyperTrace Functions // +////////////////////////////////////////////////// + +// +// Initialize the hypertrace module with the provided callbacks +// +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceInitCallback(HYPERTRACE_CALLBACKS * HyperTraceCallbacks, BOOLEAN RunningOnHypervisorEnvironment); + +// +// Uninitialize the HyperTrace module +// +IMPORT_EXPORT_HYPERTRACE VOID +HyperTraceUninit(); + +////////////////////////////////////////////////// +// LBR Functions // +////////////////////////////////////////////////// + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceLbrIsSupported(UINT32 * Capacity, BOOLEAN * IsArchLbr); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceLbrCheck(); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceLbrRestore(); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceLbrRestoreByFilter(UINT64 FilterOptions); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceLbrSave(HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceOperationRequest); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceLbrPrint(HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceOperationRequest); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceLbrFlush(HYPERTRACE_LBR_OPERATION_PACKETS * HyperTraceOperationRequest); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceLbrQueryStateOfLbrSaveAndLoadVmExitAndEntryControls(UINT32 CoreId); + +// +// Perform operations related to HyperTrace LBR dumping +// +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceLbrPerformDump(HYPERTRACE_LBR_DUMP_PACKETS * LbrDumpRequest); + +// +// Perform operations related to HyperTrace LBR based on the request type and parameters +// +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTraceLbrPerformOperation(HYPERTRACE_LBR_OPERATION_PACKETS * LbrOperationRequest); + +////////////////////////////////////////////////// +// PT Functions // +////////////////////////////////////////////////// + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTracePtEnable(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTracePtDisable(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTracePtPause(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTracePtResume(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTracePtSize(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTracePtDump(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTracePtFlush(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest); + +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTracePtFilter(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest); + +// +// Perform operations related to HyperTrace PT based on the request type and parameters +// +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTracePtPerformOperation(HYPERTRACE_PT_OPERATION_PACKETS * PtOperationRequest); + +// +// Map every per-CPU PT main output + overflow buffer into the calling +// user process. See HYPERTRACE_PT_MMAP_PACKETS for the lifetime contract. +// +IMPORT_EXPORT_HYPERTRACE BOOLEAN +HyperTracePtMmap(HYPERTRACE_PT_MMAP_PACKETS * Req); diff --git a/hyperdbg/include/SDK/Imports/HyperDbgVmmImports.h b/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h similarity index 83% rename from hyperdbg/include/SDK/Imports/HyperDbgVmmImports.h rename to hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h index e15b633c..c64991a3 100644 --- a/hyperdbg/include/SDK/Imports/HyperDbgVmmImports.h +++ b/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h @@ -21,10 +21,10 @@ ////////////////////////////////////////////////// IMPORT_EXPORT_VMM 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); IMPORT_EXPORT_VMM VOID VmFuncPerformRipIncrement(UINT32 CoreId); @@ -45,16 +45,22 @@ IMPORT_EXPORT_VMM VOID VmFuncSetRflagTrapFlag(BOOLEAN Set); IMPORT_EXPORT_VMM VOID -VmFuncRegisterMtfBreak(UINT32 CoreId); +VmFuncSetInstrumentationStepInState(UINT32 CoreId); IMPORT_EXPORT_VMM VOID -VmFuncUnRegisterMtfBreak(UINT32 CoreId); +VmFuncUnsetInstrumentationStepInState(UINT32 CoreId); IMPORT_EXPORT_VMM VOID -VmFuncSetLoadDebugControls(BOOLEAN Set); +VmFuncSetLoadDebugControls(UINT32 CoreId, BOOLEAN Set); IMPORT_EXPORT_VMM VOID -VmFuncSetSaveDebugControls(BOOLEAN Set); +VmFuncSetLoadGuestIa32LbrCtl(UINT32 CoreId, BOOLEAN Set); + +IMPORT_EXPORT_VMM VOID +VmFuncSetSaveDebugControls(UINT32 CoreId, BOOLEAN Set); + +IMPORT_EXPORT_VMM VOID +VmFuncSetClearGuestIa32LbrCtl(UINT32 CoreId, BOOLEAN Set); IMPORT_EXPORT_VMM VOID VmFuncSetPmcVmexit(BOOLEAN Set); @@ -101,12 +107,48 @@ VmFuncSetRflags(UINT64 Rflags); IMPORT_EXPORT_VMM VOID VmFuncSetRip(UINT64 Rip); +IMPORT_EXPORT_VMM VOID +VmFuncSetDebugReg7(UINT64 Value); + +IMPORT_EXPORT_VMM VOID +VmFuncSetDebugctl(UINT64 Value); + +IMPORT_EXPORT_VMM VOID +VmFuncSetDebugctlVmcallOnTargetCore(UINT64 Value); + +IMPORT_EXPORT_VMM VOID +VmFuncSetGuestIa32LbrCtl(UINT64 Value); + +IMPORT_EXPORT_VMM VOID +VmFuncSetGuestIa32LbrCtlVmcallOnTargetCore(UINT64 Value); + +IMPORT_EXPORT_VMM VOID +VmFuncSetLbrSelect(UINT64 FilterOptions); + +IMPORT_EXPORT_VMM VOID +VmFuncSetLbrSelectVmcallOnTargetCore(UINT64 FilterOptions); + +IMPORT_EXPORT_VMM VOID +VmFuncSetLoadDebugControlsVmcallOnTargetCore(BOOLEAN Set); + +IMPORT_EXPORT_VMM VOID +VmFuncSetLoadGuestIa32LbrCtlVmcallOnTargetCore(BOOLEAN Set); + +IMPORT_EXPORT_VMM VOID +VmFuncSetSaveDebugControlsVmcallOnTargetCore(BOOLEAN Set); + +IMPORT_EXPORT_VMM VOID +VmFuncSetClearGuestIa32LbrCtlVmcallOnTargetCore(BOOLEAN Set); + IMPORT_EXPORT_VMM VOID VmFuncSetTriggerEventForVmcalls(BOOLEAN Set); IMPORT_EXPORT_VMM VOID VmFuncSetTriggerEventForCpuids(BOOLEAN Set); +IMPORT_EXPORT_VMM VOID +VmFuncSetTriggerEventForXsetbvs(BOOLEAN Set); + IMPORT_EXPORT_VMM VOID VmFuncSetInterruptibilityState(UINT64 InterruptibilityState); @@ -155,6 +197,14 @@ VmFuncEnableMtfAndChangeExternalInterruptState(UINT32 CoreId); IMPORT_EXPORT_VMM VOID VmFuncEnableAndCheckForPreviousExternalInterrupts(UINT32 CoreId); +IMPORT_EXPORT_VMM VOID +VmFuncIdtQueryEntries(PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtQueryRequest, + BOOLEAN ReadFromVmxRoot); + +IMPORT_EXPORT_VMM BOOLEAN +VmFuncSmmPerformSmiOperation(SMI_OPERATION_PACKETS * SmiOperationRequest, + BOOLEAN ApplyFromVmxRootMode); + IMPORT_EXPORT_VMM UINT16 VmFuncGetCsSelector(); @@ -170,6 +220,18 @@ VmFuncGetRflags(); IMPORT_EXPORT_VMM UINT64 VmFuncGetRip(); +IMPORT_EXPORT_VMM UINT64 +VmFuncGetDebugctl(); + +IMPORT_EXPORT_VMM UINT64 +VmFuncGetDebugctlVmcallOnTargetCore(); + +IMPORT_EXPORT_VMM UINT64 +VmFuncGetGuestIa32LbrCtl(); + +IMPORT_EXPORT_VMM UINT64 +VmFuncGetGuestIa32LbrCtlVmcallOnTargetCore(); + IMPORT_EXPORT_VMM UINT64 VmFuncGetInterruptibilityState(); @@ -183,7 +245,10 @@ IMPORT_EXPORT_VMM UINT32 VmFuncVmxCompatibleStrlen(const CHAR * s); IMPORT_EXPORT_VMM UINT32 -VmFuncVmxCompatibleWcslen(const wchar_t * s); +VmFuncVmxCompatibleWcslen(const WCHAR * s); + +IMPORT_EXPORT_VMM VOID +VmFuncVmxCompatibleMicroSleep(UINT64 us); IMPORT_EXPORT_VMM BOOLEAN VmFuncNmiBroadcastRequest(UINT32 CoreId); @@ -200,14 +265,35 @@ VmFuncVmxGetCurrentExecutionMode(); IMPORT_EXPORT_VMM BOOLEAN VmFuncQueryModeExecTrap(); +IMPORT_EXPORT_VMM BOOLEAN +VmFuncCheckCpuSupportForSaveAndLoadDebugControls(); + +IMPORT_EXPORT_VMM BOOLEAN +VmFuncQueryInstrumentationStepInState(UINT32 CoreId); + +IMPORT_EXPORT_VMM BOOLEAN +VmFuncCheckCpuSupportForLoadAndClearGuestIa32LbrCtlControls(); + IMPORT_EXPORT_VMM INT32 VmFuncVmxCompatibleStrcmp(const CHAR * Address1, const CHAR * Address2); IMPORT_EXPORT_VMM INT32 -VmFuncVmxCompatibleWcscmp(const wchar_t * Address1, const wchar_t * Address2); +VmFuncVmxCompatibleStrncmp(const CHAR * Address1, const CHAR * Address2, SIZE_T Num); IMPORT_EXPORT_VMM INT32 -VmFuncVmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count); +VmFuncVmxCompatibleWcscmp(const WCHAR * Address1, const WCHAR * Address2); + +IMPORT_EXPORT_VMM INT32 +VmFuncVmxCompatibleWcsncmp(const WCHAR * Address1, const WCHAR * Address2, SIZE_T Num); + +IMPORT_EXPORT_VMM INT32 +VmFuncVmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, SIZE_T Count); + +IMPORT_EXPORT_VMM BOOLEAN +VmFuncApicStoreLocalApicFields(PLAPIC_PAGE LocalApicBuffer, PBOOLEAN IsUsingX2APIC); + +IMPORT_EXPORT_VMM BOOLEAN +VmFuncApicStoreIoApicFields(IO_APIC_ENTRY_PACKETS * IoApicPackets); ////////////////////////////////////////////////// // Configuration Functions // @@ -270,6 +356,9 @@ ConfigureModeBasedExecHookUninitializeOnAllProcessors(); IMPORT_EXPORT_VMM VOID ConfigureUninitializeExecTrapOnAllProcessors(); +IMPORT_EXPORT_VMM VOID +ConfigureExecTrapApplyMbecConfiguratinFromKernelSide(UINT32 CoreId); + IMPORT_EXPORT_VMM BOOLEAN ConfigureInitializeExecTrapOnAllProcessors(); @@ -314,6 +403,13 @@ ConfigureEptHookModifyPageWriteState(UINT32 CoreId, PVOID PhysicalAddress, BOOLEAN IsUnset); +IMPORT_EXPORT_VMM BOOLEAN +ConfigureEptHookUnHookAllByHookingTag(UINT64 HookingTag); + +IMPORT_EXPORT_VMM BOOLEAN +ConfigureEptHookUnHookSingleHookByHookingTagFromVmxRoot(UINT64 HookingTag, + EPT_SINGLE_HOOK_UNHOOKING_DETAILS * TargetUnhookingDetails); + IMPORT_EXPORT_VMM BOOLEAN ConfigureEptHookUnHookSingleAddress(UINT64 VirtualAddress, UINT64 PhysAddress, @@ -495,6 +591,9 @@ CheckAddressValidityUsingTsx(CHAR * Address); IMPORT_EXPORT_VMM BOOLEAN CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size); +IMPORT_EXPORT_VMM BOOLEAN +CheckAccessValidityAndSafetyByProcessId(UINT64 TargetAddress, UINT32 Size, UINT32 ProcessId); + IMPORT_EXPORT_VMM BOOLEAN CheckAddressPhysical(UINT64 PAddr); @@ -507,6 +606,9 @@ CheckAddressMaximumInstructionLength(PVOID Address); IMPORT_EXPORT_VMM CR3_TYPE LayoutGetCurrentProcessCr3(); +IMPORT_EXPORT_VMM CR3_TYPE +LayoutGetCr3ByProcessId(UINT32 ProcessId); + IMPORT_EXPORT_VMM CR3_TYPE LayoutGetExactGuestProcessCr3(); @@ -514,18 +616,6 @@ LayoutGetExactGuestProcessCr3(); // Memory Management Functions // ////////////////////////////////////////////////// -// ---------------------------------------------------------------------------- -// Cross Platform Memory Allocate/Free Functions -// -IMPORT_EXPORT_VMM PVOID -CrsAllocateNonPagedPool(SIZE_T NumberOfBytes); - -IMPORT_EXPORT_VMM PVOID -CrsAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes); - -IMPORT_EXPORT_VMM VOID -CrsFreePool(PVOID BufferAddress); - // ---------------------------------------------------------------------------- // PTE-related Functions // @@ -574,6 +664,17 @@ MemoryMapperReadMemorySafeOnTargetProcess(_In_ UINT64 VaAddressToRead, _Inout_ PVOID BufferToSaveMemory, _In_ SIZE_T SizeToRead); +IMPORT_EXPORT_VMM BOOLEAN +MemoryMapperReadMemorySafeFromVmxNonRootByPhysicalAddress(_In_ UINT64 PaAddressToRead, + _Inout_ PVOID BufferToSaveMemory, + _In_ SIZE_T SizeToRead); + +IMPORT_EXPORT_VMM BOOLEAN +MemoryMapperReadMemoryUnsafe(_In_ UINT64 VaAddressToRead, + _Inout_ PVOID BufferToSaveMemory, + _In_ SIZE_T SizeToRead, + _In_ UINT32 TargetProcessId); + // ---------------------------------------------------------------------------- // Disassembler Functions // @@ -583,6 +684,9 @@ DisassemblerLengthDisassembleEngine(PVOID Address, BOOLEAN Is32Bit); IMPORT_EXPORT_VMM UINT32 DisassemblerLengthDisassembleEngineInVmxRootOnTargetProcess(PVOID Address, BOOLEAN Is32Bit); +IMPORT_EXPORT_VMM UINT32 +DisassemblerLengthDisassembleEngineByProcessId(PVOID Address, BOOLEAN Is32Bit, UINT32 ProcessId); + // ---------------------------------------------------------------------------- // Writing Memory Functions // @@ -608,6 +712,11 @@ MemoryMapperWriteMemoryUnsafe(_Inout_ UINT64 Destination, _In_ SIZE_T SizeToWrite, _In_ UINT32 TargetProcessId); +IMPORT_EXPORT_VMM BOOLEAN +MemoryMapperWriteMemorySafeFromVmxNonRootyPhysicalAddress(_In_ UINT64 DestinationPa, + _In_ PVOID Source, + _In_ SIZE_T SizeToWrite); + // ---------------------------------------------------------------------------- // Reserving Memory Functions // @@ -641,24 +750,14 @@ MemoryMapperCheckIfPdeIsLargePageOnTargetProcess(_In_ PVOID Va); IMPORT_EXPORT_VMM BOOLEAN MemoryManagerReadProcessMemoryNormal(HANDLE PID, PVOID Address, DEBUGGER_READ_MEMORY_TYPE MemType, PVOID UserBuffer, SIZE_T Size, PSIZE_T ReturnSize); -////////////////////////////////////////////////// -// Pool Manager // -////////////////////////////////////////////////// +IMPORT_EXPORT_VMM BOOLEAN +MemoryManagerWritePhysicalMemoryNormal(PVOID TargetAddress, PVOID UserBuffer, SIZE_T Size); IMPORT_EXPORT_VMM BOOLEAN -PoolManagerCheckAndPerformAllocationAndDeallocation(); +ReadPhysicalMemoryUsingMapIoSpace(PVOID PhysicalAddress, PVOID Buffer, SIZE_T BufferSize); IMPORT_EXPORT_VMM BOOLEAN -PoolManagerRequestAllocation(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention); - -IMPORT_EXPORT_VMM UINT64 -PoolManagerRequestPool(POOL_ALLOCATION_INTENTION Intention, BOOLEAN RequestNewPool, UINT32 Size); - -IMPORT_EXPORT_VMM BOOLEAN -PoolManagerFreePool(UINT64 AddressToFree); - -IMPORT_EXPORT_VMM VOID -PoolManagerShowPreAllocatedPools(); +WritePhysicalMemoryUsingMapIoSpace(PVOID PhysicalAddress, PVOID Buffer, SIZE_T BufferSize); ////////////////////////////////////////////////// // VMX Registers Modification // @@ -830,11 +929,11 @@ SetDebugRegisters(UINT32 DebugRegNum, DEBUG_REGISTER_TYPE ActionType, BOOLEAN Ap // Transparent Mode // ////////////////////////////////////////////////// -IMPORT_EXPORT_VMM NTSTATUS -TransparentHideDebugger(PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE Measurements); +IMPORT_EXPORT_VMM BOOLEAN +TransparentHideDebuggerWrapper(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE * TransparentModeRequest); -IMPORT_EXPORT_VMM NTSTATUS -TransparentUnhideDebugger(); +IMPORT_EXPORT_VMM BOOLEAN +TransparentUnhideDebuggerWrapper(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE * TransparentModeRequest); ////////////////////////////////////////////////// // Non-internal Broadcasting Functions // @@ -929,3 +1028,13 @@ BroadcastEnableEferSyscallEventsOnAllProcessors(); IMPORT_EXPORT_VMM VOID BroadcastDisableEferSyscallEventsOnAllProcessors(); + +////////////////////////////////////////////////// +// Device-related Functions // +////////////////////////////////////////////////// + +IMPORT_EXPORT_VMM QWORD +PciReadCam(WORD Bus, WORD Device, WORD Function, BYTE Offset, UINT8 Width); + +IMPORT_EXPORT_VMM BOOLEAN +PciWriteCam(WORD Bus, WORD Device, WORD Function, BYTE Offset, UINT8 Width, QWORD Value); diff --git a/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h b/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h new file mode 100644 index 00000000..2491fca1 --- /dev/null +++ b/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h @@ -0,0 +1,369 @@ +/** + * @file HyperDbgLibImports.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @author jtaw5649 + * @brief Headers relating exported functions from controller interface + * @version 0.2 + * @date 2023-02-02 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#ifdef _WIN32 +// MSVC (Windows) +# ifdef HYPERDBG_LIBHYPERDBG +# define IMPORT_EXPORT_LIBHYPERDBG __declspec(dllexport) +# else +# define IMPORT_EXPORT_LIBHYPERDBG __declspec(dllimport) +# endif +#else +// GCC/Clang (Linux) +# ifdef HYPERDBG_LIBHYPERDBG +# define IMPORT_EXPORT_LIBHYPERDBG __attribute__((visibility("default"))) +# else +# define IMPORT_EXPORT_LIBHYPERDBG +# endif +#endif +// +// Header file of libhyperdbg +// Imports +// +#ifdef __cplusplus +extern "C" { +#endif + +// +// Support Detection +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_detect_vmx_support(); + +IMPORT_EXPORT_LIBHYPERDBG VOID +hyperdbg_u_read_vendor_string(CHAR *); + +IMPORT_EXPORT_LIBHYPERDBG GENERIC_PROCESSOR_VENDOR +hyperdbg_u_get_processor_vendor(); + +// +// All Modules +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_is_any_module_loaded(); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_load_all_modules(); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_unload_all_modules(); + +// +// VMM Module +// +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_load_vmm(); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_unload_vmm(); + +// +// KD (Kernel Debugger) Module +// +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_unload_kd(); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_install_kd_driver(); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_uninstall_kd_driver(); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_start_kd_driver(); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_stop_kd_driver(); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_load_kd_module(); + +// +// HyperTrace Module +// +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_load_hypertrace_module(); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_unload_hypertrace_module(); + +// +// Testing parser +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_test_command_parser(CHAR * command, + UINT32 number_of_tokens, + CHAR ** tokens_list, + UINT32 * failed_token_num, + UINT32 * failed_token_position); + +IMPORT_EXPORT_LIBHYPERDBG VOID +hyperdbg_u_test_command_parser_show_tokens(CHAR * command); + +// +// General imports/exports +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_setup_path_for_filename(const CHAR * filename, CHAR * file_location, UINT32 buffer_len, BOOLEAN check_file_existence); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_run_command(CHAR * command); + +IMPORT_EXPORT_LIBHYPERDBG VOID +hyperdbg_u_show_signature(); + +IMPORT_EXPORT_LIBHYPERDBG VOID +hyperdbg_u_set_text_message_callback(PVOID handler); + +IMPORT_EXPORT_LIBHYPERDBG PVOID +hyperdbg_u_set_text_message_callback_using_shared_buffer(PVOID handler); + +IMPORT_EXPORT_LIBHYPERDBG VOID +hyperdbg_u_unset_text_message_callback(); + +IMPORT_EXPORT_LIBHYPERDBG INT +hyperdbg_u_script_read_file_and_execute_commandline(INT argc, CHAR * argv[]); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_continue_previous_command(); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_check_multiline_command(CHAR * current_command, BOOLEAN reset); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_set_custom_driver_path(CHAR * driver_file_path, CHAR * driver_name); + +IMPORT_EXPORT_LIBHYPERDBG VOID +hyperdbg_u_use_default_driver_path(); + +// +// Connect to local or remote debugger +// Exported functionality of the '.connect' command +// +IMPORT_EXPORT_LIBHYPERDBG VOID +hyperdbg_u_connect_local_debugger(); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_connect_remote_debugger(const CHAR * ip, const CHAR * port); + +// +// Connect to the debugger in the Debugger Mode +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_connect_remote_debugger_using_com_port(const CHAR * port_name, DWORD baudrate, BOOLEAN pause_after_connection); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_connect_remote_debugger_using_named_pipe(const CHAR * named_pipe, BOOLEAN pause_after_connection); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_connect_current_debugger_using_com_port(const CHAR * port_name, DWORD baudrate); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_debug_close_remote_debugger(); + +// +// Miscalenous functions +// +IMPORT_EXPORT_LIBHYPERDBG UINT64 +hyperdbg_u_get_kernel_base(); + +// +// Reading memory +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_read_memory(UINT64 target_address, + DEBUGGER_READ_MEMORY_TYPE memory_type, + DEBUGGER_READ_READING_TYPE reading_Type, + UINT32 pid, + UINT32 size, + BOOLEAN get_address_mode, + DEBUGGER_READ_MEMORY_ADDRESS_MODE * address_mode, + BYTE * target_buffer_to_store, + UINT32 * return_length); + +IMPORT_EXPORT_LIBHYPERDBG VOID +hyperdbg_u_show_memory_or_disassemble(DEBUGGER_SHOW_MEMORY_STYLE style, + UINT64 address, + DEBUGGER_READ_MEMORY_TYPE memory_type, + DEBUGGER_READ_READING_TYPE reading_type, + UINT32 pid, + UINT32 size, + PDEBUGGER_DT_COMMAND_OPTIONS dt_details); + +// +// Writing memory +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_write_memory(PVOID destination_address, + DEBUGGER_EDIT_MEMORY_TYPE memory_type, + UINT32 process_id, + PVOID source_address, + UINT32 number_of_bytes); + +// +// Reading/Writing registers +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_read_all_registers(GUEST_REGS * guest_registers, GUEST_EXTRA_REGISTERS * extra_registers); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_read_target_register(REGS_ENUM register_id, UINT64 * target_register); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_write_target_register(REGS_ENUM register_id, UINT64 value); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_show_all_registers(); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_show_target_register(REGS_ENUM register_id); + +// +// Continue debuggee +// Exported functionality of the 'g' command +// +IMPORT_EXPORT_LIBHYPERDBG VOID +hyperdbg_u_continue_debuggee(); + +// +// Pause debuggee +// Exported functionality of the 'pause' command +// +IMPORT_EXPORT_LIBHYPERDBG VOID +hyperdbg_u_pause_debuggee(); + +// +// Set breakpoint +// Exported functionality of the 'bp' command +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_set_breakpoint(UINT64 address, UINT32 pid, UINT32 tid, UINT32 core_numer); + +// +// Stepping and tracing instruction +// Exported functionality of 't', 'p', 'i', '!track', 'gu' commands +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_stepping_instrumentation_step_in(); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_stepping_regular_step_in(); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_stepping_step_over(); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_stepping_instrumentation_step_in_for_tracking(); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_stepping_step_over_for_gu(BOOLEAN last_instruction); + +// +// Start a process +// Exported functionality of the '.start' command +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_start_process(const WCHAR * path); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_start_process_with_args(const WCHAR * path, const WCHAR * arguments); + +// +// APIC related command +// Exported functionality of the '!apic', and '!ioapic' commands +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_get_local_apic(PLAPIC_PAGE local_apic, BOOLEAN * is_using_x2apic); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_get_io_apic(IO_APIC_ENTRY_PACKETS * io_apic); + +// +// IDT related command +// Exported functionality of the '!idt' command +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_get_idt_entry(INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS * idt_packet); + +// +// SMM related command +// Exported functionality of the '!smi' command +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_perform_smi_operation(SMI_OPERATION_PACKETS * SmiOperation); + +// +// LBR related command +// Exported functionality of the '!lbrdump' command +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_lbr_dump(HYPERTRACE_LBR_DUMP_PACKETS * LbrdumpRequest); + +// +// Intel PT related commands +// Exported functionality of the '!pt' command + the PT mmap surface +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_pt_operation(HYPERTRACE_PT_OPERATION_PACKETS * PtRequest); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_pt_mmap(HYPERTRACE_PT_MMAP_PACKETS * MmapRequest); + +// +// Transparent mode related command +// Exported functionality of the '!hide', and '!unhide' commands +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_enable_transparent_mode(UINT32 ProcessId, CHAR * ProcessName, BOOLEAN IsProcessId); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_enable_transparent_mode_ex(UINT32 ProcessId, CHAR * ProcessName, BOOLEAN IsProcessId, UINT32 EvadeMask); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_disable_transparent_mode(); + +// +// Assembler +// Exported functionality of the 'a' command +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_assemble_get_length(const CHAR * assembly_code, UINT64 start_address, UINT32 * length); + +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_assemble(const CHAR * assembly_code, UINT64 start_address, PVOID buffer_to_store_assembled_data, UINT32 buffer_size); + +// +// hwdbg functions +// Exported functionality of the '!hw' and '!hw_*' commands +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hwdbg_script_run_script(const CHAR * script, + const CHAR * instance_filepath_to_read, + const CHAR * hardware_script_file_path_to_save, + UINT32 initial_bram_buffer_size); + +IMPORT_EXPORT_LIBHYPERDBG VOID +hwdbg_script_engine_wrapper_test_parser(const CHAR * Expr); + +// +// Run script and evaluate expression +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_run_script(CHAR * Expr, BOOLEAN ShowErrorMessageIfAny); + +IMPORT_EXPORT_LIBHYPERDBG UINT64 +hyperdbg_u_eval_expression(CHAR * Expr, PBOOLEAN HasError); + +#ifdef __cplusplus +} +#endif diff --git a/hyperdbg/include/SDK/imports/user/HyperDbgScriptImports.h b/hyperdbg/include/SDK/imports/user/HyperDbgScriptImports.h new file mode 100644 index 00000000..1e31f6d7 --- /dev/null +++ b/hyperdbg/include/SDK/imports/user/HyperDbgScriptImports.h @@ -0,0 +1,138 @@ +/** + * @file HyperDbgScriptImports.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers relating exported functions from script engine + * @version 0.2 + * @date 2023-02-02 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#ifdef _WIN32 + // MSVC (Windows) +# ifdef HYPERDBG_SCRIPT_ENGINE +# define IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE __declspec(dllexport) +# else +# define IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE __declspec(dllimport) +# endif +#else + // GCC/Clang (Linux) +# ifdef HYPERDBG_SCRIPT_ENGINE +# define IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE __attribute__((visibility("default"))) +# else +# define IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE +# endif +#endif + +// +// Header file of script-engine +// Imports +// +#ifdef __cplusplus +extern "C" { +#endif + +// +// Hardware scripts +// +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE VOID +HardwareScriptInterpreterShowScriptCapabilities(HWDBG_INSTANCE_INFORMATION * InstanceInfo); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +HardwareScriptInterpreterCheckScriptBufferWithScriptCapabilities(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + PVOID ScriptBuffer, + UINT32 CountOfScriptSymbolChunks, + UINT32 * NumberOfStages, + UINT32 * NumberOfOperands, + UINT32 * NumberOfOperandsImplemented); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +HardwareScriptInterpreterCompressBuffer(UINT64 * Buffer, + SIZE_T BufferLength, + UINT32 ScriptVariableLength, + UINT32 BramDataWidth, + SIZE_T * NewBufferSize, + SIZE_T * NumberOfBytesPerChunk); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +HardwareScriptInterpreterConvertSymbolToHwdbgShortSymbolBuffer( + HWDBG_INSTANCE_INFORMATION * InstanceInfo, + SYMBOL * SymbolBuffer, + SIZE_T SymbolBufferLength, + UINT32 NumberOfStages, + HWDBG_SHORT_SYMBOL ** NewShortSymbolBuffer, + SIZE_T * NewBufferSize); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE VOID +HardwareScriptInterpreterFreeHwdbgShortSymbolBuffer(HWDBG_SHORT_SYMBOL * NewShortSymbolBuffer); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE PVOID +ScriptEngineParse(CHAR * Str); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +ScriptEngineSetHwdbgInstanceInfo(HWDBG_INSTANCE_INFORMATION * InstancInfo); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE VOID +PrintSymbolBuffer(const PVOID SymbolBuffer); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE VOID +RemoveSymbolBuffer(PVOID SymbolBuffer); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE VOID +PrintSymbol(PVOID Symbol); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE UINT64 +ScriptEngineConvertNameToAddress(const CHAR * FunctionOrVariableName, PBOOLEAN WasFound); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE UINT32 +ScriptEngineLoadFileSymbol(UINT64 BaseAddress, const CHAR * PdbFileName, const CHAR * CustomModuleName); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE UINT32 +ScriptEngineUnloadAllSymbols(); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE UINT32 +ScriptEngineUnloadModuleSymbol(CHAR * ModuleName); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE UINT32 +ScriptEngineSearchSymbolForMask(const CHAR * SearchMask); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +ScriptEngineGetFieldOffset(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +ScriptEngineGetDataTypeSize(CHAR * TypeName, UINT64 * TypeSize); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +ScriptEngineCreateSymbolTableForDisassembler(PVOID CallbackFunction); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +ScriptEngineConvertFileToPdbPath(const CHAR * LocalFilePath, CHAR * ResultPath, SIZE_T ResultPathSize); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetails(const CHAR * LocalFilePath, CHAR * PdbFilePath, CHAR * GuidAndAgeDetails, BOOLEAN Is32BitModule); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +ScriptEngineConvertLoadedModuleToPdbFileAndGuidAndAgeDetails(const BYTE * LoadedImageBytes, + SIZE_T LoadedImageSize, + const CHAR * LocalFilePath, + CHAR * PdbFilePath, + CHAR * GuidAndAgeDetails, + BOOLEAN Is32BitModule); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +ScriptEngineSymbolInitLoad(PVOID BufferToStoreDetails, UINT32 StoredLength, BOOLEAN DownloadIfAvailable, const CHAR * SymbolPath, BOOLEAN IsSilentLoad); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE BOOLEAN +ScriptEngineShowDataBasedOnSymbolTypes(const CHAR * TypeName, UINT64 Address, BOOLEAN IsStruct, PVOID BufferAddress, const CHAR * AdditionalParameters); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE VOID +ScriptEngineSymbolAbortLoading(); + +IMPORT_EXPORT_HYPERDBG_SCRIPT_ENGINE VOID +ScriptEngineSetTextMessageCallback(PVOID Handler); + +#ifdef __cplusplus +} +#endif diff --git a/hyperdbg/include/SDK/imports/user/HyperDbgSymImports.h b/hyperdbg/include/SDK/imports/user/HyperDbgSymImports.h new file mode 100644 index 00000000..c5059cab --- /dev/null +++ b/hyperdbg/include/SDK/imports/user/HyperDbgSymImports.h @@ -0,0 +1,111 @@ +/** + * @file HyperDbgSymImports.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers relating exported functions from symbol parser + * @version 0.2 + * @date 2023-02-02 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#ifdef _WIN32 + // MSVC (Windows) +# ifdef HYPERDBG_SYMBOL_PARSER +# define IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER __declspec(dllexport) +# else +# define IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER __declspec(dllimport) +# endif +#else + // GCC/Clang (Linux) +# ifdef HYPERDBG_SYMBOL_PARSER +# define IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER __attribute__((visibility("default"))) +# else +# define IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER +# endif +#endif + +// +// Header file of symbol-parser +// Imports +// +#ifdef __cplusplus +extern "C" { +#endif + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER VOID +SymSetTextMessageCallback(PVOID Handler); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER VOID +SymbolAbortLoading(); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER UINT64 +SymConvertNameToAddress(const CHAR * FunctionOrVariableName, PBOOLEAN WasFound); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER UINT32 +SymLoadFileSymbol(UINT64 BaseAddress, const CHAR * PdbFileName, const CHAR * CustomModuleName); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER UINT32 +SymUnloadAllSymbols(); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER UINT32 +SymUnloadModuleSymbol(CHAR * ModuleName); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER UINT32 +SymSearchSymbolForMask(const CHAR * SearchMask); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER BOOLEAN +SymGetFieldOffset(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER BOOLEAN +SymGetDataTypeSize(CHAR * TypeName, UINT64 * TypeSize); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER BOOLEAN +SymCreateSymbolTableForDisassembler(PVOID CallbackFunction); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER BOOLEAN +SymConvertFileToPdbPath(const CHAR * LocalFilePath, CHAR * ResultPath, SIZE_T ResultPathSize); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER BOOLEAN +SymConvertFileToPdbFileAndGuidAndAgeDetails(const CHAR * LocalFilePath, + CHAR * PdbFilePath, + CHAR * GuidAndAgeDetails, + BOOLEAN Is32BitModule); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER BOOLEAN +SymConvertLoadedModuleToPdbFileAndGuidAndAgeDetails(const BYTE * LoadedImageBytes, + SIZE_T LoadedImageSize, + const CHAR * LocalFilePath, + CHAR * PdbFilePath, + CHAR * GuidAndAgeDetails, + BOOLEAN Is32BitModule); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER BOOLEAN +SymbolInitLoad(PVOID BufferToStoreDetails, + UINT32 StoredLength, + BOOLEAN DownloadIfAvailable, + const CHAR * SymbolPath, + BOOLEAN IsSilentLoad); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER BOOLEAN +SymShowDataBasedOnSymbolTypes(const CHAR * TypeName, + UINT64 Address, + BOOLEAN IsStruct, + PVOID BufferAddress, + const CHAR * AdditionalParameters); + +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER BOOLEAN +SymQuerySizeof(_In_ const CHAR * StructNameOrTypeName, _Out_ UINT32 * SizeOfField); +IMPORT_EXPORT_HYPERDBG_SYMBOL_PARSER BOOLEAN +SymCastingQueryForFiledsAndTypes(_In_ const CHAR * StructName, + _In_ const CHAR * FiledOfStructName, + _Out_ PBOOLEAN IsStructNamePointerOrNot, + _Out_ PBOOLEAN IsFiledOfStructNamePointerOrNot, + _Out_ CHAR ** NewStructOrTypeName, + _Out_ UINT32 * OffsetOfFieldFromTop, + _Out_ UINT32 * SizeOfField); + +#ifdef __cplusplus +} +#endif diff --git a/hyperdbg/include/SDK/modules/HyperEvade.h b/hyperdbg/include/SDK/modules/HyperEvade.h new file mode 100644 index 00000000..e09c7e0a --- /dev/null +++ b/hyperdbg/include/SDK/modules/HyperEvade.h @@ -0,0 +1,153 @@ +/** + * @file HyperEvade.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief HyperDbg's SDK for hyperevade project + * @details This file contains definitions of HyperEvade routines + * @version 0.14 + * @date 2025-06-07 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Callback Types // +////////////////////////////////////////////////// + +/** + * @brief A function from the message tracer that send the inputs to the + * queue of the messages + * + */ +typedef BOOLEAN (*LOG_CALLBACK_PREPARE_AND_SEND_MESSAGE_TO_QUEUE)(UINT32 OperationCode, + BOOLEAN IsImmediateMessage, + BOOLEAN ShowCurrentSystemTime, + BOOLEAN Priority, + const CHAR * Fmt, + va_list ArgList); + +/** + * @brief A function that sends the messages to message tracer buffers + * + */ +typedef BOOLEAN (*LOG_CALLBACK_SEND_MESSAGE_TO_QUEUE)(UINT32 OperationCode, BOOLEAN IsImmediateMessage, CHAR * LogMessage, UINT32 BufferLen, BOOLEAN Priority); + +/** + * @brief A function that sends the messages to message tracer buffers + * + */ +typedef BOOLEAN (*LOG_CALLBACK_SEND_BUFFER)(_In_ UINT32 OperationCode, + _In_reads_bytes_(BufferLength) PVOID Buffer, + _In_ UINT32 BufferLength, + _In_ BOOLEAN Priority); + +/** + * @brief A function that checks whether the priority or regular buffer is full or not + * + */ +typedef BOOLEAN (*LOG_CALLBACK_CHECK_IF_BUFFER_IS_FULL)(BOOLEAN Priority); + +/** + * @brief A function that checks if LBR is supported on the current CPU and gets its capacity + * + */ +typedef BOOLEAN (*HYPERTRACE_LBR_IS_SUPPORTED)(UINT32 * Capacity, BOOLEAN * IsArchLbr); + +/** + * @brief A function that checks the validity and safety of the target address + * + */ +typedef BOOLEAN (*CHECK_ACCESS_VALIDITY_AND_SAFETY)(UINT64 TargetAddress, UINT32 Size); + +/** + * @brief A function that reads memory safely on the target process + * + */ +typedef BOOLEAN (*MEMORY_MAPPER_READ_MEMORY_SAFE_ON_TARGET_PROCESS)(UINT64 VaAddressToRead, PVOID BufferToSaveMemory, SIZE_T SizeToRead); + +/** + * @brief A function that writes memory safely on the target process + * + */ +typedef BOOLEAN (*MEMORY_MAPPER_WRITE_MEMORY_SAFE_ON_TARGET_PROCESS)(UINT64 Destination, PVOID Source, SIZE_T Size); + +/** + * @brief A function that gets the process name from the process control block + * + */ +typedef PCHAR (*COMMON_GET_PROCESS_NAME_FROM_PROCESS_CONTROL_BLOCK)(PVOID Eprocess); + +/** + * @brief A function that sets the trap flag after a syscall + * + */ +typedef BOOLEAN (*SYSCALL_CALLBACK_SET_TRAP_FLAG_AFTER_SYSCALL)(GUEST_REGS * Regs, + UINT32 ProcessId, + UINT32 ThreadId, + UINT64 Context, + SYSCALL_CALLBACK_CONTEXT_PARAMS * Params); + +/** + * @brief A function that handles the trap flag + * + */ +typedef VOID (*HV_HANDLE_TRAPFLAG)(); + +/** + * @brief A function that injects a general protection (#GP) + * + */ +typedef VOID (*EVENT_INJECT_GENERAL_PROTECTION)(); + +////////////////////////////////////////////////// +// Callback Structure // +////////////////////////////////////////////////// + +/** + * @brief Prototype of each function needed by hyperevade module + * + */ +typedef struct _HYPEREVADE_CALLBACKS +{ + // + // *** Log (Hyperlog) callbacks *** + // + LOG_CALLBACK_PREPARE_AND_SEND_MESSAGE_TO_QUEUE LogCallbackPrepareAndSendMessageToQueueWrapper; + LOG_CALLBACK_SEND_MESSAGE_TO_QUEUE LogCallbackSendMessageToQueue; + LOG_CALLBACK_SEND_BUFFER LogCallbackSendBuffer; + LOG_CALLBACK_CHECK_IF_BUFFER_IS_FULL LogCallbackCheckIfBufferIsFull; + + // + // HyperTrace callback(s) + // + HYPERTRACE_LBR_IS_SUPPORTED HyperTraceLbrIsSupported; + + // + // *** HYPEREVADE callbacks *** + // + + // + // Memory callbacks + // + CHECK_ACCESS_VALIDITY_AND_SAFETY CheckAccessValidityAndSafety; + MEMORY_MAPPER_READ_MEMORY_SAFE_ON_TARGET_PROCESS MemoryMapperReadMemorySafeOnTargetProcess; + MEMORY_MAPPER_WRITE_MEMORY_SAFE_ON_TARGET_PROCESS MemoryMapperWriteMemorySafeOnTargetProcess; + + // + // Common callbacks + // + COMMON_GET_PROCESS_NAME_FROM_PROCESS_CONTROL_BLOCK CommonGetProcessNameFromProcessControlBlock; + + // + // System call callbacks + // + SYSCALL_CALLBACK_SET_TRAP_FLAG_AFTER_SYSCALL SyscallCallbackSetTrapFlagAfterSyscall; + + // + // VMX callbacks + // + HV_HANDLE_TRAPFLAG HvHandleTrapFlag; + EVENT_INJECT_GENERAL_PROTECTION EventInjectGeneralProtection; + +} HYPEREVADE_CALLBACKS, *PHYPEREVADE_CALLBACKS; diff --git a/hyperdbg/include/SDK/Modules/HyperLog.h b/hyperdbg/include/SDK/modules/HyperLog.h similarity index 100% rename from hyperdbg/include/SDK/Modules/HyperLog.h rename to hyperdbg/include/SDK/modules/HyperLog.h diff --git a/hyperdbg/include/SDK/modules/HyperPerf.h b/hyperdbg/include/SDK/modules/HyperPerf.h new file mode 100644 index 00000000..fe76e097 --- /dev/null +++ b/hyperdbg/include/SDK/modules/HyperPerf.h @@ -0,0 +1,80 @@ +/** + * @file HyperPerf.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief HyperDbg's SDK for hyperperf project + * @details This file contains definitions of HyperPerf routines + * @version 0.21 + * @date 2026-06-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Callback Types // +////////////////////////////////////////////////// + +/** + * @brief A function from the message tracer that send the inputs to the + * queue of the messages + * + */ +typedef BOOLEAN (*LOG_CALLBACK_PREPARE_AND_SEND_MESSAGE_TO_QUEUE)(UINT32 OperationCode, + BOOLEAN IsImmediateMessage, + BOOLEAN ShowCurrentSystemTime, + BOOLEAN Priority, + const CHAR * Fmt, + va_list ArgList); + +/** + * @brief A function that sends the messages to message tracer buffers + * + */ +typedef BOOLEAN (*LOG_CALLBACK_SEND_MESSAGE_TO_QUEUE)(UINT32 OperationCode, BOOLEAN IsImmediateMessage, CHAR * LogMessage, UINT32 BufferLen, BOOLEAN Priority); + +/** + * @brief A function that sends the messages to message tracer buffers + * + */ +typedef BOOLEAN (*LOG_CALLBACK_SEND_BUFFER)(_In_ UINT32 OperationCode, + _In_reads_bytes_(BufferLength) PVOID Buffer, + _In_ UINT32 BufferLength, + _In_ BOOLEAN Priority); + +/** + * @brief A function that checks whether the priority or regular buffer is full or not + * + */ +typedef BOOLEAN (*LOG_CALLBACK_CHECK_IF_BUFFER_IS_FULL)(BOOLEAN Priority); + +/** + * @brief A function that checks whether the current execution mode is VMX-root mode or not + * + */ +typedef BOOLEAN (*VM_FUNC_VMX_GET_CURRENT_EXECUTION_MODE)(); + +////////////////////////////////////////////////// +// Callback Structure // +////////////////////////////////////////////////// + +/** + * @brief Prototype of each function needed by hyperperf module + * + */ +typedef struct _HYPERPERF_CALLBACKS +{ + // + // *** Log (Hyperlog) callbacks *** + // + LOG_CALLBACK_PREPARE_AND_SEND_MESSAGE_TO_QUEUE LogCallbackPrepareAndSendMessageToQueueWrapper; + LOG_CALLBACK_SEND_MESSAGE_TO_QUEUE LogCallbackSendMessageToQueue; + LOG_CALLBACK_SEND_BUFFER LogCallbackSendBuffer; + LOG_CALLBACK_CHECK_IF_BUFFER_IS_FULL LogCallbackCheckIfBufferIsFull; + + // + // *** Hypervisor (Hyperhv) callbacks *** + // + VM_FUNC_VMX_GET_CURRENT_EXECUTION_MODE VmFuncVmxGetCurrentExecutionMode; + +} HYPERPERF_CALLBACKS, *PHYPERPERF_CALLBACKS; diff --git a/hyperdbg/include/SDK/modules/HyperTrace.h b/hyperdbg/include/SDK/modules/HyperTrace.h new file mode 100644 index 00000000..17ace198 --- /dev/null +++ b/hyperdbg/include/SDK/modules/HyperTrace.h @@ -0,0 +1,255 @@ +/** + * @file HyperTrace.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief HyperDbg's SDK for hypertrace project + * @details This file contains definitions of HyperTrace routines + * @version 0.14 + * @date 2025-06-07 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Callback Types // +////////////////////////////////////////////////// + +/** + * @brief A function from the message tracer that send the inputs to the + * queue of the messages + * + */ +typedef BOOLEAN (*LOG_CALLBACK_PREPARE_AND_SEND_MESSAGE_TO_QUEUE)(UINT32 OperationCode, + BOOLEAN IsImmediateMessage, + BOOLEAN ShowCurrentSystemTime, + BOOLEAN Priority, + const CHAR * Fmt, + va_list ArgList); + +/** + * @brief A function that sends the messages to message tracer buffers + * + */ +typedef BOOLEAN (*LOG_CALLBACK_SEND_MESSAGE_TO_QUEUE)(UINT32 OperationCode, BOOLEAN IsImmediateMessage, CHAR * LogMessage, UINT32 BufferLen, BOOLEAN Priority); + +/** + * @brief A function that sends the messages to message tracer buffers + * + */ +typedef BOOLEAN (*LOG_CALLBACK_SEND_BUFFER)(_In_ UINT32 OperationCode, + _In_reads_bytes_(BufferLength) PVOID Buffer, + _In_ UINT32 BufferLength, + _In_ BOOLEAN Priority); + +/** + * @brief A function that checks whether the priority or regular buffer is full or not + * + */ +typedef BOOLEAN (*LOG_CALLBACK_CHECK_IF_BUFFER_IS_FULL)(BOOLEAN Priority); + +/** + * @brief A function that gets the guest state of IA32_DEBUGCTL + */ +typedef UINT64 (*VM_FUNC_GET_DEBUGCTL)(); + +/** + * @brief A function that gets the guest state of IA32_DEBUGCTL on the target core using VMCALL + */ +typedef UINT64 (*VM_FUNC_GET_DEBUGCTL_VMCALL_ON_TARGET_CORE)(); + +/** + * @brief A function that gets the guest state of IA32_LBR_CTL + */ +typedef UINT64 (*VM_FUNC_GET_GUEST_IA32_LBR_CTL)(); + +/** + * @brief A function that gets the guest state of IA32_LBR_CTL on the target core using VMCALL + */ +typedef UINT64 (*VM_FUNC_GET_GUEST_IA32_LBR_CTL_VMCALL_ON_TARGET_CORE)(); + +/** + * @brief A function that gets the guest state of IA32_DEBUGCTL + * + */ +typedef VOID (*VM_FUNC_SET_DEBUGCTL)(UINT64 Value); + +/** + * @brief A function that gets the guest state of IA32_DEBUGCTL on the target core using VMCALL + * + */ +typedef VOID (*VM_FUNC_SET_DEBUGCTL_VMCALL_ON_TARGET_CORE)(UINT64 Value); + +/** + * @brief A function that sets guest IA32_LBR_CTL + * + */ +typedef VOID (*VM_FUNC_SET_GUEST_IA32_LBR_CTL)(UINT64 Value); + +/** + * @brief A function that sets guest IA32_LBR_CTL on the target core using VMCALL + * + */ +typedef VOID (*VM_FUNC_SET_GUEST_IA32_LBR_CTL_VMCALL_ON_TARGET_CORE)(UINT64 Value); + +/** + * @brief A function that set MSR_LEGACY_LBR_SELECT + * + */ +typedef VOID (*VM_FUNC_SET_LBR_SELECT)(UINT64 FilterOptions); + +/** + * @brief A function that set MSR_LEGACY_LBR_SELECT on the target core using VMCALL + * + */ +typedef VOID (*VM_FUNC_SET_LBR_SELECT_VMCALL_ON_TARGET_CORE)(UINT64 FilterOptions); + +/** + * @brief A function that checks whether IA32_DEBUGCTL can be used in load and save of exit and entry controls + * + */ +typedef BOOLEAN (*VM_FUNC_CHECK_CPU_SUPPORT_FOR_SAVE_AND_LOAD_DEBUG_CONTROLS)(); + +/** + * @brief A function that checks whether guest IA32_LBR_CTL can be used in load and clear of guest IA32_LBR_CTL controls + * + */ +typedef BOOLEAN (*VM_FUNC_CHECK_CPU_SUPPORT_FOR_LOAD_AND_CLEAR_GUEST_IA32_LBR_CTL_CONTROLS)(); + +/** + * @brief A function that sets load debug controls on VM-entry controls + * + */ +typedef VOID (*VM_FUNC_SET_LOAD_DEBUG_CONTROLS)(UINT32 CoreId, BOOLEAN Set); + +/** + * @brief A function that sets load debug controls on VM-entry controls on the target core from VMCS using VMCALL + * + */ +typedef VOID (*VM_FUNC_SET_LOAD_DEBUG_CONTROLS_VMCALL_ON_TARGET_CORE)(BOOLEAN Set); + +/** + * @brief A function that sets load guest IA32_LBR_CTL on VM-entry controls + * + */ +typedef VOID (*VM_FUNC_SET_LOAD_GUEST_IA32_LBR_CTL)(UINT32 CoreId, BOOLEAN Set); + +/** + * @brief A function that sets load guest IA32_LBR_CTL on VM-entry controls on the target core from VMCS using VMCALL + * + */ +typedef VOID (*VM_FUNC_SET_LOAD_GUEST_IA32_LBR_CTL_VMCALL_ON_TARGET_CORE)(BOOLEAN Set); + +/** + * @brief A function that sets save debug controls on VM-exit controls + * + */ +typedef VOID (*VM_FUNC_SET_SAVE_DEBUG_CONTROLS)(UINT32 CoreId, BOOLEAN Set); + +/** + * @brief A function that sets save debug controls on VM-exit controls on the target core from VMCS using VMCALL + * + */ +typedef VOID (*VM_FUNC_SET_SAVE_DEBUG_CONTROLS_VMCALL_ON_TARGET_CORE)(BOOLEAN Set); + +/** + * @brief A function that sets clear guest IA32_LBR_CTL on VM-exit controls + * + */ +typedef VOID (*VM_FUNC_SET_CLEAR_GUEST_IA32_LBR_CTL)(UINT32 CoreId, BOOLEAN Set); + +/** + * @brief A function that sets clear guest IA32_LBR_CTL on VM-exit controls on the target core from VMCS using VMCALL + * + */ +typedef VOID (*VM_FUNC_SET_CLEAR_GUEST_IA32_LBR_CTL_VMCALL_ON_TARGET_CORE)(BOOLEAN Set); + +/** + * @brief A function that checks whether the current execution mode is VMX-root mode or not + * + */ +typedef BOOLEAN (*VM_FUNC_VMX_GET_CURRENT_EXECUTION_MODE)(); + +/** + * @brief A function that checks the validity and safety of the target address + * + */ +typedef BOOLEAN (*CHECK_ACCESS_VALIDITY_AND_SAFETY)(UINT64 TargetAddress, UINT32 Size); + +/** + * @brief A function that reads memory safely on the target process + * + */ +typedef BOOLEAN (*MEMORY_MAPPER_READ_MEMORY_SAFE_ON_TARGET_PROCESS)(UINT64 VaAddressToRead, PVOID BufferToSaveMemory, SIZE_T SizeToRead); + +/** + * @brief A function that writes memory safely on the target process + * + */ +typedef BOOLEAN (*MEMORY_MAPPER_WRITE_MEMORY_SAFE_ON_TARGET_PROCESS)(UINT64 Destination, PVOID Source, SIZE_T Size); + +/** + * @brief A function that gets the process name from the process control block + * + */ +typedef PCHAR (*COMMON_GET_PROCESS_NAME_FROM_PROCESS_CONTROL_BLOCK)(PVOID Eprocess); + +////////////////////////////////////////////////// +// Callback Structure // +////////////////////////////////////////////////// + +/** + * @brief Prototype of each function needed by hypertrace module + * + */ +typedef struct _HYPERTRACE_CALLBACKS +{ + // + // *** Log (Hyperlog) callbacks *** + // + LOG_CALLBACK_PREPARE_AND_SEND_MESSAGE_TO_QUEUE LogCallbackPrepareAndSendMessageToQueueWrapper; + LOG_CALLBACK_SEND_MESSAGE_TO_QUEUE LogCallbackSendMessageToQueue; + LOG_CALLBACK_SEND_BUFFER LogCallbackSendBuffer; + LOG_CALLBACK_CHECK_IF_BUFFER_IS_FULL LogCallbackCheckIfBufferIsFull; + + // + // *** Hypervisor (Hyperhv) callbacks *** + // + VM_FUNC_VMX_GET_CURRENT_EXECUTION_MODE VmFuncVmxGetCurrentExecutionMode; + + // + // *** Legacy LBR callbacks *** + // + + VM_FUNC_CHECK_CPU_SUPPORT_FOR_SAVE_AND_LOAD_DEBUG_CONTROLS VmFuncCheckCpuSupportForSaveAndLoadDebugControls; + + VM_FUNC_GET_DEBUGCTL VmFuncGetDebugctl; + VM_FUNC_GET_DEBUGCTL_VMCALL_ON_TARGET_CORE VmFuncGetDebugctlVmcallOnTargetCore; + VM_FUNC_SET_DEBUGCTL VmFuncSetDebugctl; + VM_FUNC_SET_DEBUGCTL_VMCALL_ON_TARGET_CORE VmFuncSetDebugctlVmcallOnTargetCore; + + VM_FUNC_SET_LOAD_DEBUG_CONTROLS VmFuncSetLoadDebugControls; + VM_FUNC_SET_LOAD_DEBUG_CONTROLS_VMCALL_ON_TARGET_CORE VmFuncSetLoadDebugControlsVmcallOnTargetCore; + VM_FUNC_SET_SAVE_DEBUG_CONTROLS VmFuncSetSaveDebugControls; + VM_FUNC_SET_SAVE_DEBUG_CONTROLS_VMCALL_ON_TARGET_CORE VmFuncSetSaveDebugControlsVmcallOnTargetCore; + + VM_FUNC_SET_LBR_SELECT VmFuncSetLbrSelect; + VM_FUNC_SET_LBR_SELECT_VMCALL_ON_TARGET_CORE VmFuncSetLbrSelectVmcallOnTargetCore; + + // + // *** Architectural LBR callbacks *** + // + + VM_FUNC_CHECK_CPU_SUPPORT_FOR_LOAD_AND_CLEAR_GUEST_IA32_LBR_CTL_CONTROLS VmFuncCheckCpuSupportForLoadAndClearGuestIa32LbrCtlControls; + + VM_FUNC_GET_GUEST_IA32_LBR_CTL VmFuncGetGuestIa32LbrCtl; + VM_FUNC_GET_GUEST_IA32_LBR_CTL_VMCALL_ON_TARGET_CORE VmFuncGetGuestIa32LbrCtlVmcallOnTargetCore; + VM_FUNC_SET_GUEST_IA32_LBR_CTL VmFuncSetGuestIa32LbrCtl; + VM_FUNC_SET_GUEST_IA32_LBR_CTL_VMCALL_ON_TARGET_CORE VmFuncSetGuestIa32LbrCtlVmcallOnTargetCore; + + VM_FUNC_SET_LOAD_GUEST_IA32_LBR_CTL VmFuncSetLoadGuestIa32LbrCtl; + VM_FUNC_SET_LOAD_GUEST_IA32_LBR_CTL_VMCALL_ON_TARGET_CORE VmFuncSetLoadGuestIa32LbrCtlVmcallOnTargetCore; + VM_FUNC_SET_CLEAR_GUEST_IA32_LBR_CTL VmFuncSetClearGuestIa32LbrCtl; + VM_FUNC_SET_CLEAR_GUEST_IA32_LBR_CTL_VMCALL_ON_TARGET_CORE VmFuncSetClearGuestIa32LbrCtlVmcallOnTargetCore; + +} HYPERTRACE_CALLBACKS, *PHYPERTRACE_CALLBACKS; diff --git a/hyperdbg/include/SDK/Modules/VMM.h b/hyperdbg/include/SDK/modules/VMM.h similarity index 67% rename from hyperdbg/include/SDK/Modules/VMM.h rename to hyperdbg/include/SDK/modules/VMM.h index 569ec85f..d961d45c 100644 --- a/hyperdbg/include/SDK/Modules/VMM.h +++ b/hyperdbg/include/SDK/modules/VMM.h @@ -2,7 +2,7 @@ * @file VMM.h * @author Sina Karvandi (sina@hyperdbg.org) * @brief HyperDbg's SDK for VMM project - * @details This file contains definitions of HyperLog routines + * @details This file contains definitions of VMM routines * @version 0.2 * @date 2023-01-15 * @@ -24,7 +24,7 @@ typedef BOOLEAN (*LOG_CALLBACK_PREPARE_AND_SEND_MESSAGE_TO_QUEUE)(UINT32 O BOOLEAN IsImmediateMessage, BOOLEAN ShowCurrentSystemTime, BOOLEAN Priority, - const char * Fmt, + const CHAR * Fmt, va_list ArgList); /** @@ -48,6 +48,12 @@ typedef BOOLEAN (*LOG_CALLBACK_SEND_BUFFER)(_In_ UINT32 */ typedef BOOLEAN (*LOG_CALLBACK_CHECK_IF_BUFFER_IS_FULL)(BOOLEAN Priority); +/** + * @brief A function that checks if LBR is supported on the current CPU and gets its capacity + * + */ +typedef BOOLEAN (*HYPERTRACE_LBR_IS_SUPPORTED)(UINT32 * Capacity, BOOLEAN * IsArchLbr); + /** * @brief A function that handles trigger events * @@ -71,24 +77,43 @@ typedef BOOLEAN (*DEBUGGING_CALLBACK_HANDLE_BREAKPOINT_EXCEPTION)(UINT32 CoreId) typedef BOOLEAN (*DEBUGGING_CALLBACK_HANDLE_DEBUG_BREAKPOINT_EXCEPTION)(UINT32 CoreId); /** - * @brief Check for page-faults in user-debugger + * @brief Check for thread interception in user-debugger * */ -typedef BOOLEAN (*DEBUGGING_CALLBACK_CONDITIONAL_PAGE_FAULT_EXCEPTION)(UINT32 CoreId, - UINT64 Address, - UINT32 PageFaultErrorCode); +typedef BOOLEAN (*DEBUGGING_CALLBACK_CHECK_THREAD_INTERCEPTION)(UINT32 CoreId); /** - * @brief Check for commands in user-debugger + * @brief Trigger on clock and IPI events for checking process or thread change * */ -typedef BOOLEAN (*UD_CHECK_FOR_COMMAND)(); +typedef BOOLEAN (*DEBUGGING_CALLBACK_TRIGGER_ON_CLOCK_AND_IPI_EVENTS)(_In_ UINT32 CoreId); /** - * @brief Handle registered MTF callback + * @brief routine callback to ignore handling mov 2 debug registers + * + * @param CoreId + * + * @return BOOLEAN + */ +typedef BOOLEAN (*DEBUGGING_CALLBACK_IGNORE_HANDLING_MOV_2_DEBUG_REGS)(_In_ UINT32 CoreId); + +/** + * @brief Request pool allocation * */ -typedef VOID (*VMM_CALLBACK_REGISTERED_MTF_HANDLER)(UINT32 CoreId); +typedef BOOLEAN (*POOL_MANAGER_REQUEST_ALLOCATION)(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention); + +/** + * @brief Request pool + * + */ +typedef UINT64 (*POOL_MANAGER_REQUEST_POOL)(POOL_ALLOCATION_INTENTION Intention, BOOLEAN RequestNewPool, UINT32 Size); + +/** + * @brief Free pool + * + */ +typedef BOOLEAN (*POOL_MANAGER_FREE_POOL)(UINT64 AddressToFree); /** * @brief Check for user-mode access for loaded module details @@ -102,42 +127,24 @@ typedef BOOLEAN (*VMM_CALLBACK_RESTORE_EPT_STATE)(UINT32 CoreId); */ typedef BOOLEAN (*VMM_CALLBACK_CHECK_UNHANDLED_EPT_VIOLATION)(UINT32 CoreId, UINT64 ViolationQualification, UINT64 GuestPhysicalAddr); +/** + * @brief Handle MTF callback + * + */ +typedef BOOLEAN (*VMM_CALLBACK_HANDLE_MTF_CALLBACK)(UINT32 CoreId); + /** * @brief Handle cr3 process change callbacks * */ typedef VOID (*INTERCEPTION_CALLBACK_TRIGGER_CR3_CHANGE)(UINT32 CoreId); -/** - * @brief Check for process or thread change callback - * - */ -typedef BOOLEAN (*INTERCEPTION_CALLBACK_TRIGGER_CLOCK_AND_IPI)(_In_ UINT32 CoreId); - -/** - * @brief Check to handle cr3 events for thread interception - * - */ -typedef BOOLEAN (*ATTACHING_HANDLE_CR3_EVENTS_FOR_THREAD_INTERCEPTION)(UINT32 CoreId, CR3_TYPE NewCr3); - -/** - * @brief Check and handle reapplying breakpoint - * - */ -typedef BOOLEAN (*BREAKPOINT_CHECK_AND_HANDLE_REAPPLYING_BREAKPOINT)(UINT32 CoreId); - /** * @brief Handle NMI broadcast * */ typedef VOID (*VMM_CALLBACK_NMI_BROADCAST_REQUEST_HANDLER)(UINT32 CoreId, BOOLEAN IsOnVmxNmiHandler); -/** - * @brief Check and handle NMI callbacks - * - */ -typedef BOOLEAN (*KD_CHECK_AND_HANDLE_NMI_CALLBACK)(UINT32 CoreId); - /** * @brief Set the top-level driver's error status * @@ -153,12 +160,6 @@ typedef BOOLEAN (*VMM_CALLBACK_QUERY_TERMINATE_PROTECTED_RESOURCE)(UINT32 PVOID Context, PROTECTED_HV_RESOURCES_PASSING_OVERS PassOver); -/** - * @brief Query debugger thread or process tracing details by core ID - * - */ -typedef BOOLEAN (*KD_QUERY_DEBUGGER_THREAD_OR_PROCESS_TRACING_DETAILS_BY_CORE_ID)(UINT32 CoreId, - DEBUGGER_THREAD_PROCESS_TRACING TracingType); /** * @brief Handler of debugger specific VMCALLs * @@ -182,43 +183,47 @@ typedef struct _VMM_CALLBACKS // // Log (Hyperlog) callbacks // - LOG_CALLBACK_PREPARE_AND_SEND_MESSAGE_TO_QUEUE LogCallbackPrepareAndSendMessageToQueueWrapper; // Fixed - LOG_CALLBACK_SEND_MESSAGE_TO_QUEUE LogCallbackSendMessageToQueue; // Fixed - LOG_CALLBACK_SEND_BUFFER LogCallbackSendBuffer; // Fixed - LOG_CALLBACK_CHECK_IF_BUFFER_IS_FULL LogCallbackCheckIfBufferIsFull; // Fixed + LOG_CALLBACK_PREPARE_AND_SEND_MESSAGE_TO_QUEUE LogCallbackPrepareAndSendMessageToQueueWrapper; + LOG_CALLBACK_SEND_MESSAGE_TO_QUEUE LogCallbackSendMessageToQueue; + LOG_CALLBACK_SEND_BUFFER LogCallbackSendBuffer; + LOG_CALLBACK_CHECK_IF_BUFFER_IS_FULL LogCallbackCheckIfBufferIsFull; + + // + // HyperTrace callback(s) + // + HYPERTRACE_LBR_IS_SUPPORTED HyperTraceCallbackLbrIsSupported; // // VMM callbacks // - VMM_CALLBACK_TRIGGER_EVENTS VmmCallbackTriggerEvents; // Fixed - VMM_CALLBACK_SET_LAST_ERROR VmmCallbackSetLastError; // Fixed - VMM_CALLBACK_VMCALL_HANDLER VmmCallbackVmcallHandler; // Fixed - VMM_CALLBACK_NMI_BROADCAST_REQUEST_HANDLER VmmCallbackNmiBroadcastRequestHandler; // Fixed - VMM_CALLBACK_QUERY_TERMINATE_PROTECTED_RESOURCE VmmCallbackQueryTerminateProtectedResource; // Fixed - VMM_CALLBACK_RESTORE_EPT_STATE VmmCallbackRestoreEptState; // Fixed - VMM_CALLBACK_CHECK_UNHANDLED_EPT_VIOLATION VmmCallbackCheckUnhandledEptViolations; // Fixed + VMM_CALLBACK_TRIGGER_EVENTS VmmCallbackTriggerEvents; + VMM_CALLBACK_SET_LAST_ERROR VmmCallbackSetLastError; + VMM_CALLBACK_VMCALL_HANDLER VmmCallbackVmcallHandler; + VMM_CALLBACK_NMI_BROADCAST_REQUEST_HANDLER VmmCallbackNmiBroadcastRequestHandler; + VMM_CALLBACK_QUERY_TERMINATE_PROTECTED_RESOURCE VmmCallbackQueryTerminateProtectedResource; + VMM_CALLBACK_RESTORE_EPT_STATE VmmCallbackRestoreEptState; + VMM_CALLBACK_CHECK_UNHANDLED_EPT_VIOLATION VmmCallbackCheckUnhandledEptViolations; + VMM_CALLBACK_HANDLE_MTF_CALLBACK VmmCallbackHandleMtfCallback; // // Debugging callbacks // - DEBUGGING_CALLBACK_HANDLE_BREAKPOINT_EXCEPTION DebuggingCallbackHandleBreakpointException; // Fixed - DEBUGGING_CALLBACK_HANDLE_DEBUG_BREAKPOINT_EXCEPTION DebuggingCallbackHandleDebugBreakpointException; // Fixed - DEBUGGING_CALLBACK_CONDITIONAL_PAGE_FAULT_EXCEPTION DebuggingCallbackConditionalPageFaultException; // Fixed + DEBUGGING_CALLBACK_HANDLE_BREAKPOINT_EXCEPTION DebuggingCallbackHandleBreakpointException; + DEBUGGING_CALLBACK_HANDLE_DEBUG_BREAKPOINT_EXCEPTION DebuggingCallbackHandleDebugBreakpointException; + DEBUGGING_CALLBACK_CHECK_THREAD_INTERCEPTION DebuggingCallbackCheckThreadInterception; + DEBUGGING_CALLBACK_TRIGGER_ON_CLOCK_AND_IPI_EVENTS DebuggingCallbackTriggerOnClockAndIpiEvents; + DEBUGGING_CALLBACK_IGNORE_HANDLING_MOV_2_DEBUG_REGS DebuggingCallbackIgnoreHandlingMov2DebugRegs; + + // + // Pool manager callbacks + // + POOL_MANAGER_REQUEST_ALLOCATION PoolManagerCallbackRequestAllocation; + POOL_MANAGER_REQUEST_POOL PoolManagerCallbackRequestPool; + POOL_MANAGER_FREE_POOL PoolManagerCallbackFreePool; // // Interception callbacks // - INTERCEPTION_CALLBACK_TRIGGER_CR3_CHANGE InterceptionCallbackTriggerCr3ProcessChange; // Fixed - - // - // Callbacks to be removed - // - BREAKPOINT_CHECK_AND_HANDLE_REAPPLYING_BREAKPOINT BreakpointCheckAndHandleReApplyingBreakpoint; - UD_CHECK_FOR_COMMAND UdCheckForCommand; - KD_CHECK_AND_HANDLE_NMI_CALLBACK KdCheckAndHandleNmiCallback; - VMM_CALLBACK_REGISTERED_MTF_HANDLER VmmCallbackRegisteredMtfHandler; // Fixed but not good - INTERCEPTION_CALLBACK_TRIGGER_CLOCK_AND_IPI DebuggerCheckProcessOrThreadChange; - ATTACHING_HANDLE_CR3_EVENTS_FOR_THREAD_INTERCEPTION AttachingHandleCr3VmexitsForThreadInterception; - KD_QUERY_DEBUGGER_THREAD_OR_PROCESS_TRACING_DETAILS_BY_CORE_ID KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId; + INTERCEPTION_CALLBACK_TRIGGER_CR3_CHANGE InterceptionCallbackTriggerCr3ProcessChange; } VMM_CALLBACKS, *PVMM_CALLBACKS; diff --git a/hyperdbg/include/components/callback/code/HyperLogCallback.c b/hyperdbg/include/components/callback/code/HyperLogCallback.c new file mode 100644 index 00000000..2d77def5 --- /dev/null +++ b/hyperdbg/include/components/callback/code/HyperLogCallback.c @@ -0,0 +1,141 @@ +/** + * @file HyperLogCallback.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief VMM callback interface routines + * @details + * + * @version 0.2 + * @date 2023-01-29 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief routines callback for preparing and sending message to queue + * + * @param OperationCode + * @param IsImmediateMessage + * @param ShowCurrentSystemTime + * @param Priority + * @param Fmt + * @param ... + * + * @return BOOLEAN + */ +BOOLEAN +LogCallbackPrepareAndSendMessageToQueue(UINT32 OperationCode, + BOOLEAN IsImmediateMessage, + BOOLEAN ShowCurrentSystemTime, + BOOLEAN Priority, + const CHAR * Fmt, + ...) +{ + BOOLEAN Result; + va_list ArgList; + + if (g_Callbacks.LogCallbackPrepareAndSendMessageToQueueWrapper == NULL) + { + // + // Ignore sending message to queue + // + return FALSE; + } + + va_start(ArgList, Fmt); + + Result = g_Callbacks.LogCallbackPrepareAndSendMessageToQueueWrapper(OperationCode, + IsImmediateMessage, + ShowCurrentSystemTime, + Priority, + Fmt, + ArgList); + va_end(ArgList); + + return Result; +} + +/** + * @brief routines callback for sending message to queue + * + * @param OperationCode + * @param IsImmediateMessage + * @param LogMessage + * @param BufferLen + * @param Priority + * + * @return BOOLEAN + */ +BOOLEAN +LogCallbackSendMessageToQueue(UINT32 OperationCode, + BOOLEAN IsImmediateMessage, + CHAR * LogMessage, + UINT32 BufferLen, + BOOLEAN Priority) +{ + if (g_Callbacks.LogCallbackSendMessageToQueue == NULL) + { + // + // Ignore sending message to queue + // + return FALSE; + } + + return g_Callbacks.LogCallbackSendMessageToQueue(OperationCode, + IsImmediateMessage, + LogMessage, + BufferLen, + Priority); +} + +/** + * @brief routines callback for checking if buffer is full + * + * @param Priority + * + * @return BOOLEAN + */ +BOOLEAN +LogCallbackCheckIfBufferIsFull(BOOLEAN Priority) +{ + if (g_Callbacks.LogCallbackCheckIfBufferIsFull == NULL) + { + // + // Ignore sending message to queue + // + return FALSE; + } + + return g_Callbacks.LogCallbackCheckIfBufferIsFull(Priority); +} + +/** + * @brief routines callback for sending buffer + * @param OperationCode + * @param Buffer + * @param BufferLength + * @param Priority + * + * @return BOOLEAN + */ +BOOLEAN +LogCallbackSendBuffer(_In_ UINT32 OperationCode, + _In_reads_bytes_(BufferLength) PVOID Buffer, + _In_ UINT32 BufferLength, + _In_ BOOLEAN Priority) + +{ + if (g_Callbacks.LogCallbackSendBuffer == NULL) + { + // + // Ignore sending buffer + // + return FALSE; + } + + return g_Callbacks.LogCallbackSendBuffer(OperationCode, + Buffer, + BufferLength, + Priority); +} \ No newline at end of file diff --git a/hyperdbg/include/components/callback/header/HyperLogCallback.h b/hyperdbg/include/components/callback/header/HyperLogCallback.h new file mode 100644 index 00000000..b7906988 --- /dev/null +++ b/hyperdbg/include/components/callback/header/HyperLogCallback.h @@ -0,0 +1,41 @@ +/** + * @file HyperLogCallback.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Header for VMM callback interface routines + * @details + * + * @version 0.2 + * @date 2023-01-29 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +// +// Log Callbacks +// + +BOOLEAN +LogCallbackPrepareAndSendMessageToQueue(UINT32 OperationCode, + BOOLEAN IsImmediateMessage, + BOOLEAN ShowCurrentSystemTime, + BOOLEAN Priority, + const CHAR * Fmt, + ...); + +BOOLEAN +LogCallbackSendMessageToQueue(UINT32 OperationCode, + BOOLEAN IsImmediateMessage, + CHAR * LogMessage, + UINT32 BufferLen, + BOOLEAN Priority); + +BOOLEAN +LogCallbackCheckIfBufferIsFull(BOOLEAN Priority); + +BOOLEAN +LogCallbackSendBuffer(_In_ UINT32 OperationCode, + _In_reads_bytes_(BufferLength) PVOID Buffer, + _In_ UINT32 BufferLength, + _In_ BOOLEAN Priority); diff --git a/hyperdbg/include/components/optimizations/code/InsertionSort.c b/hyperdbg/include/components/optimizations/code/InsertionSort.c index fb6884de..949f79b2 100644 --- a/hyperdbg/include/components/optimizations/code/InsertionSort.c +++ b/hyperdbg/include/components/optimizations/code/InsertionSort.c @@ -16,12 +16,14 @@ * * @param ArrayPtr * @param NumberOfItems + * @param MaxNumOfItems + * @param Index * @param Key * * @return BOOLEAN */ BOOLEAN -InsertionSortInsertItem(UINT64 ArrayPtr[], UINT32 * NumberOfItems, UINT32 MaxNumOfItems, UINT64 Key) +InsertionSortInsertItem(UINT64 ArrayPtr[], UINT32 * NumberOfItems, UINT32 MaxNumOfItems, UINT32 * Index, UINT64 Key) { UINT32 Idx; @@ -45,6 +47,7 @@ InsertionSortInsertItem(UINT64 ArrayPtr[], UINT32 * NumberOfItems, UINT32 MaxNum Idx = Idx - 1; } ArrayPtr[Idx] = Key; + *Index = Idx; (*NumberOfItems)++; // @@ -73,7 +76,7 @@ InsertionSortDeleteItem(UINT64 ArrayPtr[], UINT32 * NumberOfItems, UINT32 Index) return FALSE; } - for (size_t i = Index + 1; i < *NumberOfItems; i++) + for (SIZE_T i = Index + 1; i < *NumberOfItems; i++) { ArrayPtr[i - 1] = ArrayPtr[i]; } diff --git a/hyperdbg/include/components/optimizations/code/OptimizationsExamples.c b/hyperdbg/include/components/optimizations/code/OptimizationsExamples.c index b3471b0e..b2c9d0b8 100644 --- a/hyperdbg/include/components/optimizations/code/OptimizationsExamples.c +++ b/hyperdbg/include/components/optimizations/code/OptimizationsExamples.c @@ -30,12 +30,12 @@ OptimizationExampleInsertionSortAndBinarySearch() UINT32 NumberOfItems = 0; UINT32 Index; - InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, 12); - InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, 11); - InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, 13); - InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, 5); - InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, 6); - InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, 8); + InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, &Index, 12); + InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, &Index, 11); + InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, &Index, 13); + InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, &Index, 5); + InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, &Index, 6); + InsertionSortInsertItem(Arr, &NumberOfItems, MAX_NUM_OF_ARRAY, &Index, 8); // // Search for item equal to 15 diff --git a/hyperdbg/include/components/optimizations/header/InsertionSort.h b/hyperdbg/include/components/optimizations/header/InsertionSort.h index 2fb18043..2f1e07ba 100644 --- a/hyperdbg/include/components/optimizations/header/InsertionSort.h +++ b/hyperdbg/include/components/optimizations/header/InsertionSort.h @@ -16,7 +16,7 @@ ////////////////////////////////////////////////// BOOLEAN -InsertionSortInsertItem(UINT64 ArrayPtr[], UINT32 * NumberOfItems, UINT32 MaxNumOfItems, UINT64 Key); +InsertionSortInsertItem(UINT64 ArrayPtr[], UINT32 * NumberOfItems, UINT32 MaxNumOfItems, UINT32 * Index, UINT64 Key); BOOLEAN InsertionSortDeleteItem(UINT64 ArrayPtr[], UINT32 * NumberOfItems, UINT32 Index); diff --git a/hyperdbg/include/components/pe/code/pe-image-reader.cpp b/hyperdbg/include/components/pe/code/pe-image-reader.cpp new file mode 100644 index 00000000..b5abaacd --- /dev/null +++ b/hyperdbg/include/components/pe/code/pe-image-reader.cpp @@ -0,0 +1,339 @@ +/** + * @file pe-image-reader.cpp + * @author jtaw5649 + * @brief Bounded in-memory Portable Executable reader + * @details + * @version 0.19 + * @date 2026-06-01 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Checks whether the byte range [Offset, Offset + Length) lies entirely within an image buffer + * + * Validates that neither the offset nor the combined offset-plus-length overflows + * and that both fall within the bounds of the image. + * + * @param ImageSize Total size of the image buffer in bytes + * @param Offset Starting byte offset to test + * @param Length Number of bytes in the range + * + * @return BOOLEAN TRUE if the range is valid, FALSE if it exceeds the image bounds + */ +static BOOLEAN +PeImageReaderHasRange(SIZE_T ImageSize, SIZE_T Offset, SIZE_T Length) +{ + return Offset <= ImageSize && Length <= ImageSize - Offset; +} + +/** + * @brief Adds two SIZE_T values with overflow detection + * + * Returns FALSE without modifying Result when the addition would overflow; + * otherwise writes the sum to *Result and returns TRUE. + * + * @param Left First operand + * @param Right Second operand + * @param Result Output pointer that receives the sum on success; must not be NULL + * + * @return BOOLEAN TRUE if the addition succeeded, FALSE on overflow or NULL pointer + */ +static BOOLEAN +PeImageReaderAddSize(SIZE_T Left, SIZE_T Right, SIZE_T * Result) +{ + if (Result == NULL || Right > (SIZE_T)-1 - Left) + { + return FALSE; + } + + *Result = Left + Right; + return TRUE; +} + +/** + * @brief Retrieves the SizeOfHeaders value from the PE optional header + * + * Reads the field from IMAGE_OPTIONAL_HEADER32 or IMAGE_OPTIONAL_HEADER64 + * depending on the bitness recorded in the reader. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER; must not be NULL + * + * @return DWORD The SizeOfHeaders value from the optional header + */ +static DWORD +PeImageReaderGetSizeOfHeaders(PPE_IMAGE_READER Reader) +{ + const BYTE * OptionalHeader = Reader->NtHeaders + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER); + + if (Reader->Is32Bit) + { + return ((const IMAGE_OPTIONAL_HEADER32 *)OptionalHeader)->SizeOfHeaders; + } + + return ((const IMAGE_OPTIONAL_HEADER64 *)OptionalHeader)->SizeOfHeaders; +} + +/** + * @brief Parses and validates all PE headers in an in-memory image buffer + * + * Verifies the DOS signature, the NT signature, the optional header magic, + * and ensures all headers and the section table fit within the supplied buffer. + * On success the Reader structure is populated with pointers into ImageBase. + * + * @param ImageBase Pointer to the start of the image buffer; must not be NULL + * @param ImageSize Size of the buffer in bytes + * @param Reader Output structure to populate on success; must not be NULL + * + * @return BOOLEAN TRUE if the image was parsed successfully, FALSE on any + * validation failure or NULL argument + */ +BOOLEAN +PeImageReaderInitialize(const BYTE * ImageBase, SIZE_T ImageSize, PPE_IMAGE_READER Reader) +{ + if (ImageBase == NULL || Reader == NULL) + { + return FALSE; + } + + ZeroMemory(Reader, sizeof(*Reader)); + + if (!PeImageReaderHasRange(ImageSize, 0, sizeof(IMAGE_DOS_HEADER))) + { + return FALSE; + } + + const IMAGE_DOS_HEADER * DosHeader = (const IMAGE_DOS_HEADER *)ImageBase; + if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE || DosHeader->e_lfanew < 0) + { + return FALSE; + } + + SIZE_T NtHeaderOffset = (SIZE_T)DosHeader->e_lfanew; + if (!PeImageReaderHasRange(ImageSize, NtHeaderOffset, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))) + { + return FALSE; + } + + const BYTE * NtHeaders = ImageBase + NtHeaderOffset; + if (*(const DWORD *)NtHeaders != IMAGE_NT_SIGNATURE) + { + return FALSE; + } + + const IMAGE_FILE_HEADER * FileHeader = (const IMAGE_FILE_HEADER *)(NtHeaders + sizeof(DWORD)); + SIZE_T OptionalHeaderOffset = NtHeaderOffset + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER); + + if (FileHeader->SizeOfOptionalHeader < sizeof(WORD) || + !PeImageReaderHasRange(ImageSize, OptionalHeaderOffset, FileHeader->SizeOfOptionalHeader)) + { + return FALSE; + } + + WORD OptionalHeaderMagic = *(const WORD *)(ImageBase + OptionalHeaderOffset); + BOOLEAN Is32Bit = FALSE; + SIZE_T MinimumOptionalHeaderSize = 0; + + if (OptionalHeaderMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + Is32Bit = TRUE; + MinimumOptionalHeaderSize = sizeof(IMAGE_OPTIONAL_HEADER32); + } + else if (OptionalHeaderMagic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + MinimumOptionalHeaderSize = sizeof(IMAGE_OPTIONAL_HEADER64); + } + else + { + return FALSE; + } + + if (FileHeader->SizeOfOptionalHeader < MinimumOptionalHeaderSize) + { + return FALSE; + } + + SIZE_T SectionTableOffset = OptionalHeaderOffset + FileHeader->SizeOfOptionalHeader; + SIZE_T SectionTableSize = (SIZE_T)FileHeader->NumberOfSections * sizeof(IMAGE_SECTION_HEADER); + + if (FileHeader->NumberOfSections != 0 && SectionTableSize / sizeof(IMAGE_SECTION_HEADER) != FileHeader->NumberOfSections) + { + return FALSE; + } + + if (!PeImageReaderHasRange(ImageSize, SectionTableOffset, SectionTableSize)) + { + return FALSE; + } + + Reader->ImageBase = ImageBase; + Reader->ImageSize = ImageSize; + Reader->DosHeader = DosHeader; + Reader->NtHeaders = NtHeaders; + Reader->FileHeader = FileHeader; + Reader->SectionHeaders = (const IMAGE_SECTION_HEADER *)(ImageBase + SectionTableOffset); + Reader->OptionalHeaderMagic = OptionalHeaderMagic; + Reader->Is32Bit = Is32Bit; + + return TRUE; +} + +/** + * @brief Returns whether the PE image is a 32-bit (PE32) image + * + * Examines the Is32Bit flag populated by PeImageReaderInitialize. + * A return value of FALSE means either the reader is NULL or the image is PE32+. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * + * @return BOOLEAN TRUE for PE32 (32-bit), FALSE for PE32+ (64-bit) or NULL reader + */ +BOOLEAN +PeImageReaderIs32Bit(PPE_IMAGE_READER Reader) +{ + if (Reader == NULL) + { + return FALSE; + } + + return Reader->Is32Bit; +} + +/** + * @brief Returns a validated pointer into the image at a raw file offset + * + * Verifies that the range [Offset, Offset + Length) lies within the image + * buffer before setting *Pointer. Use this function when working with raw + * file offsets rather than virtual addresses. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER; must not be NULL + * @param Offset Raw file offset from the start of the image + * @param Length Number of bytes that must be accessible at the offset + * @param Pointer Output pointer set to ImageBase + Offset on success; must not be NULL + * + * @return BOOLEAN TRUE on success, FALSE on invalid arguments or out-of-bounds offset + */ +BOOLEAN +PeImageReaderGetPointerAtOffset(PPE_IMAGE_READER Reader, SIZE_T Offset, SIZE_T Length, const BYTE ** Pointer) +{ + if (Reader == NULL || Reader->ImageBase == NULL || Pointer == NULL || !PeImageReaderHasRange(Reader->ImageSize, Offset, Length)) + { + return FALSE; + } + + *Pointer = Reader->ImageBase + Offset; + return TRUE; +} + +/** + * @brief Copies the section name from a section header into a null-terminated buffer + * + * The PE section name field (IMAGE_SIZEOF_SHORT_NAME bytes) is not required to be + * null-terminated when it uses all 8 bytes. This function always appends a null + * terminator and truncates to NameBufferSize - 1 characters if necessary. + * + * @param SectionHeader Pointer to the section header to read; must not be NULL + * @param NameBuffer Destination buffer for the null-terminated name; must not be NULL + * @param NameBufferSize Size of NameBuffer in bytes; must be at least 1 + * + * @return BOOLEAN TRUE on success, FALSE on NULL arguments or zero-length buffer + */ +BOOLEAN +PeImageReaderGetSectionName(const IMAGE_SECTION_HEADER * SectionHeader, CHAR * NameBuffer, SIZE_T NameBufferSize) +{ + if (SectionHeader == NULL || NameBuffer == NULL || NameBufferSize == 0) + { + return FALSE; + } + + SIZE_T NameLength = 0; + while (NameLength < IMAGE_SIZEOF_SHORT_NAME && SectionHeader->Name[NameLength] != '\0') + { + NameLength++; + } + + SIZE_T CopyLength = NameLength; + if (CopyLength >= NameBufferSize) + { + CopyLength = NameBufferSize - 1; + } + + CopyMemory(NameBuffer, SectionHeader->Name, CopyLength); + NameBuffer[CopyLength] = '\0'; + + return TRUE; +} + +/** + * @brief Translates a relative virtual address (RVA) to a raw file offset + * + * First checks whether the RVA falls within the PE headers (before any section), + * in which case the file offset equals the RVA. Otherwise iterates the section + * table to find the section that contains the range [Rva, Rva + Length) and + * computes the corresponding raw offset via PointerToRawData. Returns FALSE if + * no section contains the range, if the raw data mapping is out of bounds, or if + * any arithmetic overflows. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER; must not be NULL + * @param Rva Relative virtual address to translate + * @param Length Number of bytes that must be accessible at the translated offset + * @param FileOffset Output pointer that receives the raw file offset on success; must not be NULL + * + * @return BOOLEAN TRUE if the RVA was translated successfully, FALSE otherwise + */ +BOOLEAN +PeImageReaderRvaToFileOffset(PPE_IMAGE_READER Reader, DWORD Rva, DWORD Length, PSIZE_T FileOffset) +{ + if (Reader == NULL || Reader->ImageBase == NULL || Reader->FileHeader == NULL || Reader->SectionHeaders == NULL || FileOffset == NULL) + { + return FALSE; + } + + DWORD SizeOfHeaders = PeImageReaderGetSizeOfHeaders(Reader); + SIZE_T HeaderEnd = 0; + + if (PeImageReaderAddSize((SIZE_T)Rva, (SIZE_T)Length, &HeaderEnd) && + SizeOfHeaders <= Reader->ImageSize && Rva < SizeOfHeaders && HeaderEnd <= SizeOfHeaders && + PeImageReaderHasRange(Reader->ImageSize, (SIZE_T)Rva, (SIZE_T)Length)) + { + *FileOffset = (SIZE_T)Rva; + return TRUE; + } + + for (WORD Index = 0; Index < Reader->FileHeader->NumberOfSections; Index++) + { + const IMAGE_SECTION_HEADER * SectionHeader = &Reader->SectionHeaders[Index]; + DWORD SectionSpan = max(SectionHeader->Misc.VirtualSize, SectionHeader->SizeOfRawData); + + if (SectionSpan == 0 || Rva < SectionHeader->VirtualAddress) + { + continue; + } + + DWORD Delta = Rva - SectionHeader->VirtualAddress; + if (Delta >= SectionSpan || Length > SectionSpan - Delta) + { + continue; + } + + if (Delta > SectionHeader->SizeOfRawData || Length > SectionHeader->SizeOfRawData - Delta) + { + return FALSE; + } + + SIZE_T RawOffset = 0; + + if (!PeImageReaderAddSize((SIZE_T)SectionHeader->PointerToRawData, (SIZE_T)Delta, &RawOffset) || + !PeImageReaderHasRange(Reader->ImageSize, RawOffset, (SIZE_T)Length)) + { + return FALSE; + } + + *FileOffset = RawOffset; + return TRUE; + } + + return FALSE; +} diff --git a/hyperdbg/include/components/pe/header/pe-image-reader.h b/hyperdbg/include/components/pe/header/pe-image-reader.h new file mode 100644 index 00000000..61fd23a5 --- /dev/null +++ b/hyperdbg/include/components/pe/header/pe-image-reader.h @@ -0,0 +1,102 @@ +/** + * @file pe-image-reader.h + * @author jtaw5649 + * @brief Bounded in-memory Portable Executable reader + * @details + * @version 0.19 + * @date 2026-06-01 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#ifndef _WIN32 +// On Windows these are provided by winnt.h; define them here for other platforms. + +typedef struct _IMAGE_DOS_HEADER +{ // DOS .EXE header + WORD e_magic; // Magic number + WORD e_cblp; // Bytes on last page of file + WORD e_cp; // Pages in file + WORD e_crlc; // Relocations + WORD e_cparhdr; // Size of header in paragraphs + WORD e_minalloc; // Minimum extra paragraphs needed + WORD e_maxalloc; // Maximum extra paragraphs needed + WORD e_ss; // Initial (relative) SS value + WORD e_sp; // Initial SP value + WORD e_csum; // Checksum + WORD e_ip; // Initial IP value + WORD e_cs; // Initial (relative) CS value + WORD e_lfarlc; // File address of relocation table + WORD e_ovno; // Overlay number + WORD e_res[4]; // Reserved words + WORD e_oemid; // OEM identifier (for e_oeminfo) + WORD e_oeminfo; // OEM information; e_oemid specific + WORD e_res2[10]; // Reserved words + LONG e_lfanew; // File address of new exe header +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_FILE_HEADER +{ + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +# define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER +{ + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union + { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#endif // _WIN32 + +typedef struct _PE_IMAGE_READER +{ + const BYTE * ImageBase; + SIZE_T ImageSize; + const IMAGE_DOS_HEADER * DosHeader; + const BYTE * NtHeaders; + const IMAGE_FILE_HEADER * FileHeader; + const IMAGE_SECTION_HEADER * SectionHeaders; + WORD OptionalHeaderMagic; + BOOLEAN Is32Bit; +} PE_IMAGE_READER, *PPE_IMAGE_READER; + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +PeImageReaderInitialize(const BYTE * ImageBase, SIZE_T ImageSize, PPE_IMAGE_READER Reader); + +BOOLEAN +PeImageReaderIs32Bit(PPE_IMAGE_READER Reader); + +BOOLEAN +PeImageReaderGetPointerAtOffset(PPE_IMAGE_READER Reader, SIZE_T Offset, SIZE_T Length, const BYTE ** Pointer); + +BOOLEAN +PeImageReaderGetSectionName(const IMAGE_SECTION_HEADER * SectionHeader, CHAR * NameBuffer, SIZE_T NameBufferSize); + +BOOLEAN +PeImageReaderRvaToFileOffset(PPE_IMAGE_READER Reader, DWORD Rva, DWORD Length, PSIZE_T FileOffset); diff --git a/hyperdbg/include/components/spinlock/code/Spinlock.c b/hyperdbg/include/components/spinlock/code/Spinlock.c index 53c47c8b..4b3e908b 100644 --- a/hyperdbg/include/components/spinlock/code/Spinlock.c +++ b/hyperdbg/include/components/spinlock/code/Spinlock.c @@ -26,15 +26,15 @@ #include "pch.h" /** - * @brief The maximum wait before PAUSE + * @brief The maximum Wait before PAUSE * */ -static unsigned MaxWait = 65536; +static UINT32 g_MaxWait = 65536; /** * @brief Tries to get the lock otherwise returns * - * @param LONG Lock variable + * @param Lock Lock variable * @return BOOLEAN If it was successful on getting the lock */ BOOLEAN @@ -46,32 +46,33 @@ SpinlockTryLock(volatile LONG * Lock) /** * @brief Tries to get the lock and won't return until successfully get the lock * - * @param LONG Lock variable + * @param Lock Lock variable + * @return VOID */ -void +VOID SpinlockLock(volatile LONG * Lock) { - unsigned wait = 1; + UINT32 Wait = 1; while (!SpinlockTryLock(Lock)) { - for (unsigned i = 0; i < wait; ++i) + for (UINT32 i = 0; i < Wait; ++i) { _mm_pause(); } // - // Don't call "pause" too many times. If the wait becomes too big, + // Don't call "pause" too many times. If the Wait becomes too big, // clamp it to the MaxWait. // - if (wait * 2 > MaxWait) + if (Wait * 2 > g_MaxWait) { - wait = MaxWait; + Wait = g_MaxWait; } else { - wait = wait * 2; + Wait = Wait * 2; } } } @@ -83,34 +84,35 @@ SpinlockLock(volatile LONG * Lock) * @param Destination A pointer to the destination value * @param Exchange The exchange value * @param Comperand The value to compare to Destination + * @return VOID */ -void +VOID SpinlockInterlockedCompareExchange( LONG volatile * Destination, LONG Exchange, LONG Comperand) { - unsigned wait = 1; + UINT32 Wait = 1; while (InterlockedCompareExchange(Destination, Exchange, Comperand) != Comperand) { - for (unsigned i = 0; i < wait; ++i) + for (UINT32 i = 0; i < Wait; ++i) { _mm_pause(); } // - // Don't call "pause" too many times. If the wait becomes too big, + // Don't call "pause" too many times. If the Wait becomes too big, // clamp it to the MaxWait. // - if (wait * 2 > MaxWait) + if (Wait * 2 > g_MaxWait) { - wait = MaxWait; + Wait = g_MaxWait; } else { - wait = wait * 2; + Wait = Wait * 2; } } } @@ -118,33 +120,34 @@ SpinlockInterlockedCompareExchange( /** * @brief Tries to get the lock and won't return until successfully get the lock * - * @param LONG Lock variable - * @param LONG MaxWait Maximum wait (pause) count + * @param Lock Lock variable + * @param MaximumWait Maximum wait (pause) count + * @return VOID */ -void -SpinlockLockWithCustomWait(volatile LONG * Lock, unsigned MaximumWait) +VOID +SpinlockLockWithCustomWait(volatile LONG * Lock, UINT32 MaximumWait) { - unsigned wait = 1; + UINT32 Wait = 1; while (!SpinlockTryLock(Lock)) { - for (unsigned i = 0; i < wait; ++i) + for (UINT32 i = 0; i < Wait; ++i) { _mm_pause(); } // - // Don't call "pause" too many times. If the wait becomes too big, + // Don't call "pause" too many times. If the Wait becomes too big, // clamp it to the MaxWait. // - if (wait * 2 > MaximumWait) + if (Wait * 2 > MaximumWait) { - wait = MaximumWait; + Wait = MaximumWait; } else { - wait = wait * 2; + Wait = Wait * 2; } } } @@ -152,9 +155,10 @@ SpinlockLockWithCustomWait(volatile LONG * Lock, unsigned MaximumWait) /** * @brief Release the lock * - * @param LONG Lock variable + * @param Lock Lock variable + * @return VOID */ -void +VOID SpinlockUnlock(volatile LONG * Lock) { *Lock = 0; @@ -163,7 +167,8 @@ SpinlockUnlock(volatile LONG * Lock) /** * @brief Check the lock without changing the state * - * @param LONG Lock variable + * @param Lock Lock variable + * @return BOOLEAN Whether the lock is acquired or not */ BOOLEAN SpinlockCheckLock(volatile LONG * Lock) diff --git a/hyperdbg/include/components/spinlock/header/Spinlock.h b/hyperdbg/include/components/spinlock/header/Spinlock.h index bd3f2d0a..13cdf22b 100644 --- a/hyperdbg/include/components/spinlock/header/Spinlock.h +++ b/hyperdbg/include/components/spinlock/header/Spinlock.h @@ -21,16 +21,16 @@ SpinlockTryLock(volatile LONG * Lock); BOOLEAN SpinlockCheckLock(volatile LONG * Lock); -void +VOID SpinlockLock(volatile LONG * Lock); -void -SpinlockLockWithCustomWait(volatile LONG * Lock, unsigned MaxWait); +VOID +SpinlockLockWithCustomWait(volatile LONG * Lock, UINT32 MaxWait); -void +VOID SpinlockUnlock(volatile LONG * Lock); -void +VOID SpinlockInterlockedCompareExchange( LONG volatile * Destination, LONG Exchange, diff --git a/hyperdbg/include/Configuration.h b/hyperdbg/include/config/Configuration.h similarity index 96% rename from hyperdbg/include/Configuration.h rename to hyperdbg/include/config/Configuration.h index 95d5d6d6..9a78bc41 100644 --- a/hyperdbg/include/Configuration.h +++ b/hyperdbg/include/config/Configuration.h @@ -63,13 +63,18 @@ */ #define DebugMode FALSE +/** + * @brief Enable or disable the instant event mechanism + * @details for more information: https://docs.hyperdbg.org/tips-and-tricks/misc/instant-events + */ +#define EnableInstantEventMechanism TRUE + /** * @brief Activates the user-mode debugger */ #define ActivateUserModeDebugger FALSE /** - * @brief Enable or disable the instant event mechanism - * @details for more information: https://docs.hyperdbg.org/tips-and-tricks/misc/instant-events + * @brief Activates the hyperevade project */ -#define EnableInstantEventMechanism TRUE +#define ActivateHyperEvadeProject FALSE diff --git a/hyperdbg/include/config/Definition.h b/hyperdbg/include/config/Definition.h new file mode 100644 index 00000000..1580f1e4 --- /dev/null +++ b/hyperdbg/include/config/Definition.h @@ -0,0 +1,132 @@ +/** + * @file Definition.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Header files for global definitions + * @details This file contains definitions that are use in both user mode and + * kernel mode Means that if you change the following files, structures or + * enums, then these settings apply to both usermode and kernel mode + * @version 0.1 + * @date 2020-04-10 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Config File // +////////////////////////////////////////////////// + +/** + * @brief Config file name for HyperDbg + * + */ +#define CONFIG_FILE_NAME L"config.ini" + +////////////////////////////////////////////////// +// Installer // +////////////////////////////////////////////////// + +/** + * @brief name of HyperDbg's VMM driver + * + */ +#define VMM_DRIVER_NAME "hyperhv" + +/** + * @brief name of HyperDbg's debugger driver + * + */ +#define KERNEL_DEBUGGER_DRIVER_NAME "hyperkd" + +/** + * @brief name of HyperDbg's debugger driver + extension + * + */ +#define KERNEL_DEBUGGER_DRIVER_NAME_AND_EXTENSION "hyperkd.sys" + +////////////////////////////////////////////////// +// Test Cases // +////////////////////////////////////////////////// + +/** + * @brief Default named pipe name for communication between debugger and debuggee process + */ +#define TEST_DEFAULT_NAMED_PIPE "\\\\.\\pipe\\HyperDbgPipe" + +/** + * @brief Maximum buffer to communicate between debugger and debuggee process + */ +#define TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE 0x1000 + +/** + * @brief Maximum hwdbg testing pins count (for emulating the script behavior) + */ +#define MAX_HWDBG_TESTING_PIN_COUNT 500 + +/** + * @brief Test cases file name for command parser + */ +#define COMMAND_PARSER_TEST_CASES_FILE "..\\..\\..\\tests\\command-parser\\command-parser-testcases.txt" + +/** + * @brief Test case parameter for testing main command parser + */ +#define TEST_HWDBG_FUNCTIONALITIES "test-hwdbg-functionalities" + +/** + * @brief Test case parameter for testing main command parser + */ +#define TEST_CASE_PARAMETER_FOR_MAIN_COMMAND_PARSER "test-command-parser" + +/** + * @brief Test case parameter for testing PE parser + */ +#define TEST_CASE_PARAMETER_FOR_PE_PARSER "test-pe-parser" + +/** + * @brief Test case parameter for testing CodeView RSDS parser + */ +#define TEST_CASE_PARAMETER_FOR_CODEVIEW_RSDS_PARSER "test-codeview-rsds-parser" + +/** + * @brief Test case parameter for testing semantic script tests + */ +#define TEST_CASE_PARAMETER_FOR_SCRIPT_SEMANTIC_TEST_CASES "test-script-semantic-test-cases" + +/** + * @brief Test cases file name + */ +#define SCRIPT_ENGINE_TEST_CASES_DIRECTORY "script-test-cases" + +/** + * @brief Test cases directory name for script semantic tests + */ +#define SCRIPT_SEMANTIC_TEST_CASE_DIRECTORY "..\\..\\..\\tests\\script-engine-test\\semantic-test-cases" + +/** + * @brief Test cases directory name for hwdbg script (code) tests + */ +#define HWDBG_SCRIPT_TEST_CASE_CODE_DIRECTORY "..\\..\\..\\tests\\hwdbg-tests\\scripts\\codes" + +/** + * @brief Test cases directory name for hwdbg script (compiled-scripts) tests + */ +#define HWDBG_SCRIPT_TEST_CASE_COMPILED_SCRIPTS_DIRECTORY "..\\..\\..\\tests\\hwdbg-tests\\scripts\\compiled-scripts" + +/** + * @brief Test cases directory name for hwdbg script (sample-tests) tests + */ +#define HWDBG_SCRIPT_TEST_CASE_SAMPLE_TESTS_DIRECTORY "..\\..\\..\\tests\\hwdbg-tests\\scripts\\sample-tests" + +////////////////////////////////////////////////// +// Delay Speeds // +////////////////////////////////////////////////// + +/** + * @brief The speed delay for showing messages from kernel-mode + * to user-mode in VMI-mode, using a lower value causes the + * HyperDbg to show messages faster but you should keep in mind, + * not to eat all of the CPU + */ +#define DefaultSpeedOfReadingKernelMessages 30 diff --git a/hyperdbg/hprdbghv/header/vmm/vmx/HypervTlfs.h b/hyperdbg/include/hyper-v/HypervTlfs.h similarity index 91% rename from hyperdbg/hprdbghv/header/vmm/vmx/HypervTlfs.h rename to hyperdbg/include/hyper-v/HypervTlfs.h index b5646015..4df98634 100644 --- a/hyperdbg/hprdbghv/header/vmm/vmx/HypervTlfs.h +++ b/hyperdbg/include/hyper-v/HypervTlfs.h @@ -216,6 +216,29 @@ enum hv_isolation_type #define HV_REGISTER_SINT14 0x4000009E #define HV_REGISTER_SINT15 0x4000009F +// #define HV_X64_MSR_TIME_REF_COUNT 0x40000020ULL +// #define HV_X64_MSR_REFERENCE_TSC 0x40000021ULL +#define HV_X64_MSR_NPIEP_CONFIG 0x40000040ULL +// #define HV_X64_MSR_SCONTROL 0x40000080ULL +// #define HV_X64_MSR_EOM 0x40000084ULL +// #define HV_X64_MSR_SINT0 0x40000090ULL +// #define HV_X64_MSR_SINT15 0x4000009FULL +// #define HV_X64_MSR_STIMER0_CONFIG 0x400000B0ULL +// #define HV_X64_MSR_STIMER3_COUNT 0x400000B7ULL +// #define HV_X64_MSR_GUEST_IDLE 0x400000F0ULL +// #define HV_X64_MSR_CRASH_P0 0x40000100ULL +// #define HV_X64_MSR_CRASH_CTL 0x40000105ULL +// #define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x40000106ULL +// #define HV_X64_MSR_TSC_EMULATION_CONTROL 0x40000107ULL +// #define HV_X64_MSR_TSC_EMULATION_STATUS 0x40000108ULL +#define HV_X64_MSR_STIME_UNHALTED_TIMER_CONFIG 0x40000114ULL +#define HV_X64_MSR_STIME_UNHALTED_TIMER_COUNT 0x40000115ULL +#define HV_X64_MSR_NESTED_VP_INDEX 0x40001002ULL +#define HV_X64_MSR_NESTED_SCONTROL 0x40001080ULL +#define HV_X64_MSR_NESTED_EOM 0x40001084ULL +#define HV_X64_MSR_NESTED_SINT0 0x40001090ULL +#define HV_X64_MSR_NESTED_SINT15 0x4000109FULL + /* * Synthetic Timer MSRs. Four timers per vcpu. */ @@ -273,6 +296,29 @@ enum hv_isolation_type #define HV_X64_MSR_TIME_REF_COUNT HV_REGISTER_TIME_REF_COUNT #define HV_X64_MSR_REFERENCE_TSC HV_REGISTER_REFERENCE_TSC +// +// Define the synthetic timer configuration structure +// +typedef struct _HV_X64_MSR_STIMER_CONFIG_CONTENTS +{ + union + { + UINT64 AsUINT64; + struct + { + UINT64 Enable : 1; + UINT64 Periodic : 1; + UINT64 Lazy : 1; + UINT64 AutoEnable : 1; + UINT64 ApicVector : 8; + UINT64 DirectMode : 1; + UINT64 ReservedZ1 : 1; + UINT64 SINTx : 4; + UINT64 ReservedZ2 : 44; + }; + }; +} HV_X64_MSR_STIMER_CONFIG_CONTENTS, *PHV_X64_MSR_STIMER_CONFIG_CONTENTS; + /* Hyper-V memory host visibility */ enum hv_mem_host_visibility { diff --git a/hyperdbg/include/keystone/arm.h b/hyperdbg/include/keystone/arm.h new file mode 100644 index 00000000..f4d2489a --- /dev/null +++ b/hyperdbg/include/keystone/arm.h @@ -0,0 +1,23 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_ARM_H +#define KEYSTONE_ARM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_arm { + KS_ERR_ASM_ARM_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_ARM_MISSINGFEATURE, + KS_ERR_ASM_ARM_MNEMONICFAIL, +} ks_err_asm_arm; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/keystone/arm64.h b/hyperdbg/include/keystone/arm64.h new file mode 100644 index 00000000..7a7af411 --- /dev/null +++ b/hyperdbg/include/keystone/arm64.h @@ -0,0 +1,23 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_ARM64_H +#define KEYSTONE_ARM64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_arm64 { + KS_ERR_ASM_ARM64_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_ARM64_MISSINGFEATURE, + KS_ERR_ASM_ARM64_MNEMONICFAIL, +} ks_err_asm_arm64; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/keystone/evm.h b/hyperdbg/include/keystone/evm.h new file mode 100644 index 00000000..60ac408c --- /dev/null +++ b/hyperdbg/include/keystone/evm.h @@ -0,0 +1,23 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016-2018 */ + +#ifndef KEYSTONE_EVM_H +#define KEYSTONE_EVM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_evm { + KS_ERR_ASM_EVM_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_EVM_MISSINGFEATURE, + KS_ERR_ASM_EVM_MNEMONICFAIL, +} ks_err_asm_evm; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/keystone/hexagon.h b/hyperdbg/include/keystone/hexagon.h new file mode 100644 index 00000000..e6158123 --- /dev/null +++ b/hyperdbg/include/keystone/hexagon.h @@ -0,0 +1,24 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_HEXAGON_H +#define KEYSTONE_HEXAGON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_hexagon { + KS_ERR_ASM_HEXAGON_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_HEXAGON_MISSINGFEATURE, + KS_ERR_ASM_HEXAGON_MNEMONICFAIL, +} ks_err_asm_hexagon; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/keystone/keystone.h b/hyperdbg/include/keystone/keystone.h new file mode 100644 index 00000000..503508c6 --- /dev/null +++ b/hyperdbg/include/keystone/keystone.h @@ -0,0 +1,349 @@ +/* Keystone Assembler Engine (www.keystone-engine.org) */ +/* By Nguyen Anh Quynh , 2016 */ + +#ifndef KEYSTONE_ENGINE_H +#define KEYSTONE_ENGINE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#ifdef _MSC_VER // MSVC compiler +# pragma warning(disable : 4201) +# pragma warning(disable : 4100) +# ifndef KEYSTONE_STATIC +# define KEYSTONE_EXPORT __declspec(dllexport) +# else +# define KEYSTONE_EXPORT +# endif +#else +# ifdef __GNUC__ +# include +# ifndef KEYSTONE_STATIC +# define KEYSTONE_EXPORT __attribute__((visibility("default"))) +# else +# define KEYSTONE_EXPORT +# endif +# else +# define KEYSTONE_EXPORT +# endif +#endif + +struct ks_struct; +typedef struct ks_struct ks_engine; + +// Keystone API version +#define KS_API_MAJOR 0 +#define KS_API_MINOR 9 + +// Package version +#define KS_VERSION_MAJOR KS_API_MAJOR +#define KS_VERSION_MINOR KS_API_MINOR +#define KS_VERSION_EXTRA 2 + +/* + Macro to create combined version which can be compared to + result of ks_version() API. +*/ +#define KS_MAKE_VERSION(major, minor) ((major << 8) + minor) + +// Architecture type +typedef enum ks_arch +{ + KS_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2) + KS_ARCH_ARM64, // ARM-64, also called AArch64 + KS_ARCH_MIPS, // Mips architecture + KS_ARCH_X86, // X86 architecture (including x86 & x86-64) + KS_ARCH_PPC, // PowerPC architecture (currently unsupported) + KS_ARCH_SPARC, // Sparc architecture + KS_ARCH_SYSTEMZ, // SystemZ architecture (S390X) + KS_ARCH_HEXAGON, // Hexagon architecture + KS_ARCH_EVM, // Ethereum Virtual Machine architecture + KS_ARCH_RISCV, // RISC-V architecture + KS_ARCH_MAX, +} ks_arch; + +// Mode type +typedef enum ks_mode +{ + KS_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) + KS_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode + // arm / arm64 + KS_MODE_ARM = 1 << 0, // ARM mode + KS_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2) + KS_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM + // mips + KS_MODE_MICRO = 1 << 4, // MicroMips mode + KS_MODE_MIPS3 = 1 << 5, // Mips III ISA + KS_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA + KS_MODE_MIPS32 = 1 << 2, // Mips32 ISA + KS_MODE_MIPS64 = 1 << 3, // Mips64 ISA + // x86 / x64 + KS_MODE_16 = 1 << 1, // 16-bit mode + KS_MODE_32 = 1 << 2, // 32-bit mode + KS_MODE_64 = 1 << 3, // 64-bit mode + // ppc + KS_MODE_PPC32 = 1 << 2, // 32-bit mode + KS_MODE_PPC64 = 1 << 3, // 64-bit mode + KS_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode + // riscv + KS_MODE_RISCV32 = 1 << 2, // 32-bit mode + KS_MODE_RISCV64 = 1 << 3, // 64-bit mode + // sparc + KS_MODE_SPARC32 = 1 << 2, // 32-bit mode + KS_MODE_SPARC64 = 1 << 3, // 64-bit mode + KS_MODE_V9 = 1 << 4, // SparcV9 mode +} ks_mode; + +// All generic errors related to input assembly >= KS_ERR_ASM +#define KS_ERR_ASM 128 + +// All architecture-specific errors related to input assembly >= KS_ERR_ASM_ARCH +#define KS_ERR_ASM_ARCH 512 + +// All type of errors encountered by Keystone API. +typedef enum ks_err +{ + KS_ERR_OK = 0, // No error: everything was fine + KS_ERR_NOMEM, // Out-Of-Memory error: ks_open(), ks_emulate() + KS_ERR_ARCH, // Unsupported architecture: ks_open() + KS_ERR_HANDLE, // Invalid handle + KS_ERR_MODE, // Invalid/unsupported mode: ks_open() + KS_ERR_VERSION, // Unsupported version (bindings) + KS_ERR_OPT_INVALID, // Unsupported option + + // generic input assembly errors - parser specific + KS_ERR_ASM_EXPR_TOKEN = KS_ERR_ASM, // unknown token in expression + KS_ERR_ASM_DIRECTIVE_VALUE_RANGE, // literal value out of range for directive + KS_ERR_ASM_DIRECTIVE_ID, // expected identifier in directive + KS_ERR_ASM_DIRECTIVE_TOKEN, // unexpected token in directive + KS_ERR_ASM_DIRECTIVE_STR, // expected string in directive + KS_ERR_ASM_DIRECTIVE_COMMA, // expected comma in directive + KS_ERR_ASM_DIRECTIVE_RELOC_NAME, // expected relocation name in directive + KS_ERR_ASM_DIRECTIVE_RELOC_TOKEN, // unexpected token in .reloc directive + KS_ERR_ASM_DIRECTIVE_FPOINT, // invalid floating point in directive + KS_ERR_ASM_DIRECTIVE_UNKNOWN, // unknown directive + KS_ERR_ASM_DIRECTIVE_EQU, // invalid equal directive + KS_ERR_ASM_DIRECTIVE_INVALID, // (generic) invalid directive + KS_ERR_ASM_VARIANT_INVALID, // invalid variant + KS_ERR_ASM_EXPR_BRACKET, // brackets expression not supported on this target + KS_ERR_ASM_SYMBOL_MODIFIER, // unexpected symbol modifier following '@' + KS_ERR_ASM_SYMBOL_REDEFINED, // invalid symbol redefinition + KS_ERR_ASM_SYMBOL_MISSING, // cannot find a symbol + KS_ERR_ASM_RPAREN, // expected ')' in parentheses expression + KS_ERR_ASM_STAT_TOKEN, // unexpected token at start of statement + KS_ERR_ASM_UNSUPPORTED, // unsupported token yet + KS_ERR_ASM_MACRO_TOKEN, // unexpected token in macro instantiation + KS_ERR_ASM_MACRO_PAREN, // unbalanced parentheses in macro argument + KS_ERR_ASM_MACRO_EQU, // expected '=' after formal parameter identifier + KS_ERR_ASM_MACRO_ARGS, // too many positional arguments + KS_ERR_ASM_MACRO_LEVELS_EXCEED, // macros cannot be nested more than 20 levels deep + KS_ERR_ASM_MACRO_STR, // invalid macro string + KS_ERR_ASM_MACRO_INVALID, // invalid macro (generic error) + KS_ERR_ASM_ESC_BACKSLASH, // unexpected backslash at end of escaped string + KS_ERR_ASM_ESC_OCTAL, // invalid octal escape sequence (out of range) + KS_ERR_ASM_ESC_SEQUENCE, // invalid escape sequence (unrecognized character) + KS_ERR_ASM_ESC_STR, // broken escape string + KS_ERR_ASM_TOKEN_INVALID, // invalid token + KS_ERR_ASM_INSN_UNSUPPORTED, // this instruction is unsupported in this mode + KS_ERR_ASM_FIXUP_INVALID, // invalid fixup + KS_ERR_ASM_LABEL_INVALID, // invalid label + KS_ERR_ASM_FRAGMENT_INVALID, // invalid fragment + + // generic input assembly errors - architecture specific + KS_ERR_ASM_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_MISSINGFEATURE, + KS_ERR_ASM_MNEMONICFAIL, +} ks_err; + +// Resolver callback to provide value for a missing symbol in @symbol. +// To handle a symbol, the resolver must put value of the symbol in @value, +// then returns True. +// If we do not resolve a missing symbol, this function must return False. +// In that case, ks_asm() would eventually return with error KS_ERR_ASM_SYMBOL_MISSING. + +// To register the resolver, pass its function address to ks_option(), using +// option KS_OPT_SYM_RESOLVER. For example, see samples/sample.c. +typedef bool (*ks_sym_resolver)(const char * symbol, uint64_t * value); + +// Runtime option for the Keystone engine +typedef enum ks_opt_type +{ + KS_OPT_SYNTAX = 1, // Choose syntax for input assembly + KS_OPT_SYM_RESOLVER, // Set symbol resolver callback +} ks_opt_type; + +// Runtime option value (associated with ks_opt_type above) +typedef enum ks_opt_value +{ + KS_OPT_SYNTAX_INTEL = 1 << 0, // X86 Intel syntax - default on X86 (KS_OPT_SYNTAX). + KS_OPT_SYNTAX_ATT = 1 << 1, // X86 ATT asm syntax (KS_OPT_SYNTAX). + KS_OPT_SYNTAX_NASM = 1 << 2, // X86 Nasm syntax (KS_OPT_SYNTAX). + KS_OPT_SYNTAX_MASM = 1 << 3, // X86 Masm syntax (KS_OPT_SYNTAX) - unsupported yet. + KS_OPT_SYNTAX_GAS = 1 << 4, // X86 GNU GAS syntax (KS_OPT_SYNTAX). + KS_OPT_SYNTAX_RADIX16 = 1 << 5, // All immediates are in hex format (i.e 12 is 0x12) +} ks_opt_value; + +#include "arm64.h" +#include "arm.h" +#include "evm.h" +#include "hexagon.h" +#include "mips.h" +#include "ppc.h" +#include "riscv.h" +#include "sparc.h" +#include "systemz.h" +#include "x86.h" + +/* + Return combined API version & major and minor version numbers. + + @major: major number of API version + @minor: minor number of API version + + @return hexical number as (major << 8 | minor), which encodes both + major & minor versions. + NOTE: This returned value can be compared with version number made + with macro KS_MAKE_VERSION + + For example, second API version would return 1 in @major, and 1 in @minor + The return value would be 0x0101 + + NOTE: if you only care about returned value, but not major and minor values, + set both @major & @minor arguments to NULL. +*/ +KEYSTONE_EXPORT +unsigned int +ks_version(unsigned int * major, unsigned int * minor); + +/* + Determine if the given architecture is supported by this library. + + @arch: architecture type (KS_ARCH_*) + + @return True if this library supports the given arch. +*/ +KEYSTONE_EXPORT +bool +ks_arch_supported(ks_arch arch); + +/* + Create new instance of Keystone engine. + + @arch: architecture type (KS_ARCH_*) + @mode: hardware mode. This is combined of KS_MODE_* + @ks: pointer to ks_engine, which will be updated at return time + + @return KS_ERR_OK on success, or other value on failure (refer to ks_err enum + for detailed error). +*/ +KEYSTONE_EXPORT +ks_err +ks_open(ks_arch arch, int mode, ks_engine ** ks); + +/* + Close KS instance: MUST do to release the handle when it is not used anymore. + NOTE: this must be called only when there is no longer usage of Keystone. + The reason is the this API releases some cached memory, thus access to any + Keystone API after ks_close() might crash your application. + After this, @ks is invalid, and nolonger usable. + + @ks: pointer to a handle returned by ks_open() + + @return KS_ERR_OK on success, or other value on failure (refer to ks_err enum + for detailed error). +*/ +KEYSTONE_EXPORT +ks_err +ks_close(ks_engine * ks); + +/* + Report the last error number when some API function fail. + Like glibc's errno, ks_errno might not retain its old error once accessed. + + @ks: handle returned by ks_open() + + @return: error code of ks_err enum type (KS_ERR_*, see above) +*/ +KEYSTONE_EXPORT +ks_err +ks_errno(ks_engine * ks); + +/* + Return a string describing given error code. + + @code: error code (see KS_ERR_* above) + + @return: returns a pointer to a string that describes the error code + passed in the argument @code + */ +KEYSTONE_EXPORT +const char * +ks_strerror(ks_err code); + +/* + Set option for Keystone engine at runtime + + @ks: handle returned by ks_open() + @type: type of option to be set. See ks_opt_type + @value: option value corresponding with @type + + @return: KS_ERR_OK on success, or other value on failure. + Refer to ks_err enum for detailed error. +*/ +KEYSTONE_EXPORT +ks_err +ks_option(ks_engine * ks, ks_opt_type type, size_t value); + +/* + Assemble a string given its the buffer, size, start address and number + of instructions to be decoded. + This API dynamically allocate memory to contain assembled instruction. + Resulted array of bytes containing the machine code is put into @*encoding + + NOTE 1: this API will automatically determine memory needed to contain + output bytes in *encoding. + + NOTE 2: caller must free the allocated memory itself to avoid memory leaking. + + @ks: handle returned by ks_open() + @str: NULL-terminated assembly string. Use ; or \n to separate statements. + @address: address of the first assembly instruction, or 0 to ignore. + @encoding: array of bytes containing encoding of input assembly string. + NOTE: *encoding will be allocated by this function, and should be freed + with ks_free() function. + @encoding_size: size of *encoding + @stat_count: number of statements successfully processed + + @return: 0 on success, or -1 on failure. + + On failure, call ks_errno() for error code. +*/ +KEYSTONE_EXPORT +int +ks_asm(ks_engine * ks, + const char * string, + uint64_t address, + unsigned char ** encoding, + size_t * encoding_size, + size_t * stat_count); + +/* + Free memory allocated by ks_asm() + + @p: memory allocated in @encoding argument of ks_asm() +*/ +KEYSTONE_EXPORT +void +ks_free(unsigned char * p); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/keystone/mips.h b/hyperdbg/include/keystone/mips.h new file mode 100644 index 00000000..e71c553c --- /dev/null +++ b/hyperdbg/include/keystone/mips.h @@ -0,0 +1,23 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_MIPS_H +#define KEYSTONE_MIPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_mips { + KS_ERR_ASM_MIPS_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_MIPS_MISSINGFEATURE, + KS_ERR_ASM_MIPS_MNEMONICFAIL, +} ks_err_asm_mips; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/keystone/ppc.h b/hyperdbg/include/keystone/ppc.h new file mode 100644 index 00000000..39a602c2 --- /dev/null +++ b/hyperdbg/include/keystone/ppc.h @@ -0,0 +1,24 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_PPC_H +#define KEYSTONE_PPC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_ppc { + KS_ERR_ASM_PPC_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_PPC_MISSINGFEATURE, + KS_ERR_ASM_PPC_MNEMONICFAIL, +} ks_err_asm_ppc; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/keystone/riscv.h b/hyperdbg/include/keystone/riscv.h new file mode 100644 index 00000000..0910f986 --- /dev/null +++ b/hyperdbg/include/keystone/riscv.h @@ -0,0 +1,24 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ +/* Added by Mark Juvan, 2023*/ +#ifndef KEYSTONE_RISCV_H +#define KEYSTONE_RISCV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_riscv { + KS_ERR_ASM_RISCV_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_RISCV_MISSINGFEATURE, + KS_ERR_ASM_RISCV_MNEMONICFAIL, +} ks_err_asm_riscv; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/keystone/sparc.h b/hyperdbg/include/keystone/sparc.h new file mode 100644 index 00000000..e49c4264 --- /dev/null +++ b/hyperdbg/include/keystone/sparc.h @@ -0,0 +1,24 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_SPARC_H +#define KEYSTONE_SPARC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_sparc { + KS_ERR_ASM_SPARC_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_SPARC_MISSINGFEATURE, + KS_ERR_ASM_SPARC_MNEMONICFAIL, +} ks_err_asm_sparc; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/keystone/systemz.h b/hyperdbg/include/keystone/systemz.h new file mode 100644 index 00000000..ec2b07a4 --- /dev/null +++ b/hyperdbg/include/keystone/systemz.h @@ -0,0 +1,24 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_SYSTEMZ_H +#define KEYSTONE_SYSTEMZ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_systemz { + KS_ERR_ASM_SYSTEMZ_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_SYSTEMZ_MISSINGFEATURE, + KS_ERR_ASM_SYSTEMZ_MNEMONICFAIL, +} ks_err_asm_systemz; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/keystone/x86.h b/hyperdbg/include/keystone/x86.h new file mode 100644 index 00000000..1fac684e --- /dev/null +++ b/hyperdbg/include/keystone/x86.h @@ -0,0 +1,23 @@ +/* Keystone Assembler Engine */ +/* By Nguyen Anh Quynh, 2016 */ + +#ifndef KEYSTONE_X86_H +#define KEYSTONE_X86_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "keystone.h" + +typedef enum ks_err_asm_x86 { + KS_ERR_ASM_X86_INVALIDOPERAND = KS_ERR_ASM_ARCH, + KS_ERR_ASM_X86_MISSINGFEATURE, + KS_ERR_ASM_X86_MNEMONICFAIL, +} ks_err_asm_x86; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hyperdbg/include/platform/general/code/.gitkeep b/hyperdbg/include/platform/general/code/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/hyperdbg/include/platform/general/header/Environment.h b/hyperdbg/include/platform/general/header/Environment.h new file mode 100644 index 00000000..4abf4d21 --- /dev/null +++ b/hyperdbg/include/platform/general/header/Environment.h @@ -0,0 +1,96 @@ +/** + * @file Environment.h + * @author Behrooz Abbassi (BehroozAbbassi@hyperdbg.org) + * @brief The running environment of HyperDbg + * @details + * @version 0.1 + * @date 2022-01-17 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Definitions // +////////////////////////////////////////////////// + +// +// Check for platform +// +#if defined(_WIN32) || defined(_WIN64) +# define HYPERDBG_ENV_WINDOWS +#elif defined(__linux__) +// # error "This code cannot compile on Linux yet" +# define HYPERDBG_ENV_LINUX +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +# error "This code cannot compile on BSD yet" +# define HYPERDBG_ENV_BSD +#else +# error "This code cannot compile on non-Windows, non-Linux, and non-BSD platforms" +#endif + +#ifdef HYPERDBG_ENV_LINUX + +// SAL annotations +# define _In_ +# define _Out_ +# define _Inout_ +# define _In_opt_ +# define _Out_opt_ +# define _In_z_ +# define _Outptr_ +# define _In_reads_bytes_(x) +# define _Out_writes_bytes_(x) +# define _Inout_updates_bytes_all_(x) + +// wchar_t is a C++ built-in but needs this header in C +# include + +// POSIX sleep primitives (usleep) backing the Win32 Sleep() shim below +# include + +// Windows string/char types +typedef char TCHAR; +typedef char * LPTSTR; +typedef const char * LPCTSTR; +typedef const char * LPCSTR; +typedef char * LPSTR; +typedef const char * PCSTR; +typedef char * PSTR; +typedef short * PWCHAR; + +// Windows socket type (Linux sockets are plain int) +typedef int SOCKET; +# define INVALID_SOCKET ((SOCKET)(-1)) +# define SOCKET_ERROR (-1) + +// Windows calling convention (no-op on Linux) +# define WINAPI + +// Windows module handle (equivalent to dlopen's void * on Linux) +typedef void * HMODULE; + +// Misc Windows macros +# define UNREFERENCED_PARAMETER(P) ((void)(P)) + +// Win32 wait/event constants (used by the cross-platform sync wrappers) +# define INFINITE 0xFFFFFFFF +# define WAIT_OBJECT_0 0x00000000 + +// Win32 invalid handle sentinel (returned by the cross-platform file/serial wrappers) +# define INVALID_HANDLE_VALUE ((HANDLE)(SIZE_T)-1) + +// Win32 console-control event codes (kept at their Windows values so the +// shared BreakController() switch compiles unchanged). On Linux these are +// produced by the platform-signal layer from POSIX signals. +# define CTRL_C_EVENT 0 +# define CTRL_BREAK_EVENT 1 +# define CTRL_CLOSE_EVENT 2 +# define CTRL_LOGOFF_EVENT 5 +# define CTRL_SHUTDOWN_EVENT 6 + +// Win32 Sleep(milliseconds) -> POSIX usleep(microseconds) +# define Sleep(Milliseconds) usleep((useconds_t)(Milliseconds) * 1000) + +#endif // HYPERDBG_ENV_LINUX diff --git a/hyperdbg/include/platform/general/header/nt-list.h b/hyperdbg/include/platform/general/header/nt-list.h new file mode 100644 index 00000000..0dc4dd2b --- /dev/null +++ b/hyperdbg/include/platform/general/header/nt-list.h @@ -0,0 +1,145 @@ +/** + * @file nt-list.h + * @author Max Raulea (max.raulea@gmail.com) + * @brief Cross-platform NT-style intrusive doubly-linked list helpers + CONTAINING_RECORD + * @details The shared debugger code uses the NT LIST_ENTRY API (InitializeListHead, + * InsertHeadList, RemoveEntryList, CONTAINING_RECORD, ...). On Windows these + * come from (or, under USE_NATIVE_SDK_HEADERS, from the in-tree + * platform/user/header/Windows.h). Platforms whose system headers don't ship + * them (Linux) get them here, so the shared code compiles unchanged. + * + * These operate on the exact LIST_ENTRY {Flink, Blink} layout defined in + * SDK/headers/DataTypes.h, which is part of the kernel<->user IOCTL ABI -- + * that's why we mirror the NT list rather than reaching for sys/queue.h + * (different layout + a colliding LIST_ENTRY name). + * + * The body is compiled only where the OS headers don't already provide these + * (i.e. not on Windows), so including this unconditionally is safe. + * + * @version 0.20 + * @date 2026-06-16 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#ifndef _WIN32 + +# include // offsetof + +// +// Given the address of a LIST_ENTRY field embedded in a struct, recover the +// address of the containing struct. +// +# ifndef CONTAINING_RECORD +# define CONTAINING_RECORD(address, type, field) \ + ((type *)((char *)(address) - offsetof(type, field))) +# endif + +// +// Initialize a list head to the empty (points-to-self) state. +// +static inline VOID +InitializeListHead(PLIST_ENTRY ListHead) +{ + ListHead->Flink = ListHead->Blink = ListHead; +} + +// +// TRUE if the list has no entries. +// +static inline BOOLEAN +IsListEmpty(const LIST_ENTRY * ListHead) +{ + return (BOOLEAN)(ListHead->Flink == ListHead); +} + +// +// Unlink an entry. Returns TRUE if the list is now empty. +// +static inline BOOLEAN +RemoveEntryList(PLIST_ENTRY Entry) +{ + PLIST_ENTRY Flink = Entry->Flink; + PLIST_ENTRY Blink = Entry->Blink; + + Blink->Flink = Flink; + Flink->Blink = Blink; + + return (BOOLEAN)(Flink == Blink); +} + +// +// Unlink and return the first entry. +// +static inline PLIST_ENTRY +RemoveHeadList(PLIST_ENTRY ListHead) +{ + PLIST_ENTRY Entry = ListHead->Flink; + PLIST_ENTRY Flink = Entry->Flink; + + ListHead->Flink = Flink; + Flink->Blink = ListHead; + + return Entry; +} + +// +// Unlink and return the last entry. +// +static inline PLIST_ENTRY +RemoveTailList(PLIST_ENTRY ListHead) +{ + PLIST_ENTRY Entry = ListHead->Blink; + PLIST_ENTRY Blink = Entry->Blink; + + ListHead->Blink = Blink; + Blink->Flink = ListHead; + + return Entry; +} + +// +// Insert an entry at the tail of the list. +// +static inline VOID +InsertTailList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry) +{ + PLIST_ENTRY Blink = ListHead->Blink; + + Entry->Flink = ListHead; + Entry->Blink = Blink; + Blink->Flink = Entry; + ListHead->Blink = Entry; +} + +// +// Insert an entry at the head of the list. +// +static inline VOID +InsertHeadList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry) +{ + PLIST_ENTRY Flink = ListHead->Flink; + + Entry->Flink = Flink; + Entry->Blink = ListHead; + Flink->Blink = Entry; + ListHead->Flink = Entry; +} + +// +// Splice the entries of ListToAppend onto the tail of ListHead. +// +static inline VOID +AppendTailList(PLIST_ENTRY ListHead, PLIST_ENTRY ListToAppend) +{ + PLIST_ENTRY ListEnd = ListHead->Blink; + + ListHead->Blink->Flink = ListToAppend; + ListHead->Blink = ListToAppend->Blink; + ListToAppend->Blink->Flink = ListHead; + ListToAppend->Blink = ListEnd; +} + +#endif // !_WIN32 diff --git a/hyperdbg/include/platform/kernel/code/PlatformBroadcast.c b/hyperdbg/include/platform/kernel/code/PlatformBroadcast.c new file mode 100644 index 00000000..4c097194 --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformBroadcast.c @@ -0,0 +1,44 @@ +/** + * @file PlatformBroadcast.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for broadcasting routines + * @details + * @version 0.19 + * @date 2026-05-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformBroadcast.h" +#endif // defined(__linux__) + +/** + * @brief This function synchronize the function execution for a single core + * + * @return VOID + */ +VOID +PlatformBroadcastSynchronizeEndOfRoutine(PVOID SystemArgument1, PVOID SystemArgument2) +{ +#if defined(_WIN32) || defined(_WIN64) + // + // Wait for all DPCs to synchronize at this point + // + KeSignalCallDpcSynchronize(SystemArgument2); + + // + // Mark the DPC as being complete + // + KeSignalCallDpcDone(SystemArgument1); + +#elif defined(__linux__) + // + // Not needed for Linux + // +#else +# error "Unsupported platform" +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformCpu.c b/hyperdbg/include/platform/kernel/code/PlatformCpu.c new file mode 100644 index 00000000..eaece365 --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformCpu.c @@ -0,0 +1,62 @@ +/** + * @file PlatformCpu.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for CPU and processor queries + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformCpu.h" +#endif // defined(__linux__) + +/** + * @brief Get the count of active logical processors + * + * @return ULONG + */ +ULONG +PlatformCpuGetActiveProcessorCount(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + + return KeQueryActiveProcessorCount(0); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Get the current logical processor number + * + * @return ULONG + */ +ULONG +PlatformCpuGetCurrentProcessorNumber(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + + return KeGetCurrentProcessorNumberEx(NULL); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformDbg.c b/hyperdbg/include/platform/kernel/code/PlatformDbg.c new file mode 100644 index 00000000..f1f866ec --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformDbg.c @@ -0,0 +1,44 @@ +/** + * @file PlatformDbg.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for kernel debug output + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformDbg.h" +#endif // defined(__linux__) + +/** + * @brief Print a debug message to the kernel debugger + * + * @param Format printf-style format string + * @param ... Variable arguments + * @return VOID + */ +VOID +PlatformDbgPrint(const CHAR * Format, ...) +{ +#if defined(_WIN32) || defined(_WIN64) + + va_list ArgList; + va_start(ArgList, Format); + vDbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, Format, ArgList); + va_end(ArgList); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformDpc.c b/hyperdbg/include/platform/kernel/code/PlatformDpc.c new file mode 100644 index 00000000..6c459699 --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformDpc.c @@ -0,0 +1,68 @@ +/** + * @file PlatformDpc.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for Deferred Procedure Call (DPC) management + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformDpc.h" +#endif // defined(__linux__) + +/** + * @brief Initialize a DPC object + * + * @param Dpc Pointer to the KDPC structure to initialize + * @param DeferredRoutine The deferred procedure to be called + * @param DeferredContext Optional context passed to the deferred routine + * @return VOID + */ +VOID +PlatformDpcInitialize(PRKDPC Dpc, PKDEFERRED_ROUTINE DeferredRoutine, PVOID DeferredContext) +{ +#if defined(_WIN32) || defined(_WIN64) + + KeInitializeDpc(Dpc, DeferredRoutine, DeferredContext); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Insert a DPC into the system DPC queue for execution + * + * @param Dpc Pointer to the initialized KDPC structure + * @param SystemArgument1 First system-defined argument passed to the deferred routine + * @param SystemArgument2 Second system-defined argument passed to the deferred routine + * @return BOOLEAN TRUE if the DPC was successfully queued, FALSE if it was already in the queue + */ +BOOLEAN +PlatformDpcInsertQueueDpc(PRKDPC Dpc, PVOID SystemArgument1, PVOID SystemArgument2) +{ +#if defined(_WIN32) || defined(_WIN64) + + return KeInsertQueueDpc(Dpc, SystemArgument1, SystemArgument2); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformEvent.c b/hyperdbg/include/platform/kernel/code/PlatformEvent.c new file mode 100644 index 00000000..aed1673c --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformEvent.c @@ -0,0 +1,105 @@ +/** + * @file PlatformEvent.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for kernel event and object management + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformEvent.h" +#endif // defined(__linux__) + +/** + * @brief Dereference a kernel object, decrementing its reference count + * + * @param Object Pointer to the kernel object to dereference + * @return VOID + */ +VOID +PlatformObjectDereference(PVOID Object) +{ +#if defined(_WIN32) || defined(_WIN64) + + ObDereferenceObject(Object); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Signal (set) a kernel event object + * + * @param Event Pointer to the KEVENT to signal + * @param Increment Priority increment for any waiting threads to be awakened + * @param Wait If TRUE, the caller intends to immediately call a wait routine after this call + * @return LONG The previous signal state of the event + */ +LONG +PlatformEventSet(PKEVENT Event, KPRIORITY Increment, BOOLEAN Wait) +{ +#if defined(_WIN32) || defined(_WIN64) + + return KeSetEvent(Event, Increment, Wait); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Obtain a pointer to a kernel object by its user-mode handle and increment its reference count + * + * @param Handle User-mode handle referencing the kernel object + * @param DesiredAccess Access mask for the requested access rights + * @param ObjectType Pointer to the object type object (e.g., *ExEventObjectType); NULL to skip type check + * @param AccessMode Processor mode to use for access checks (KernelMode or UserMode) + * @param Object Receives a pointer to the referenced kernel object body + * @param HandleInformation Optional; receives access state information + * @return NTSTATUS STATUS_SUCCESS on success, or an error code on failure + */ +NTSTATUS +PlatformObjectReferenceByHandle(HANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID * Object, + POBJECT_HANDLE_INFORMATION HandleInformation) +{ +#if defined(_WIN32) || defined(_WIN64) + + return ObReferenceObjectByHandle(Handle, + DesiredAccess, + ObjectType, + AccessMode, + Object, + HandleInformation); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformIntrinsics.c b/hyperdbg/include/platform/kernel/code/PlatformIntrinsics.c new file mode 100644 index 00000000..3233d67e --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformIntrinsics.c @@ -0,0 +1,792 @@ +/** + * @file PlatformIntrinsics.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for intrinsic functions (x86 instructions) + * @details + * @version 0.19 + * @date 2026-04-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformIntrinsics.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// CR Registers // +////////////////////////////////////////////////// + +/** + * @brief Read CR0 + * + * @return ULONG_PTR + */ +inline ULONG_PTR +CpuReadCr0(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + return __readcr0(); +#elif defined(__linux__) + ULONG_PTR __val; + __asm__ __volatile__("mov %%cr0, %0" : "=r"(__val)); + return __val; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write CR0 + * + * @param Cr0Value + */ +inline VOID +CpuWriteCr0(ULONG_PTR Cr0Value) +{ +#if defined(_WIN32) || defined(_WIN64) + __writecr0(Cr0Value); +#elif defined(__linux__) + __asm__ __volatile__("mov %0, %%cr0" : : "r"(Cr0Value) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Read CR2 + * + * @return ULONG_PTR + */ +inline ULONG_PTR +CpuReadCr2(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + return __readcr2(); +#elif defined(__linux__) + ULONG_PTR __val; + __asm__ __volatile__("mov %%cr2, %0" : "=r"(__val)); + return __val; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write CR2 + * + * @param Cr2Value + */ +inline VOID +CpuWriteCr2(ULONG_PTR Cr2Value) +{ +#if defined(_WIN32) || defined(_WIN64) + __writecr2(Cr2Value); +#elif defined(__linux__) + __asm__ __volatile__("mov %0, %%cr2" : : "r"(Cr2Value) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Read CR3 + * + * @return ULONG_PTR + */ +inline ULONG_PTR +CpuReadCr3(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + return __readcr3(); +#elif defined(__linux__) + ULONG_PTR __val; + __asm__ __volatile__("mov %%cr3, %0" : "=r"(__val)); + return __val; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write CR3 + * + * @param Cr3Value + */ +inline VOID +CpuWriteCr3(ULONG_PTR Cr3Value) +{ +#if defined(_WIN32) || defined(_WIN64) + __writecr3(Cr3Value); +#elif defined(__linux__) + __asm__ __volatile__("mov %0, %%cr3" : : "r"(Cr3Value) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Read CR4 + * + * @return ULONG_PTR + */ +inline ULONG_PTR +CpuReadCr4(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + return __readcr4(); +#elif defined(__linux__) + ULONG_PTR __val; + __asm__ __volatile__("mov %%cr4, %0" : "=r"(__val)); + return __val; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write CR4 + * + * @param Cr4Value + */ +inline VOID +CpuWriteCr4(ULONG_PTR Cr4Value) +{ +#if defined(_WIN32) || defined(_WIN64) + __writecr4(Cr4Value); +#elif defined(__linux__) + __asm__ __volatile__("mov %0, %%cr4" : : "r"(Cr4Value) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Read CR8 + * + * @return ULONG_PTR + */ +inline ULONG_PTR +CpuReadCr8(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + return __readcr8(); +#elif defined(__linux__) + ULONG_PTR __val; + __asm__ __volatile__("mov %%cr8, %0" : "=r"(__val)); + return __val; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write CR8 + * + * @param Cr8Value + */ +inline VOID +CpuWriteCr8(ULONG_PTR Cr8Value) +{ +#if defined(_WIN32) || defined(_WIN64) + __writecr8(Cr8Value); +#elif defined(__linux__) + __asm__ __volatile__("mov %0, %%cr8" : : "r"(Cr8Value) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// MSR Instructions // +////////////////////////////////////////////////// + +/** + * @brief Read an MSR + * + * @param MsrAddress + * @return UINT64 + */ +inline UINT64 +CpuReadMsr(ULONG MsrAddress) +{ +#if defined(_WIN32) || defined(_WIN64) + return __readmsr(MsrAddress); +#elif defined(__linux__) + UINT32 __lo, __hi; + __asm__ __volatile__("rdmsr" : "=a"(__lo), "=d"(__hi) : "c"(MsrAddress)); + return ((UINT64)__hi << 32) | __lo; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write an MSR + * + * @param MsrAddress + * @param MsrValue + */ +inline VOID +CpuWriteMsr(ULONG MsrAddress, UINT64 MsrValue) +{ +#if defined(_WIN32) || defined(_WIN64) + __writemsr(MsrAddress, MsrValue); +#elif defined(__linux__) + __asm__ __volatile__("wrmsr" : : "c"(MsrAddress), "a"((UINT32)MsrValue), "d"((UINT32)(MsrValue >> 32))); +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// CPUID Instructions // +////////////////////////////////////////////////// + +/** + * @brief Execute CPUID + * + * @param CpuInfo + * @param FunctionId + */ +inline VOID +CpuCpuId(INT32 * CpuInfo, INT32 FunctionId) +{ +#if defined(_WIN32) || defined(_WIN64) + __cpuid(CpuInfo, FunctionId); +#elif defined(__linux__) + __asm__ __volatile__("cpuid" : "=a"(CpuInfo[0]), "=b"(CpuInfo[1]), "=c"(CpuInfo[2]), "=d"(CpuInfo[3]) : "a"(FunctionId), "c"(0)); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Execute CPUID with sub-leaf + * + * @param CpuInfo + * @param FunctionId + * @param SubFunctionId + */ +inline VOID +CpuCpuIdEx(INT32 * CpuInfo, INT32 FunctionId, INT32 SubFunctionId) +{ +#if defined(_WIN32) || defined(_WIN64) + __cpuidex(CpuInfo, FunctionId, SubFunctionId); +#elif defined(__linux__) + __asm__ __volatile__("cpuid" : "=a"(CpuInfo[0]), "=b"(CpuInfo[1]), "=c"(CpuInfo[2]), "=d"(CpuInfo[3]) : "a"(FunctionId), "c"(SubFunctionId)); +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// TSC Instructions // +////////////////////////////////////////////////// + +/** + * @brief Read Time-Stamp Counter + * + * @return UINT64 + */ +inline UINT64 +CpuReadTsc(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + return __rdtsc(); +#elif defined(__linux__) + UINT32 __lo, __hi; + __asm__ __volatile__("rdtsc" : "=a"(__lo), "=d"(__hi)); + return ((UINT64)__hi << 32) | __lo; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Read Time-Stamp Counter and Processor ID + * + * @param Aux + * @return UINT64 + */ +inline UINT64 +CpuReadTscp(UINT32 * Aux) +{ +#if defined(_WIN32) || defined(_WIN64) + return __rdtscp(Aux); +#elif defined(__linux__) + UINT32 __lo, __hi; + __asm__ __volatile__("rdtscp" : "=a"(__lo), "=d"(__hi), "=c"(*Aux)); + return ((UINT64)__hi << 32) | __lo; +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// Interlocked (Atomic) Operations // +////////////////////////////////////////////////// + +/** + * @brief Atomic 64-bit exchange + */ +inline INT64 +CpuInterlockedExchange64(INT64 volatile * Target, INT64 Value) +{ +#if defined(_WIN32) || defined(_WIN64) + return InterlockedExchange64(Target, Value); +#elif defined(__linux__) + return __atomic_exchange_n(Target, Value, __ATOMIC_SEQ_CST); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Atomic 64-bit exchange-add + */ +inline INT64 +CpuInterlockedExchangeAdd64(INT64 volatile * Addend, INT64 Value) +{ +#if defined(_WIN32) || defined(_WIN64) + return InterlockedExchangeAdd64(Addend, Value); +#elif defined(__linux__) + return __atomic_fetch_add(Addend, Value, __ATOMIC_SEQ_CST); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Atomic 64-bit increment + */ +inline INT64 +CpuInterlockedIncrement64(INT64 volatile * Addend) +{ +#if defined(_WIN32) || defined(_WIN64) + return InterlockedIncrement64(Addend); +#elif defined(__linux__) + return __atomic_add_fetch(Addend, 1LL, __ATOMIC_SEQ_CST); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Atomic 64-bit decrement + */ +inline INT64 +CpuInterlockedDecrement64(INT64 volatile * Addend) +{ +#if defined(_WIN32) || defined(_WIN64) + return InterlockedDecrement64(Addend); +#elif defined(__linux__) + return __atomic_sub_fetch(Addend, 1LL, __ATOMIC_SEQ_CST); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Atomic 64-bit compare-exchange + */ +inline INT64 +CpuInterlockedCompareExchange64(INT64 volatile * Destination, INT64 ExChange, INT64 Comparand) +{ +#if defined(_WIN32) || defined(_WIN64) + return InterlockedCompareExchange64(Destination, ExChange, Comparand); +#elif defined(__linux__) + INT64 Expected = Comparand; + __atomic_compare_exchange_n(Destination, &Expected, ExChange, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return Expected; +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// Descriptor Table Instructions // +////////////////////////////////////////////////// + +/** + * @brief Store Interrupt Descriptor Table Register + * + * @param Idtr + */ +inline VOID +CpuSidt(VOID * Idtr) +{ +#if defined(_WIN32) || defined(_WIN64) + __sidt(Idtr); +#elif defined(__linux__) + __asm__ __volatile__("sidt %0" : "=m"(*(char *)Idtr) : : "memory"); +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// TLB Instructions // +////////////////////////////////////////////////// + +/** + * @brief Invalidate TLB entry for a virtual address + * + * @param Address + */ +inline VOID +CpuInvlpg(VOID * Address) +{ +#if defined(_WIN32) || defined(_WIN64) + __invlpg(Address); +#elif defined(__linux__) + __asm__ __volatile__("invlpg (%0)" : : "r"(Address) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// String Store Instructions // +////////////////////////////////////////////////// + +/** + * @brief Store UINT64 value to memory Count times + * + * @param Destination + * @param Value + * @param Count + */ +inline VOID +CpuStosQ(UINT64 * Destination, UINT64 Value, SIZE_T Count) +{ +#if defined(_WIN32) || defined(_WIN64) + __stosq((unsigned __int64 *)Destination, Value, Count); +#elif defined(__linux__) + __asm__ __volatile__("rep stosq" : "+D"(Destination), "+c"(Count) : "a"(Value) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// Bit Scan Instructions // +////////////////////////////////////////////////// + +/** + * @brief Bit scan forward (64-bit) + * + * @param Index + * @param Mask + * @return UCHAR + */ +inline UCHAR +CpuBitScanForward64(ULONG * Index, UINT64 Mask) +{ +#if defined(_WIN32) || defined(_WIN64) + return (UCHAR)_BitScanForward64((unsigned long *)Index, Mask); +#elif defined(__linux__) + if (!Mask) + return 0; + *Index = (ULONG)__builtin_ctzll(Mask); + return 1; +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// Misc Instructions // +////////////////////////////////////////////////// + +/** + * @brief Execute NOP + */ +inline VOID +CpuNop(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + __nop(); +#elif defined(__linux__) + __asm__ __volatile__("nop"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Execute PAUSE (spin-wait hint) + */ +inline VOID +CpuPause(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + _mm_pause(); +#elif defined(__linux__) + __asm__ __volatile__("pause"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Return the segment limit for a selector + * + * @param Selector + * @return ULONG + */ +inline ULONG +CpuSegmentLimit(UINT32 Selector) +{ +#if defined(_WIN32) || defined(_WIN64) + return __segmentlimit(Selector); +#elif defined(__linux__) + + UINT32 Limit; + + __asm__ __volatile__( + "lsl %1, %0" + : "=r"(Limit) + : "rm"(Selector) + : "cc"); + + return Limit; + +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// I/O Port Instructions // +////////////////////////////////////////////////// + +/** + * @brief Read a byte from an I/O port + * + * @param Port + * @return UINT8 + */ +inline UINT8 +CpuIoInByte(UINT16 Port) +{ +#if defined(_WIN32) || defined(_WIN64) + return __inbyte(Port); +#elif defined(__linux__) + UINT8 __val; + __asm__ __volatile__("inb %1, %0" : "=a"(__val) : "Nd"(Port)); + return __val; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Read a word from an I/O port + * + * @param Port + * @return UINT16 + */ +inline UINT16 +CpuIoInWord(UINT16 Port) +{ +#if defined(_WIN32) || defined(_WIN64) + return __inword(Port); +#elif defined(__linux__) + UINT16 __val; + __asm__ __volatile__("inw %1, %0" : "=a"(__val) : "Nd"(Port)); + return __val; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Read a dword from an I/O port + * + * @param Port + * @return UINT32 + */ +inline UINT32 +CpuIoInDword(UINT16 Port) +{ +#if defined(_WIN32) || defined(_WIN64) + return __indword(Port); +#elif defined(__linux__) + UINT32 __val; + __asm__ __volatile__("inl %1, %0" : "=a"(__val) : "Nd"(Port)); + return __val; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Read a byte string from an I/O port + * + * @param Port + * @param Data + * @param Size + */ +inline VOID +CpuIoInByteString(UINT16 Port, UINT8 * Data, UINT32 Size) +{ +#if defined(_WIN32) || defined(_WIN64) + __inbytestring(Port, Data, Size); +#elif defined(__linux__) + __asm__ __volatile__("rep insb" : "+D"(Data), "+c"(Size) : "d"(Port) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Read a word string from an I/O port + * + * @param Port + * @param Data + * @param Size + */ +inline VOID +CpuIoInWordString(UINT16 Port, UINT16 * Data, UINT32 Size) +{ +#if defined(_WIN32) || defined(_WIN64) + __inwordstring(Port, Data, Size); +#elif defined(__linux__) + __asm__ __volatile__("rep insw" : "+D"(Data), "+c"(Size) : "d"(Port) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Read a dword string from an I/O port + * + * @param Port + * @param Data + * @param Size + */ +inline VOID +CpuIoInDwordString(UINT16 Port, UINT32 * Data, UINT32 Size) +{ +#if defined(_WIN32) || defined(_WIN64) + __indwordstring(Port, (unsigned long *)Data, Size); +#elif defined(__linux__) + __asm__ __volatile__("rep insl" : "+D"(Data), "+c"(Size) : "d"(Port) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write a byte to an I/O port + * + * @param Port + * @param Value + */ +inline VOID +CpuIoOutByte(UINT16 Port, UINT8 Value) +{ +#if defined(_WIN32) || defined(_WIN64) + __outbyte(Port, Value); +#elif defined(__linux__) + __asm__ __volatile__("outb %0, %1" : : "a"(Value), "Nd"(Port)); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write a word to an I/O port + * + * @param Port + * @param Value + */ +inline VOID +CpuIoOutWord(UINT16 Port, UINT16 Value) +{ +#if defined(_WIN32) || defined(_WIN64) + __outword(Port, Value); +#elif defined(__linux__) + __asm__ __volatile__("outw %0, %1" : : "a"(Value), "Nd"(Port)); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write a dword to an I/O port + * + * @param Port + * @param Value + */ +inline VOID +CpuIoOutDword(UINT16 Port, UINT32 Value) +{ +#if defined(_WIN32) || defined(_WIN64) + __outdword(Port, Value); +#elif defined(__linux__) + __asm__ __volatile__("outl %0, %1" : : "a"(Value), "Nd"(Port)); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write a byte string to an I/O port + * + * @param Port + * @param Data + * @param Count + */ +inline VOID +CpuIoOutByteString(UINT16 Port, UINT8 * Data, UINT32 Count) +{ +#if defined(_WIN32) || defined(_WIN64) + __outbytestring(Port, Data, Count); +#elif defined(__linux__) + __asm__ __volatile__("rep outsb" : "+S"(Data), "+c"(Count) : "d"(Port) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write a word string to an I/O port + * + * @param Port + * @param Data + * @param Count + */ +inline VOID +CpuIoOutWordString(UINT16 Port, UINT16 * Data, UINT32 Count) +{ +#if defined(_WIN32) || defined(_WIN64) + __outwordstring(Port, Data, Count); +#elif defined(__linux__) + __asm__ __volatile__("rep outsw" : "+S"(Data), "+c"(Count) : "d"(Port) : "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Write a dword string to an I/O port + * + * @param Port + * @param Data + * @param Count + */ +inline VOID +CpuIoOutDwordString(UINT16 Port, UINT32 * Data, UINT32 Count) +{ +#if defined(_WIN32) || defined(_WIN64) + __outdwordstring(Port, (unsigned long *)Data, Count); +#elif defined(__linux__) + __asm__ __volatile__("rep outsl" : "+S"(Data), "+c"(Count) : "d"(Port) : "memory"); +#else +# error "Unsupported platform" +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformIntrinsicsVmx.c b/hyperdbg/include/platform/kernel/code/PlatformIntrinsicsVmx.c new file mode 100644 index 00000000..e3abc6fa --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformIntrinsicsVmx.c @@ -0,0 +1,456 @@ +/** + * @file PlatformIntrinsicsVmx.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for intrinsic functions (VMX instructions) + * @details + * @version 0.19 + * @date 2026-04-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformIntrinsicsVmx.h" +#endif // defined(__linux__) + +#if defined(__linux__) + +/** + * @brief Linux inline-asm helper for VMREAD + * Mirrors __vmx_vmread: returns 0=success, 1=VMfail valid (ZF), 2=VMfail invalid (CF) + */ +static inline UCHAR +__linux_vmx_vmread(size_t Field, size_t * FieldValue) +{ + unsigned char cf, zf; + __asm__ __volatile__( + "vmread %[field], %[val] \n\t" + "setc %[cf] \n\t" + "setz %[zf] \n\t" + : [val] "=rm"(*FieldValue), + [cf] "=qm"(cf), + [zf] "=qm"(zf) + : [field] "r"(Field) + : "cc"); + return cf ? 2 : (zf ? 1 : 0); +} + +/** + * @brief Linux inline-asm helper for VMWRITE + * Mirrors __vmx_vmwrite: returns 0=success, 1=VMfail valid (ZF), 2=VMfail invalid (CF) + */ +static inline UCHAR +__linux_vmx_vmwrite(size_t Field, size_t FieldValue) +{ + unsigned char cf, zf; + __asm__ __volatile__( + "vmwrite %[val], %[field] \n\t" + "setc %[cf] \n\t" + "setz %[zf] \n\t" + : [cf] "=qm"(cf), + [zf] "=qm"(zf) + : [val] "rm"(FieldValue), + [field] "r"(Field) + : "cc"); + return cf ? 2 : (zf ? 1 : 0); +} + +/** + * @brief Linux inline-asm helper for VMPTRST + * Stores the current VMCS pointer into the given physical address + */ +static inline VOID +__linux_vmx_vmptrst(UINT64 * VmcsPhysicalAddress) +{ + __asm__ __volatile__( + "vmptrst %[addr]" + : + : [addr] "m"(*VmcsPhysicalAddress) + : "memory"); +} + +/** + * @brief Linux inline-asm helper for VMPTRLD + * Returns 0=success, 1=VMfail valid (ZF), 2=VMfail invalid (CF) + */ +static inline UCHAR +__linux_vmx_vmptrld(UINT64 * VmcsPhysicalAddress) +{ + unsigned char cf, zf; + __asm__ __volatile__( + "vmptrld %[addr] \n\t" + "setc %[cf] \n\t" + "setz %[zf] \n\t" + : [cf] "=qm"(cf), + [zf] "=qm"(zf) + : [addr] "m"(*VmcsPhysicalAddress) + : "cc", "memory"); + return cf ? 2 : (zf ? 1 : 0); +} + +/** + * @brief Linux inline-asm helper for VMCLEAR + * Returns 0=success, 1=VMfail valid (ZF), 2=VMfail invalid (CF) + */ +static inline UCHAR +__linux_vmx_vmclear(UINT64 * VmcsPhysicalAddress) +{ + unsigned char cf, zf; + __asm__ __volatile__( + "vmclear %[addr] \n\t" + "setc %[cf] \n\t" + "setz %[zf] \n\t" + : [cf] "=qm"(cf), + [zf] "=qm"(zf) + : [addr] "m"(*VmcsPhysicalAddress) + : "cc", "memory"); + return cf ? 2 : (zf ? 1 : 0); +} + +/** + * @brief Linux inline-asm helper for VMXON + * Returns 0=success, 1=VMfail valid (ZF), 2=VMfail invalid (CF) + */ +static inline UCHAR +__linux_vmx_vmxon(UINT64 * VmxonRegionPhysicalAddress) +{ + unsigned char cf, zf; + __asm__ __volatile__( + "vmxon %[addr] \n\t" + "setc %[cf] \n\t" + "setz %[zf] \n\t" + : [cf] "=qm"(cf), + [zf] "=qm"(zf) + : [addr] "m"(*VmxonRegionPhysicalAddress) + : "cc", "memory"); + return cf ? 2 : (zf ? 1 : 0); +} + +#endif // defined(__linux__) + +/** + * @brief VMX VMREAD instruction (64-bit) + * @param Field + * @param FieldValue + * + * @return UCHAR + */ +inline UCHAR +VmxVmread64(size_t Field, + UINT64 FieldValue) +{ +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmread((size_t)Field, (size_t *)FieldValue); +#elif defined(__linux__) + return __linux_vmx_vmread((size_t)Field, (size_t *)FieldValue); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMREAD instruction (32-bit) + * @param Field + * @param FieldValue + * + * @return UCHAR + */ +inline UCHAR +VmxVmread32(size_t Field, + UINT32 FieldValue) +{ + UINT64 TargetField = 0ull; + TargetField = FieldValue; + +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmread((size_t)Field, (size_t *)TargetField); +#elif defined(__linux__) + return __linux_vmx_vmread((size_t)Field, (size_t *)TargetField); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMREAD instruction (16-bit) + * @param Field + * @param FieldValue + * + * @return UCHAR + */ +inline UCHAR +VmxVmread16(size_t Field, + UINT16 FieldValue) +{ + UINT64 TargetField = 0ull; + TargetField = FieldValue; + +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmread((size_t)Field, (size_t *)TargetField); +#elif defined(__linux__) + return __linux_vmx_vmread((size_t)Field, (size_t *)TargetField); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMREAD instruction (64-bit, pointer variant) + * @param Field + * @param FieldValue + * + * @return UCHAR + */ +inline UCHAR +VmxVmread64P(size_t Field, + UINT64 * FieldValue) +{ +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmread((size_t)Field, (size_t *)FieldValue); +#elif defined(__linux__) + return __linux_vmx_vmread((size_t)Field, (size_t *)FieldValue); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMREAD instruction (32-bit, pointer variant) + * @param Field + * @param FieldValue + * + * @return UCHAR + */ +inline UCHAR +VmxVmread32P(size_t Field, + UINT32 * FieldValue) +{ + UINT64 TargetField = 0ull; + TargetField = (UINT64)FieldValue; + +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmread((size_t)Field, (size_t *)TargetField); +#elif defined(__linux__) + return __linux_vmx_vmread((size_t)Field, (size_t *)TargetField); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMREAD instruction (16-bit, pointer variant) + * @param Field + * @param FieldValue + * + * @return UCHAR + */ +inline UCHAR +VmxVmread16P(size_t Field, + UINT16 * FieldValue) +{ + UINT64 TargetField = 0ull; + TargetField = (UINT64)FieldValue; + +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmread((size_t)Field, (size_t *)TargetField); +#elif defined(__linux__) + return __linux_vmx_vmread((size_t)Field, (size_t *)TargetField); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMWRITE instruction (64-bit) + * @param Field + * @param FieldValue + * + * @return UCHAR + */ +inline UCHAR +VmxVmwrite64(size_t Field, + UINT64 FieldValue) +{ +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmwrite((size_t)Field, (size_t)FieldValue); +#elif defined(__linux__) + return __linux_vmx_vmwrite((size_t)Field, (size_t)FieldValue); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMWRITE instruction (32-bit) + * @param Field + * @param FieldValue + * + * @return UCHAR + */ +inline UCHAR +VmxVmwrite32(size_t Field, + UINT32 FieldValue) +{ + UINT64 TargetValue = NULL64_ZERO; + TargetValue = (UINT64)FieldValue; + +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmwrite((size_t)Field, (size_t)TargetValue); +#elif defined(__linux__) + return __linux_vmx_vmwrite((size_t)Field, (size_t)TargetValue); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMWRITE instruction (16-bit) + * @param Field + * @param FieldValue + * + * @return UCHAR + */ +inline UCHAR +VmxVmwrite16(size_t Field, + UINT16 FieldValue) +{ + UINT64 TargetValue = NULL64_ZERO; + TargetValue = (UINT64)FieldValue; + +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmwrite((size_t)Field, (size_t)TargetValue); +#elif defined(__linux__) + return __linux_vmx_vmwrite((size_t)Field, (size_t)TargetValue); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMPTRST instruction + * + * @param VmcsPhysicalAddress + * + * @return VOID + */ +inline VOID +VmxVmptrst(UINT64 * VmcsPhysicalAddress) +{ +#if defined(_WIN32) || defined(_WIN64) + __vmx_vmptrst(VmcsPhysicalAddress); +#elif defined(__linux__) + __linux_vmx_vmptrst(VmcsPhysicalAddress); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMRESUME instruction + * + * @return VOID + */ +inline VOID +VmxVmresume(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + __vmx_vmresume(); +#elif defined(__linux__) + __asm__ __volatile__("vmresume" ::: "cc", "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMXOFF instruction + * + * @return VOID + */ +inline VOID +VmxVmxoff(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + __vmx_off(); +#elif defined(__linux__) + __asm__ __volatile__("vmxoff" ::: "cc", "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMLAUNCH instruction + * + * @return VOID + */ +inline VOID +VmxVmlaunch(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + __vmx_vmlaunch(); +#elif defined(__linux__) + __asm__ __volatile__("vmlaunch" ::: "cc", "memory"); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMPTRLD instruction + * + * @param VmcsPhysicalAddress + * + * @return UCHAR + */ +inline UCHAR +VmxVmptrld(UINT64 * VmcsPhysicalAddress) +{ +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmptrld(VmcsPhysicalAddress); +#elif defined(__linux__) + return __linux_vmx_vmptrld(VmcsPhysicalAddress); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMCLEAR instruction + * + * @param VmcsPhysicalAddress + * + * @return UCHAR + */ +inline UCHAR +VmxVmclear(UINT64 * VmcsPhysicalAddress) +{ +#if defined(_WIN32) || defined(_WIN64) + return __vmx_vmclear(VmcsPhysicalAddress); +#elif defined(__linux__) + return __linux_vmx_vmclear(VmcsPhysicalAddress); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief VMX VMXON instruction + * + * @param VmxonRegionPhysicalAddress + * + * @return UCHAR + */ +inline UCHAR +VmxVmxon(UINT64 * VmxonRegionPhysicalAddress) +{ +#if defined(_WIN32) || defined(_WIN64) + return __vmx_on(VmxonRegionPhysicalAddress); +#elif defined(__linux__) + return __linux_vmx_vmxon(VmxonRegionPhysicalAddress); +#else +# error "Unsupported platform" +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformIo.c b/hyperdbg/include/platform/kernel/code/PlatformIo.c new file mode 100644 index 00000000..36af0a73 --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformIo.c @@ -0,0 +1,89 @@ +/** + * @file PlatformIo.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for I/O Request Packet (IRP) management + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformIo.h" +#endif // defined(__linux__) + +/** + * @brief Get the current I/O stack location from an IRP + * + * @param Irp Pointer to the IRP (I/O Request Packet) + * @return PIO_STACK_LOCATION Pointer to the current stack location + */ +PIO_STACK_LOCATION +PlatformIoGetCurrentIrpStackLocation(PIRP Irp) +{ +#if defined(_WIN32) || defined(_WIN64) + + return IoGetCurrentIrpStackLocation(Irp); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Complete an IRP and release it back to the I/O manager + * + * @param Irp Pointer to the IRP to complete + * @param PriorityBoost Priority boost value (e.g., IO_NO_INCREMENT) + * @return VOID + */ +VOID +PlatformIoCompleteRequest(PIRP Irp, CCHAR PriorityBoost) +{ +#if defined(_WIN32) || defined(_WIN64) + + IoCompleteRequest(Irp, PriorityBoost); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Mark the current IRP stack location as pending + * + * @param Irp Pointer to the IRP to mark as pending + * @return VOID + */ +VOID +PlatformIoMarkIrpPending(PIRP Irp) +{ +#if defined(_WIN32) || defined(_WIN64) + + IoMarkIrpPending(Irp); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformIrql.c b/hyperdbg/include/platform/kernel/code/PlatformIrql.c new file mode 100644 index 00000000..dd44f269 --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformIrql.c @@ -0,0 +1,63 @@ +/** + * @file PlatformIrql.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for IRQL management + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformIrql.h" +#endif // defined(__linux__) + +/** + * @brief Raise the current IRQL to DISPATCH_LEVEL + * + * @return KIRQL The previous IRQL before the raise + */ +KIRQL +PlatformIrqlRaiseToDpcLevel(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + + return KeRaiseIrqlToDpcLevel(); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Lower the current IRQL to the previously saved value + * + * @param OldIrql The previous IRQL to restore + * @return VOID + */ +VOID +PlatformIrqlLower(KIRQL OldIrql) +{ +#if defined(_WIN32) || defined(_WIN64) + + KeLowerIrql(OldIrql); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformMem.c b/hyperdbg/include/platform/kernel/code/PlatformMem.c new file mode 100644 index 00000000..27e8112d --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformMem.c @@ -0,0 +1,280 @@ +/** + * @file PlatformMem.c + * @author Behrooz Abbassi (BehroozAbbassi@hyperdbg.org) + * @author Sina Karvandi (sina@hyperdbg.org) + * @author alireza moradi (alish014) + * @brief Implementation of cross APIs for different platforms for memory allocation + * @details + * @version 0.1 + * @date 2022-01-17 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformMem.h" +#endif // defined(__linux__) + +/** + * @brief Platform independent wrapper for sprintf_s / snprintf + * + * @param Buffer output buffer + * @param BufferSize size of the output buffer + * @param Format format string + * @return INT number of characters written, or -1 on error + */ +INT +PlatformSprintf(char * Buffer, SIZE_T BufferSize, const char * Format, ...) +{ + va_list Args; + va_start(Args, Format); + INT Result; +#if defined(_WIN32) || defined(_WIN64) + Result = vsprintf_s(Buffer, BufferSize, Format, Args); +#elif defined(__linux__) + Result = vsnprintf(Buffer, BufferSize, Format, Args); +#else +# error "Unsupported platform" +#endif + va_end(Args); + return Result; +} + +///////////////////////////////////////////////// +/// ... New Unified API ... +///////////////////////////////////////////////// + +/** + * @brief Allocates a block of memory in the kernel pool. + * @details On Windows: Allocates from NonPagedPool and zeroes it. + * On Linux: Uses kzalloc (GFP_KERNEL) which zeroes memory. + * + * @param Size The number of bytes to allocate. + * @return PVOID Pointer to the allocated memory, or NULL on failure. + */ +PVOID +PlatformAllocateMemory( + SIZE_T Size) +{ +#ifdef _WIN32 + PVOID Result = ExAllocatePool2( + POOL_FLAG_NON_PAGED, // non-paged pool + Size, + POOLTAG); + + if (Result != NULL) + RtlSecureZeroMemory(Result, Size); + + return Result; +#else + // Linux Kernel: kzalloc allocates zeroed memory + PVOID ptr = kzalloc(Size, GFP_KERNEL); + + if (ptr) + { + printk(KERN_INFO "MemAllocKernel: Allocated %zu bytes at %px\n", Size, ptr); + } + else + { + printk(KERN_ERR "MemAllocKernel: failed to allocate %zu bytes\n", Size); + } + + return ptr; +#endif +} + +/** + * @brief Frees a previously allocated memory block. + * @param Memory Pointer to the memory block. Handles NULL safely. + */ +VOID +PlatformFreeMemory( + PVOID Memory) +{ + if (!Memory) + return; + +#ifdef _WIN32 + ExFreePoolWithTag(Memory, POOLTAG); +#else + kfree(Memory); +#endif +} + +/** + * @brief Writes data from a buffer to a memory address. + * @param Process Reserved (unused). + * @param Address Destination address. + * @param Buffer Source buffer. + * @param Size Number of bytes to copy. + * @return VOID + */ +VOID +PlatformWriteMemory( + PVOID Address, // Destination + PVOID Buffer, // Source + SIZE_T Size) +{ +#ifdef _WIN32 + RtlCopyMemory(Address, Buffer, Size); +#else + memcpy(Address, Buffer, Size); +#endif +} + +/** + * @brief Sets a memory block to a specific value. + * @param Destination Memory address. + * @param Value Value to set. + * @param Size Number of bytes. + */ +VOID +PlatformSetMemory( + PVOID Destination, + int Value, + SIZE_T Size) +{ + if (!Destination) + return; + +#ifdef _WIN32 + RtlFillMemory(Destination, Size, Value); +#else + memset(Destination, Value, Size); +#endif +} + +/** + * @brief Zeros a memory block. + * @param Destination Memory address. + * @param Size Number of bytes. + */ +VOID +PlatformZeroMemory( + PVOID Destination, + SIZE_T Size) +{ + if (!Destination) + return; + +#ifdef _WIN32 + RtlZeroMemory(Destination, Size); +#elif defined(__linux__) + memset(Destination, 0, Size); +#else +# error "Unsupported platform" +#endif +} + +///////////////////////////////////////////////// +/// ... Backward Compatibility / Specific APIs ... +///////////////////////////////////////////////// + +/** + * @brief Allocates contiguous zeroed physical memory. + * @details On Windows: Uses MmAllocateContiguousMemory. + * On Linux: Uses kmalloc (which is usually physically contiguous) or dma_alloc_coherent. + * For simplicity in this driver, we map to kzalloc. + * @param NumberOfBytes Size in bytes. + * @return PVOID Pointer to memory or NULL. + */ +PVOID +PlatformMemAllocateContiguousZeroedMemory(SIZE_T NumberOfBytes) +{ +#ifdef _WIN32 + PVOID Result = NULL; + PHYSICAL_ADDRESS MaxPhysicalAddr = {0}; + MaxPhysicalAddr.QuadPart = MAXULONG64; + + Result = MmAllocateContiguousMemory(NumberOfBytes, MaxPhysicalAddr); + if (Result != NULL) + RtlSecureZeroMemory(Result, NumberOfBytes); + return Result; +#else + // In Linux, kmalloc/kzalloc returns physically contiguous memory + // (unless vmalloc is used, which we aren't using here). + return kzalloc(NumberOfBytes, GFP_KERNEL); +#endif +} + +/** + * @brief Allocates non-paged pool memory. + * @param NumberOfBytes Size in bytes. + * @return PVOID Pointer to memory. + */ +PVOID +PlatformMemAllocateNonPagedPool(SIZE_T NumberOfBytes) +{ +#ifdef _WIN32 + return ExAllocatePool2( + POOL_FLAG_NON_PAGED, + NumberOfBytes, + POOLTAG); +#else + // Linux kernel memory is non-paged by default (except vmalloc) + return kmalloc(NumberOfBytes, GFP_KERNEL); +#endif +} + +/** + * @brief Allocates non-paged pool memory with quota charging. + * @param NumberOfBytes Size in bytes. + * @return PVOID Pointer to memory. + */ +PVOID +PlatformMemAllocateNonPagedPoolWithQuota(SIZE_T NumberOfBytes) +{ +#ifdef _WIN32 + // POOL_FLAG_USE_QUOTA is used with ExAllocatePool2 + // Note: Ensure your WDK supports ExAllocatePool2, otherwise use ExAllocatePoolWithQuotaTag + return ExAllocatePool2( + POOL_FLAG_NON_PAGED | POOL_FLAG_USE_QUOTA, + NumberOfBytes, + POOLTAG); +#else + // Quotas are not explicitly managed in simple Linux kernel allocations like this + return kmalloc(NumberOfBytes, GFP_KERNEL); +#endif +} + +/** + * @brief Allocates zeroed non-paged pool memory. + * @param NumberOfBytes Size in bytes. + * @return PVOID Pointer to memory. + */ +PVOID +PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes) +{ +#ifdef _WIN32 + PVOID Result = ExAllocatePool2( + POOL_FLAG_NON_PAGED, + NumberOfBytes, + POOLTAG); + if (Result != NULL) + RtlSecureZeroMemory(Result, NumberOfBytes); + return Result; +#else + return kzalloc(NumberOfBytes, GFP_KERNEL); +#endif +} + +/** + * @brief Frees a memory pool. + * @param BufferAddress Pointer to the memory to free. + * @return PVOID (Void pointer in original API, usually ignored). + */ +PVOID +PlatformMemFreePool(PVOID BufferAddress) +{ + if (!BufferAddress) + return NULL; + +#ifdef _WIN32 + ExFreePoolWithTag(BufferAddress, POOLTAG); +#else + kfree(BufferAddress); +#endif + return NULL; +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformProcess.c b/hyperdbg/include/platform/kernel/code/PlatformProcess.c new file mode 100644 index 00000000..5943df34 --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformProcess.c @@ -0,0 +1,131 @@ +/** + * @file PlatformProcess.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for process and thread queries + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformProcess.h" +#endif // defined(__linux__) + +/** + * @brief Get the current thread ID + * + * @return HANDLE + */ +HANDLE +PlatformProcessGetCurrentThreadId(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + + return PsGetCurrentThreadId(); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Get the current process ID + * + * @return HANDLE + */ +HANDLE +PlatformProcessGetCurrentProcessId(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + + return PsGetCurrentProcessId(); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Get the current process (PEPROCESS) + * + * @return PVOID Pointer to the EPROCESS structure for the current process + */ +PVOID +PlatformProcessGetCurrentProcess(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + + return (PVOID)PsGetCurrentProcess(); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Get the current thread (PETHREAD) + * + * @return PVOID Pointer to the ETHREAD structure for the current thread + */ +PVOID +PlatformProcessGetCurrentThread(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + + return (PVOID)PsGetCurrentThread(); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Get the TEB (Thread Environment Block) of the current thread + * + * @return PVOID Pointer to the TEB of the current thread + */ +PVOID +PlatformProcessGetCurrentThreadTeb(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + + return PsGetCurrentThreadTeb(); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformSpinlock.c b/hyperdbg/include/platform/kernel/code/PlatformSpinlock.c new file mode 100644 index 00000000..7e091499 --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformSpinlock.c @@ -0,0 +1,90 @@ +/** + * @file PlatformSpinlock.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for kernel spinlock operations + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformSpinlock.h" +#endif // defined(__linux__) + +/** + * @brief Initialize a kernel spinlock + * + * @param SpinLock Pointer to the KSPIN_LOCK to initialize + * @return VOID + */ +VOID +PlatformSpinlockInitialize(PKSPIN_LOCK SpinLock) +{ +#if defined(_WIN32) || defined(_WIN64) + + KeInitializeSpinLock(SpinLock); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Acquire a kernel spinlock, raising IRQL to DISPATCH_LEVEL + * + * @param SpinLock Pointer to the KSPIN_LOCK to acquire + * @param OldIrql Receives the previous IRQL value to be restored on release + * @return VOID + */ +VOID +PlatformSpinlockAcquire(PKSPIN_LOCK SpinLock, PKIRQL OldIrql) +{ +#if defined(_WIN32) || defined(_WIN64) + + KeAcquireSpinLock(SpinLock, OldIrql); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Release a previously acquired kernel spinlock and restore IRQL + * + * @param SpinLock Pointer to the KSPIN_LOCK to release + * @param OldIrql The previous IRQL value saved during acquire + * @return VOID + */ +VOID +PlatformSpinlockRelease(PKSPIN_LOCK SpinLock, KIRQL OldIrql) +{ +#if defined(_WIN32) || defined(_WIN64) + + KeReleaseSpinLock(SpinLock, OldIrql); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} diff --git a/hyperdbg/include/platform/kernel/code/PlatformTime.c b/hyperdbg/include/platform/kernel/code/PlatformTime.c new file mode 100644 index 00000000..dcb80a8d --- /dev/null +++ b/hyperdbg/include/platform/kernel/code/PlatformTime.c @@ -0,0 +1,90 @@ +/** + * @file PlatformTime.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for system time operations + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/PlatformTime.h" +#endif // defined(__linux__) + +/** + * @brief Query the current system time + * + * @param SystemTime Receives the current system time as a LARGE_INTEGER (100-nanosecond units since January 1, 1601) + * @return VOID + */ +VOID +PlatformTimeQuerySystemTime(PLARGE_INTEGER SystemTime) +{ +#if defined(_WIN32) || defined(_WIN64) + + KeQuerySystemTime(SystemTime); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Convert system time (UTC) to local time + * + * @param SystemTime Pointer to the system time value in UTC + * @param LocalTime Receives the converted local time value + * @return VOID + */ +VOID +PlatformTimeConvertToLocalTime(PLARGE_INTEGER SystemTime, PLARGE_INTEGER LocalTime) +{ +#if defined(_WIN32) || defined(_WIN64) + + ExSystemTimeToLocalTime(SystemTime, LocalTime); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} + +/** + * @brief Convert a LARGE_INTEGER time value to a TIME_FIELDS structure + * + * @param Time Pointer to the time value to convert + * @param TimeFields Receives the broken-down time fields (year, month, day, hour, minute, etc.) + * @return VOID + */ +VOID +PlatformTimeConvertToTimeFields(PLARGE_INTEGER Time, PTIME_FIELDS TimeFields) +{ +#if defined(_WIN32) || defined(_WIN64) + + RtlTimeToTimeFields(Time, TimeFields); + +#elif defined(__linux__) + +# error "Not yet implemented" + +#else + +# error "Unsupported platform" + +#endif +} diff --git a/hyperdbg/hprdbghv/header/common/Dpc.h b/hyperdbg/include/platform/kernel/header/PlatformBroadcast.h similarity index 56% rename from hyperdbg/hprdbghv/header/common/Dpc.h rename to hyperdbg/include/platform/kernel/header/PlatformBroadcast.h index 30b419ec..97b2bab1 100644 --- a/hyperdbg/hprdbghv/header/common/Dpc.h +++ b/hyperdbg/include/platform/kernel/header/PlatformBroadcast.h @@ -1,20 +1,26 @@ /** - * @file Dpc.h + * @file PlatformBroadcast.h * @author Sina Karvandi (sina@hyperdbg.org) - * @brief Definition for Windows DPC functions + * @brief Cross platform APIs for broadcasting routines * @details - * @version 0.1 - * @date 2020-04-10 + * @version 0.19 + * @date 2026-05-08 * * @copyright This project is released under the GNU Public License v3. * */ #pragma once +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + ////////////////////////////////////////////////// // Functions // ////////////////////////////////////////////////// +#if defined(_WIN32) || defined(_WIN64) + NTKERNELAPI _IRQL_requires_max_(APC_LEVEL) _IRQL_requires_min_(PASSIVE_LEVEL) @@ -37,3 +43,12 @@ _IRQL_requires_same_ LOGICAL KeSignalCallDpcSynchronize( _In_ PVOID SystemArgument2); + +#endif // defined(_WIN32) || defined(_WIN64) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +PlatformBroadcastSynchronizeEndOfRoutine(PVOID SystemArgument1, PVOID SystemArgument2); diff --git a/hyperdbg/include/platform/kernel/header/PlatformCpu.h b/hyperdbg/include/platform/kernel/header/PlatformCpu.h new file mode 100644 index 00000000..fb3413f9 --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformCpu.h @@ -0,0 +1,26 @@ +/** + * @file PlatformCpu.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for CPU and processor queries + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +ULONG +PlatformCpuGetActiveProcessorCount(VOID); + +ULONG +PlatformCpuGetCurrentProcessorNumber(VOID); diff --git a/hyperdbg/include/platform/kernel/header/PlatformDbg.h b/hyperdbg/include/platform/kernel/header/PlatformDbg.h new file mode 100644 index 00000000..c10e6cc3 --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformDbg.h @@ -0,0 +1,23 @@ +/** + * @file PlatformDbg.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for kernel debug output + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +PlatformDbgPrint(const CHAR * Format, ...); diff --git a/hyperdbg/include/platform/kernel/header/PlatformDpc.h b/hyperdbg/include/platform/kernel/header/PlatformDpc.h new file mode 100644 index 00000000..72476ae8 --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformDpc.h @@ -0,0 +1,30 @@ +/** + * @file PlatformDpc.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for Deferred Procedure Call (DPC) management + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +#if defined(_WIN32) || defined(_WIN64) + +VOID +PlatformDpcInitialize(PRKDPC Dpc, PKDEFERRED_ROUTINE DeferredRoutine, PVOID DeferredContext); + +BOOLEAN +PlatformDpcInsertQueueDpc(PRKDPC Dpc, PVOID SystemArgument1, PVOID SystemArgument2); + +#endif // defined(_WIN32) || defined(_WIN64) diff --git a/hyperdbg/include/platform/kernel/header/PlatformEvent.h b/hyperdbg/include/platform/kernel/header/PlatformEvent.h new file mode 100644 index 00000000..da38a7da --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformEvent.h @@ -0,0 +1,38 @@ +/** + * @file PlatformEvent.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for kernel event and object management + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +PlatformObjectDereference(PVOID Object); + +#if defined(_WIN32) || defined(_WIN64) + +LONG +PlatformEventSet(PKEVENT Event, KPRIORITY Increment, BOOLEAN Wait); + +NTSTATUS +PlatformObjectReferenceByHandle(HANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID * Object, + POBJECT_HANDLE_INFORMATION HandleInformation); + +#endif // defined(_WIN32) || defined(_WIN64) diff --git a/hyperdbg/include/platform/kernel/header/PlatformIntrinsics.h b/hyperdbg/include/platform/kernel/header/PlatformIntrinsics.h new file mode 100644 index 00000000..618fc71b --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformIntrinsics.h @@ -0,0 +1,365 @@ +/** + * @file PlatformIntrinsics.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for intrinsic functions (x86 instructions) + * @details + * @version 0.19 + * @date 2026-05-05 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// CR Registers // +////////////////////////////////////////////////// + +// +// READCR0 +// +extern inline ULONG_PTR + CpuReadCr0(VOID); + +// +// WRITECR0 +// +extern inline VOID +CpuWriteCr0(ULONG_PTR Cr0Value); + +// +// READCR2 +// +extern inline ULONG_PTR + CpuReadCr2(VOID); + +// +// WRITECR2 +// +extern inline VOID +CpuWriteCr2(ULONG_PTR Cr2Value); + +// +// READCR3 +// +extern inline ULONG_PTR + CpuReadCr3(VOID); + +// +// WRITECR3 +// +extern inline VOID +CpuWriteCr3(ULONG_PTR Cr3Value); + +// +// READCR4 +// +extern inline ULONG_PTR + CpuReadCr4(VOID); + +// +// WRITECR4 +// +extern inline VOID +CpuWriteCr4(ULONG_PTR Cr4Value); + +// +// READCR8 +// +extern inline ULONG_PTR + CpuReadCr8(VOID); + +// +// WRITECR8 +// +extern inline VOID +CpuWriteCr8(ULONG_PTR Cr8Value); + +////////////////////////////////////////////////// +// MSR Instructions // +////////////////////////////////////////////////// + +// +// RDMSR +// +extern inline UINT64 +CpuReadMsr(ULONG MsrAddress); + +// +// WRMSR +// +extern inline VOID +CpuWriteMsr(ULONG MsrAddress, UINT64 MsrValue); + +////////////////////////////////////////////////// +// Debug Register Instructions // +////////////////////////////////////////////////// + +// +// MOV DR (read) +// +#if defined(_WIN32) || defined(_WIN64) +# define CpuReadDr(DrNumber) __readdr(DrNumber) +#elif defined(__linux__) +# define CpuReadDr(DrNumber) \ + ({ \ + ULONG_PTR __val; \ + switch (DrNumber) \ + { \ + case 0: \ + __asm__ volatile("mov %%dr0, %0" : "=r"(__val)); \ + break; \ + case 1: \ + __asm__ volatile("mov %%dr1, %0" : "=r"(__val)); \ + break; \ + case 2: \ + __asm__ volatile("mov %%dr2, %0" : "=r"(__val)); \ + break; \ + case 3: \ + __asm__ volatile("mov %%dr3, %0" : "=r"(__val)); \ + break; \ + case 6: \ + __asm__ volatile("mov %%dr6, %0" : "=r"(__val)); \ + break; \ + case 7: \ + __asm__ volatile("mov %%dr7, %0" : "=r"(__val)); \ + break; \ + default: \ + __val = 0; \ + break; \ + } \ + __val; \ + }) +#else +# error "Unsupported platform" +#endif + +// +// MOV DR (write) +// +#if defined(_WIN32) || defined(_WIN64) +# define CpuWriteDr(DrNumber, DrValue) __writedr(DrNumber, DrValue) +#elif defined(__linux__) +# define CpuWriteDr(DrNumber, DrValue) \ + do \ + { \ + switch (DrNumber) \ + { \ + case 0: \ + __asm__ volatile("mov %0, %%dr0" : : "r"((ULONG_PTR)(DrValue))); \ + break; \ + case 1: \ + __asm__ volatile("mov %0, %%dr1" : : "r"((ULONG_PTR)(DrValue))); \ + break; \ + case 2: \ + __asm__ volatile("mov %0, %%dr2" : : "r"((ULONG_PTR)(DrValue))); \ + break; \ + case 3: \ + __asm__ volatile("mov %0, %%dr3" : : "r"((ULONG_PTR)(DrValue))); \ + break; \ + case 6: \ + __asm__ volatile("mov %0, %%dr6" : : "r"((ULONG_PTR)(DrValue))); \ + break; \ + case 7: \ + __asm__ volatile("mov %0, %%dr7" : : "r"((ULONG_PTR)(DrValue))); \ + break; \ + default: \ + break; \ + } \ + } while (0) +#else +# error "Unsupported platform" +#endif + +////////////////////////////////////////////////// +// CPUID Instructions // +////////////////////////////////////////////////// + +// +// CPUID +// +extern inline VOID +CpuCpuId(INT32 * CpuInfo, INT32 FunctionId); + +// +// CPUID (with sub-leaf) +// +extern inline VOID +CpuCpuIdEx(INT32 * CpuInfo, INT32 FunctionId, INT32 SubFunctionId); + +////////////////////////////////////////////////// +// TSC Instructions // +////////////////////////////////////////////////// + +// +// RDTSC +// +extern inline UINT64 + CpuReadTsc(VOID); + +// +// RDTSCP +// +extern inline UINT64 +CpuReadTscp(UINT32 * Aux); + +////////////////////////////////////////////////// +// Interlocked (Atomic) Operations // +////////////////////////////////////////////////// + +extern inline INT64 +CpuInterlockedExchange64(INT64 volatile * Target, INT64 Value); + +extern inline INT64 +CpuInterlockedExchangeAdd64(INT64 volatile * Addend, INT64 Value); + +extern inline INT64 +CpuInterlockedIncrement64(INT64 volatile * Addend); + +extern inline INT64 +CpuInterlockedDecrement64(INT64 volatile * Addend); + +extern inline INT64 +CpuInterlockedCompareExchange64(INT64 volatile * Destination, INT64 ExChange, INT64 Comparand); + +////////////////////////////////////////////////// +// Descriptor Table Instructions // +////////////////////////////////////////////////// + +// +// SIDT +// +extern inline VOID +CpuSidt(VOID * Idtr); + +////////////////////////////////////////////////// +// TLB Instructions // +////////////////////////////////////////////////// + +// +// INVLPG +// +extern inline VOID +CpuInvlpg(VOID * Address); + +////////////////////////////////////////////////// +// String Store Instructions // +////////////////////////////////////////////////// + +// +// STOSQ +// +extern inline VOID +CpuStosQ(UINT64 * Destination, UINT64 Value, SIZE_T Count); + +////////////////////////////////////////////////// +// Bit Scan Instructions // +////////////////////////////////////////////////// + +// +// BSF 64 +// +extern inline UCHAR +CpuBitScanForward64(ULONG * Index, UINT64 Mask); + +////////////////////////////////////////////////// +// Misc Instructions // +////////////////////////////////////////////////// + +// +// NOP +// +extern inline VOID + CpuNop(VOID); + +// +// PAUSE +// +extern inline VOID + CpuPause(VOID); + +// +// Segment Limit +// +extern inline ULONG +CpuSegmentLimit(UINT32 Selector); + +////////////////////////////////////////////////// +// I/O Port Instructions // +////////////////////////////////////////////////// + +// +// IN Byte +// +extern inline UINT8 +CpuIoInByte(UINT16 Port); + +// +// IN Word +// +extern inline UINT16 +CpuIoInWord(UINT16 Port); + +// +// IN Dword +// +extern inline UINT32 +CpuIoInDword(UINT16 Port); + +// +// IN Byte String +// +extern inline VOID +CpuIoInByteString(UINT16 Port, UINT8 * Data, UINT32 Size); + +// +// IN Word String +// +extern inline VOID +CpuIoInWordString(UINT16 Port, UINT16 * Data, UINT32 Size); + +// +// IN Dword String +// +extern inline VOID +CpuIoInDwordString(UINT16 Port, UINT32 * Data, UINT32 Size); + +// +// OUT Byte +// +extern inline VOID +CpuIoOutByte(UINT16 Port, UINT8 Value); + +// +// OUT Word +// +extern inline VOID +CpuIoOutWord(UINT16 Port, UINT16 Value); + +// +// OUT Dword +// +extern inline VOID +CpuIoOutDword(UINT16 Port, UINT32 Value); + +// +// OUT Byte String +// +extern inline VOID +CpuIoOutByteString(UINT16 Port, UINT8 * Data, UINT32 Count); + +// +// OUT Word String +// +extern inline VOID +CpuIoOutWordString(UINT16 Port, UINT16 * Data, UINT32 Count); + +// +// OUT Dword String +// +extern inline VOID +CpuIoOutDwordString(UINT16 Port, UINT32 * Data, UINT32 Count); diff --git a/hyperdbg/include/platform/kernel/header/PlatformIntrinsicsVmx.h b/hyperdbg/include/platform/kernel/header/PlatformIntrinsicsVmx.h new file mode 100644 index 00000000..7b27b1aa --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformIntrinsicsVmx.h @@ -0,0 +1,95 @@ +/** + * @file PlatformIntrinsicsVmx.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for intrinsic functions (VMX instructions) + * @details + * @version 0.19 + * @date 2026-04-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// VMX Instructions // +////////////////////////////////////////////////// + +// +// VMPTRST +// +extern inline VOID +VmxVmptrst(UINT64 * VmcsPhysicalAddress); + +// +// VMPTRLD +// +extern inline UCHAR +VmxVmptrld(UINT64 * VmcsPhysicalAddress); + +// +// VMCLEAR +// +extern inline UCHAR +VmxVmclear(UINT64 * VmcsPhysicalAddress); + +// +// VMXON +// +extern inline UCHAR +VmxVmxon(UINT64 * VmxonRegionPhysicalAddress); + +// +// VMLAUNCH +// +extern inline VOID + VmxVmlaunch(VOID); + +// +// VMRESUME +// +extern inline VOID + VmxVmresume(VOID); + +// +// VMXOFF +// +extern inline VOID + VmxVmxoff(VOID); + +// +// VMREAD +// +extern inline UCHAR +VmxVmread64(size_t Field, UINT64 FieldValue); + +extern inline UCHAR +VmxVmread32(size_t Field, UINT32 FieldValue); + +extern inline UCHAR +VmxVmread16(size_t Field, UINT16 FieldValue); + +extern inline UCHAR +VmxVmread64P(size_t Field, UINT64 * FieldValue); + +extern inline UCHAR +VmxVmread32P(size_t Field, UINT32 * FieldValue); + +extern inline UCHAR +VmxVmread16P(size_t Field, UINT16 * FieldValue); + +// +// VMWRITE +// +extern inline UCHAR +VmxVmwrite64(size_t Field, UINT64 FieldValue); + +extern inline UCHAR +VmxVmwrite32(size_t Field, UINT32 FieldValue); + +extern inline UCHAR +VmxVmwrite16(size_t Field, UINT16 FieldValue); diff --git a/hyperdbg/include/platform/kernel/header/PlatformIo.h b/hyperdbg/include/platform/kernel/header/PlatformIo.h new file mode 100644 index 00000000..e6df744e --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformIo.h @@ -0,0 +1,33 @@ +/** + * @file PlatformIo.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for I/O Request Packet (IRP) management + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +#if defined(_WIN32) || defined(_WIN64) + +PIO_STACK_LOCATION +PlatformIoGetCurrentIrpStackLocation(PIRP Irp); + +VOID +PlatformIoCompleteRequest(PIRP Irp, CCHAR PriorityBoost); + +VOID +PlatformIoMarkIrpPending(PIRP Irp); + +#endif // defined(_WIN32) || defined(_WIN64) diff --git a/hyperdbg/include/platform/kernel/header/PlatformIrql.h b/hyperdbg/include/platform/kernel/header/PlatformIrql.h new file mode 100644 index 00000000..8ebaa70c --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformIrql.h @@ -0,0 +1,30 @@ +/** + * @file PlatformIrql.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for IRQL (Interrupt Request Level) management + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +#if defined(_WIN32) || defined(_WIN64) + +KIRQL +PlatformIrqlRaiseToDpcLevel(VOID); + +VOID +PlatformIrqlLower(KIRQL OldIrql); + +#endif // defined(_WIN32) || defined(_WIN64) diff --git a/hyperdbg/include/platform/kernel/header/PlatformMem.h b/hyperdbg/include/platform/kernel/header/PlatformMem.h new file mode 100644 index 00000000..b031fee1 --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformMem.h @@ -0,0 +1,74 @@ +/** + * @file PlatformMem.h + * @author Behrooz Abbassi (BehroozAbbassi@hyperdbg.org) + * @author Sina Karvandi (sina@hyperdbg.org) + * @author Alirez Moradi (alish014) + * @brief Cross platform APIs for memory allocation + * @details + * @version 0.1 + * @date 2022-01-17 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +// # include "../../general/header/GeneralTypes.h" +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +INT +PlatformSprintf(char * Buffer, SIZE_T BufferSize, const char * Format, ...); + +VOID +PlatformFreeMemory(PVOID Memory); + +VOID +PlatformWriteMemory(PVOID Address, PVOID Buffer, SIZE_T Size); + +VOID +PlatformSetMemory(PVOID Destination, int Value, SIZE_T Size); + +VOID +PlatformZeroMemory(PVOID Destination, SIZE_T Size); + +VOID +PlatformFreeMemory(PVOID Memory); + +PVOID +PlatformAllocateMemory(SIZE_T Size); + +PVOID +PlatformMemAllocateContiguousZeroedMemory(SIZE_T NumberOfBytes); + +PVOID +PlatformMemAllocateNonPagedPool(SIZE_T NumberOfBytes); + +PVOID +PlatformMemAllocateNonPagedPoolWithQuota(SIZE_T NumberOfBytes); + +PVOID +PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes); + +PVOID +PlatformMemFreePool(PVOID BufferAddress); + +PVOID +PlatformMemAllocateContiguousZeroedMemory(SIZE_T NumberOfBytes); + +PVOID +PlatformMemAllocateNonPagedPool(SIZE_T NumberOfBytes); + +PVOID +PlatformMemAllocateNonPagedPoolWithQuota(SIZE_T NumberOfBytes); + +PVOID +PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes); + +PVOID +PlatformMemFreePool(PVOID BufferAddress); diff --git a/hyperdbg/include/platform/kernel/header/PlatformModuleInfo.h b/hyperdbg/include/platform/kernel/header/PlatformModuleInfo.h new file mode 100644 index 00000000..5f83f048 --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformModuleInfo.h @@ -0,0 +1,17 @@ +// PlatformModuleInfo.h + +#if defined(__linux__) + +# ifndef MODULE_INFO_H +# define MODULE_INFO_H + +# include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alish"); +MODULE_DESCRIPTION("Linux Kernel module Mock"); +MODULE_VERSION("0.1"); + +# endif // _MODULE_INFO_H_ + +#endif // defined(__linux__) diff --git a/hyperdbg/include/platform/kernel/header/PlatformProcess.h b/hyperdbg/include/platform/kernel/header/PlatformProcess.h new file mode 100644 index 00000000..4eedd377 --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformProcess.h @@ -0,0 +1,35 @@ +/** + * @file PlatformProcess.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for process and thread queries + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +HANDLE +PlatformProcessGetCurrentThreadId(VOID); + +HANDLE +PlatformProcessGetCurrentProcessId(VOID); + +PVOID +PlatformProcessGetCurrentProcess(VOID); + +PVOID +PlatformProcessGetCurrentThread(VOID); + +PVOID +PlatformProcessGetCurrentThreadTeb(VOID); diff --git a/hyperdbg/include/platform/kernel/header/PlatformSpinlock.h b/hyperdbg/include/platform/kernel/header/PlatformSpinlock.h new file mode 100644 index 00000000..e8327e8e --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformSpinlock.h @@ -0,0 +1,33 @@ +/** + * @file PlatformSpinlock.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for kernel spinlock operations + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +#if defined(_WIN32) || defined(_WIN64) + +VOID +PlatformSpinlockInitialize(PKSPIN_LOCK SpinLock); + +VOID +PlatformSpinlockAcquire(PKSPIN_LOCK SpinLock, PKIRQL OldIrql); + +VOID +PlatformSpinlockRelease(PKSPIN_LOCK SpinLock, KIRQL OldIrql); + +#endif // defined(_WIN32) || defined(_WIN64) diff --git a/hyperdbg/include/platform/kernel/header/PlatformTime.h b/hyperdbg/include/platform/kernel/header/PlatformTime.h new file mode 100644 index 00000000..b760c184 --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/PlatformTime.h @@ -0,0 +1,33 @@ +/** + * @file PlatformTime.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Cross platform APIs for system time operations + * @details + * @version 0.19 + * @date 2026-05-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +#if defined(_WIN32) || defined(_WIN64) + +VOID +PlatformTimeQuerySystemTime(PLARGE_INTEGER SystemTime); + +VOID +PlatformTimeConvertToLocalTime(PLARGE_INTEGER SystemTime, PLARGE_INTEGER LocalTime); + +VOID +PlatformTimeConvertToTimeFields(PLARGE_INTEGER Time, PTIME_FIELDS TimeFields); + +#endif // defined(_WIN32) || defined(_WIN64) diff --git a/hyperdbg/include/platform/kernel/header/pch.h b/hyperdbg/include/platform/kernel/header/pch.h new file mode 100644 index 00000000..3111fda3 --- /dev/null +++ b/hyperdbg/include/platform/kernel/header/pch.h @@ -0,0 +1,5 @@ +// +// DO NOT DELETE OR INCLDUE THIS FILE +// +// It is used to tell the Linux compiler that the header "pch.h" is empty while it is used within Windows MSVC compiler +// diff --git a/hyperdbg/include/platform/user/code/platform-intrinsics.c b/hyperdbg/include/platform/user/code/platform-intrinsics.c new file mode 100644 index 00000000..805c78e9 --- /dev/null +++ b/hyperdbg/include/platform/user/code/platform-intrinsics.c @@ -0,0 +1,201 @@ +/** + * @file platform-intrinsics.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of cross platform APIs for intrinsic functions (x86 instructions) + * @details + * @version 0.19 + * @date 2026-05-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/platform-intrinsics.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// CPUID Instructions // +////////////////////////////////////////////////// + +/** + * @brief Execute CPUID + * + * @param CpuInfo + * @param FunctionId + */ + VOID +CpuCpuId(INT32 * CpuInfo, INT32 FunctionId) +{ +#if defined(_WIN32) || defined(_WIN64) + __cpuid(CpuInfo, FunctionId); +#elif defined(__linux__) + __asm__ __volatile__("cpuid" : "=a"(CpuInfo[0]), "=b"(CpuInfo[1]), "=c"(CpuInfo[2]), "=d"(CpuInfo[3]) : "a"(FunctionId), "c"(0)); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Execute CPUID with sub-leaf + * + * @param CpuInfo + * @param FunctionId + * @param SubFunctionId + */ + VOID +CpuCpuIdEx(INT32 * CpuInfo, INT32 FunctionId, INT32 SubFunctionId) +{ +#if defined(_WIN32) || defined(_WIN64) + __cpuidex(CpuInfo, FunctionId, SubFunctionId); +#elif defined(__linux__) + __asm__ __volatile__("cpuid" : "=a"(CpuInfo[0]), "=b"(CpuInfo[1]), "=c"(CpuInfo[2]), "=d"(CpuInfo[3]) : "a"(FunctionId), "c"(SubFunctionId)); +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// TSC Instructions // +////////////////////////////////////////////////// + +/** + * @brief Read Time-Stamp Counter + * + * @return UINT64 + */ + UINT64 +CpuReadTsc(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + return __rdtsc(); +#elif defined(__linux__) + UINT32 __lo, __hi; + __asm__ __volatile__("rdtsc" : "=a"(__lo), "=d"(__hi)); + return ((UINT64)__hi << 32) | __lo; +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// Misc Instructions // +////////////////////////////////////////////////// + +/** + * @brief Read Time-Stamp Counter (serializing) + * + * @param Aux processor ID output (may be NULL) + * @return UINT64 + */ +UINT64 +CpuReadTscp(UINT32 * Aux) +{ +#if defined(_WIN32) || defined(_WIN64) + return __rdtscp(Aux); +#elif defined(__linux__) + UINT32 __lo, __hi, __aux; + __asm__ __volatile__("rdtscp" : "=a"(__lo), "=d"(__hi), "=c"(__aux)); + if (Aux) + *Aux = __aux; + return ((UINT64)__hi << 32) | __lo; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Execute PAUSE (spin-wait hint) + */ +VOID +CpuPause(VOID) +{ +#if defined(_WIN32) || defined(_WIN64) + _mm_pause(); +#elif defined(__linux__) + __asm__ __volatile__("pause"); +#else +# error "Unsupported platform" +#endif +} + +////////////////////////////////////////////////// +// Interlocked (Atomic) Operations // +////////////////////////////////////////////////// + +INT64 +CpuInterlockedExchange64(INT64 volatile * Target, INT64 Value) +{ +#if defined(_WIN32) || defined(_WIN64) + return InterlockedExchange64(Target, Value); +#elif defined(__linux__) + return __atomic_exchange_n(Target, Value, __ATOMIC_SEQ_CST); +#else +# error "Unsupported platform" +#endif +} + +INT64 +CpuInterlockedExchangeAdd64(INT64 volatile * Addend, INT64 Value) +{ +#if defined(_WIN32) || defined(_WIN64) + return InterlockedExchangeAdd64(Addend, Value); +#elif defined(__linux__) + return __atomic_fetch_add(Addend, Value, __ATOMIC_SEQ_CST); +#else +# error "Unsupported platform" +#endif +} + +INT64 +CpuInterlockedIncrement64(INT64 volatile * Addend) +{ +#if defined(_WIN32) || defined(_WIN64) + return InterlockedIncrement64(Addend); +#elif defined(__linux__) + return __atomic_add_fetch(Addend, 1LL, __ATOMIC_SEQ_CST); +#else +# error "Unsupported platform" +#endif +} + +INT64 +CpuInterlockedDecrement64(INT64 volatile * Addend) +{ +#if defined(_WIN32) || defined(_WIN64) + return InterlockedDecrement64(Addend); +#elif defined(__linux__) + return __atomic_sub_fetch(Addend, 1LL, __ATOMIC_SEQ_CST); +#else +# error "Unsupported platform" +#endif +} + +INT64 +CpuInterlockedCompareExchange64(INT64 volatile * Destination, INT64 ExChange, INT64 Comparand) +{ +#if defined(_WIN32) || defined(_WIN64) + return InterlockedCompareExchange64(Destination, ExChange, Comparand); +#elif defined(__linux__) + INT64 Expected = Comparand; + __atomic_compare_exchange_n(Destination, &Expected, ExChange, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return Expected; +#else +# error "Unsupported platform" +#endif +} + +UCHAR +CpuInterlockedBitTestAndSet(volatile LONG * Base, LONG Bit) +{ +#if defined(_WIN32) || defined(_WIN64) + return _interlockedbittestandset(Base, Bit); +#elif defined(__linux__) + LONG Mask = (1L << Bit); + LONG Old = __atomic_fetch_or(Base, Mask, __ATOMIC_SEQ_CST); + return (UCHAR)((Old >> Bit) & 1); +#else +# error "Unsupported platform" +#endif +} diff --git a/hyperdbg/include/platform/user/code/platform-ioctl.c b/hyperdbg/include/platform/user/code/platform-ioctl.c new file mode 100644 index 00000000..edfc699d --- /dev/null +++ b/hyperdbg/include/platform/user/code/platform-ioctl.c @@ -0,0 +1,83 @@ +/** + * @file platform-ioctl.c + * @author Max Raulea (max.raulea@gmail.com) + * @brief User mode cross-platform implementation of the local kernel-driver IOCTL transport + * @details See platform-ioctl.h. The Windows branch forwards directly to Win32 + * DeviceIoControl. The Linux branch is currently stubbed (returns FALSE) and is + * the home where the ioctl()-based implementation against the /dev/HyperDbg + * character device will live once the kernel module exists. + * + * @version 0.20 + * @date 2026-06-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/platform-ioctl.h" +#endif // defined(__linux__) + +#if defined(_WIN32) + +BOOL +PlatformDeviceIoControl(HANDLE Device, + DWORD IoControlCode, + LPVOID InBuffer, + DWORD InBufferSize, + LPVOID OutBuffer, + DWORD OutBufferSize, + LPDWORD BytesReturned, + LPVOID Overlapped) +{ + return DeviceIoControl(Device, + IoControlCode, + InBuffer, + InBufferSize, + OutBuffer, + OutBufferSize, + BytesReturned, + (LPOVERLAPPED)Overlapped); +} + +#elif defined(__linux__) + +// +// TODO: implement the local driver transport on Linux using ioctl() against a +// /dev/HyperDbg character device exposed by the kernel module: +// - open the device once (in the library init path) -> file descriptor stored +// in g_DeviceHandle +// - PlatformDeviceIoControl -> ioctl(fd, IoControlCode, ...) with the in/out +// buffer marshalling the driver expects (likely a single in-out buffer) +// - close on teardown +// The kernel module does not exist yet, so this returns failure for now: callers +// that have already asserted g_DeviceHandle will simply report the IOCTL failed +// rather than crashing. +// + +BOOL +PlatformDeviceIoControl(HANDLE Device, + DWORD IoControlCode, + LPVOID InBuffer, + DWORD InBufferSize, + LPVOID OutBuffer, + DWORD OutBufferSize, + LPDWORD BytesReturned, + LPVOID Overlapped) +{ + (void)Device; + (void)IoControlCode; + (void)InBuffer; + (void)InBufferSize; + (void)OutBuffer; + (void)OutBufferSize; + (void)Overlapped; + if (BytesReturned) + *BytesReturned = 0; + return FALSE; +} + +#else +# error "Unsupported platform" +#endif diff --git a/hyperdbg/include/platform/user/code/platform-lib-calls.c b/hyperdbg/include/platform/user/code/platform-lib-calls.c new file mode 100644 index 00000000..19768c55 --- /dev/null +++ b/hyperdbg/include/platform/user/code/platform-lib-calls.c @@ -0,0 +1,613 @@ +/** + * @file platform-lib-calls.c + * @author Max Raulea (max.raulea@gmail.com) + * @brief User mode Cross platform APIs for platofrm dependend library calls + * @details + * @version 0.19 + * @date 2026-06-01 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/platform-lib-calls.h" +# include +# include +# include +# include +# include +#endif // defined(__linux__) + +/** + * @brief Platform independent wrapper for vsprintf_s / vsnprintf + * + * @param Buffer output buffer + * @param BufferSize size of the output buffer + * @param Format format string + * @param ArgList variadic argument list + * @return INT number of characters written, or -1 on error + */ +INT +PlatformVsnprintf(char * Buffer, SIZE_T BufferSize, const char * Format, va_list ArgList) +{ +#if defined(_WIN32) + return vsprintf_s(Buffer, BufferSize, Format, ArgList); +#elif defined(__linux__) + return vsnprintf(Buffer, BufferSize, Format, ArgList); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for _strdup / strdup + * + * @param Str string to duplicate + * @return char * pointer to the duplicated string, or NULL on failure + */ +char * +PlatformStrDup(const char * Str) +{ +#if defined(_WIN32) + return _strdup(Str); +#elif defined(__linux__) + return strdup(Str); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for RtlZeroMemory / memset + * + * @param Buffer pointer to the memory region to zero + * @param Size number of bytes to zero + */ +VOID +PlatformZeroMemory(PVOID Buffer, SIZE_T Size) +{ +#if defined(_WIN32) + RtlZeroMemory(Buffer, Size); +#elif defined(__linux__) + memset(Buffer, 0, Size); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for QueryPerformanceFrequency + * + * @param Frequency output — ticks per second + * @return BOOLEAN TRUE on success + */ +BOOLEAN +PlatformQueryPerformanceFrequency(LARGE_INTEGER * Frequency) +{ +#if defined(_WIN32) + return (BOOLEAN)QueryPerformanceFrequency((LARGE_INTEGER *)Frequency); +#elif defined(__linux__) + Frequency->QuadPart = 1000000000LL; // clock_gettime gives nanosecond resolution + return TRUE; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for QueryPerformanceCounter + * + * @param Count output — current tick count + * @return BOOLEAN TRUE on success + */ +BOOLEAN +PlatformQueryPerformanceCounter(LARGE_INTEGER * Count) +{ +#if defined(_WIN32) + return (BOOLEAN)QueryPerformanceCounter((LARGE_INTEGER *)Count); +#elif defined(__linux__) + struct timespec Ts; + clock_gettime(CLOCK_MONOTONIC, &Ts); + Count->QuadPart = (INT64)Ts.tv_sec * 1000000000LL + Ts.tv_nsec; + return TRUE; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for sprintf_s / snprintf + * + * @param Buffer output buffer + * @param BufferSize size of the output buffer + * @param Format format string + * @return INT number of characters written, or -1 on error + */ +INT +PlatformSprintf(char * Buffer, SIZE_T BufferSize, const char * Format, ...) +{ + va_list Args; + va_start(Args, Format); + INT Result; +#if defined(_WIN32) + Result = vsprintf_s(Buffer, BufferSize, Format, Args); +#elif defined(__linux__) + Result = vsnprintf(Buffer, BufferSize, Format, Args); +#else +# error "Unsupported platform" +#endif + va_end(Args); + return Result; +} + +/** + * @brief Platform independent wrapper for GetCurrentThreadId / gettid + * + * @return UINT32 thread ID of the calling thread + */ +UINT32 +PlatformGetCurrentThreadId(VOID) +{ +#if defined(_WIN32) + return (UINT32)GetCurrentThreadId(); +#elif defined(__linux__) + return (UINT32)syscall(SYS_gettid); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for GetCurrentProcessorNumber / sched_getcpu + * + * @return UINT32 logical processor index the calling thread is running on + */ +UINT32 +PlatformGetCurrentProcessorNumber(VOID) +{ +#if defined(_WIN32) + return (UINT32)GetCurrentProcessorNumber(); +#elif defined(__linux__) + return (UINT32)sched_getcpu(); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for GetCurrentProcessId / getpid + * + * @return UINT32 PID of the calling process + */ +UINT32 +PlatformGetCurrentProcessId(VOID) +{ +#if defined(_WIN32) + return (UINT32)GetCurrentProcessId(); +#elif defined(__linux__) + return (UINT32)getpid(); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper to get the current process name + * + * @return CHAR* pointer to a static buffer holding the process name, or NULL on failure + */ +CHAR * +PlatformGetCurrentProcessName(VOID) +{ + static CHAR ProcessNameBuf[MAX_PATH] = {0}; + +#if defined(_WIN32) + // + // Use base kernel32 only (no psapi/shlwapi) so this compiles in every + // project that builds platform-lib-calls.c (e.g. script-engine, which has + // a minimal include set). GetModuleFileNameA(NULL, ...) returns the full + // path of the current process image. + // + if (GetModuleFileNameA(NULL, ProcessNameBuf, MAX_PATH) == 0) + { + return NULL; + } + + // + // Return the basename (strip the directory part) + // + char * LastSeparator = strrchr(ProcessNameBuf, '\\'); + if (LastSeparator) + { + return LastSeparator + 1; + } + + return ProcessNameBuf; + +#elif defined(__linux__) + FILE * f = fopen("/proc/self/comm", "r"); + if (f) + { + if (fgets(ProcessNameBuf, sizeof(ProcessNameBuf), f)) + { + size_t Len = strlen(ProcessNameBuf); + if (Len > 0 && ProcessNameBuf[Len - 1] == '\n') + ProcessNameBuf[Len - 1] = '\0'; + } + fclose(f); + return ProcessNameBuf; + } + return NULL; + +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for CreateEvent + * + * @param ManualReset TRUE for a manual-reset event, FALSE for auto-reset + * @param InitialState TRUE if the event starts signaled + * @return HANDLE to the event, or NULL on failure + */ +HANDLE +PlatformCreateEvent(BOOLEAN ManualReset, BOOLEAN InitialState) +{ +#if defined(_WIN32) + return CreateEvent(NULL, ManualReset, InitialState, NULL); +#elif defined(__linux__) + // + // TODO: back this with a pthread mutex+cond (or eventfd) when the Linux + // kernel-debugger transport is implemented. For now return a dummy + // non-NULL handle so existing NULL-checks treat creation as success. + // + (void)ManualReset; + (void)InitialState; + return (HANDLE)(uintptr_t)1; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for SetEvent + */ +BOOLEAN +PlatformSetEvent(HANDLE EventHandle) +{ +#if defined(_WIN32) + return (BOOLEAN)SetEvent(EventHandle); +#elif defined(__linux__) + (void)EventHandle; // TODO: signal the underlying cond/eventfd + return TRUE; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for ResetEvent + */ +BOOLEAN +PlatformResetEvent(HANDLE EventHandle) +{ +#if defined(_WIN32) + return (BOOLEAN)ResetEvent(EventHandle); +#elif defined(__linux__) + (void)EventHandle; // TODO: clear the underlying cond/eventfd + return TRUE; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for WaitForSingleObject + * + * @return 0 (WAIT_OBJECT_0) on success + */ +DWORD +PlatformWaitForSingleObject(HANDLE Handle, DWORD TimeoutMilliseconds) +{ +#if defined(_WIN32) + return WaitForSingleObject(Handle, TimeoutMilliseconds); +#elif defined(__linux__) + // + // TODO: wait on the underlying cond/eventfd. For now return immediately as + // success — no real transport exists yet to wait on. + // + (void)Handle; + (void)TimeoutMilliseconds; + return 0; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for CloseHandle + */ +BOOLEAN +PlatformCloseHandle(HANDLE Handle) +{ +#if defined(_WIN32) + return (BOOLEAN)CloseHandle(Handle); +#elif defined(__linux__) + (void)Handle; // TODO: free the underlying cond/eventfd or close the fd + return TRUE; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for GetLastError + */ +DWORD +PlatformGetLastError(VOID) +{ +#if defined(_WIN32) + return GetLastError(); +#elif defined(__linux__) + return (DWORD)errno; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper to write raw bytes to the console + * + * @details Used to emit pre-encoded UTF-8 byte sequences (e.g. box-drawing + * characters) directly to standard output. On Windows this goes + * through WriteConsoleA so the console code page is bypassed; on + * Linux the terminal is UTF-8 native so the bytes are written as-is. + * + * @param Buffer pointer to the bytes to write + * @param NumberOfBytes number of bytes to write + * @return BOOLEAN TRUE on success + */ +BOOLEAN +PlatformWriteConsole(const VOID * Buffer, DWORD NumberOfBytes) +{ +#if defined(_WIN32) + return (BOOLEAN)WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), Buffer, NumberOfBytes, NULL, NULL); +#elif defined(__linux__) + return (BOOLEAN)(fwrite(Buffer, 1, NumberOfBytes, stdout) == NumberOfBytes); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper to create/open a file for writing + * + * @param Path wide path of the file to create (truncated if it exists) + * @return HANDLE to the opened file, or INVALID_HANDLE_VALUE on failure + */ +HANDLE +PlatformOpenFileForWriting(const WCHAR * Path) +{ +#if defined(_WIN32) + return CreateFileW(Path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); +#elif defined(__linux__) + // + // TODO: handle this later. The path arrives as a std::wstring (4-byte + // wchar_t on Linux) and must be narrowed to a UTF-8 char* before it + // can be handed to fopen. Until that conversion is wired up, fail the + // open so callers (e.g. dump.cpp) bail out cleanly instead of writing + // to a bogus handle. + // + (void)Path; + return INVALID_HANDLE_VALUE; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper to write a buffer to an open file + * + * @param FileHandle handle returned by PlatformOpenFileForWriting + * @param Buffer pointer to the bytes to write + * @param NumberOfBytes number of bytes to write + * @return BOOLEAN TRUE on success + */ +BOOLEAN +PlatformWriteFile(HANDLE FileHandle, const VOID * Buffer, DWORD NumberOfBytes) +{ +#if defined(_WIN32) + DWORD BytesWritten; + return (BOOLEAN)WriteFile(FileHandle, Buffer, NumberOfBytes, &BytesWritten, NULL); +#elif defined(__linux__) + return (BOOLEAN)(fwrite(Buffer, 1, NumberOfBytes, (FILE *)FileHandle) == NumberOfBytes); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper to close a file opened by + * PlatformOpenFileForWriting + * + * @param FileHandle handle to close + * @return BOOLEAN TRUE on success + */ +BOOLEAN +PlatformCloseFile(HANDLE FileHandle) +{ +#if defined(_WIN32) + return (BOOLEAN)CloseHandle(FileHandle); +#elif defined(__linux__) + return (BOOLEAN)(fclose((FILE *)FileHandle) == 0); +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper to map an entire file read-only into memory + * + * @details The returned pointer stays valid until released with PlatformUnmapFile; + * the underlying file/descriptor is closed before returning (the mapping + * outlives it on both platforms). + * + * @param Path wide path of the file to map + * @param OutFileSize output — size of the file in bytes (0 on failure) + * @return VOID* base address of the mapped file, or NULL on failure + */ +VOID * +PlatformMapFileReadOnly(const WCHAR * Path, PSIZE_T OutFileSize, PHANDLE OutFileHandle) +{ +#if defined(_WIN32) + HANDLE FileHandle; + HANDLE MapObjectHandle; + VOID * BaseAddr; + LARGE_INTEGER FileSize; + + *OutFileSize = 0; + *OutFileHandle = INVALID_HANDLE_VALUE; + + FileHandle = CreateFileW(Path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle == INVALID_HANDLE_VALUE) + { + return NULL; + } + + if (!GetFileSizeEx(FileHandle, &FileSize)) + { + CloseHandle(FileHandle); + return NULL; + } + + MapObjectHandle = CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL); + if (MapObjectHandle == NULL) + { + CloseHandle(FileHandle); + return NULL; + } + + BaseAddr = MapViewOfFile(MapObjectHandle, FILE_MAP_READ, 0, 0, 0); + + // + // The view stays valid after the mapping object handle is closed. The file + // handle is kept open and handed back so the caller can still issue raw + // reads (PlatformReadFileAtOffset); it is closed by PlatformUnmapFile. + // + CloseHandle(MapObjectHandle); + + if (BaseAddr == NULL) + { + CloseHandle(FileHandle); + return NULL; + } + + *OutFileSize = (SIZE_T)FileSize.QuadPart; + *OutFileHandle = FileHandle; + return BaseAddr; +#elif defined(__linux__) + // + // TODO (linux): implement the real mapping. Expected contract: + // 1. Narrow the 4-byte wchar_t 'Path' to a UTF-8 char* (the project still + // lacks a wchar_t->UTF-8 helper; the same one is needed by + // PlatformOpenFileForWriting for the dump.cpp write path). + // 2. fd = open(narrowed_path, O_RDONLY); // fail -> NULL + // 3. fstat(fd, &st) to get the file size. + // 4. base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + // 5. *OutFileHandle = (HANDLE)(intptr_t)fd; // keep fd open for raw reads + // 6. *OutFileSize = st.st_size; return base; (return NULL on any failure) + // PlatformUnmapFile must then munmap(base, size) and close the fd — which is + // why both the size and the handle are passed back in on unmap. The raw-read + // path (PlatformReadFileAtOffset) would pread() from that same fd. + // + // Until implemented, fail the map so PE-parser callers print "could not open + // the file" and bail out cleanly instead of dereferencing a bogus pointer. + // + (void)Path; + *OutFileSize = 0; + *OutFileHandle = INVALID_HANDLE_VALUE; + return NULL; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper for a positioned (seek + read) file read + * + * @param FileHandle handle handed back by PlatformMapFileReadOnly + * @param Offset byte offset to read from (absolute, from start of file) + * @param Buffer destination buffer + * @param NumberOfBytes number of bytes to read + * @param BytesRead output — number of bytes actually read + * @return BOOLEAN TRUE on success + */ +BOOLEAN +PlatformReadFileAtOffset(HANDLE FileHandle, UINT64 Offset, VOID * Buffer, DWORD NumberOfBytes, LPDWORD BytesRead) +{ +#if defined(_WIN32) + LARGE_INTEGER Distance; + Distance.QuadPart = (LONGLONG)Offset; + + if (!SetFilePointerEx(FileHandle, Distance, NULL, FILE_BEGIN)) + { + return FALSE; + } + + return (BOOLEAN)ReadFile(FileHandle, Buffer, NumberOfBytes, BytesRead, NULL); +#elif defined(__linux__) + // + // TODO (linux): pread((int)(intptr_t)FileHandle, Buffer, NumberOfBytes, Offset) + // once PlatformMapFileReadOnly wraps a real fd. Unreached today + // because the map returns NULL on Linux, so callers bail first. + // + (void)FileHandle; + (void)Offset; + (void)Buffer; + (void)NumberOfBytes; + if (BytesRead != NULL) + { + *BytesRead = 0; + } + return FALSE; +#else +# error "Unsupported platform" +#endif +} + +/** + * @brief Platform independent wrapper to release a mapping from PlatformMapFileReadOnly + * + * @param BaseAddress base address returned by PlatformMapFileReadOnly + * @param FileSize size that was reported by PlatformMapFileReadOnly (needed by munmap) + * @param FileHandle file handle handed back by PlatformMapFileReadOnly + */ +VOID +PlatformUnmapFile(VOID * BaseAddress, SIZE_T FileSize, HANDLE FileHandle) +{ +#if defined(_WIN32) + (void)FileSize; // not needed by UnmapViewOfFile + if (BaseAddress != NULL) + { + UnmapViewOfFile(BaseAddress); + } + if (FileHandle != INVALID_HANDLE_VALUE) + { + CloseHandle(FileHandle); + } +#elif defined(__linux__) + // + // TODO (linux): munmap(BaseAddress, FileSize) and close the fd behind + // FileHandle once PlatformMapFileReadOnly is implemented. + // No-op for now since the map always returns NULL. + // + (void)BaseAddress; + (void)FileSize; + (void)FileHandle; +#else +# error "Unsupported platform" +#endif +} diff --git a/hyperdbg/include/platform/user/code/platform-serial.c b/hyperdbg/include/platform/user/code/platform-serial.c new file mode 100644 index 00000000..6266c0a8 --- /dev/null +++ b/hyperdbg/include/platform/user/code/platform-serial.c @@ -0,0 +1,270 @@ +/** + * @file platform-serial.c + * @author Max Raulea (max.raulea@gmail.com) + * @brief User mode cross-platform implementation of the kernel-debugger serial transport + * @details See platform-serial.h. The Windows branch wraps the Win32 serial primitives + * (CreateFile / Comm* / overlapped ReadFile/WriteFile) and owns the per-direction + * OVERLAPPED state internally so the protocol layer never sees it. The Linux + * branch is currently stubbed (returns FALSE/NULL) and is the home where the + * termios-based implementation over /dev/tty* will live. + * + * @version 0.20 + * @date 2026-06-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/platform-serial.h" +#endif // defined(__linux__) + +#if defined(_WIN32) + +// +// Per-direction overlapped I/O state, owned by the transport layer. +// +static OVERLAPPED g_PlatformOverlappedReadDebugger = {0}; +static OVERLAPPED g_PlatformOverlappedReadDebuggee = {0}; +static OVERLAPPED g_PlatformOverlappedWriteDebugger = {0}; + +HANDLE +PlatformSerialOpen(const char * PortName, PLATFORM_SERIAL_IO_ROLE Role) +{ + HANDLE Comm; + char PortNo[24] = {0}; + + // + // Append name to make a Windows-understandable format + // + sprintf_s(PortNo, sizeof(PortNo), "\\\\.\\%s", PortName); + + if (Role == PLATFORM_SERIAL_IO_DEBUGGEE) + { + // + // Debuggee uses non-overlapped (blocking) I/O + // + Comm = CreateFile(PortNo, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL); + + g_PlatformOverlappedReadDebuggee.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + } + else + { + // + // Debugger uses overlapped (async) I/O + // + Comm = CreateFile(PortNo, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + + g_PlatformOverlappedReadDebugger.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + g_PlatformOverlappedWriteDebugger.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + } + + if (Comm == INVALID_HANDLE_VALUE) + { + return NULL; + } + + // + // Purge the serial port + // + PurgeComm(Comm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); + + return Comm; +} + +BOOLEAN +PlatformSerialConfigure(HANDLE Handle, DWORD BaudRate) +{ + DCB SerialParams = {0}; + SerialParams.DCBlength = sizeof(SerialParams); + + if (GetCommState(Handle, &SerialParams) == FALSE) + { + return FALSE; + } + + SerialParams.BaudRate = BaudRate; + SerialParams.ByteSize = 8; + SerialParams.StopBits = ONESTOPBIT; + SerialParams.Parity = NOPARITY; + + if (SetCommState(Handle, &SerialParams) == FALSE) + { + return FALSE; + } + + return TRUE; +} + +BOOLEAN +PlatformSerialReadByte(HANDLE Handle, + CHAR * OutByte, + DWORD * BytesRead, + PLATFORM_SERIAL_IO_ROLE Role) +{ + OVERLAPPED * Ovl = (Role == PLATFORM_SERIAL_IO_DEBUGGEE) + ? &g_PlatformOverlappedReadDebuggee + : &g_PlatformOverlappedReadDebugger; + + if (Role == PLATFORM_SERIAL_IO_DEBUGGEE) + { + // + // Apply a read timeout for the debuggee side + // + COMMTIMEOUTS Timeouts; + GetCommTimeouts(Handle, &Timeouts); + Timeouts.ReadIntervalTimeout = MAXDWORD; + Timeouts.ReadTotalTimeoutConstant = 5000; + Timeouts.ReadTotalTimeoutMultiplier = 0; + Timeouts.WriteTotalTimeoutConstant = 0; + Timeouts.WriteTotalTimeoutMultiplier = 0; + SetCommTimeouts(Handle, &Timeouts); + } + + if (!ReadFile(Handle, OutByte, sizeof(CHAR), NULL, Ovl)) + { + if (GetLastError() != ERROR_IO_PENDING) + { + return FALSE; + } + } + + WaitForSingleObject(Ovl->hEvent, INFINITE); + GetOverlappedResult(Handle, Ovl, BytesRead, FALSE); + ResetEvent(Ovl->hEvent); + + return TRUE; +} + +BOOLEAN +PlatformSerialWrite(HANDLE Handle, const void * Buffer, UINT32 Length, BOOLEAN Synchronous) +{ + if (Synchronous) + { + DWORD BytesWritten = 0; + if (WriteFile(Handle, Buffer, Length, &BytesWritten, NULL) == FALSE) + { + return FALSE; + } + return (BytesWritten == Length); + } + else + { + if (WriteFile(Handle, Buffer, Length, NULL, &g_PlatformOverlappedWriteDebugger)) + { + return TRUE; + } + + if (GetLastError() != ERROR_IO_PENDING) + { + return FALSE; + } + + if (WaitForSingleObject(g_PlatformOverlappedWriteDebugger.hEvent, INFINITE) != WAIT_OBJECT_0) + { + return FALSE; + } + + ResetEvent(g_PlatformOverlappedWriteDebugger.hEvent); + return TRUE; + } +} + +BOOLEAN +PlatformSerialClose(HANDLE Handle) +{ + if (g_PlatformOverlappedReadDebugger.hEvent) + CloseHandle(g_PlatformOverlappedReadDebugger.hEvent); + if (g_PlatformOverlappedReadDebuggee.hEvent) + CloseHandle(g_PlatformOverlappedReadDebuggee.hEvent); + if (g_PlatformOverlappedWriteDebugger.hEvent) + CloseHandle(g_PlatformOverlappedWriteDebugger.hEvent); + + g_PlatformOverlappedReadDebugger.hEvent = NULL; + g_PlatformOverlappedReadDebuggee.hEvent = NULL; + g_PlatformOverlappedWriteDebugger.hEvent = NULL; + + if (Handle) + return (BOOLEAN)CloseHandle(Handle); + + return TRUE; +} + +#elif defined(__linux__) + +// +// TODO: implement the serial transport on Linux using termios over /dev/tty*: +// - PlatformSerialOpen -> open(PortName, O_RDWR | O_NOCTTY) +// - PlatformSerialConfigure -> tcgetattr/cfsetspeed/tcsetattr (raw, 8-N-1) +// - PlatformSerialReadByte -> read() (with VTIME/VMIN or poll() for the timeout role) +// - PlatformSerialWrite -> write() +// - PlatformSerialClose -> close() +// Named-pipe transport would map onto a UNIX domain socket / FIFO. +// +// Until then these return failure so the kernel-debugger connection simply +// reports "not supported on Linux yet" rather than crashing. +// + +HANDLE +PlatformSerialOpen(const char * PortName, PLATFORM_SERIAL_IO_ROLE Role) +{ + (void)PortName; + (void)Role; + return NULL; +} + +BOOLEAN +PlatformSerialConfigure(HANDLE Handle, DWORD BaudRate) +{ + (void)Handle; + (void)BaudRate; + return FALSE; +} + +BOOLEAN +PlatformSerialReadByte(HANDLE Handle, + CHAR * OutByte, + DWORD * BytesRead, + PLATFORM_SERIAL_IO_ROLE Role) +{ + (void)Handle; + (void)OutByte; + (void)Role; + if (BytesRead) + *BytesRead = 0; + return FALSE; +} + +BOOLEAN +PlatformSerialWrite(HANDLE Handle, const void * Buffer, UINT32 Length, BOOLEAN Synchronous) +{ + (void)Handle; + (void)Buffer; + (void)Length; + (void)Synchronous; + return FALSE; +} + +BOOLEAN +PlatformSerialClose(HANDLE Handle) +{ + (void)Handle; + return TRUE; +} + +#else +# error "Unsupported platform" +#endif diff --git a/hyperdbg/include/platform/user/code/platform-signal.c b/hyperdbg/include/platform/user/code/platform-signal.c new file mode 100644 index 00000000..b0f83071 --- /dev/null +++ b/hyperdbg/include/platform/user/code/platform-signal.c @@ -0,0 +1,137 @@ +/** + * @file platform-signal.c + * @author Max Raulea (max.raulea@gmail.com) + * @brief User mode cross-platform implementation of the console-control handler + * @details See platform-signal.h. The Windows branch forwards to SetConsoleCtrlHandler. + * The Linux branch blocks the handled signals and dispatches them from a + * dedicated sigwait() thread. sigwait() (rather than a sigaction() handler) + * is used deliberately: BreakController calls ShowMessages (printf), socket + * I/O and Sleep, none of which are async-signal-safe. Running the handler on + * a normal thread woken by sigwait() sidesteps that entirely and mirrors the + * Windows model where the console-control handler also runs on its own thread. + * + * @version 0.20 + * @date 2026-06-16 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#if defined(__linux__) +# include "../header/platform-signal.h" +#endif // defined(__linux__) + +#if defined(_WIN32) + +BOOLEAN +PlatformInstallCtrlHandler(PLATFORM_CTRL_HANDLER Handler) +{ + return (BOOLEAN)SetConsoleCtrlHandler((PHANDLER_ROUTINE)Handler, TRUE); +} + +#elif defined(__linux__) + +# include +# include + +// +// The installed handler, read by the dispatch thread. +// +static PLATFORM_CTRL_HANDLER g_PlatformCtrlHandler = NULL; + +// +// Map a POSIX signal onto the Win32 console-control event the shared handler +// understands. Only the two interactive break signals are mapped: +// SIGINT (CTRL+C) -> CTRL_C_EVENT +// SIGQUIT (CTRL+\) -> CTRL_BREAK_EVENT +// SIGTERM/SIGHUP are intentionally left at their default disposition so the +// process stays killable/terminable the usual way; the CLOSE/LOGOFF/SHUTDOWN +// console events have no clean Linux analog. +// +static DWORD +PlatformMapSignalToCtrlType(int Signal) +{ + switch (Signal) + { + case SIGINT: + return CTRL_C_EVENT; + case SIGQUIT: + return CTRL_BREAK_EVENT; + default: + return (DWORD)-1; + } +} + +// +// Dedicated thread: waits for the handled signals and dispatches them to the +// installed handler in ordinary (async-signal-safe) thread context. +// +static void * +PlatformSignalThread(void * Arg) +{ + sigset_t WaitSet; + int Signal; + + (void)Arg; + + sigemptyset(&WaitSet); + sigaddset(&WaitSet, SIGINT); + sigaddset(&WaitSet, SIGQUIT); + + while (1) + { + if (sigwait(&WaitSet, &Signal) != 0) + { + continue; + } + + DWORD CtrlType = PlatformMapSignalToCtrlType(Signal); + + if (g_PlatformCtrlHandler != NULL && CtrlType != (DWORD)-1) + { + g_PlatformCtrlHandler(CtrlType); + } + } + + return NULL; +} + +BOOLEAN +PlatformInstallCtrlHandler(PLATFORM_CTRL_HANDLER Handler) +{ + sigset_t BlockSet; + pthread_t Thread; + + g_PlatformCtrlHandler = Handler; + + // + // Block the handled signals in this (main) thread. Done before any other + // thread is created, the mask is inherited by every thread, guaranteeing + // the signals are delivered to our sigwait() thread and nowhere else. + // + sigemptyset(&BlockSet); + sigaddset(&BlockSet, SIGINT); + sigaddset(&BlockSet, SIGQUIT); + + if (pthread_sigmask(SIG_BLOCK, &BlockSet, NULL) != 0) + { + return FALSE; + } + + if (pthread_create(&Thread, NULL, PlatformSignalThread, NULL) != 0) + { + return FALSE; + } + + // + // Fire-and-forget: the thread lives for the life of the process. + // + pthread_detach(Thread); + + return TRUE; +} + +#else +# error "Unsupported platform" +#endif diff --git a/hyperdbg/include/platform/user/code/windows-only/windows-privilege.c b/hyperdbg/include/platform/user/code/windows-only/windows-privilege.c new file mode 100644 index 00000000..67f84983 --- /dev/null +++ b/hyperdbg/include/platform/user/code/windows-only/windows-privilege.c @@ -0,0 +1,67 @@ +/** + * @file windows-privilege.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Implementation of Windows only APIs for adjusting privileges + * @details + * @version 0.19 + * @date 2026-05-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Is privileges already adjusted + */ +BOOLEAN g_PrivilegesAlreadyAdjusted = FALSE; + +/** + * @brief Adjust kernel debug privilege + * + * @return BOOLEAN return TRUE if it was successful or FALSE if there + */ +BOOLEAN +WindowsSetDebugPrivilege() +{ +#ifdef _WIN32 // Windows + BOOL Status; + HANDLE Token; + + // + // Check if we already adjusted the privilege + // + if (g_PrivilegesAlreadyAdjusted) + { + return TRUE; + } + + // + // Enable Debug privilege + // + Status = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &Token); + if (!Status) + { + ShowMessages("err, OpenProcessToken failed (%x)\n", GetLastError()); + return FALSE; + } + + Status = SetPrivilege(Token, SE_DEBUG_NAME, TRUE); + if (!Status) + { + CloseHandle(Token); + return FALSE; + } + + // + // Indicate that the privilege is already adjusted + // + g_PrivilegesAlreadyAdjusted = TRUE; + + CloseHandle(Token); + return TRUE; + +#elif defined(__linux__) // Linux + return TRUE; // No need to adjust privileges on Linux +#endif +} diff --git a/hyperdbg/include/platform/user/header/Windows.h b/hyperdbg/include/platform/user/header/Windows.h new file mode 100644 index 00000000..79f0c3a9 --- /dev/null +++ b/hyperdbg/include/platform/user/header/Windows.h @@ -0,0 +1,178 @@ +/** + * @file Windows.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Windows specific headers + * @details + * @version 0.10 + * @date 2024-06-24 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Definitions // +////////////////////////////////////////////////// + +typedef struct _RTL_PROCESS_MODULE_INFORMATION +{ + PVOID Section; + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[256]; +} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; + +typedef struct _RTL_PROCESS_MODULES +{ + ULONG NumberOfModules; + _Field_size_(NumberOfModules) RTL_PROCESS_MODULE_INFORMATION Modules[1]; +} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; + +// Linked lists + +FORCEINLINE VOID +InitializeListHead( + _Out_ PLIST_ENTRY ListHead) +{ + ListHead->Flink = ListHead->Blink = ListHead; +} + +_Check_return_ +FORCEINLINE BOOLEAN +IsListEmpty( + _In_ PLIST_ENTRY ListHead) +{ + return ListHead->Flink == ListHead; +} + +FORCEINLINE BOOLEAN +RemoveEntryList( + _In_ PLIST_ENTRY Entry) +{ + PLIST_ENTRY Blink; + PLIST_ENTRY Flink; + + Flink = Entry->Flink; + Blink = Entry->Blink; + Blink->Flink = Flink; + Flink->Blink = Blink; + + return Flink == Blink; +} + +FORCEINLINE PLIST_ENTRY +RemoveHeadList( + _Inout_ PLIST_ENTRY ListHead) +{ + PLIST_ENTRY Flink; + PLIST_ENTRY Entry; + + Entry = ListHead->Flink; + Flink = Entry->Flink; + ListHead->Flink = Flink; + Flink->Blink = ListHead; + + return Entry; +} + +FORCEINLINE PLIST_ENTRY +RemoveTailList( + _Inout_ PLIST_ENTRY ListHead) +{ + PLIST_ENTRY Blink; + PLIST_ENTRY Entry; + + Entry = ListHead->Blink; + Blink = Entry->Blink; + ListHead->Blink = Blink; + Blink->Flink = ListHead; + + return Entry; +} + +FORCEINLINE VOID +InsertTailList( + _Inout_ PLIST_ENTRY ListHead, + _Inout_ PLIST_ENTRY Entry) +{ + PLIST_ENTRY Blink; + + Blink = ListHead->Blink; + Entry->Flink = ListHead; + Entry->Blink = Blink; + Blink->Flink = Entry; + ListHead->Blink = Entry; +} + +FORCEINLINE VOID +InsertHeadList( + _Inout_ PLIST_ENTRY ListHead, + _Inout_ PLIST_ENTRY Entry) +{ + PLIST_ENTRY Flink; + + Flink = ListHead->Flink; + Entry->Flink = Flink; + Entry->Blink = ListHead; + Flink->Blink = Entry; + ListHead->Flink = Entry; +} + +FORCEINLINE VOID +AppendTailList( + _Inout_ PLIST_ENTRY ListHead, + _Inout_ PLIST_ENTRY ListToAppend) +{ + PLIST_ENTRY ListEnd = ListHead->Blink; + + ListHead->Blink->Flink = ListToAppend; + ListHead->Blink = ListToAppend->Blink; + ListToAppend->Blink->Flink = ListHead; + ListToAppend->Blink = ListEnd; +} + +FORCEINLINE PSINGLE_LIST_ENTRY +PopEntryList( + _Inout_ PSINGLE_LIST_ENTRY ListHead) +{ + PSINGLE_LIST_ENTRY FirstEntry; + + FirstEntry = ListHead->Next; + + if (FirstEntry) + ListHead->Next = FirstEntry->Next; + + return FirstEntry; +} + +FORCEINLINE VOID +PushEntryList( + _Inout_ PSINGLE_LIST_ENTRY ListHead, + _Inout_ PSINGLE_LIST_ENTRY Entry) +{ + Entry->Next = ListHead->Next; + ListHead->Next = Entry; +} + +// +// MessageId: STATUS_UNSUCCESSFUL +// +// MessageText: +// +// {Operation Failed} +// The requested operation was unsuccessful. +// +#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) + +typedef enum _SYSTEM_INFORMATION_CLASS2 +{ + SystemModuleInformation = 11 // q: RTL_PROCESS_MODULES + +} SYSTEM_INFORMATION_CLASS2; diff --git a/hyperdbg/include/platform/user/header/platform-intrinsics.h b/hyperdbg/include/platform/user/header/platform-intrinsics.h new file mode 100644 index 00000000..f90b7c90 --- /dev/null +++ b/hyperdbg/include/platform/user/header/platform-intrinsics.h @@ -0,0 +1,80 @@ +/** + * @file platform-intrinsics.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief User mode Cross platform APIs for intrinsic functions (x86 instructions) + * @details + * @version 0.19 + * @date 2026-05-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// CPUID Instructions // +////////////////////////////////////////////////// + +// +// CPUID +// +VOID +CpuCpuId(INT32 * CpuInfo, INT32 FunctionId); + +// +// CPUID (with sub-leaf) +// +VOID +CpuCpuIdEx(INT32 * CpuInfo, INT32 FunctionId, INT32 SubFunctionId); + +////////////////////////////////////////////////// +// TSC Instructions // +////////////////////////////////////////////////// + +// +// RDTSC +// +UINT64 +CpuReadTsc(VOID); + +// +// RDTSCP +// +UINT64 +CpuReadTscp(UINT32 * Aux); + +////////////////////////////////////////////////// +// Misc Instructions // +////////////////////////////////////////////////// + +// +// PAUSE +// +VOID +CpuPause(VOID); + +////////////////////////////////////////////////// +// Interlocked (Atomic) Operations // +////////////////////////////////////////////////// + +INT64 +CpuInterlockedExchange64(INT64 volatile * Target, INT64 Value); + +INT64 +CpuInterlockedExchangeAdd64(INT64 volatile * Addend, INT64 Value); + +INT64 +CpuInterlockedIncrement64(INT64 volatile * Addend); + +INT64 +CpuInterlockedDecrement64(INT64 volatile * Addend); + +INT64 +CpuInterlockedCompareExchange64(INT64 volatile * Destination, INT64 ExChange, INT64 Comparand); + +UCHAR +CpuInterlockedBitTestAndSet(volatile LONG * Base, LONG Bit); diff --git a/hyperdbg/include/platform/user/header/platform-ioctl.h b/hyperdbg/include/platform/user/header/platform-ioctl.h new file mode 100644 index 00000000..c2c7ce14 --- /dev/null +++ b/hyperdbg/include/platform/user/header/platform-ioctl.h @@ -0,0 +1,40 @@ +/** + * @file platform-ioctl.h + * @author Max Raulea (max.raulea@gmail.com) + * @brief User mode cross-platform interface for the local kernel-driver IOCTL transport + * @details Distinct from the serial transport (platform-serial), which talks to a remote + * debuggee. This interface is the LOCAL control channel: the userspace library + * drives the HyperDbg kernel driver through device I/O control codes. The command + * and packet layers are platform independent; only the device-control primitive + * underneath them is OS specific. Windows maps onto Win32 DeviceIoControl over a + * \\.\HyperDbgDebuggerDevice handle; Linux will map onto ioctl() against a + * /dev/HyperDbg character device exposed by the (future) kernel module (TODO). + * + * @version 0.20 + * @date 2026-06-09 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +// +// SEND an I/O control code to the local kernel driver. Mirrors the Win32 +// DeviceIoControl signature so the call sites stay verbatim apart from the name. +// The Overlapped parameter is kept as a void * so the shared signature does not +// leak OVERLAPPED into the protocol code; synchronous callers pass NULL. +// Returns TRUE on success; on failure use PlatformGetLastError for the reason. +// +BOOL +PlatformDeviceIoControl(HANDLE Device, + DWORD IoControlCode, + LPVOID InBuffer, + DWORD InBufferSize, + LPVOID OutBuffer, + DWORD OutBufferSize, + LPDWORD BytesReturned, + LPVOID Overlapped); diff --git a/hyperdbg/include/platform/user/header/platform-lib-calls.h b/hyperdbg/include/platform/user/header/platform-lib-calls.h new file mode 100644 index 00000000..021d4a5b --- /dev/null +++ b/hyperdbg/include/platform/user/header/platform-lib-calls.h @@ -0,0 +1,137 @@ +/** + * @file platform-lib-calls.h + * @author Max Raulea (max.raulea@gmail.com) + * @brief User mode Cross platform APIs for platofrm dependend library calls + * @details + * @version 0.19 + * @date 2026-06-01 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +#include +#include + +// +// VSNPRINTF +// +INT +PlatformVsnprintf(char * Buffer, SIZE_T BufferSize, const char * Format, va_list ArgList); + +// +// STRDUP +// +char * +PlatformStrDup(const char * Str); + +// +// SET MEMORY TO ZERO +// +VOID +PlatformZeroMemory(PVOID Buffer, SIZE_T Size); + +// +// SPRINTF +// +INT +PlatformSprintf(char * Buffer, SIZE_T BufferSize, const char * Format, ...); + +// +// HIGH-RESOLUTION PERFORMANCE COUNTER +// +BOOLEAN +PlatformQueryPerformanceFrequency(LARGE_INTEGER * Frequency); + +BOOLEAN +PlatformQueryPerformanceCounter(LARGE_INTEGER * Count); + +// +// EVENT / SYNCHRONIZATION OBJECTS +// +HANDLE +PlatformCreateEvent(BOOLEAN ManualReset, BOOLEAN InitialState); + +BOOLEAN +PlatformSetEvent(HANDLE EventHandle); + +BOOLEAN +PlatformResetEvent(HANDLE EventHandle); + +DWORD +PlatformWaitForSingleObject(HANDLE Handle, DWORD TimeoutMilliseconds); + +BOOLEAN +PlatformCloseHandle(HANDLE Handle); + +// +// LAST OS ERROR +// +// TODO (linux, correctness): the wrappers below only unify the success/failure +// *boolean* convention. The actual error semantics still differ across platforms +// and must be reconciled later: +// - PlatformGetLastError returns raw Linux errno (EACCES=13, ...) which does NOT +// match the Win32 ERROR_* code space (ERROR_ACCESS_DENIED=5, ...). Code that +// merely logs/checks-nonzero is fine; code that compares against ERROR_* needs +// an errno -> ERROR_* mapping here. +// - Failure sentinels are not uniform across the Win32 calls we wrap: file opens +// fail with INVALID_HANDLE_VALUE (not NULL), most other handle calls fail with +// NULL. Callers must test the right one. +// For now: getting the project to compile is step 1; correctness comes next. +// +DWORD +PlatformGetLastError(VOID); + +// +// CONSOLE OUTPUT (raw bytes to stdout) +// +BOOLEAN +PlatformWriteConsole(const VOID * Buffer, DWORD NumberOfBytes); + +// +// FILE I/O +// +HANDLE +PlatformOpenFileForWriting(const WCHAR * Path); + +BOOLEAN +PlatformWriteFile(HANDLE FileHandle, const VOID * Buffer, DWORD NumberOfBytes); + +BOOLEAN +PlatformCloseFile(HANDLE FileHandle); + +// +// READ-ONLY FILE MAPPING +// +// PlatformMapFileReadOnly also hands back the still-open file handle in +// *OutFileHandle, so callers can issue supplementary raw reads via +// PlatformReadFileAtOffset; release everything with PlatformUnmapFile. +// +VOID * +PlatformMapFileReadOnly(const WCHAR * Path, PSIZE_T OutFileSize, PHANDLE OutFileHandle); + +BOOLEAN +PlatformReadFileAtOffset(HANDLE FileHandle, UINT64 Offset, VOID * Buffer, DWORD NumberOfBytes, LPDWORD BytesRead); + +VOID +PlatformUnmapFile(VOID * BaseAddress, SIZE_T FileSize, HANDLE FileHandle); + +// +// PROCESS / THREAD IDENTITY +// +UINT32 +PlatformGetCurrentThreadId(VOID); + +UINT32 +PlatformGetCurrentProcessorNumber(VOID); + +UINT32 +PlatformGetCurrentProcessId(VOID); + +CHAR * + PlatformGetCurrentProcessName(VOID); diff --git a/hyperdbg/include/platform/user/header/platform-serial.h b/hyperdbg/include/platform/user/header/platform-serial.h new file mode 100644 index 00000000..f33b48ec --- /dev/null +++ b/hyperdbg/include/platform/user/header/platform-serial.h @@ -0,0 +1,70 @@ +/** + * @file platform-serial.h + * @author Max Raulea (max.raulea@gmail.com) + * @brief User mode cross-platform interface for the kernel-debugger serial transport + * @details The kernel-debugging *protocol* in kd.cpp is platform independent; only + * the byte transport underneath it (serial COM port / named pipe) is OS + * specific. This interface isolates those primitives so the protocol layer + * can stay shared. Windows maps onto Win32 (CreateFile / Comm* / overlapped + * ReadFile/WriteFile); Linux will map onto termios over /dev/tty* (TODO). + * + * @version 0.20 + * @date 2026-06-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +// +// Distinguishes the two I/O modes the transport uses. On Windows the debugger +// side opens the port for overlapped (async) I/O while the debuggee side uses +// blocking I/O; this enum lets the platform layer pick the right mechanism +// without leaking OVERLAPPED into the protocol code. +// +typedef enum _PLATFORM_SERIAL_IO_ROLE +{ + PLATFORM_SERIAL_IO_DEBUGGER, // overlapped / async reads + PLATFORM_SERIAL_IO_DEBUGGEE, // blocking reads (with comm timeout) + +} PLATFORM_SERIAL_IO_ROLE; + +// +// OPEN a serial COM port by name for the given role. +// Returns a transport handle, or NULL on failure. +// +HANDLE +PlatformSerialOpen(const char * PortName, PLATFORM_SERIAL_IO_ROLE Role); + +// +// CONFIGURE baud rate and the fixed 8-N-1 framing the protocol expects. +// +BOOLEAN +PlatformSerialConfigure(HANDLE Handle, DWORD BaudRate); + +// +// READ a single byte. *BytesRead is set to the number of bytes actually read. +// The caller (protocol layer) owns the packet-assembly loop. +// +BOOLEAN +PlatformSerialReadByte(HANDLE Handle, + CHAR * OutByte, + DWORD * BytesRead, + PLATFORM_SERIAL_IO_ROLE Role); + +// +// WRITE a buffer. Synchronous selects blocking write (debuggee/handshaking) +// versus overlapped write (debugger). +// +BOOLEAN +PlatformSerialWrite(HANDLE Handle, const void * Buffer, UINT32 Length, BOOLEAN Synchronous); + +// +// CLOSE the transport handle and release any associated OS resources. +// +BOOLEAN +PlatformSerialClose(HANDLE Handle); diff --git a/hyperdbg/include/platform/user/header/platform-signal.h b/hyperdbg/include/platform/user/header/platform-signal.h new file mode 100644 index 00000000..9a3f73db --- /dev/null +++ b/hyperdbg/include/platform/user/header/platform-signal.h @@ -0,0 +1,43 @@ +/** + * @file platform-signal.h + * @author Max Raulea (max.raulea@gmail.com) + * @brief User mode cross-platform interface for the console-control (CTRL+C / CTRL+BREAK) handler + * @details HyperDbg installs a single handler (BreakController) that pauses the + * debuggee when the user hits CTRL+C / CTRL+BREAK. The handler body is + * platform independent; only the OS mechanism that delivers the event + * and the thread context it runs in are OS specific. This interface + * isolates that registration. Windows maps onto SetConsoleCtrlHandler; + * Linux maps onto POSIX signals serviced by a dedicated sigwait() thread + * so the handler runs in ordinary thread context (matching Windows, which + * also dispatches the handler on its own thread). + * + * @version 0.20 + * @date 2026-06-16 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +// +// Console-control handler signature. Matches the Win32 PHANDLER_ROUTINE shape +// (and BreakController) so the same function pointer is usable on both platforms. +// CtrlType is one of the CTRL_*_EVENT codes. +// +typedef BOOL (*PLATFORM_CTRL_HANDLER)(DWORD CtrlType); + +// +// INSTALL the process console-control handler. +// Windows: registers Handler via SetConsoleCtrlHandler. +// Linux: blocks the relevant signals process-wide and starts a dedicated +// sigwait() thread that translates them into CTRL_*_EVENT codes and +// invokes Handler. Must be called once, before other threads spawn, +// so the blocked-signal mask is inherited by every thread. +// Returns TRUE on success, FALSE on failure. +// +BOOLEAN +PlatformInstallCtrlHandler(PLATFORM_CTRL_HANDLER Handler); diff --git a/hyperdbg/include/platform/user/header/windows-only/windows-privilege.h b/hyperdbg/include/platform/user/header/windows-only/windows-privilege.h new file mode 100644 index 00000000..a8c19eaa --- /dev/null +++ b/hyperdbg/include/platform/user/header/windows-only/windows-privilege.h @@ -0,0 +1,23 @@ +/** + * @file windows-privilege.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Windows only APIs for adjusting privileges + * @details + * @version 0.19 + * @date 2026-05-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#if defined(__linux__) +# include "../../../../include/SDK/HyperDbgSdk.h" +#endif // defined(__linux__) + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +WindowsSetDebugPrivilege(); diff --git a/hyperdbg/include/ZycoreExportConfig.h b/hyperdbg/include/zydis/ZycoreExportConfig.h similarity index 100% rename from hyperdbg/include/ZycoreExportConfig.h rename to hyperdbg/include/zydis/ZycoreExportConfig.h diff --git a/hyperdbg/include/ZydisExportConfig.h b/hyperdbg/include/zydis/ZydisExportConfig.h similarity index 100% rename from hyperdbg/include/ZydisExportConfig.h rename to hyperdbg/include/zydis/ZydisExportConfig.h diff --git a/hyperdbg/kdserial/CMakeLists.txt b/hyperdbg/kdserial/CMakeLists.txt new file mode 100644 index 00000000..922affe9 --- /dev/null +++ b/hyperdbg/kdserial/CMakeLists.txt @@ -0,0 +1,29 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "common.c" + "hardware.c" + "ioaccess.c" + "uartio.c" + "apm88xxxx.c" + "bcm2835.c" + "msm8974.c" + "msm8x60.c" + "mx6uart.c" + "nvidia.c" + "omap.c" + "pl011.c" + "sam5250.c" + "sdm845.c" + "spimax311.c" + "uart16550.c" + "usif.c" + "kdcom.h" + "uartp.h" + "common.h" + "win11sdk.h" + "kdserial.def" +) +wdk_add_library(kdserial SHARED + KMDF 1.15 + ${SourceFiles} +) diff --git a/hyperdbg/kdserial/kdserial.vcxproj b/hyperdbg/kdserial/kdserial.vcxproj index 5e17ff37..22ed068a 100644 --- a/hyperdbg/kdserial/kdserial.vcxproj +++ b/hyperdbg/kdserial/kdserial.vcxproj @@ -1,5 +1,8 @@  + + + debug @@ -31,6 +34,7 @@ + @@ -45,7 +49,7 @@ v4.5 14.0 kdserial - Universal + Desktop 10.0.10135.0 $(LatestTargetPlatformVersion) @@ -77,6 +81,7 @@ false $(SolutionDir)build\bin\$(Configuration)\ $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + false kdserial @@ -84,6 +89,7 @@ false $(SolutionDir)build\bin\$(Configuration)\ $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ + false false @@ -94,6 +100,7 @@ $(IntDir);%(AdditionalIncludeDirectories);$(KM_IncludePath);$(ProjectDir)..\..\inc Default true + stdcpp20 $(DDK_LIB_PATH);%(AdditionalLibraryDirectories);$(SolutionDir)libraries\kdserial\$(PlatformTarget) @@ -116,6 +123,8 @@ $(IntDir);%(AdditionalIncludeDirectories);$(KM_IncludePath);$(ProjectDir)..\..\inc true + stdcpp20 + Full $(DDK_LIB_PATH);%(AdditionalLibraryDirectories);$(SolutionDir)libraries\kdserial\$(PlatformTarget) @@ -135,5 +144,15 @@ + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/hyperdbg/kdserial/packages.config b/hyperdbg/kdserial/packages.config new file mode 100644 index 00000000..eb276766 --- /dev/null +++ b/hyperdbg/kdserial/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/hyperdbg/kdserial/usif.c b/hyperdbg/kdserial/usif.c index 263ec62a..a409130f 100644 --- a/hyperdbg/kdserial/usif.c +++ b/hyperdbg/kdserial/usif.c @@ -21,7 +21,7 @@ Abstract: #define USIF_FIFO_STAT 0x00000044 // FIFO status register #define USIF_FIFO_STAT_TXFFS 0x00FF0000 // TX filled FIFO stages #define USIF_FIFO_STAT_RXFFS 0x000000FF // RX filled FIFO stages -#define USIF_TXD 0x00040000 // Transmisson data register +#define USIF_TXD 0x00040000 // Transmission data register #define USIF_RXD 0x00080000 // Reception data register // ------------------------------------------------------------------ Functions diff --git a/hyperdbg/libhyperdbg/CMakeLists.txt b/hyperdbg/libhyperdbg/CMakeLists.txt new file mode 100644 index 00000000..fac7603f --- /dev/null +++ b/hyperdbg/libhyperdbg/CMakeLists.txt @@ -0,0 +1,193 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "../include/platform/general/header/Environment.h" + "../include/platform/user/header/Windows.h" + "header/assembler.h" + "header/commands.h" + "header/common.h" + "header/communication.h" + "header/debugger.h" + "header/export.h" + "header/forwarding.h" + "header/globals.h" + "header/help.h" + "header/hwdbg-interpreter.h" + "header/inipp.h" + "header/install.h" + "header/kd.h" + "header/libhyperdbg.h" + "header/list.h" + "header/namedpipe.h" + "header/objects.h" + "header/pe-parser.h" + "header/rev-ctrl.h" + "header/script-engine.h" + "header/symbol.h" + "header/tests.h" + "header/transparency.h" + "header/ud.h" + "pch.h" + "../include/platform/user/code/platform-intrinsics.c" + "../include/platform/user/code/platform-lib-calls.c" + "../include/platform/user/code/platform-serial.c" + "../include/platform/user/code/platform-ioctl.c" + "../include/platform/user/code/platform-signal.c" + "../script-eval/code/Functions.c" + "../script-eval/code/Keywords.c" + "../script-eval/code/PseudoRegisters.c" + "../script-eval/code/Regs.c" + "../script-eval/code/ScriptEngineEval.c" + "code/common/spinlock.cpp" + "code/debugger/commands/debugging-commands/a.cpp" + "code/debugger/commands/debugging-commands/core.cpp" + "code/debugger/commands/debugging-commands/dt-struct.cpp" + "code/debugger/commands/debugging-commands/gu.cpp" + "code/debugger/commands/debugging-commands/k.cpp" + "code/debugger/commands/debugging-commands/preactivate.cpp" + "code/debugger/commands/debugging-commands/prealloc.cpp" + "code/debugger/commands/extension-commands/crwrite.cpp" + "code/debugger/commands/extension-commands/rev.cpp" + "code/debugger/commands/extension-commands/trace.cpp" + "code/debugger/commands/extension-commands/track.cpp" + "code/debugger/commands/extension-commands/mode.cpp" + "code/debugger/commands/hwdbg-commands/hw_clk.cpp" + "code/debugger/commands/meta-commands/dump.cpp" + "code/debugger/commands/meta-commands/kill.cpp" + "code/debugger/commands/meta-commands/pagein.cpp" + "code/debugger/commands/meta-commands/pe.cpp" + "code/debugger/commands/meta-commands/restart.cpp" + "code/debugger/commands/meta-commands/start.cpp" + "code/debugger/commands/meta-commands/switch.cpp" + "code/debugger/commands/meta-commands/thread.cpp" + "code/debugger/core/break-control.cpp" + "code/debugger/core/debugger.cpp" + "code/debugger/core/interpreter.cpp" + "code/debugger/kernel-level/kd.cpp" + "code/debugger/kernel-level/kernel-listening.cpp" + "code/debugger/misc/assembler.cpp" + "code/debugger/misc/callstack.cpp" + "code/debugger/misc/disassembler.cpp" + "code/debugger/misc/readmem.cpp" + "code/debugger/script-engine/script-engine-wrapper.cpp" + "code/debugger/script-engine/script-engine.cpp" + "code/debugger/script-engine/symbol.cpp" + "code/debugger/user-level/pe-parser.cpp" + "code/debugger/user-level/ud.cpp" + "code/debugger/user-level/user-listening.cpp" + "code/export/export.cpp" + "code/hwdbg/hwdbg-interpreter.cpp" + "code/objects/objects.cpp" + "code/rev/rev-ctrl.cpp" + "pch.cpp" + "code/app/dllmain.cpp" + "code/app/libhyperdbg.cpp" + "code/common/common.cpp" + "code/common/list.cpp" + "code/debugger/commands/debugging-commands/bc.cpp" + "code/debugger/commands/debugging-commands/bd.cpp" + "code/debugger/commands/debugging-commands/be.cpp" + "code/debugger/commands/debugging-commands/bl.cpp" + "code/debugger/commands/debugging-commands/bp.cpp" + "code/debugger/commands/debugging-commands/cpu.cpp" + "code/debugger/commands/debugging-commands/d-u.cpp" + "code/debugger/commands/debugging-commands/e.cpp" + "code/debugger/commands/debugging-commands/eval.cpp" + "code/debugger/commands/debugging-commands/events.cpp" + "code/debugger/commands/debugging-commands/exit.cpp" + "code/debugger/commands/debugging-commands/flush.cpp" + "code/debugger/commands/debugging-commands/g.cpp" + "code/debugger/commands/debugging-commands/i.cpp" + "code/debugger/commands/debugging-commands/lm.cpp" + "code/debugger/commands/debugging-commands/load.cpp" + "code/debugger/commands/debugging-commands/output.cpp" + "code/debugger/commands/debugging-commands/p.cpp" + "code/debugger/commands/debugging-commands/pause.cpp" + "code/debugger/commands/debugging-commands/print.cpp" + "code/debugger/commands/debugging-commands/r.cpp" + "code/debugger/commands/debugging-commands/rdmsr.cpp" + "code/debugger/commands/debugging-commands/s.cpp" + "code/debugger/commands/debugging-commands/settings.cpp" + "code/debugger/commands/debugging-commands/sleep.cpp" + "code/debugger/commands/debugging-commands/t.cpp" + "code/debugger/commands/debugging-commands/test.cpp" + "code/debugger/commands/debugging-commands/unload.cpp" + "code/debugger/commands/debugging-commands/wrmsr.cpp" + "code/debugger/commands/debugging-commands/x.cpp" + "code/debugger/commands/extension-commands/cpuid.cpp" + "code/debugger/commands/extension-commands/dr.cpp" + "code/debugger/commands/extension-commands/epthook.cpp" + "code/debugger/commands/extension-commands/epthook2.cpp" + "code/debugger/commands/extension-commands/exception.cpp" + "code/debugger/commands/extension-commands/hide.cpp" + "code/debugger/commands/extension-commands/interrupt.cpp" + "code/debugger/commands/extension-commands/ioin.cpp" + "code/debugger/commands/extension-commands/ioout.cpp" + "code/debugger/commands/extension-commands/measure.cpp" + "code/debugger/commands/extension-commands/monitor.cpp" + "code/debugger/commands/extension-commands/msrread.cpp" + "code/debugger/commands/extension-commands/msrwrite.cpp" + "code/debugger/commands/extension-commands/pa2va.cpp" + "code/debugger/commands/extension-commands/pmc.cpp" + "code/debugger/commands/extension-commands/pte.cpp" + "code/debugger/commands/extension-commands/syscall-sysret.cpp" + "code/debugger/commands/extension-commands/tsc.cpp" + "code/debugger/commands/extension-commands/unhide.cpp" + "code/debugger/commands/extension-commands/va2pa.cpp" + "code/debugger/commands/extension-commands/vmcall.cpp" + "code/debugger/commands/meta-commands/attach.cpp" + "code/debugger/commands/meta-commands/cls.cpp" + "code/debugger/commands/meta-commands/connect.cpp" + "code/debugger/commands/meta-commands/debug.cpp" + "code/debugger/commands/meta-commands/detach.cpp" + "code/debugger/commands/meta-commands/disconnect.cpp" + "code/debugger/commands/meta-commands/formats.cpp" + "code/debugger/commands/meta-commands/help.cpp" + "code/debugger/commands/meta-commands/listen.cpp" + "code/debugger/commands/meta-commands/logclose.cpp" + "code/debugger/commands/meta-commands/logopen.cpp" + "code/debugger/commands/meta-commands/process.cpp" + "code/debugger/commands/meta-commands/script.cpp" + "code/debugger/commands/meta-commands/status.cpp" + "code/debugger/commands/meta-commands/sym.cpp" + "code/debugger/commands/meta-commands/sympath.cpp" + "code/debugger/communication/forwarding.cpp" + "code/debugger/communication/namedpipe.cpp" + "code/debugger/communication/remote-connection.cpp" + "code/debugger/communication/tcpclient.cpp" + "code/debugger/communication/tcpserver.cpp" + "code/debugger/driver-loader/install.cpp" + "code/debugger/tests/tests.cpp" + "code/debugger/transparency/gaussian-rng.cpp" + "code/debugger/transparency/transparency.cpp" + "code/assembly/asm-vmx-checks.asm" +) +include_directories( + "../dependencies/phnt" + "../dependencies" + "../dependencies/zydis/dependencies/zycore/include" + "../include" + "../dependencies/zydis/include" + "." + "../script-eval" + "../dependencies/keystone/include" +) +set_source_files_properties( + "../include/platform/user/code/platform-intrinsics.c" + "../include/platform/user/code/platform-lib-calls.c" + "../include/platform/user/code/platform-serial.c" + "../include/platform/user/code/platform-ioctl.c" + "../include/platform/user/code/platform-signal.c" + "../script-eval/code/Functions.c" + "../script-eval/code/Keywords.c" + "../script-eval/code/PseudoRegisters.c" + "../script-eval/code/Regs.c" + "../script-eval/code/ScriptEngineEval.c" + PROPERTIES LANGUAGE CXX +) + +if(UNIX) + list(REMOVE_ITEM SourceFiles "code/debugger/script-engine/symbol.cpp") + list(APPEND SourceFiles "code/debugger/script-engine/symbol-linux.cpp") +endif() + +add_library(libhyperdbg SHARED ${SourceFiles}) diff --git a/hyperdbg/hprdbgctrl/code/app/dllmain.cpp b/hyperdbg/libhyperdbg/code/app/dllmain.cpp similarity index 100% rename from hyperdbg/hprdbgctrl/code/app/dllmain.cpp rename to hyperdbg/libhyperdbg/code/app/dllmain.cpp diff --git a/hyperdbg/libhyperdbg/code/app/libhyperdbg.cpp b/hyperdbg/libhyperdbg/code/app/libhyperdbg.cpp new file mode 100644 index 00000000..5a2c812a --- /dev/null +++ b/hyperdbg/libhyperdbg/code/app/libhyperdbg.cpp @@ -0,0 +1,937 @@ +/** + * @file libhyperdbg.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Main interface to connect applications to driver + * @details + * @version 0.1 + * @date 2020-04-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +using namespace std; + +// +// Global Variables +// +extern HANDLE g_DeviceHandle; +extern HANDLE g_IsDriverLoadedSuccessfully; +extern BOOLEAN g_IsMessageLoggingWindowClosed; +extern TCHAR g_DriverLocation[MAX_PATH]; +extern TCHAR g_DriverName[MAX_PATH]; +extern BOOLEAN g_UseCustomDriverLocation; +extern LIST_ENTRY g_EventTrace; +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsVmmModuleLoaded; +extern BOOLEAN g_IsHyperTraceModuleLoaded; + +/** + * @brief Install (start) VMM driver + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgStartDriver() +{ + if (!ManageDriver(g_DriverName, g_DriverLocation, DRIVER_FUNC_INSTALL)) + { + // + // Error - remove driver + // + ManageDriver(g_DriverName, g_DriverLocation, DRIVER_FUNC_REMOVE); + + return 1; + } + + return 0; +} + +/** + * @brief Stop the driver + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgStopDriver(LPCTSTR DriverName) +{ + // + // Unload the driver if loaded + // + if (g_DriverLocation[0] != (TCHAR)0 && ManageDriver(DriverName, g_DriverLocation, DRIVER_FUNC_STOP)) + { + return 0; + } + else + { + return 1; + } +} + +/** + * @brief Install KD (Kernel Debugger) driver + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgInstallKdDriver() +{ + // + // Check if the driver is already loaded, if that's the case, we shouldn't try to load it again + // + if (g_IsKdModuleLoaded) + { + // + // The driver is already loaded, so we shouldn't try to load it again + // but we can consider it as success and return zero + // + return 0; + } + + // + // The driver is not started yet so let us the install driver + // First setup full path to driver name + // + + // + // If the user has not specified a custom driver location, then we + // need to find the driver in the same directory as the executable + // + if (!g_UseCustomDriverLocation) + { + if (!SetupPathForFileName(KERNEL_DEBUGGER_DRIVER_NAME_AND_EXTENSION, g_DriverLocation, sizeof(g_DriverLocation), TRUE)) + { + return 1; + } + + // + // Use default driver name + // + strcpy_s(g_DriverName, KERNEL_DEBUGGER_DRIVER_NAME); + } + + if (HyperDbgStartDriver() != 0) + { + ShowMessages("unable to install KD driver\n"); + + return 1; + } + + return 0; +} + +/** + * @brief Start KD driver + * + * @return INT return zero if it was successful or non-zero if there was error + */ +INT +HyperDbgStartKdDriver() +{ + return HyperDbgStartDriver(); +} + +/** + * @brief Stop KD driver + * + * @return INT return zero if it was successful or non-zero if there was error + */ +INT +HyperDbgStopKdDriver() +{ + return HyperDbgStopDriver(g_DriverName); +} + +/** + * @brief Remove the driver + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgUninstallDriver(LPCTSTR DriverName) +{ + // + // Unload the driver if loaded. Ignore any errors + // + if (g_DriverLocation[0] != (TCHAR)0 && ManageDriver(DriverName, g_DriverLocation, DRIVER_FUNC_REMOVE)) + { + return 0; + } + else + { + return 1; + } +} + +/** + * @brief Remove the KD (Kernel Debugger) driver + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgUninstallKdDriver() +{ + return HyperDbgUninstallDriver(g_DriverName); +} + +/** + * @brief Initialize VMM module + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgInitHyperTraceModule() +{ + BOOL Status; + DWORD BytesReturned; + DEBUGGER_INIT_HYPERTRACE_PACKET InitHyperTracePacket = {0}; + + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnOne); + + // + // Send IOCTL to initialize HyperTrace module + // + Status = DeviceIoControl(g_DeviceHandle, // Handle to device + IOCTL_INIT_HYPERTRACE, // IO Control Code (IOCTL) + &InitHyperTracePacket, // Input Buffer to driver. + SIZEOF_DEBUGGER_INIT_HYPERTRACE_PACKET, // Length of input buffer in bytes. + &InitHyperTracePacket, // Output Buffer from driver. + SIZEOF_DEBUGGER_INIT_HYPERTRACE_PACKET, // Length of output buffer in bytes. + &BytesReturned, // Bytes placed in buffer. + NULL // synchronous call + ); + + // + // Check if the IOCTL was successful, if not show the error message and return + // + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + return 1; + } + + // + // Check the kernel status + // + if (InitHyperTracePacket.KernelStatus != DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + ShowErrorMessage(InitHyperTracePacket.KernelStatus); + return 1; + } + + return 0; +} + +/** + * @brief Initialize VMM module + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgInitVmmModule() +{ + BOOL Status; + DWORD BytesReturned; + DEBUGGER_INIT_VMM_PACKET InitVmmPacket = {0}; + + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnOne); + + // + // Create event to show if the kd module is loaded or not + // + g_IsDriverLoadedSuccessfully = CreateEvent(NULL, FALSE, FALSE, NULL); + + // + // Send IOCTL to initialize VMM module + // + Status = DeviceIoControl(g_DeviceHandle, // Handle to device + IOCTL_INIT_VMM, // IO Control Code (IOCTL) + &InitVmmPacket, // Input Buffer to driver. + SIZEOF_DEBUGGER_INIT_VMM_PACKET, // Length of input buffer in bytes. + &InitVmmPacket, // Output Buffer from driver. + SIZEOF_DEBUGGER_INIT_VMM_PACKET, // Length of output buffer in bytes. + &BytesReturned, // Bytes placed in buffer. + NULL // synchronous call + ); + + // + // check if the IOCTL was successful, if not show the error message and return + // + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + CloseHandle(g_IsDriverLoadedSuccessfully); + return 1; + } + + // + // Check the kernel status for early errors (e.g., HyperTrace already loaded) + // + if (InitVmmPacket.KernelStatus != DEBUGGER_OPERATION_WAS_SUCCESSFUL && + InitVmmPacket.KernelStatus != 0) + { + ShowErrorMessage(InitVmmPacket.KernelStatus); + CloseHandle(g_IsDriverLoadedSuccessfully); + return 1; + } + + // + // We wait for the first message from the kernel debugger to continue + // + WaitForSingleObject( + g_IsDriverLoadedSuccessfully, + INFINITE); + + // + // No need to handle anymore + // + CloseHandle(g_IsDriverLoadedSuccessfully); + + // + // VMM module is initialized at this point + // + return 0; +} + +/** + * @brief Create handle from KD (HyperKD) module + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgCreateHandleFromKdModule() +{ + DWORD ErrorNum; + DWORD ThreadId; + + if (g_DeviceHandle) + { + ShowMessages("handle of the driver found, if you use the 'load' command before, please " + "unload it using the 'unload' command\n"); + return 1; + } + + // + // Make sure that this variable is false, because it might be set to + // true as the result of a previous load + // + g_IsMessageLoggingWindowClosed = FALSE; + + // + // Init entering vmx + // + g_DeviceHandle = CreateFileA( + "\\\\.\\HyperDbgDebuggerDevice", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, /// lpSecurityAttirbutes + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); /// lpTemplateFile + + if (g_DeviceHandle == INVALID_HANDLE_VALUE) + { + ErrorNum = GetLastError(); + if (ErrorNum == ERROR_ACCESS_DENIED) + { + ShowMessages("err, access denied\nare you sure you have administrator " + "rights?\n"); + } + else if (ErrorNum == ERROR_GEN_FAILURE) + { + ShowMessages("err, a device attached to the system is not functioning\n" + "vmx feature might be disabled from BIOS or VBS/HVCI is active\n"); + } + else + { + ShowMessages("err, CreateFile failed (%x)\n", ErrorNum); + } + + g_DeviceHandle = NULL; + return 1; + } + + // + // Initialize the list of events + // + InitializeListHead(&g_EventTrace); + +#if !UseDbgPrintInsteadOfUsermodeMessageTracking + HANDLE Thread = CreateThread(NULL, 0, IrpBasedBufferThread, NULL, 0, &ThreadId); + + // if (Thread) + // { + // ShowMessages("thread Created successfully\n"); + // } + +#endif + + return 0; +} + +/** + * @brief Unload VMM module + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgUnloadVmm() +{ + BOOL Status; + DWORD BytesReturned; + + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnOne); + + ShowMessages("start terminating vmm...\n"); + + // + // Check if HyperTrace module is loaded, if so we need to unload it before unloading VMM + // + if (g_IsHyperTraceModuleLoaded) + { + ShowMessages( + "the trace module is currently loaded and will be unloaded before the vmm module\nnote that hypertrace (trace) " + "use the hypervisor (vmm) features when it is loaded after vmm, however, hypertrace can also operate without the vmm " + "module, although hypervisor-specific features will not be available\n" + "the 'trace' module will now be unloaded automatically. You can reload it later " + "using the command 'load trace', which will load the trace module again without enabling hypervisor-dependent features\n"); + + HyperDbgUnloadHyperTrace(); + } + + // + // Uninitialize the user debugger if it's initialized + // + UdUninitializeUserDebugger(); + + // + // Send IOCTL terminate VMX + // + Status = DeviceIoControl(g_DeviceHandle, // Handle to device + IOCTL_TERMINATE_VMX, // IO Control Code (IOCTL) + NULL, // Input Buffer to driver. + 0, // Length of input buffer in bytes. (x 2 is bcuz + // as the driver is x64 and has 64 bit values) + NULL, // Output Buffer from driver. + 0, // Length of output buffer in bytes. + &BytesReturned, // Bytes placed in buffer. + NULL // synchronous call + ); + + // + // wait to make sure we don't use an invalid handle in another Ioctl + // + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + return 1; + } + + // + // Hypervisor (VMM) module is not loaded anymore + // + g_IsVmmModuleLoaded = FALSE; + + ShowMessages("you're not on HyperDbg's hypervisor anymore!\n"); + + return 0; +} + +/** + * @brief Unload HyperTrace module + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgUnloadHyperTrace() +{ + BOOL Status; + DWORD BytesReturned; + + AssertShowMessageReturnStmt(g_IsHyperTraceModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_HYPERTRACE_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnOne); + + ShowMessages("start terminating trace module...\n"); + + // + // Send IOCTL to unload HyperTrace module + // + Status = DeviceIoControl(g_DeviceHandle, // Handle to device + IOCTL_PERFORM_HYPERTRACE_UNLOAD, // IO Control Code (IOCTL) + NULL, // Input Buffer to driver. + 0, // Length of input buffer in bytes. (x 2 is bcuz + // as the driver is x64 and has 64 bit values) + NULL, // Output Buffer from driver. + 0, // Length of output buffer in bytes. + &BytesReturned, // Bytes placed in buffer. + NULL // synchronous call + ); + + // + // wait to make sure we don't use an invalid handle in another Ioctl + // + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + return 1; + } + + // + // HyperTrace module is not loaded anymore + // + g_IsHyperTraceModuleLoaded = FALSE; + + ShowMessages("the trace module is unloaded!\n"); + + return 0; +} + +/** + * @brief Unload KD driver + * + * @return INT return zero if it was successful or non-zero if there was error + */ +INT +HyperDbgUnloadKd() +{ + BOOL Status; + DWORD BytesReturned; + + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnOne); + + // + // Check if HyperTrace module is loaded, if so we need to unload it before unloading KD because KD is used by HyperTrace + // + if (g_IsHyperTraceModuleLoaded) + { + ShowMessages("err, unable to unload the kd module because the trace module is currently loaded " + "and uses the kd module, if you want to unload the kd module, please first unload " + "the trace module using the 'unload trace' command\n"); + return 1; + } + + // + // Check if VMM module is loaded, if so we need to unload it before unloading KD because KD is used by VMM + // + if (g_IsVmmModuleLoaded) + { + ShowMessages("err, unable to unload the kd module because the vmm module is currently loaded " + "and uses the kd module, if you want to unload the kd module, please first unload " + "the vmm module using the 'unload vmm' command\n"); + return 1; + } + + // + // Indicate that the message logging window is closed + // + g_IsMessageLoggingWindowClosed = TRUE; + + // + // Send IOCTL to mark complete all IRP Pending + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_RETURN_IRP_PENDING_PACKETS_AND_DISALLOW_IOCTL, // IO Control Code (IOCTL) + NULL, // Input Buffer to driver. + 0, // Length of input buffer in bytes. (x 2 is bcuz as the + // driver is x64 and has 64 bit values) + NULL, // Output Buffer from driver. + 0, // Length of output buffer in bytes. + &BytesReturned, // Bytes placed in buffer. + NULL // synchronous call + ); + + // + // wait to make sure we don't use an invalid handle in another Ioctl + // + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + return 1; + } + + // + // Wait for a while to make sure that all IRP pending are completed and the driver is ready to be unloaded + // + Sleep(1000); + + // + // Send IRP_MJ_CLOSE to driver to terminate Vmxs + // + if (!CloseHandle(g_DeviceHandle)) + { + ShowMessages("err, closing handle 0x%x\n", GetLastError()); + return 1; + }; + + // + // Null the handle to indicate that the driver's device is not ready + // to use + // + g_DeviceHandle = NULL; + + // + // Debugger module is not loaded anymore + // + g_IsKdModuleLoaded = FALSE; + + // + // Check if we found an already built symbol table + // + SymbolDeleteSymTable(); + + ShowMessages("the debugger module is unloaded!\n"); + + return 0; +} + +/** + * @brief check if any module is loaded (KD, VMM, HyperTrace, etc.) + * + * @return BOOLEAN return TRUE if any module is loaded, otherwise return FALSE + */ +BOOLEAN +HyperDbgIsAnyModuleLoaded() +{ + INT RetVal = 0; + + // + // Check if any module is loaded (KD, VMM, HyperTrace, etc.) + // + if (g_IsKdModuleLoaded || g_IsVmmModuleLoaded || g_IsHyperTraceModuleLoaded) + { + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief unload all modules (KD, VMM, HyperTrace, etc.) + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgUnloadAllModules() +{ + INT RetVal = 0; + + // + // Unload HyperTrace module if loaded + // + if (g_IsHyperTraceModuleLoaded && HyperDbgUnloadHyperTrace() != 0) + { + return 1; + } + + // + // Unload VMM module if loaded + // + if (g_IsVmmModuleLoaded && HyperDbgUnloadVmm() != 0) + { + return 1; + } + + // + // Unload KD module if loaded + // + if (g_IsKdModuleLoaded && HyperDbgUnloadKd() != 0) + { + return 1; + } + + return 0; +} + +/** + * @brief load kd module + * + * @return int return zero if it was successful or non-zero if there + */ +INT +HyperDbgLoadKdModule() +{ + // + // Check if the module is already loaded, if that's the case, we don't + // need to handle anymore + // + if (g_IsKdModuleLoaded) + { + // + // Return zero to indicate that the module is loaded successfully, + // and we no need to re-load it anymore + // + return 0; + } + + // + // Enable Debug privilege to the current token + // + if (!WindowsSetDebugPrivilege()) + { + ShowMessages("err, couldn't set debug privilege\n"); + return 1; + } + + // + // Create handle from the KD module + // + if (HyperDbgCreateHandleFromKdModule() == 1) + { + // + // No need to handle anymore + // + return 1; + } + + // + // KD module is loaded at this point + // + + // + // If we reach here so the module are loaded + // + g_IsKdModuleLoaded = TRUE; + + return 0; +} + +/** + * @brief Get the vendor of the current processor + * + * @return GENERIC_PROCESSOR_VENDOR the vendor of the processor + */ +GENERIC_PROCESSOR_VENDOR +HyperDbgGetProcessorVendor() +{ + CHAR CpuId[13] = {0}; + + // + // Read the vendor string + // + CpuReadVendorString(CpuId); + + // ShowMessages("current processor vendor is : %s\n", CpuId); + + if (strcmp(CpuId, "GenuineIntel") == 0) + { + return GENERIC_PROCESSOR_VENDOR_INTEL; + } + else if (strcmp(CpuId, "AuthenticAMD") == 0) + { + return GENERIC_PROCESSOR_VENDOR_AMD; + } + else + { + return GENERIC_PROCESSOR_VENDOR_OTHERS; + } +} + +/** + * @brief load vmm module + * + * @return int return zero if it was successful or non-zero if there + */ +INT +HyperDbgLoadVmmModule() +{ + // + // Check if the module is already loaded, if that's the case, we don't + // need to handle anymore + // + if (g_IsVmmModuleLoaded) + { + // + // Return zero to indicate that the module is loaded successfully, + // and we no need to re-load it anymore + // + return 0; + } + + // + // Check if the HyperTrace module is loaded or not + // + if (g_IsHyperTraceModuleLoaded) + { + ShowMessages( + "err, the trace module is currently loaded and should be unloaded before loading the vmm module\n" + "Note that HyperTrace (trace) uses the hypervisor (vmm) features when it is loaded after the vmm module, " + "however, HyperTrace can also operate without the vmm module, although hypervisor-specific features will not be available\n" + "to solve this problem, first unload the trace module using the 'unload trace' command, next, load " + "the vmm module and then load the trace module again. This way, the trace module is reloaded with hypervisor APIs\n"); + return 1; + } + + // + // Check if the processor is a genuine Intel processor (required for VT-x) + // + if (HyperDbgGetProcessorVendor() != GENERIC_PROCESSOR_VENDOR_INTEL) + { + ShowMessages("err, this program is not designed to run in a non-VT-x " + "environment. It needs an Intel processor.\n"); + return 1; + } + + ShowMessages("virtualization technology is vt-x\n"); + + if (VmxSupportDetection()) + { + ShowMessages("vmx operation is supported by your processor\n"); + } + else + { +#ifdef HYPERDBG_ENV_WINDOWS + ShowMessages("vmx operation is not supported by your processor " + "(if you are using an Intel processor, it might be because VBS is not disabled!)\n"); +#endif + return 1; + } + + // + // Load the KD module and create handle to it + // + if (HyperDbgLoadKdModule() == 1) + { + return 1; + } + + // + // Initialize VMM module + // + if (HyperDbgInitVmmModule() == 1) + { + ShowMessages("err, initializing VMM module\n"); + + return 1; + } + + // + // If we reach here so the module are loaded + // + g_IsVmmModuleLoaded = TRUE; + + ShowMessages("vmm module is running...\n"); + + return 0; +} + +/** + * @brief load hypertrace module + * + * @return int return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgLoadHyperTraceModule() +{ + // + // Check if the module is already loaded, if that's the case, we don't + // need to handle anymore + // + if (g_IsHyperTraceModuleLoaded) + { + // + // Return zero to indicate that the module is loaded successfully, + // and we no need to re-load it anymore + // + return 0; + } + + // + // Enable Debug privilege to the current token + // + if (!WindowsSetDebugPrivilege()) + { + ShowMessages("err, couldn't set debug privilege\n"); + return 1; + } + + // + // Check if the processor is a genuine Intel processor (required for HyperTrace) + // + if (HyperDbgGetProcessorVendor() != GENERIC_PROCESSOR_VENDOR_INTEL) + { + ShowMessages("err, this program is not designed to run in a non-Intel " + "environment as it needs Intel PT (Processor Trace) and Intel LBR " + "(Last Branch Record). It needs an Intel processor.\n"); + return 1; + } + + // + // Load the KD module and create handle to it + // + if (HyperDbgLoadKdModule() == 1) + { + return 1; + } + + // + // Initialize HyperTrace module + // + if (HyperDbgInitHyperTraceModule() == 1) + { + ShowMessages("err, initializing hypertrace module\n"); + + return 1; + } + + // + // If we reach here so the module are loaded + // + g_IsHyperTraceModuleLoaded = TRUE; + + ShowMessages("hypertrace (trace) module is running...\n"); + + return 0; +} + +/** + * @brief load all modules (KD, VMM, HyperTrace, etc.) + * + * @return INT return zero if it was successful or non-zero if there + * was error + */ +INT +HyperDbgLoadAllModules() +{ + INT RetVal = 0; + + // + // Load KD module if not loaded + // + if (!g_IsKdModuleLoaded && HyperDbgLoadKdModule() != 0) + { + return 1; + } + + // + // Load VMM module if not loaded + // + if (!g_IsVmmModuleLoaded && HyperDbgLoadVmmModule() != 0) + { + return 1; + } + + // + // Load HyperTrace module if not loaded + // + if (!g_IsHyperTraceModuleLoaded && HyperDbgLoadHyperTraceModule() != 0) + { + return 1; + } + + return 0; +} diff --git a/hyperdbg/libhyperdbg/code/app/messaging.cpp b/hyperdbg/libhyperdbg/code/app/messaging.cpp new file mode 100644 index 00000000..ca0f7264 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/app/messaging.cpp @@ -0,0 +1,149 @@ +/** + * @file messaging.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Functions for handling messages + * @details + * @version 0.19 + * @date 2026-05-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +using namespace std; + +// +// Global Variables +// +extern PVOID g_MessageHandler; +extern PVOID g_MessageHandlerSharedBuffer; +extern BOOLEAN g_LogOpened; +extern BOOLEAN g_IsConnectedToRemoteDebugger; +extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; + +/** + * @brief Set the function callback that will be called if any message + * needs to be shown + * + * @param Handler Function that handles the messages + * @return VOID + */ +VOID +SetTextMessageCallback(PVOID Handler) +{ + g_MessageHandler = Handler; +} + +/** + * @brief Set the function callback that will be called if any message + * needs to be shown + * + * @param Handler Function that handles the messages + * @return PVOID + */ +PVOID +SetTextMessageCallbackUsingSharedBuffer(PVOID Handler) +{ + g_MessageHandler = Handler; + g_MessageHandlerSharedBuffer = malloc(COMMUNICATION_BUFFER_SIZE + TCP_END_OF_BUFFER_CHARS_COUNT); + + if (!g_MessageHandlerSharedBuffer) + { + g_MessageHandler = NULL; + return NULL; + } + + RtlZeroMemory(g_MessageHandlerSharedBuffer, COMMUNICATION_BUFFER_SIZE + TCP_END_OF_BUFFER_CHARS_COUNT); + + return g_MessageHandlerSharedBuffer; +} + +/** + * @brief Unset the function callback that will be called if any message + * needs to be shown + * + * @return VOID + */ +VOID +UnsetTextMessageCallback() +{ + g_MessageHandler = NULL; + free(g_MessageHandlerSharedBuffer); + g_MessageHandlerSharedBuffer = NULL; +} + +/** + * @brief Show messages + * + * @param Fmt format string message + * @param ... arguments + * @return VOID + */ +VOID +ShowMessages(const CHAR * Fmt, ...) +{ + va_list ArgList; + va_list Args; + CHAR TempMessage[COMMUNICATION_BUFFER_SIZE + TCP_END_OF_BUFFER_CHARS_COUNT] = {0}; + + if (g_MessageHandler == NULL && !g_IsConnectedToRemoteDebugger && !g_IsSerialConnectedToRemoteDebugger) + { + va_start(Args, Fmt); + + vprintf(Fmt, Args); + + va_end(Args); + + if (!g_LogOpened) + { + return; + } + } + + va_start(ArgList, Fmt); + + INT SprintfResult = PlatformVsnprintf(TempMessage, sizeof(TempMessage), Fmt, ArgList); + + va_end(ArgList); + + if (SprintfResult != -1) + { + if (g_IsConnectedToRemoteDebugger) + { + // + // vsprintf_s and vswprintf_s return the number of characters written, + // not including the terminating null character, or a negative value + // if an output error occurs. + // + RemoteConnectionSendResultsToHost(TempMessage, SprintfResult); + } + else if (g_IsSerialConnectedToRemoteDebugger) + { + KdSendUsermodePrints(TempMessage, SprintfResult); + } + + if (g_LogOpened) + { + // + // .logopen command executed + // + LogopenSaveToFile(TempMessage); + } + if (g_MessageHandler != NULL) + { + // + // There is another handler + // + if (g_MessageHandlerSharedBuffer == NULL) + { + ((SendMessageWithParamCallback)g_MessageHandler)(TempMessage); + } + else + { + memcpy(g_MessageHandlerSharedBuffer, TempMessage, strlen(TempMessage) + 1); + ((SendMessageWithSharedBufferCallback)g_MessageHandler)(); + } + } + } +} diff --git a/hyperdbg/libhyperdbg/code/app/packets.cpp b/hyperdbg/libhyperdbg/code/app/packets.cpp new file mode 100644 index 00000000..e7a39339 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/app/packets.cpp @@ -0,0 +1,347 @@ +/** + * @file packets.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Functions for handling packets from the driver + * @details + * @version 0.19 + * @date 2026-05-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +using namespace std; + +// +// Global Variables +// +extern HANDLE g_DeviceHandle; +extern HANDLE g_IsDriverLoadedSuccessfully; +extern BOOLEAN g_IsMessageLoggingWindowClosed; +extern BOOLEAN g_BreakPrintingOutput; +extern BOOLEAN g_OutputSourcesInitialized; + +/** + * @brief Read kernel buffers using IRP Pending + * + * @param Device Driver handle + * @return VOID + */ +VOID +ReadIrpBasedBuffer() +{ + BOOL Status; + ULONG ReturnedLength; + REGISTER_NOTIFY_BUFFER RegisterEvent; + DWORD ErrorNum; + HANDLE Handle; + UINT32 OperationCode; + + RegisterEvent.hEvent = NULL; + RegisterEvent.Type = IRP_BASED; + + // + // Keep the packet reader on a dedicated synchronous handle. It blocks on + // a pending IOCTL while the main debugger handle continues sending other + // synchronous IOCTLs. + // + Handle = CreateFileA( + "\\\\.\\HyperDbgDebuggerDevice", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, /// lpSecurityAttirbutes + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); /// lpTemplateFile + + if (Handle == INVALID_HANDLE_VALUE) + { + ErrorNum = GetLastError(); + + if (ErrorNum == ERROR_ACCESS_DENIED) + { + ShowMessages("err, access denied\nare you sure you have administrator " + "rights?\n"); + } + else if (ErrorNum == ERROR_GEN_FAILURE) + { + ShowMessages("err, a device attached to the system is not functioning\n" + "vmx feature might be disabled from BIOS or VBS/HVCI is active\n"); + } + else + { + ShowMessages("err, CreateFile failed with (%x)\n", ErrorNum); + } + + g_DeviceHandle = NULL; + Handle = NULL; + + return; + } + + // + // allocate buffer for transferring messages + // + CHAR * OutputBuffer = (CHAR *)malloc(UsermodeBufferSize); + + try + { + while (!g_IsMessageLoggingWindowClosed) + { + // + // Clear the buffer + // + ZeroMemory(OutputBuffer, UsermodeBufferSize); + + Status = DeviceIoControl( + Handle, // Handle to device + IOCTL_REGISTER_EVENT, // IO Control Code (IOCTL) + &RegisterEvent, // Input Buffer to driver. + SIZEOF_REGISTER_EVENT * 2, // Length of input buffer in bytes. (x 2 is bcuz as the + // driver is x64 and has 64 bit values) + OutputBuffer, // Output Buffer from driver. + UsermodeBufferSize, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + // + // Error occurred for second time, and we show the error message + // + // ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + + // + // if we reach here, the packet is probably failed, it might + // be because of using flush command + // + continue; + } + + // + // Compute the received buffer's operation code + // + memcpy(&OperationCode, OutputBuffer, sizeof(UINT32)); + + // ShowMessages("Returned Length : 0x%x \n", ReturnedLength); + // ShowMessages("Operation Code : 0x%x \n", OperationCode); + + // + // Check if the operation code contains mandatory debuggee bit + // If that's the case, we shouldn't wait (sleep) for new messages + // + if ((OperationCode & OPERATION_MANDATORY_DEBUGGEE_BIT) == 0) + { + Sleep(DefaultSpeedOfReadingKernelMessages); // we're not trying to eat all of the CPU ;) + } + + switch (OperationCode) + { + case OPERATION_LOG_NON_IMMEDIATE_MESSAGE: + + if (g_BreakPrintingOutput) + { + // + // means that the user asserts a CTRL+C or CTRL+BREAK Signal + // we shouldn't show or save anything in this case + // + continue; + } + + ShowMessages("%s", OutputBuffer + sizeof(UINT32)); + + break; + + case OPERATION_LOG_MESSAGE_MANDATORY: + + ShowMessages("%s", OutputBuffer + sizeof(UINT32)); + + break; + + case OPERATION_LOG_INFO_MESSAGE: + + if (g_BreakPrintingOutput) + { + // + // means that the user asserts a CTRL+C or CTRL+BREAK Signal + // we shouldn't show or save anything in this case + // + continue; + } + + ShowMessages("%s", OutputBuffer + sizeof(UINT32)); + + break; + + case OPERATION_LOG_ERROR_MESSAGE: + if (g_BreakPrintingOutput) + { + // + // means that the user asserts a CTRL+C or CTRL+BREAK Signal + // we shouldn't show or save anything in this case + // + continue; + } + + ShowMessages("%s", OutputBuffer + sizeof(UINT32)); + + break; + + case OPERATION_LOG_WARNING_MESSAGE: + + if (g_BreakPrintingOutput) + { + // + // means that the user asserts a CTRL+C or CTRL+BREAK Signal + // we shouldn't show or save anything in this case + // + continue; + } + + ShowMessages("%s", OutputBuffer + sizeof(UINT32)); + + break; + + case OPERATION_COMMAND_FROM_DEBUGGER_CLOSE_AND_UNLOAD_VMM: + + KdCloseConnection(); + + break; + + case OPERATION_DEBUGGEE_USER_INPUT: + + KdHandleUserInputInDebuggee((DEBUGGEE_USER_INPUT_PACKET *)(OutputBuffer + sizeof(UINT32))); + + break; + + case OPERATION_DEBUGGEE_REGISTER_EVENT: + + KdRegisterEventInDebuggee( + (PDEBUGGER_GENERAL_EVENT_DETAIL)(OutputBuffer + sizeof(UINT32)), + ReturnedLength); + + break; + + case OPERATION_DEBUGGEE_ADD_ACTION_TO_EVENT: + + KdAddActionToEventInDebuggee( + (PDEBUGGER_GENERAL_ACTION)(OutputBuffer + sizeof(UINT32)), + ReturnedLength); + + break; + + case OPERATION_DEBUGGEE_CLEAR_EVENTS: + + KdSendModifyEventInDebuggee( + (PDEBUGGER_MODIFY_EVENTS)(OutputBuffer + sizeof(UINT32)), + TRUE); + + break; + + case OPERATION_DEBUGGEE_CLEAR_EVENTS_WITHOUT_NOTIFYING_DEBUGGER: + + KdSendModifyEventInDebuggee( + (PDEBUGGER_MODIFY_EVENTS)(OutputBuffer + sizeof(UINT32)), + FALSE); + + break; + + case OPERATION_HYPERVISOR_DRIVER_IS_SUCCESSFULLY_LOADED: + + // + // Indicate that driver (Hypervisor) is loaded successfully + // + SetEvent(g_IsDriverLoadedSuccessfully); + + break; + + case OPERATION_HYPERVISOR_DRIVER_END_OF_IRPS: + + // + // End of receiving messages (IRPs), nothing to do + // it will just end the thread at next round because of the check of + // g_IsMessageLoggingWindowClosed at the beginning of the loop + // + break; + + case OPERATION_COMMAND_FROM_DEBUGGER_RELOAD_SYMBOL: + + // + // Pause debugger after getting the results + // + KdReloadSymbolsInDebuggee(TRUE, + ((PDEBUGGEE_SYMBOL_REQUEST_PACKET)(OutputBuffer + sizeof(UINT32)))->ProcessId); + + break; + + case OPERATION_NOTIFICATION_FROM_USER_DEBUGGER_PAUSE: + + // + // handle pausing packet from user debugger + // + UdHandleUserDebuggerPausing( + (PDEBUGGEE_UD_PAUSED_PACKET)(OutputBuffer + sizeof(UINT32))); + + break; + + default: + + // + // Check if there are available output sources + // + if (!g_OutputSourcesInitialized || !ForwardingCheckAndPerformEventForwarding(OperationCode, + OutputBuffer + sizeof(UINT32), + ReturnedLength - sizeof(UINT32) - 1)) + { + if (g_BreakPrintingOutput) + { + // + // means that the user asserts a CTRL+C or CTRL+BREAK Signal + // we shouldn't show or save anything in this case + // + continue; + } + + ShowMessages("%s", OutputBuffer + sizeof(UINT32)); + } + + break; + } + } + } + catch (const std::exception &) + { + ShowMessages("err, exception occurred in creating handle or parsing buffer\n"); + } + + free(OutputBuffer); + + // + // close handle + // + if (!CloseHandle(Handle)) + { + ShowMessages("err, closing handle 0x%x\n", GetLastError()); + } +} + +/** + * @brief Create a thread for pending buffers + * + * @param Data + * @return DWORD Device Handle + */ +DWORD WINAPI +IrpBasedBufferThread(PVOID Data) +{ + // + // Do stuff. This will be the first function called on the new + // thread. When this function returns, the thread goes away. See + // MSDN for more details. Test Irp Based Notifications + // + ReadIrpBasedBuffer(); + + return 0; +} diff --git a/hyperdbg/hprdbgctrl/code/assembly/asm-vmx-checks.asm b/hyperdbg/libhyperdbg/code/assembly/asm-vmx-checks.asm similarity index 72% rename from hyperdbg/hprdbgctrl/code/assembly/asm-vmx-checks.asm rename to hyperdbg/libhyperdbg/code/assembly/asm-vmx-checks.asm index bc2360d7..dd81a1d8 100644 --- a/hyperdbg/hprdbgctrl/code/assembly/asm-vmx-checks.asm +++ b/hyperdbg/libhyperdbg/code/assembly/asm-vmx-checks.asm @@ -10,25 +10,32 @@ PUBLIC AsmVmxSupportDetection ;------------------------------------------------------------------------ AsmVmxSupportDetection PROC - - xor eax, eax - inc eax + push rbx + push rcx + push rdx + + xor eax, eax + inc eax cpuid - xor rax, rax - bt ecx, 05h - jc VMXSupport + xor rax, rax + bt ecx, 05h + jc VMXSupport VMXNotSupport: jmp RetInst VMXSupport: - mov rax, 01h + mov rax, 01h RetInst: + pop rdx + pop rcx + pop rbx + ret AsmVmxSupportDetection ENDP ;------------------------------------------------------------------------ -END \ No newline at end of file +END \ No newline at end of file diff --git a/hyperdbg/hprdbgctrl/code/common/common.cpp b/hyperdbg/libhyperdbg/code/common/common.cpp similarity index 82% rename from hyperdbg/hprdbgctrl/code/common/common.cpp rename to hyperdbg/libhyperdbg/code/common/common.cpp index 27182631..2f494eab 100644 --- a/hyperdbg/hprdbgctrl/code/common/common.cpp +++ b/hyperdbg/libhyperdbg/code/common/common.cpp @@ -44,11 +44,11 @@ SeparateTo64BitValue(UINT64 Value) * @return VOID */ VOID -PrintBits(const UINT32 Size, const void * Ptr) +PrintBits(const UINT32 Size, const VOID * Ptr) { - unsigned char * Buf = (unsigned char *)Ptr; - unsigned char Byte; - int i, j; + UCHAR * Buf = (UCHAR *)Ptr; + UCHAR Byte; + INT i, j; for (i = Size - 1; i >= 0; i--) { @@ -72,10 +72,10 @@ PrintBits(const UINT32 Size, const void * Ptr) BOOL Replace(std::string & str, const std::string & from, const std::string & to) { - size_t start_pos = str.find(from); - if (start_pos == std::string::npos) + SIZE_T StartPos = str.find(from); + if (StartPos == std::string::npos) return FALSE; - str.replace(start_pos, from.size(), to); + str.replace(StartPos, from.size(), to); return TRUE; } @@ -90,7 +90,7 @@ Replace(std::string & str, const std::string & from, const std::string & to) VOID ReplaceAll(string & str, const string & from, const string & to) { - size_t SartPos = 0; + SIZE_T SartPos = 0; if (from.empty()) return; @@ -114,7 +114,7 @@ ReplaceAll(string & str, const string & from, const string & to) * @return const vector */ const vector -Split(const string & s, const char & c) +Split(const string & s, const CHAR & c) { string buff {""}; vector v; @@ -210,18 +210,18 @@ IsDecimalNotation(const string & s) * @brief converts hex to bytes * * @param hex - * @return vector + * @return vector */ -vector +vector HexToBytes(const string & hex) { - vector Bytes; + vector Bytes; - for (unsigned int i = 0; i < hex.length(); i += 2) + for (UINT32 i = 0; i < hex.length(); i += 2) { std::string byteString = hex.substr(i, 2); - char byte = (char)strtol(byteString.c_str(), NULL, 16); - Bytes.push_back(byte); + CHAR Byte = (CHAR)strtol(byteString.c_str(), NULL, 16); + Bytes.push_back(Byte); } return Bytes; @@ -283,19 +283,19 @@ ConvertStringToUInt64(string TextToConvert, PUINT64 Result) } else { - errno = 0; - char * unparsed = NULL; - const char * s = TextToConvert.c_str(); - const unsigned long long int n = strtoull(s, &unparsed, 10); + errno = 0; + CHAR * Unparsed = NULL; + const CHAR * S = TextToConvert.c_str(); + const UINT64 N = strtoull(S, &Unparsed, 10); - if (errno || (!n && s == unparsed)) + if (errno || (!N && S == Unparsed)) { // fflush(stdout); // perror(s); return FALSE; } - *Result = n; + *Result = N; return TRUE; } } @@ -316,11 +316,11 @@ ConvertStringToUInt64(string TextToConvert, PUINT64 Result) // // It's a hex number // - const char * Text = TextToConvert.c_str(); - errno = 0; - unsigned long long result = strtoull(Text, NULL, 16); + const CHAR * Text = TextToConvert.c_str(); + errno = 0; + UINT64 ResultValue = strtoull(Text, NULL, 16); - *Result = result; + *Result = ResultValue; if (errno == EINVAL) { @@ -386,8 +386,8 @@ ConvertStringToUInt32(string TextToConvert, PUINT32 Result) { try { - int i = std::stoi(TextToConvert); - *Result = i; + INT I = std::stoi(TextToConvert); + *Result = I; return TRUE; } catch (std::invalid_argument const &) @@ -435,6 +435,127 @@ ConvertStringToUInt32(string TextToConvert, PUINT32 Result) } } +/** + * @brief check and convert command token to a 64 bit unsigned integer + * + * @param TargetToken the target command token + * @param Result result will be save to the pointer + * + * @return BOOLEAN shows whether the conversion was successful or not + */ +BOOLEAN +ConvertTokenToUInt64(CommandToken TargetToken, PUINT64 Result) +{ + // + // Extract the token type and value from the tuple + // + std::string TargetTokenValue = std::get<1>(TargetToken); + + // + // Convert the token value to 64 bit unsigned integer + // + return ConvertStringToUInt64(TargetTokenValue, Result); +} + +/** + * @brief Get case sensitive string from command token + * + * @param TargetToken the target command token + * @return string the string value of the token + */ +std::string +GetCaseSensitiveStringFromCommandToken(CommandToken TargetToken) +{ + // + // Extract the token type and value from the tuple + // + std::string TargetTokenValue = std::get<1>(TargetToken); // the first index is case sensitive + + return TargetTokenValue; +} + +/** + * @brief Get lower case string from command token + * + * @param TargetToken the target command token + * @return string the string value of the token + */ +std::string +GetLowerStringFromCommandToken(CommandToken TargetToken) +{ + // + // Extract the token type and value from the tuple + // + std::string TargetTokenValue = std::get<2>(TargetToken); // the second index is lower case + + return TargetTokenValue; +} + +/** + * @brief Compare lower case strings + * + * @param TargetToken the target command token + * @param StringToCompare the string to compare + * + * @return BOOLEAN shows whether text is equal or not + */ +BOOLEAN +CompareLowerCaseStrings(CommandToken TargetToken, const CHAR * StringToCompare) +{ + // + // Extract the token type and value from the tuple + // + std::string TargetTokenValue = std::get<2>(TargetToken); // the second index is lower case + + // + // Convert the token value to 64 bit unsigned integer + // + return _stricmp(TargetTokenValue.c_str(), StringToCompare) == 0; +} + +/** + * @brief Is token bracket string + * + * @param TargetToken the target command token + * + * @return BOOLEAN shows whether the token is bracket string or not + */ +BOOLEAN +IsTokenBracketString(CommandToken TargetToken) +{ + // + // Extract the token type and value from the tuple + // + CommandParsingTokenType TargetTokenValue = std::get<0>(TargetToken); + + // + // Check if the token is a bracket string + // + return TargetTokenValue == CommandParsingTokenType::BracketString; +} + +/** + * @brief check and convert command token to a 32 bit unsigned integer + * + * @param TargetToken the target command token + * @param Result result will be save to the pointer + * + * @return BOOLEAN shows whether the conversion was successful or not + */ +BOOLEAN +ConvertTokenToUInt32(CommandToken TargetToken, PUINT32 Result) +{ + // + // Extract the token type and value from the tuple + // + std::string TargetTokenValue = std::get<1>(TargetToken); + + // + // Convert the token value to 32 bit unsigned integer + // + return ConvertStringToUInt32(TargetTokenValue, Result); +} + /** * @brief checks whether the string ends with a special string or not * @@ -501,8 +622,8 @@ ValidateIP(const string & ip) * @return true if vmx is supported * @return false if vmx is not supported */ -HPRDBGCTRL_API bool -HyperDbgVmxSupportDetection() +BOOLEAN +VmxSupportDetection() { // // Call assembly function @@ -553,7 +674,7 @@ SetPrivilege(HANDLE Token, // access token handle if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { - ShowMessages("err, the token does not have the specified privilege (ACCESS DENIED!)\n"); + ShowMessages("err, the token does not have the specified (debug) privilege (ACCESS DENIED!)\n"); ShowMessages("make sure to run it with administrator privileges\n"); return FALSE; } @@ -566,7 +687,7 @@ SetPrivilege(HANDLE Token, // access token handle * * @param s */ -static inline void +static inline VOID ltrim(std::string & s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { return !std::isspace(ch); })); @@ -577,7 +698,7 @@ ltrim(std::string & s) * * @param s */ -static inline void +static inline VOID rtrim(std::string & s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }) @@ -590,7 +711,7 @@ rtrim(std::string & s) * * @param s */ -void +VOID Trim(std::string & s) { ltrim(s); @@ -616,7 +737,7 @@ RemoveSpaces(std::string str) * @return BOOLEAN shows whether the file exist or not */ BOOLEAN -IsFileExistA(const char * FileName) +IsFileExistA(const CHAR * FileName) { struct stat buffer; return (stat(FileName, &buffer) == 0); @@ -629,7 +750,7 @@ IsFileExistA(const char * FileName) * @return BOOLEAN shows whether the file exist or not */ BOOLEAN -IsFileExistW(const wchar_t * FileName) +IsFileExistW(const WCHAR * FileName) { struct _stat64i32 buffer; return (_wstat(FileName, &buffer) == 0); @@ -641,9 +762,9 @@ IsFileExistW(const wchar_t * FileName) * @param Text */ BOOLEAN -IsEmptyString(char * Text) +IsEmptyString(CHAR * Text) { - size_t Len; + SIZE_T Len; if (Text == NULL || Text[0] == '\0') { @@ -651,7 +772,7 @@ IsEmptyString(char * Text) } Len = strlen(Text); - for (size_t i = 0; i < Len; i++) + for (SIZE_T i = 0; i < Len; i++) { if (Text[i] != ' ' && Text[i] != '\t' && Text[i] != '\n') { @@ -733,88 +854,16 @@ StringToWString(std::wstring & ws, const std::string & s) ws = WsTmp; } -/** - * @brief Split path and arguments and handle strings between quotes - * - * @param Qargs - * @param Command - * @return VOID - */ -VOID -SplitPathAndArgs(std::vector & Qargs, const std::string & Command) -{ - int Len = (int)Command.length(); - bool Qot = false, Sqot = false; - int ArgLen; - - for (int i = 0; i < Len; i++) - { - int start = i; - if (Command[i] == '\"') - { - Qot = true; - } - else if (Command[i] == '\'') - Sqot = true; - - if (Qot) - { - i++; - start++; - while (i < Len && Command[i] != '\"') - i++; - if (i < Len) - Qot = false; - ArgLen = i - start; - i++; - } - else if (Sqot) - { - i++; - while (i < Len && Command[i] != '\'') - i++; - if (i < Len) - Sqot = false; - ArgLen = i - start; - i++; - } - else - { - while (i < Len && Command[i] != ' ') - i++; - ArgLen = i - start; - } - - string Temp = Command.substr(start, ArgLen); - if (!Temp.empty() && Temp != " ") - { - Qargs.push_back(Temp); - } - } - - /* - for (int i = 0; i < Qargs.size(); i++) - { - std::cout << Qargs[i] << std::endl; - } - - std::cout << Qargs.size(); - - if (Qot || Sqot) - std::cout << "One of the quotes is open\n"; - */ -} - /** * @brief Find case insensitive sub string in a given substring * * @param Input * @param ToSearch * @param Pos - * @return size_t + * @return SIZE_T */ -size_t -FindCaseInsensitive(std::string Input, std::string ToSearch, size_t Pos) +SIZE_T +FindCaseInsensitive(std::string Input, std::string ToSearch, SIZE_T Pos) { // Convert complete given String to lower case std::transform(Input.begin(), Input.end(), Input.begin(), ::tolower); @@ -830,10 +879,10 @@ FindCaseInsensitive(std::string Input, std::string ToSearch, size_t Pos) * @param Input * @param ToSearch * @param Pos - * @return size_t + * @return SIZE_T */ -size_t -FindCaseInsensitiveW(std::wstring Input, std::wstring ToSearch, size_t Pos) +SIZE_T +FindCaseInsensitiveW(std::wstring Input, std::wstring ToSearch, SIZE_T Pos) { // Convert complete given String to lower case std::transform(Input.begin(), Input.end(), Input.begin(), ::tolower); @@ -849,31 +898,29 @@ FindCaseInsensitiveW(std::wstring Input, std::wstring ToSearch, size_t Pos) * std::transform(vs.begin(), vs.end(), std::back_inserter(vc), ConvertStringVectorToCharPointerArray); * from: https://stackoverflow.com/questions/7048888/stdvectorstdstring-to-char-array * - * @param Input - * @param ToSearch - * @param Pos - * @return size_t + * @param s + * @return CHAR* */ -char * +CHAR * ConvertStringVectorToCharPointerArray(const std::string & s) { - char * pc = new char[s.size() + 1]; - std::strcpy(pc, s.c_str()); - return pc; + CHAR * Pc = new CHAR[s.size() + 1]; + std::strcpy(Pc, s.c_str()); + return Pc; } /** * @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) { - __cpuidex(CpuInfo, Func, SubFunc); + CpuIdEx(CpuInfo, Func, SubFunc); } /** @@ -884,7 +931,7 @@ CommonCpuidInstruction(UINT32 Func, UINT32 SubFunc, int * CpuInfo) UINT32 Getx86VirtualAddressWidth() { - int Regs[4]; + INT Regs[4]; CommonCpuidInstruction(CPUID_ADDR_WIDTH, 0, Regs); @@ -902,8 +949,8 @@ Getx86VirtualAddressWidth() BOOLEAN CheckCpuSupportRtm() { - int Regs1[4]; - int Regs2[4]; + INT Regs1[4]; + INT Regs2[4]; BOOLEAN Result; // @@ -1205,3 +1252,24 @@ CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size) // return TRUE; } + +/** + * @brief Function to compute log2Ceil + * @param n + * + * @return UINT32 + */ +UINT32 +Log2Ceil(UINT32 n) +{ + if (n == 0) + return 0; // log2Ceil(0) is undefined, returning 0 for safety. + + n--; // Decrease by 1 to check if it is a power of 2 + UINT32 log2Floor = 0; + while (n >>= 1) + { + log2Floor++; + } + return log2Floor + 1; +} diff --git a/hyperdbg/hprdbgctrl/code/common/spinlock.cpp b/hyperdbg/libhyperdbg/code/common/spinlock.cpp similarity index 73% rename from hyperdbg/hprdbgctrl/code/common/spinlock.cpp rename to hyperdbg/libhyperdbg/code/common/spinlock.cpp index 4303a100..96cc5e0c 100644 --- a/hyperdbg/hprdbgctrl/code/common/spinlock.cpp +++ b/hyperdbg/libhyperdbg/code/common/spinlock.cpp @@ -29,35 +29,35 @@ * @brief The maximum wait before PAUSE * */ -static unsigned MaxWait = 65536; +static UINT32 MaxWait = 65536; /** * @brief Tries to get the lock otherwise returns * - * @param LONG Lock variable + * @param Lock Lock variable * @return BOOLEAN If it was successful on getting the lock */ BOOLEAN SpinlockTryLock(volatile LONG * Lock) { - return (!(*Lock) && !_interlockedbittestandset(Lock, 0)); + return (!(*Lock) && !CpuInterlockedBitTestAndSet(Lock, 0)); } /** * @brief Tries to get the lock and won't return until successfully get the lock * - * @param LONG Lock variable + * @param Lock Lock variable */ -void +VOID SpinlockLock(volatile LONG * Lock) { - unsigned wait = 1; + UINT32 Wait = 1; while (!SpinlockTryLock(Lock)) { - for (unsigned i = 0; i < wait; ++i) + for (UINT32 i = 0; i < Wait; ++i) { - _mm_pause(); + CpuPause(); } // @@ -65,13 +65,13 @@ SpinlockLock(volatile LONG * Lock) // clamp it to the MaxWait. // - if (wait * 2 > MaxWait) + if (Wait * 2 > MaxWait) { - wait = MaxWait; + Wait = MaxWait; } else { - wait = wait * 2; + Wait = Wait * 2; } } } @@ -79,19 +79,19 @@ SpinlockLock(volatile LONG * Lock) /** * @brief Tries to get the lock and won't return until successfully get the lock * - * @param LONG Lock variable - * @param LONG MaxWait Maximum wait (pause) count + * @param Lock Lock variable + * @param MaximumWait Maximum wait (pause) count */ -void -SpinlockLockWithCustomWait(volatile LONG * Lock, unsigned MaximumWait) +VOID +SpinlockLockWithCustomWait(volatile LONG * Lock, UINT32 MaximumWait) { - unsigned wait = 1; + UINT32 Wait = 1; while (!SpinlockTryLock(Lock)) { - for (unsigned i = 0; i < wait; ++i) + for (UINT32 i = 0; i < Wait; ++i) { - _mm_pause(); + CpuPause(); } // @@ -99,13 +99,13 @@ SpinlockLockWithCustomWait(volatile LONG * Lock, unsigned MaximumWait) // clamp it to the MaxWait. // - if (wait * 2 > MaximumWait) + if (Wait * 2 > MaximumWait) { - wait = MaximumWait; + Wait = MaximumWait; } else { - wait = wait * 2; + Wait = Wait * 2; } } } @@ -113,9 +113,9 @@ SpinlockLockWithCustomWait(volatile LONG * Lock, unsigned MaximumWait) /** * @brief Release the lock * - * @param LONG Lock variable + * @param Lock Lock variable */ -void +VOID SpinlockUnlock(volatile LONG * Lock) { *Lock = 0; diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/a.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/a.cpp new file mode 100644 index 00000000..c7aca424 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/a.cpp @@ -0,0 +1,297 @@ +/** + * @file a.cpp + * @author Abbas Masoumi Gorji (AbbasMG@hyperdbg.org) + * @brief a command + * @details + * @version 0.10 + * @date 2024-07-15 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; + +class _CMD +{ +public: + std::string CommandStr; + std::string AddressStr; + std::string AsmSnippet; + std::string StartAddressStr; + std::string ProcIdStr; + + _CMD() = default; + + bool isEmpty() const + { + return CommandStr.empty() && + AddressStr.empty() && + AsmSnippet.empty() && + StartAddressStr.empty() && + ProcIdStr.empty(); + } +}; + +/** + * @brief help of a and !a command + * + * @return VOID + */ +VOID +CommandAssembleHelp() +{ + ShowMessages("a !a : assembles snippet at specific address. symbols are supported.\n"); + ShowMessages("\nIf you want to assemble to physical (address) memory then add '!' " + "at the start of the command\n"); + + ShowMessages("syntax : \ta [Address (hex)] [asm {AsmCmd1; AsmCmd2}] [pid ProcessId (hex)]\n"); + ShowMessages("syntax : \t!a [Address (hex)] [asm {AsmCmd1; AsmCmd2}]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : a fffff8077356f010 {nop; nop; nop} \n"); + ShowMessages("\t\te.g : a nt!ExAllocatePoolWithTag+10+@rcx {jmp } \n"); + ShowMessages("\t\te.g : a nt!ExAllocatePoolWithTag {add DWORD PTR [], 99} \n"); + ShowMessages("\t\t note that within assembly snippet, symbols must be enclosed by \" <> \"\n"); + ShowMessages("\t\t note that type specifier must be capital\n"); + + ShowMessages("\n"); + ShowMessages("\tto merely view the byte code of an assembly snippet:\n"); + ShowMessages("\t\ta {jmp } [StartAddress]\n"); + ShowMessages("\t\t\"StartAddress\" is useful when dealing with relative instructions like \" jmp \" "); +} + +_CMD +ParseUserCmd(const std::string & command) +{ + std::vector CmdVec; + _CMD CMD {}; + _CMD CmdEmpty {}; + + auto CmdIt = command.begin(); + auto CmdEnd = command.end(); + + while (CmdIt != CmdEnd) + { + // + // skip leading whitespace + // + CmdIt = std::find_if_not(CmdIt, CmdEnd, ::isspace); + if (CmdIt == CmdEnd) + break; + if (*CmdIt == '{') + { + // + // find matching closing brace + // + auto CloseIt = std::find(CmdIt + 1, CmdEnd, '}'); + if (CloseIt != CmdEnd) + { + if (CmdVec.size() < 2) + { + // + // if yes, asm snippet was provided right after "a" command (2nd index) + // i.e. no address were provided to assembling to + // + CmdVec.emplace_back(""); // empty address string + } + std::string RawAsm(CmdIt + 1, CloseIt); // remove "{}" + CmdVec.emplace_back(RawAsm); + CmdIt = CloseIt + 1; + } + else + { + // + // no matching brace + // + ShowMessages("err, assembly snippet is not closed."); + } + } + else + { + // + // normal text, find next space + // + auto SpaceIt = std::find_if(CmdIt, CmdEnd, ::isspace); + CmdVec.emplace_back(CmdIt, SpaceIt); + CmdIt = SpaceIt; + } + } + + // + // Check if there is any "pid" + // + auto PidIt = std::find_if(CmdVec.begin(), CmdVec.end(), [](const std::string & s) { return s.find("pid") != std::string::npos; }); + if (PidIt != CmdVec.end()) + { + bool IsLast = (PidIt == std::prev(CmdVec.end())); + bool IsSecondLast = (PidIt == std::prev(CmdVec.end(), 2)); + if (!IsLast && !IsSecondLast) + { + ShowMessages("pid must be the last argument"); + return CmdEmpty; + } + if (g_IsSerialConnectedToRemoteDebuggee) + { + ShowMessages(ASSERT_MESSAGE_CANNOT_SPECIFY_PID); + return CmdEmpty; + } + + if (std::next(PidIt) != CmdVec.end()) // is there anything after "pid"? + { + CMD.ProcIdStr = std::string(*(++PidIt)); + } + else + { + ShowMessages("no hex number was provided as process id\n\n"); + return CmdEmpty; + } + } + else + { + // + // user didn't provide pid at all. ignoring. + // + } + + // + // fill the CMD object. will be optimized later + // + if (CmdVec.size() > 0) + CMD.CommandStr = CmdVec.at(0); + if (CmdVec.size() > 1) + CMD.AddressStr = CmdVec.at(1); + if (CmdVec.size() > 2) + CMD.AsmSnippet = CmdVec.at(2); + if (CmdVec.size() > 3) + CMD.StartAddressStr = CmdVec.at(3); + // if (CmdVec.size() > 4) CMD.ProcId_str = CmdVec.at(5); 4 is the "pid" string + + return CMD; +} + +/** + * @brief a and !a commands handler + * + * @param CommandTokens + * @param Command + * @return VOID + */ +VOID +CommandAssemble(vector CommandTokens, string Command) +{ + DEBUGGER_EDIT_MEMORY_TYPE MemoryType {}; + _CMD CMD {}; + UINT64 Address {}; + UINT64 StartAddress {}; + UINT32 ProcId = 0; + + CMD = ParseUserCmd(Command); + + if (CMD.isEmpty()) + { + // + // Error messages are already printed + // + return; + } + + if (!CMD.ProcIdStr.empty()) + { + if (!ConvertStringToUInt32(CMD.ProcIdStr, &ProcId)) + { + ShowMessages("please specify a correct hex process id\n\n"); + CommandAssembleHelp(); + return; + } + } + + if (g_ActiveProcessDebuggingState.IsActive) + { + ProcId = g_ActiveProcessDebuggingState.ProcessId; + } + + if (CMD.AsmSnippet.empty()) + { + ShowMessages("no assembly snippet provided\n"); + CommandAssembleHelp(); + return; + } + else if (CMD.CommandStr == "a") + { + MemoryType = EDIT_VIRTUAL_MEMORY; + } + else if (CMD.CommandStr == "!a") + { + MemoryType = EDIT_PHYSICAL_MEMORY; + } + else + { + ShowMessages("unknown assemble command\n\n"); + CommandAssembleHelp(); + return; + } + + // + // Fetching start_address i.e. address to assemble to + // + if (!CMD.AddressStr.empty()) // was any address provided to assemble to? + { + if (!SymbolConvertNameOrExprToAddress(CMD.AddressStr, &Address)) + { + ShowMessages("err, couldn't resolve Address at '%s'\n\n", + CMD.AddressStr.c_str()); + CommandAssembleHelp(); + return; + } + } + else if (!CMD.StartAddressStr.empty()) // was a custom start_address provided? + { + if (!SymbolConvertNameOrExprToAddress(CMD.StartAddressStr, &StartAddress)) + { + ShowMessages("err, couldn't resolve Address at '%s'\n\n", + CMD.StartAddressStr.c_str()); + CommandAssembleHelp(); + return; + } + Address = StartAddress; + } + else + { + ShowMessages("warning, no start address provided to calculate relative asm commands\n\n"); + } + + AssembleData AssembleData; + AssembleData.AsmRaw = CMD.AsmSnippet; // third element + AssembleData.ParseAssemblyData(); + + if (AssembleData.Assemble(Address)) + { + ShowMessages("err, code: '%u'\n\n", AssembleData.KsErr); + CommandAssembleHelp(); + return; + } + + if (ProcId == 0) + { + ProcId = PlatformGetCurrentProcessId(); + } + + if (Address) // was the user only trying to get the bytes? + { + if (HyperDbgWriteMemory( + (PVOID)Address, + MemoryType, + ProcId, + (PVOID)AssembleData.EncodedBytes, + (UINT32)AssembleData.BytesCount)) + { + ShowMessages("successfully assembled at 0x%016llx address\n", static_cast(Address)); + } + else + { + ShowMessages("failed to write generated assembly to memory\n"); + } + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bc.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bc.cpp similarity index 84% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bc.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bc.cpp index bf6c6b38..4955075c 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bc.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bc.cpp @@ -36,12 +36,13 @@ CommandBcHelp() /** * @brief handler of bc command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandBc(vector SplitCommand, string Command) +CommandBc(vector CommandTokens, string Command) { UINT64 BreakpointId; DEBUGGEE_BP_LIST_OR_MODIFY_PACKET Request = {0}; @@ -49,9 +50,10 @@ CommandBc(vector SplitCommand, string Command) // // Validate the commands // - if (SplitCommand.size() != 2) + if (CommandTokens.size() != 2) { - ShowMessages("incorrect use of the 'bc'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandBcHelp(); return; } @@ -59,7 +61,7 @@ CommandBc(vector SplitCommand, string Command) // // Get the breakpoint id // - if (!ConvertStringToUInt64(SplitCommand.at(1), &BreakpointId)) + if (!ConvertTokenToUInt64(CommandTokens.at(1), &BreakpointId)) { ShowMessages("please specify a correct hex value for breakpoint id\n\n"); CommandBcHelp(); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bd.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bd.cpp similarity index 84% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bd.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bd.cpp index f79206fc..6d10ba99 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bd.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bd.cpp @@ -36,12 +36,13 @@ CommandBdHelp() /** * @brief handler of bd command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandBd(vector SplitCommand, string Command) +CommandBd(vector CommandTokens, string Command) { UINT64 BreakpointId; DEBUGGEE_BP_LIST_OR_MODIFY_PACKET Request = {0}; @@ -49,9 +50,10 @@ CommandBd(vector SplitCommand, string Command) // // Validate the commands // - if (SplitCommand.size() != 2) + if (CommandTokens.size() != 2) { - ShowMessages("incorrect use of the 'bd'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandBdHelp(); return; } @@ -59,7 +61,7 @@ CommandBd(vector SplitCommand, string Command) // // Get the breakpoint id // - if (!ConvertStringToUInt64(SplitCommand.at(1), &BreakpointId)) + if (!ConvertTokenToUInt64(CommandTokens.at(1), &BreakpointId)) { ShowMessages("please specify a correct hex value for breakpoint id\n\n"); CommandBdHelp(); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/be.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/be.cpp similarity index 84% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/be.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/be.cpp index 1e3a0a69..7841b03b 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/be.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/be.cpp @@ -36,12 +36,13 @@ CommandBeHelp() /** * @brief handler of be command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandBe(vector SplitCommand, string Command) +CommandBe(vector CommandTokens, string Command) { UINT64 BreakpointId; DEBUGGEE_BP_LIST_OR_MODIFY_PACKET Request = {0}; @@ -49,9 +50,10 @@ CommandBe(vector SplitCommand, string Command) // // Validate the commands // - if (SplitCommand.size() != 2) + if (CommandTokens.size() != 2) { - ShowMessages("incorrect use of the 'be'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandBeHelp(); return; } @@ -59,7 +61,7 @@ CommandBe(vector SplitCommand, string Command) // // Get the breakpoint id // - if (!ConvertStringToUInt64(SplitCommand.at(1), &BreakpointId)) + if (!ConvertTokenToUInt64(CommandTokens.at(1), &BreakpointId)) { ShowMessages("please specify a correct hex value for breakpoint id\n\n"); CommandBeHelp(); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bl.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bl.cpp similarity index 83% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bl.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bl.cpp index 5339233b..a5751bbf 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/bl.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bl.cpp @@ -32,21 +32,23 @@ CommandBlHelp() /** * @brief handler of the bl command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandBl(vector SplitCommand, string Command) +CommandBl(vector CommandTokens, string Command) { DEBUGGEE_BP_LIST_OR_MODIFY_PACKET Request = {0}; // // Validate the commands // - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the 'bl'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandBlHelp(); return; } diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bp.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bp.cpp new file mode 100644 index 00000000..8beed864 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/bp.cpp @@ -0,0 +1,346 @@ +/** + * @file bp.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief bp command + * @details + * @version 0.1 + * @date 2021-10-03 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsVmmModuleLoaded; +extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; + +/** + * @brief help of the bp command + * + * @return VOID + */ +VOID +CommandBpHelp() +{ + ShowMessages("bp : puts a breakpoint (0xcc).\n"); + + ShowMessages( + "Note : 'bp' is not an event, if you want to use an event version " + "of breakpoints use !epthook or !epthook2 instead. See " + "documentation for more information.\n\n"); + + ShowMessages("syntax : \tbp [Address (hex)] [pid ProcessId (hex)] [tid ThreadId (hex)] [core CoreId (hex)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : bp nt!ExAllocatePoolWithTag\n"); + ShowMessages("\t\te.g : bp nt!ExAllocatePoolWithTag+5\n"); + ShowMessages("\t\te.g : bp nt!ExAllocatePoolWithTag+@rcx+rbx\n"); + ShowMessages("\t\te.g : bp fffff8077356f010\n"); + ShowMessages("\t\te.g : bp fffff8077356f010 pid 0x4\n"); + ShowMessages("\t\te.g : bp fffff8077356f010 tid 0x1000\n"); + ShowMessages("\t\te.g : bp fffff8077356f010 pid 0x4 core 2\n"); +} + +/** + * @brief Apply breakpoint on the user debugger + * @param BpPacket + * + * @return BOOLEAN + */ +BOOLEAN +CommandBpPerformApplyingBreakpointOnUserDebugger(DEBUGGEE_BP_PACKET * BpPacket) +{ + BOOL Status; + ULONG ReturnedLength; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Check if the debugger is connected to a remote debuggee, this request + // is not for the kernel debugger + // + return FALSE; + } + else + { + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // Send IOCTL + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_SET_BREAKPOINT_USER_DEBUGGER, // IO Control Code (IOCTL) + BpPacket, // Input Buffer to driver. + SIZEOF_DEBUGGEE_BP_PACKET, // Input buffer length (not used in this case) + BpPacket, // Output Buffer from driver. + SIZEOF_DEBUGGEE_BP_PACKET, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + + return FALSE; + } + + if (BpPacket->Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + return TRUE; + } + else + { + // + // An err occurred, no results + // + ShowErrorMessage(BpPacket->Result); + return FALSE; + } + } +} + +/** + * @brief request breakpoint + * + * @param Address Address + * @param Pid Process Id + * @param Tid Thread Id + * @param CoreNumer Core Number + * + * @return BOOLEAN + */ +BOOLEAN +CommandBpRequest(UINT64 Address, UINT32 Pid, UINT32 Tid, UINT32 CoreNumer) +{ + DEBUGGEE_BP_PACKET BpPacket = {0}; + + // + // Check if the debugger is connected to a remote debuggee or a user-debugger is active + // + if (!g_IsSerialConnectedToRemoteDebuggee && !g_ActiveProcessDebuggingState.IsActive) + { + return FALSE; + } + + // + // Set the details for the remote packet + // + BpPacket.Address = Address; + BpPacket.Core = CoreNumer; + BpPacket.Pid = Pid; + BpPacket.Tid = Tid; + + // + // Send the bp packet either to the user debugger or the kernel debugger + // + if (g_ActiveProcessDebuggingState.IsActive) + { + return CommandBpPerformApplyingBreakpointOnUserDebugger(&BpPacket); + } + else if (g_IsSerialConnectedToRemoteDebuggee) + { + return KdSendBpPacketToDebuggee(&BpPacket); + } + else + { + // + // couldn't set breakpoint, no active process or remote debuggee + // + return FALSE; + } +} + +/** + * @brief bp command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandBp(vector CommandTokens, string Command) +{ + BOOL IsNextCoreId = FALSE; + BOOL IsNextPid = FALSE; + BOOL IsNextTid = FALSE; + + BOOLEAN SetCoreId = FALSE; + BOOLEAN SetPid = FALSE; + BOOLEAN SetTid = FALSE; + BOOLEAN SetAddress = FALSE; + + UINT32 Tid = DEBUGGEE_BP_APPLY_TO_ALL_THREADS; + UINT32 Pid = DEBUGGEE_BP_APPLY_TO_ALL_PROCESSES; + UINT32 CoreNumer = DEBUGGEE_BP_APPLY_TO_ALL_CORES; + UINT64 Address = NULL; + BOOLEAN IsFirstCommand = TRUE; + + if (CommandTokens.size() >= 9) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandBpHelp(); + return; + } + + // +// Disable user-mode debugger in this version +// +#if ActivateUserModeDebugger == FALSE + + if (!g_IsSerialConnectedToRemoteDebuggee) + { + ShowMessages("the user-mode debugger in VMI Mode is still in the beta version and not stable. " + "we decided to exclude it from this release and release it in future versions. " + "if you want to test the user-mode debugger in VMI Mode, you should build " + "HyperDbg with special instructions. But starting processes is fully supported " + "in the Debugger Mode.\n" + "(it's not recommended to use it in VMI Mode yet!)\n"); + return; + } + +#endif // !ActivateUserModeDebugger + + // + // If the user is debugging a process, use its pid + // + if (g_ActiveProcessDebuggingState.IsActive) + { + Pid = g_ActiveProcessDebuggingState.ProcessId; + } + + for (auto Section : CommandTokens) + { + // + // Ignore the first argument as it's the command string itself (bp) + // + if (IsFirstCommand == TRUE) + { + IsFirstCommand = FALSE; + continue; + } + + if (IsNextCoreId) + { + if (!ConvertTokenToUInt32(Section, &CoreNumer)) + { + ShowMessages("please specify a correct hex value for core id\n\n"); + CommandBpHelp(); + return; + } + IsNextCoreId = FALSE; + continue; + } + if (IsNextPid) + { + if (!ConvertTokenToUInt32(Section, &Pid)) + { + ShowMessages("please specify a correct hex value for process id\n\n"); + CommandBpHelp(); + return; + } + IsNextPid = FALSE; + continue; + } + + if (IsNextTid) + { + if (!ConvertTokenToUInt32(Section, &Tid)) + { + ShowMessages("please specify a correct hex value for thread id\n\n"); + CommandBpHelp(); + return; + } + IsNextTid = FALSE; + continue; + } + + if (CompareLowerCaseStrings(Section, "pid")) + { + IsNextPid = TRUE; + continue; + } + if (CompareLowerCaseStrings(Section, "tid")) + { + IsNextTid = TRUE; + continue; + } + if (CompareLowerCaseStrings(Section, "core")) + { + IsNextCoreId = TRUE; + continue; + } + + if (!SetAddress) + { + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &Address)) + { + // + // Couldn't resolve or unknown parameter + // + ShowMessages("err, couldn't resolve error at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); + CommandBpHelp(); + return; + } + else + { + // + // Means that address is received + // + SetAddress = TRUE; + continue; + } + } + } + + // + // Check if address is set or not + // + if (!SetAddress) + { + ShowMessages("please specify a correct hex value as the breakpoint address\n\n"); + CommandBpHelp(); + return; + } + if (IsNextPid) + { + ShowMessages("please specify a correct hex value for process id\n\n"); + CommandBpHelp(); + return; + } + if (IsNextCoreId) + { + ShowMessages("please specify a correct hex value for core\n\n"); + CommandBpHelp(); + return; + } + if (IsNextTid) + { + ShowMessages("please specify a correct hex value for thread id\n\n"); + CommandBpHelp(); + return; + } + + if (!g_IsSerialConnectedToRemoteDebuggee && !g_ActiveProcessDebuggingState.IsActive) + { + ShowMessages("setting breakpoints is not possible when you're not connected " + "to a target debuggee (kernel debugger or user debugger)\n"); + return; + } + + // + // Request breakpoint the bp packet + // + if (!CommandBpRequest(Address, Pid, Tid, CoreNumer)) + { + ShowMessages("err, couldn't set breakpoint\n"); + } +} diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/continue.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/continue.cpp new file mode 100644 index 00000000..af385224 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/continue.cpp @@ -0,0 +1,58 @@ +/** + * @file continue.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief continue command + * @details + * @version 0.14 + * @date 2025-06-25 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief help of the continue command + * + * @return VOID + */ +VOID +CommandContinueHelp() +{ + ShowMessages("continue : continues debuggee or continues processing kernel messages (in test mode, it operates as a user-mode continue command).\n\n"); + + ShowMessages("syntax : \tcontinue \n"); +} + +/** + * @brief Request to continue + * + * @return VOID + */ +VOID +CommandContinueRequest() +{ + CommandGRequest(); +} + +/** + * @brief handler of continue command + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandContinue(vector CommandTokens, string Command) +{ + if (CommandTokens.size() != 1) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandGHelp(); + return; + } + + CommandContinueRequest(); +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/~.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/core.cpp similarity index 76% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/~.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/core.cpp index 650924e9..2a1852db 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/~.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/core.cpp @@ -1,5 +1,5 @@ /** - * @file ~.cpp + * @file core.cpp * @author Sina Karvandi (sina@hyperdbg.org) * @brief show and change processor * @details @@ -38,18 +38,20 @@ CommandCoreHelp() /** * @brief ~ command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandCore(vector SplitCommand, string Command) +CommandCore(vector CommandTokens, string Command) { UINT32 TargetCore = 0; - if (SplitCommand.size() != 1 && SplitCommand.size() != 2) + if (CommandTokens.size() != 1 && CommandTokens.size() != 2) { - ShowMessages("incorrect use of the '~'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandCoreHelp(); return; } @@ -63,13 +65,13 @@ CommandCore(vector SplitCommand, string Command) return; } - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { ShowMessages("current processor : 0x%x\n", g_CurrentRemoteCore); } - else if (SplitCommand.size() == 2) + else if (CommandTokens.size() == 2) { - if (!ConvertStringToUInt32(SplitCommand.at(1), &TargetCore)) + if (!ConvertTokenToUInt32(CommandTokens.at(1), &TargetCore)) { ShowMessages("please specify a correct hex value for the core that you " "want to operate on it\n\n"); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/cpu.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/cpu.cpp similarity index 95% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/cpu.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/cpu.cpp index 3845151f..970d44ec 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/cpu.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/cpu.cpp @@ -27,19 +27,22 @@ CommandCpuHelp() /** * @brief cpu command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandCpu(vector SplitCommand, string Command) +CommandCpu(vector CommandTokens, string Command) { - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the 'cpu'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandCpuHelp(); return; } + ReadCpuDetails(); } @@ -137,12 +140,12 @@ private: // Calling __cpuid with 0x0 as the function_id argument // gets the number of the highest valid function ID. // - __cpuid(cpui.data(), 0); + CpuCpuId(cpui.data(), 0); nIds_ = cpui[0]; for (int i = 0; i <= nIds_; ++i) { - __cpuidex(cpui.data(), i, 0); + CpuIdEx(cpui.data(), i, 0); data_.push_back(cpui); } @@ -186,7 +189,7 @@ private: // Calling __cpuid with 0x80000000 as the function_id argument // gets the number of the highest valid extended ID. // - __cpuid(cpui.data(), 0x80000000); + CpuCpuId(cpui.data(), 0x80000000); nExIds_ = cpui[0]; char brand[0x40]; @@ -194,7 +197,7 @@ private: for (int i = 0x80000000; i <= nExIds_; ++i) { - __cpuidex(cpui.data(), i, 0); + CpuIdEx(cpui.data(), i, 0); extdata_.push_back(cpui); } @@ -243,10 +246,10 @@ const InstructionSet::InstructionSet_Internal InstructionSet::CPU_Rep; /** * @brief Reads the CPU vendor string * - * @return char * + * @return VOID */ -HPRDBGCTRL_API VOID -HyperDbgReadVendorString(char * Result) +VOID +CpuReadVendorString(CHAR * Result) { std::string VendorString = InstructionSet::Vendor(); strcpy(Result, VendorString.c_str()); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/d-u.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/d-u.cpp similarity index 52% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/d-u.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/d-u.cpp index 75988c29..c853df5a 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/d-u.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/d-u.cpp @@ -64,23 +64,22 @@ CommandReadMemoryAndDisassemblerHelp() /** * @brief u* d* !u* !d* commands handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) +CommandReadMemoryAndDisassembler(vector CommandTokens, string Command) { - UINT32 Pid = 0; - UINT32 Length = 0; - UINT64 TargetAddress = 0; - BOOLEAN IsNextProcessId = FALSE; - BOOLEAN IsFirstCommand = TRUE; - BOOLEAN IsNextLength = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - UINT32 IndexInCommandCaseSensitive = 0; + UINT32 Pid = 0; + UINT32 Length = 0; + UINT64 TargetAddress = 0; + BOOLEAN IsNextProcessId = FALSE; + BOOLEAN IsFirstCommand = TRUE; + BOOLEAN IsNextLength = FALSE; - string FirstCommand = SplitCommand.front(); + string FirstCommand = GetCaseSensitiveStringFromCommandToken(CommandTokens.front()); // // By default if the user-debugger is active, we use these commands @@ -91,20 +90,19 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) Pid = g_ActiveProcessDebuggingState.ProcessId; } - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { // // Means that user entered one command without any parameter // - ShowMessages("incorrect use of the '%s' command\n\n", FirstCommand.c_str()); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandReadMemoryAndDisassemblerHelp(); return; } - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - IndexInCommandCaseSensitive++; - if (IsFirstCommand) { IsFirstCommand = FALSE; @@ -113,7 +111,7 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) if (IsNextProcessId == TRUE) { - if (!ConvertStringToUInt32(Section, &Pid)) + if (!ConvertTokenToUInt32(Section, &Pid)) { ShowMessages("err, you should enter a valid process id\n\n"); return; @@ -124,7 +122,7 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) if (IsNextLength == TRUE) { - if (!ConvertStringToUInt32(Section, &Length)) + if (!ConvertTokenToUInt32(Section, &Length)) { ShowMessages("err, you should enter a valid length\n\n"); return; @@ -133,13 +131,13 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) continue; } - if (!Section.compare("l")) + if (CompareLowerCaseStrings(Section, "l")) { IsNextLength = TRUE; continue; } - if (!Section.compare("pid")) + if (CompareLowerCaseStrings(Section, "pid")) { IsNextProcessId = TRUE; continue; @@ -150,14 +148,13 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) // if (TargetAddress == 0) { - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1), - &TargetAddress)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &TargetAddress)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1).c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); return; } } @@ -167,7 +164,7 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) // User inserts two address // ShowMessages("err, incorrect use of the '%s' command\n\n", - FirstCommand.c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandReadMemoryAndDisassemblerHelp(); return; @@ -189,10 +186,10 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) // // Default length (user doesn't specified) // - if (!FirstCommand.compare("u") || - !FirstCommand.compare("!u") || - !FirstCommand.compare("u64") || - !FirstCommand.compare("!u64")) + if (CompareLowerCaseStrings(CommandTokens.at(0), "u") || + CompareLowerCaseStrings(CommandTokens.at(0), "!u") || + CompareLowerCaseStrings(CommandTokens.at(0), "u64") || + CompareLowerCaseStrings(CommandTokens.at(0), "!u64")) { Length = 0x40; } @@ -204,7 +201,8 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) if (IsNextLength || IsNextProcessId) { - ShowMessages("incorrect use of the '%s' command\n\n", FirstCommand.c_str()); + ShowMessages("incorrect use of the '%s' command\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandReadMemoryAndDisassemblerHelp(); return; } @@ -226,93 +224,93 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) Pid = GetCurrentProcessId(); } - if (!FirstCommand.compare("db")) + if (CompareLowerCaseStrings(CommandTokens.at(0), "db")) { - HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DB, - TargetAddress, - DEBUGGER_READ_VIRTUAL_ADDRESS, - READ_FROM_KERNEL, - Pid, - Length, - NULL); + HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_COMMAND_DB, + TargetAddress, + DEBUGGER_READ_VIRTUAL_ADDRESS, + READ_FROM_KERNEL, + Pid, + Length, + NULL); } - else if (!FirstCommand.compare("dc")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "dc")) { - HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DC, - TargetAddress, - DEBUGGER_READ_VIRTUAL_ADDRESS, - READ_FROM_KERNEL, - Pid, - Length, - NULL); + HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_COMMAND_DC, + TargetAddress, + DEBUGGER_READ_VIRTUAL_ADDRESS, + READ_FROM_KERNEL, + Pid, + Length, + NULL); } - else if (!FirstCommand.compare("dd")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "dd")) { - HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DD, - TargetAddress, - DEBUGGER_READ_VIRTUAL_ADDRESS, - READ_FROM_KERNEL, - Pid, - Length, - NULL); + HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_COMMAND_DD, + TargetAddress, + DEBUGGER_READ_VIRTUAL_ADDRESS, + READ_FROM_KERNEL, + Pid, + Length, + NULL); } - else if (!FirstCommand.compare("dq")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "dq")) { - HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DQ, - TargetAddress, - DEBUGGER_READ_VIRTUAL_ADDRESS, - READ_FROM_KERNEL, - Pid, - Length, - NULL); + HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_COMMAND_DQ, + TargetAddress, + DEBUGGER_READ_VIRTUAL_ADDRESS, + READ_FROM_KERNEL, + Pid, + Length, + NULL); } - else if (!FirstCommand.compare("!db")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "!db")) { - HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DB, - TargetAddress, - DEBUGGER_READ_PHYSICAL_ADDRESS, - READ_FROM_KERNEL, - Pid, - Length, - NULL); + HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_COMMAND_DB, + TargetAddress, + DEBUGGER_READ_PHYSICAL_ADDRESS, + READ_FROM_KERNEL, + Pid, + Length, + NULL); } - else if (!FirstCommand.compare("!dc")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "!dc")) { - HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DC, - TargetAddress, - DEBUGGER_READ_PHYSICAL_ADDRESS, - READ_FROM_KERNEL, - Pid, - Length, - NULL); + HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_COMMAND_DC, + TargetAddress, + DEBUGGER_READ_PHYSICAL_ADDRESS, + READ_FROM_KERNEL, + Pid, + Length, + NULL); } - else if (!FirstCommand.compare("!dd")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "!dd")) { - HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DD, - TargetAddress, - DEBUGGER_READ_PHYSICAL_ADDRESS, - READ_FROM_KERNEL, - Pid, - Length, - NULL); + HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_COMMAND_DD, + TargetAddress, + DEBUGGER_READ_PHYSICAL_ADDRESS, + READ_FROM_KERNEL, + Pid, + Length, + NULL); } - else if (!FirstCommand.compare("!dq")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "!dq")) { - HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DQ, - TargetAddress, - DEBUGGER_READ_PHYSICAL_ADDRESS, - READ_FROM_KERNEL, - Pid, - Length, - NULL); + HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_COMMAND_DQ, + TargetAddress, + DEBUGGER_READ_PHYSICAL_ADDRESS, + READ_FROM_KERNEL, + Pid, + Length, + NULL); } // // Disassembler (!u or u or u2 !u2) // - else if (!FirstCommand.compare("u") || !FirstCommand.compare("u64")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "u") || CompareLowerCaseStrings(CommandTokens.at(0), "u64")) { - HyperDbgReadMemoryAndDisassemble( + HyperDbgShowMemoryOrDisassemble( DEBUGGER_SHOW_COMMAND_DISASSEMBLE64, TargetAddress, DEBUGGER_READ_VIRTUAL_ADDRESS, @@ -321,9 +319,9 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) Length, NULL); } - else if (!FirstCommand.compare("!u") || !FirstCommand.compare("!u64")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "!u") || CompareLowerCaseStrings(CommandTokens.at(0), "!u64")) { - HyperDbgReadMemoryAndDisassemble( + HyperDbgShowMemoryOrDisassemble( DEBUGGER_SHOW_COMMAND_DISASSEMBLE64, TargetAddress, DEBUGGER_READ_PHYSICAL_ADDRESS, @@ -332,9 +330,9 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) Length, NULL); } - else if (!FirstCommand.compare("u2") || !FirstCommand.compare("u32")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "u2") || CompareLowerCaseStrings(CommandTokens.at(0), "u32")) { - HyperDbgReadMemoryAndDisassemble( + HyperDbgShowMemoryOrDisassemble( DEBUGGER_SHOW_COMMAND_DISASSEMBLE32, TargetAddress, DEBUGGER_READ_VIRTUAL_ADDRESS, @@ -343,9 +341,9 @@ CommandReadMemoryAndDisassembler(vector SplitCommand, string Command) Length, NULL); } - else if (!FirstCommand.compare("!u2") || !FirstCommand.compare("!u32")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "!u2") || CompareLowerCaseStrings(CommandTokens.at(0), "!u32")) { - HyperDbgReadMemoryAndDisassemble( + HyperDbgShowMemoryOrDisassemble( DEBUGGER_SHOW_COMMAND_DISASSEMBLE32, TargetAddress, DEBUGGER_READ_PHYSICAL_ADDRESS, diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/dt-struct.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/dt-struct.cpp similarity index 75% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/dt-struct.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/dt-struct.cpp index d43e94cf..c3c3db68 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/dt-struct.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/dt-struct.cpp @@ -35,13 +35,13 @@ CommandDtHelp() "[pid ProcessId (hex)] [padding Padding (yesno)] [offset Offset (yesno)] " "[bitfield Bitfield (yesno)] [native Native (yesno)] [decl Declaration (yesno)] " "[def Definitions (yesno)] [func Functions (yesno)] [pragma Pragma (yesno)] " - "[prefix Prefix (string)] [suffix Suffix (string)] [inline Expantion (string)] " + "[prefix Prefix (string)] [suffix Suffix (string)] [inline Expansion (string)] " "[output FileName (string)]\n\n"); ShowMessages("syntax : \t!dt [Module!SymbolName (string)] [AddressExpression (string)] " "[padding Padding (yesno)] [offset Offset (yesno)] [bitfield Bitfield (yesno)] " "[native Native (yesno)] [decl Declaration (yesno)] [def Definitions (yesno)] " "[func Functions (yesno)] [pragma Pragma (yesno)] [prefix Prefix (string)] " - "[suffix Suffix (string)] [inline Expantion (string)] [output FileName (string)]\n"); + "[suffix Suffix (string)] [inline Expansion (string)] [output FileName (string)]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : dt nt!_EPROCESS\n"); @@ -49,7 +49,7 @@ CommandDtHelp() ShowMessages("\t\te.g : dt nt!_EPROCESS $proc\n"); ShowMessages("\t\te.g : dt nt!_KPROCESS @rax+@rbx+c0\n"); ShowMessages("\t\te.g : !dt nt!_EPROCESS 1f0300\n"); - ShowMessages("\t\te.g : dt nt!_MY_STRUCT 7ff00040 pid 1420\n"); + ShowMessages("\t\te.g : dt MyModule!_MY_STRUCT 7ff00040 pid 1420\n"); ShowMessages("\t\te.g : dt nt!_EPROCESS $proc inline all\n"); ShowMessages("\t\te.g : dt nt!_EPROCESS fffff8077356f010 inline no\n"); } @@ -75,6 +75,7 @@ CommandStructHelp() ShowMessages("\t\te.g : struct nt!* output ntheader.h\n"); ShowMessages("\t\te.g : struct nt!* func yes output ntheader.h\n"); ShowMessages("\t\te.g : struct nt!* func yes output ntheader.h\n"); + ShowMessages("\t\te.g : struct nt!* func yes output \"c:\\users\\sina\\desktop\\nt header.h\"\n"); } /** @@ -89,9 +90,9 @@ CommandStructHelp() * @return BOOLEAN */ BOOLEAN -CommandDtAndStructConvertHyperDbgArgsToPdbex(vector ExtraArgs, - std::string & PdbexArgs, - UINT32 * ProcessId) +CommandDtAndStructConvertHyperDbgArgsToPdbex(vector ExtraArgs, + std::string & PdbexArgs, + UINT32 * ProcessId) { UINT32 TargetProcessId = NULL; BOOLEAN NextItemIsYesNo = FALSE; @@ -115,7 +116,7 @@ CommandDtAndStructConvertHyperDbgArgsToPdbex(vector ExtraArgs, // if (NextItemIsFileName) { - PdbexArgs += Item + " "; + PdbexArgs += "\"" + GetCaseSensitiveStringFromCommandToken(Item) + "\" "; NextItemIsFileName = FALSE; continue; @@ -126,7 +127,7 @@ CommandDtAndStructConvertHyperDbgArgsToPdbex(vector ExtraArgs, // if (NextItemIsProcessId) { - if (!ConvertStringToUInt32(Item, &TargetProcessId)) + if (!ConvertTokenToUInt32(Item, &TargetProcessId)) { ShowMessages("err, you should enter a valid process id\n\n"); return FALSE; @@ -141,11 +142,11 @@ CommandDtAndStructConvertHyperDbgArgsToPdbex(vector ExtraArgs, // if (NextItemIsYesNo) { - if (!Item.compare("yes")) + if (CompareLowerCaseStrings(Item, "yes")) { PdbexArgs += " "; } - else if (!Item.compare("no")) + else if (CompareLowerCaseStrings(Item, "no")) { PdbexArgs += "- "; } @@ -167,24 +168,24 @@ CommandDtAndStructConvertHyperDbgArgsToPdbex(vector ExtraArgs, // if (NextItemIsInline) { - if (!Item.compare("none")) + if (CompareLowerCaseStrings(Item, "none")) { PdbexArgs += "n "; } - else if (!Item.compare("all")) + else if (CompareLowerCaseStrings(Item, "all")) { PdbexArgs += "a "; } - else if (!Item.compare("unnamed") || !Item.compare("unamed")) + else if (CompareLowerCaseStrings(Item, "unnamed") || CompareLowerCaseStrings(Item, "unamed")) { PdbexArgs += "i "; } else { // - // none/inline/all expected but didn't see it + // none/unnamed/all expected but didn't see it // - ShowMessages("err, please insert 'none', 'inline', or 'all' as the argument\n\n"); + ShowMessages("err, please insert 'none', 'unnamed', or 'all' as the argument\n\n"); return FALSE; } @@ -197,7 +198,7 @@ CommandDtAndStructConvertHyperDbgArgsToPdbex(vector ExtraArgs, // if (NextItemIsString) { - PdbexArgs += Item + " "; + PdbexArgs += GetCaseSensitiveStringFromCommandToken(Item) + " "; NextItemIsString = FALSE; continue; @@ -206,66 +207,66 @@ CommandDtAndStructConvertHyperDbgArgsToPdbex(vector ExtraArgs, // // Check for args // - if (!Item.compare("pid")) + if (CompareLowerCaseStrings(Item, "pid")) { NextItemIsProcessId = TRUE; } - else if (!Item.compare("output")) + else if (CompareLowerCaseStrings(Item, "output")) { NextItemIsFileName = TRUE; PdbexArgs += "-o "; } - else if (!Item.compare("inline")) + else if (CompareLowerCaseStrings(Item, "inline")) { NextItemIsInline = TRUE; PdbexArgs += "-e "; } - else if (!Item.compare("prefix")) + else if (CompareLowerCaseStrings(Item, "prefix")) { NextItemIsString = TRUE; PdbexArgs += "-r "; } - else if (!Item.compare("suffix")) + else if (CompareLowerCaseStrings(Item, "suffix")) { NextItemIsString = TRUE; PdbexArgs += "-g "; } - else if (!Item.compare("padding")) + else if (CompareLowerCaseStrings(Item, "padding")) { NextItemIsYesNo = TRUE; PdbexArgs += "-p"; } - else if (!Item.compare("offset") || !Item.compare("offsets")) + else if (CompareLowerCaseStrings(Item, "offset") || CompareLowerCaseStrings(Item, "offsets")) { NextItemIsYesNo = TRUE; PdbexArgs += "-x"; } - else if (!Item.compare("bitfield") || !Item.compare("bitfields")) + else if (CompareLowerCaseStrings(Item, "bitfield") || CompareLowerCaseStrings(Item, "bitfields")) { NextItemIsYesNo = TRUE; PdbexArgs += "-b"; } - else if (!Item.compare("native")) + else if (CompareLowerCaseStrings(Item, "native")) { NextItemIsYesNo = TRUE; PdbexArgs += "-i"; } - else if (!Item.compare("decl")) + else if (CompareLowerCaseStrings(Item, "decl")) { NextItemIsYesNo = TRUE; PdbexArgs += "-n"; } - else if (!Item.compare("def")) + else if (CompareLowerCaseStrings(Item, "def")) { NextItemIsYesNo = TRUE; PdbexArgs += "-l"; } - else if (!Item.compare("func")) + else if (CompareLowerCaseStrings(Item, "func")) { NextItemIsYesNo = TRUE; PdbexArgs += "-f"; } - else if (!Item.compare("pragma")) + else if (CompareLowerCaseStrings(Item, "pragma")) { NextItemIsYesNo = TRUE; PdbexArgs += "-z"; @@ -275,7 +276,8 @@ CommandDtAndStructConvertHyperDbgArgsToPdbex(vector ExtraArgs, // // Unknown args // - ShowMessages("err, unknown argument at '%s'\n\n", Item.c_str()); + ShowMessages("err, unknown argument at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Item).c_str()); return FALSE; } } @@ -312,13 +314,13 @@ CommandDtAndStructConvertHyperDbgArgsToPdbex(vector ExtraArgs, */ BOOLEAN CommandDtShowDataBasedOnSymbolTypes( - const char * TypeName, + const CHAR * TypeName, UINT64 Address, BOOLEAN IsStruct, PVOID BufferAddress, UINT32 TargetPid, BOOLEAN IsPhysicalAddress, - const char * AdditionalParameters) + const CHAR * AdditionalParameters) { UINT64 StructureSize = 0; BOOLEAN ResultOfFindingSize = FALSE; @@ -351,7 +353,7 @@ CommandDtShowDataBasedOnSymbolTypes( // // Use the current process for the pid // - TargetPid = GetCurrentProcessId(); + TargetPid = PlatformGetCurrentProcessId(); } } @@ -396,13 +398,13 @@ CommandDtShowDataBasedOnSymbolTypes( // // Read the memory // - HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DT, - Address, - IsPhysicalAddress ? DEBUGGER_READ_PHYSICAL_ADDRESS : DEBUGGER_READ_VIRTUAL_ADDRESS, - READ_FROM_KERNEL, - TargetPid, - (UINT32)StructureSize, - &DtOptions); + HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_COMMAND_DT, + Address, + IsPhysicalAddress ? DEBUGGER_READ_PHYSICAL_ADDRESS : DEBUGGER_READ_VIRTUAL_ADDRESS, + READ_FROM_KERNEL, + TargetPid, + (UINT32)StructureSize, + &DtOptions); return TRUE; } @@ -419,26 +421,26 @@ CommandDtShowDataBasedOnSymbolTypes( /** * @brief dt and struct command handler * - * @param SplitCommand + * @param CommandTokens * @param Command * @return VOID */ VOID -CommandDtAndStruct(vector SplitCommand, string Command) +CommandDtAndStruct(vector CommandTokens, string Command) { - std::string TempTypeNameHolder; - std::string PdbexArgs = ""; - BOOLEAN IsStruct = FALSE; - UINT64 TargetAddress = NULL; - PVOID BufferAddressRetrievedFromDebuggee = NULL; - UINT32 TargetPid = NULL; - BOOLEAN IsPhysicalAddress = FALSE; + CommandToken TempTypeNameHolder; + std::string PdbexArgs = ""; + BOOLEAN IsStruct = FALSE; + UINT64 TargetAddress = NULL; + PVOID BufferAddressRetrievedFromDebuggee = NULL; + UINT32 TargetPid = NULL; + BOOLEAN IsPhysicalAddress = FALSE; // // Check if command is 'struct' or not // - if (!SplitCommand.at(0).compare("struct") || - !SplitCommand.at(0).compare("structure")) + if (CompareLowerCaseStrings(CommandTokens.at(0), "struct") || + CompareLowerCaseStrings(CommandTokens.at(0), "structure")) { IsStruct = TRUE; } @@ -450,7 +452,7 @@ CommandDtAndStruct(vector SplitCommand, string Command) // // Check if command is '!dt' for physical address or not // - if (!SplitCommand.at(0).compare("!dt")) + if (!IsStruct && CompareLowerCaseStrings(CommandTokens.at(0), "!dt")) { IsPhysicalAddress = TRUE; } @@ -459,9 +461,10 @@ CommandDtAndStruct(vector SplitCommand, string Command) IsPhysicalAddress = FALSE; } - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { - ShowMessages("incorrect use of the '%s'\n\n", SplitCommand.at(0).c_str()); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); if (IsStruct) { @@ -476,35 +479,20 @@ CommandDtAndStruct(vector SplitCommand, string Command) } // - // Trim the command + // Create TempSplitTokens by copying elements from CommandTokens, excluding the first element // - Trim(Command); - - // - // Remove dt, struct, or structure from it - // - Command.erase(0, SplitCommand.at(0).size()); - - // - // Trim it again - // - Trim(Command); - - // - // Check for the first and second arguments - // - vector TempSplitCommand {Split(Command, ' ')}; + std::vector TempSplitTokens(CommandTokens.begin() + 1, CommandTokens.end()); // // If the size is zero, then it's only a type name // - if (TempSplitCommand.size() == 1) + if (TempSplitTokens.size() == 1) { // // Call the dt parser wrapper, it's only a structure (type) name // Call it with default configuration // - CommandDtShowDataBasedOnSymbolTypes(TempSplitCommand.at(0).c_str(), + CommandDtShowDataBasedOnSymbolTypes(GetCaseSensitiveStringFromCommandToken(TempSplitTokens.at(0)).c_str(), NULL, IsStruct, NULL, @@ -523,31 +511,31 @@ CommandDtAndStruct(vector SplitCommand, string Command) // // Check if the first parameter is an address or valid expression // - if (IsStruct || !SymbolConvertNameOrExprToAddress(TempSplitCommand.at(0).c_str(), + if (IsStruct || !SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(TempSplitTokens.at(0)).c_str(), &TargetAddress)) { // // No it's not, we'll get the first argument as the structure (type) name // And we have to check whether the second argument is a buffer address or not // - if (IsStruct || !SymbolConvertNameOrExprToAddress(TempSplitCommand.at(1).c_str(), + if (IsStruct || !SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(TempSplitTokens.at(1)).c_str(), &TargetAddress)) { // // The second argument is also not buffer address // probably the user entered a structure (type) name along with some params // - TempTypeNameHolder = TempSplitCommand.at(0); + TempTypeNameHolder = TempSplitTokens.at(0); // // Remove the first argument // - TempSplitCommand.erase(TempSplitCommand.begin()); + TempSplitTokens.erase(TempSplitTokens.begin()); // // Convert to pdbex args // - if (!CommandDtAndStructConvertHyperDbgArgsToPdbex(TempSplitCommand, PdbexArgs, &TargetPid)) + if (!CommandDtAndStructConvertHyperDbgArgsToPdbex(TempSplitTokens, PdbexArgs, &TargetPid)) { if (IsStruct) { @@ -564,7 +552,7 @@ CommandDtAndStruct(vector SplitCommand, string Command) // // Call the wrapper of pdbex // - CommandDtShowDataBasedOnSymbolTypes(TempTypeNameHolder.c_str(), + CommandDtShowDataBasedOnSymbolTypes(GetCaseSensitiveStringFromCommandToken(TempTypeNameHolder).c_str(), TargetAddress, IsStruct, BufferAddressRetrievedFromDebuggee, @@ -578,13 +566,13 @@ CommandDtAndStruct(vector SplitCommand, string Command) // The second argument is a buffer address // The user entered a structure (type) name along with buffer address // - if (TempSplitCommand.size() == 2) + if (TempSplitTokens.size() == 2) { // // There is not parameters, only a symbol name and then a buffer address // Call it with default configuration // - CommandDtShowDataBasedOnSymbolTypes(TempSplitCommand.at(0).c_str(), + CommandDtShowDataBasedOnSymbolTypes(GetCaseSensitiveStringFromCommandToken(TempSplitTokens.at(0)).c_str(), TargetAddress, IsStruct, BufferAddressRetrievedFromDebuggee, @@ -599,18 +587,18 @@ CommandDtAndStruct(vector SplitCommand, string Command) // the second argument which is buffer address, there are other parameters, so // we WON'T call it with default parameters // - TempTypeNameHolder = TempSplitCommand.at(0); + TempTypeNameHolder = TempSplitTokens.at(0); // // Remove the first, and the second arguments // - TempSplitCommand.erase(TempSplitCommand.begin()); - TempSplitCommand.erase(TempSplitCommand.begin()); + TempSplitTokens.erase(TempSplitTokens.begin()); + TempSplitTokens.erase(TempSplitTokens.begin()); // // Convert to pdbex args // - if (!CommandDtAndStructConvertHyperDbgArgsToPdbex(TempSplitCommand, PdbexArgs, &TargetPid)) + if (!CommandDtAndStructConvertHyperDbgArgsToPdbex(TempSplitTokens, PdbexArgs, &TargetPid)) { if (IsStruct) { @@ -627,7 +615,7 @@ CommandDtAndStruct(vector SplitCommand, string Command) // // Call the wrapper of pdbex // - CommandDtShowDataBasedOnSymbolTypes(TempTypeNameHolder.c_str(), + CommandDtShowDataBasedOnSymbolTypes(GetCaseSensitiveStringFromCommandToken(TempTypeNameHolder).c_str(), TargetAddress, IsStruct, BufferAddressRetrievedFromDebuggee, @@ -643,13 +631,13 @@ CommandDtAndStruct(vector SplitCommand, string Command) // The first argument is a buffer address, so we get the first argument as // a buffer address and the second argument as the structure (type) name // - if (TempSplitCommand.size() == 2) + if (TempSplitTokens.size() == 2) { // // There is not parameters, only a buffer address and then a symbol name // Call it with default configuration // - CommandDtShowDataBasedOnSymbolTypes(TempSplitCommand.at(1).c_str(), + CommandDtShowDataBasedOnSymbolTypes(GetCaseSensitiveStringFromCommandToken(TempSplitTokens.at(1)).c_str(), TargetAddress, IsStruct, BufferAddressRetrievedFromDebuggee, @@ -664,18 +652,18 @@ CommandDtAndStruct(vector SplitCommand, string Command) // argument which is structure (type) name, there are other parameters, so // we WON'T call it with default parameters // - TempTypeNameHolder = TempSplitCommand.at(1); + TempTypeNameHolder = TempSplitTokens.at(1); // // Remove the first, and the second arguments // - TempSplitCommand.erase(TempSplitCommand.begin()); - TempSplitCommand.erase(TempSplitCommand.begin()); + TempSplitTokens.erase(TempSplitTokens.begin()); + TempSplitTokens.erase(TempSplitTokens.begin()); // // Convert to pdbex args // - if (!CommandDtAndStructConvertHyperDbgArgsToPdbex(TempSplitCommand, PdbexArgs, &TargetPid)) + if (!CommandDtAndStructConvertHyperDbgArgsToPdbex(TempSplitTokens, PdbexArgs, &TargetPid)) { if (IsStruct) { @@ -692,7 +680,7 @@ CommandDtAndStruct(vector SplitCommand, string Command) // // Call the wrapper of pdbex // - CommandDtShowDataBasedOnSymbolTypes(TempTypeNameHolder.c_str(), + CommandDtShowDataBasedOnSymbolTypes(GetCaseSensitiveStringFromCommandToken(TempTypeNameHolder).c_str(), TargetAddress, IsStruct, BufferAddressRetrievedFromDebuggee, diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/e.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/e.cpp new file mode 100644 index 00000000..f85bf35a --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/e.cpp @@ -0,0 +1,559 @@ +/** + * @file e.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief e* command + * @details + * @version 0.1 + * @date 2020-07-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsVmmModuleLoaded; +extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; + +/** + * @brief help of !e* and e* commands + * + * @return VOID + */ +VOID +CommandEditMemoryHelp() +{ + ShowMessages("eb !eb ed !ed eq !eq : edits the memory at specific address \n"); + ShowMessages("eb Byte and ASCII characters\n"); + ShowMessages("ed Double-word values (4 bytes)\n"); + ShowMessages("eq Quad-word values (8 bytes). \n"); + + ShowMessages("\n If you want to edit physical (address) memory then add '!' " + "at the start of the command\n"); + + ShowMessages("syntax : \teb [Address (hex)] [Contents (hex)] [pid ProcessId (hex)]\n"); + ShowMessages("syntax : \ted [Address (hex)] [Contents (hex)] [pid ProcessId (hex)]\n"); + ShowMessages("syntax : \teq [Address (hex)] [Contents (hex)] [pid ProcessId (hex)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : eb fffff8077356f010 90 \n"); + ShowMessages("\t\te.g : eb nt!Kd_DEFAULT_Mask ff ff ff ff \n"); + ShowMessages("\t\te.g : eb nt!Kd_DEFAULT_Mask+10+@rcx ff ff ff ff \n"); + ShowMessages("\t\te.g : eb fffff8077356f010 90 90 90 90 \n"); + ShowMessages("\t\te.g : !eq 100000 9090909090909090\n"); + ShowMessages("\t\te.g : !eq nt!ExAllocatePoolWithTag+55 9090909090909090\n"); + ShowMessages("\t\te.g : !eq 100000 9090909090909090 9090909090909090 " + "9090909090909090 9090909090909090 9090909090909090\n"); +} + +/** + * @brief Perform writing the memory content + * + * @param AddressToEdit + * @param MemoryType + * @param ByteSize + * @param Pid + * @param CountOf64Chunks + * @param BufferToEdit + * + * @return BOOLEAN + */ +BOOLEAN +WriteMemoryContent(UINT64 AddressToEdit, + DEBUGGER_EDIT_MEMORY_TYPE MemoryType, + DEBUGGER_EDIT_MEMORY_BYTE_SIZE ByteSize, + UINT32 Pid, + UINT32 CountOf64Chunks, + UINT64 * BufferToEdit) +{ + BOOL Status; + DWORD BytesReturned; + BOOLEAN StatusReturn = FALSE; + DEBUGGER_EDIT_MEMORY * FinalBuffer; + DEBUGGER_EDIT_MEMORY EditMemoryRequest = {0}; + UINT32 FinalSize = 0; + + // + // Check if driver is loaded if it's in VMI mode + // + if (!g_IsSerialConnectedToRemoteDebuggee) + { + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + } + + // + // Fill the structure + // + EditMemoryRequest.ProcessId = Pid; + EditMemoryRequest.Address = AddressToEdit; + EditMemoryRequest.CountOf64Chunks = CountOf64Chunks; + EditMemoryRequest.MemoryType = MemoryType; + EditMemoryRequest.ByteSize = ByteSize; + + // + // Now it's time to put everything together in one structure + // + FinalSize = (CountOf64Chunks * sizeof(UINT64)) + SIZEOF_DEBUGGER_EDIT_MEMORY; + + // + // Set the size + // + EditMemoryRequest.FinalStructureSize = FinalSize; + + // + // Allocate structure + buffer + // + FinalBuffer = (DEBUGGER_EDIT_MEMORY *)malloc(FinalSize); + + if (!FinalBuffer) + { + ShowMessages("unable to allocate memory\n\n"); + return FALSE; + } + + // + // Zero the buffer + // + ZeroMemory(FinalBuffer, FinalSize); + + // + // Copy the structure on top of the allocated buffer + // + memcpy((PVOID)FinalBuffer, &EditMemoryRequest, SIZEOF_DEBUGGER_EDIT_MEMORY); + + // + // Copy the values to the buffer + // + memcpy((UINT64 *)((UINT64)FinalBuffer + SIZEOF_DEBUGGER_EDIT_MEMORY), BufferToEdit, (CountOf64Chunks * sizeof(UINT64))); + + // + // send the request + // + if (g_IsSerialConnectedToRemoteDebuggee) + { + if (!KdSendEditMemoryPacketToDebuggee(FinalBuffer, FinalSize)) + { + free(FinalBuffer); + return FALSE; + } + } + else + { + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_DEBUGGER_EDIT_MEMORY, // IO Control Code (IOCTL) + FinalBuffer, // Input Buffer to driver. + FinalSize, // Input buffer length + FinalBuffer, // Output Buffer from driver. + SIZEOF_DEBUGGER_EDIT_MEMORY, // Length of output buffer in bytes. + &BytesReturned, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + free(FinalBuffer); + return FALSE; + } + } + + // + // Check the result + // + if (FinalBuffer->Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // + // Was successful, nothing to do + // + free(FinalBuffer); + return TRUE; + } + else + { + ShowErrorMessage(FinalBuffer->Result); + free(FinalBuffer); + return FALSE; + } +} + +/** + * @brief API function for writing the memory content + * + * @param AddressToEdit + * @param MemoryType + * @param ProcessId + * @param SourceAddress + * @param NumberOfBytes + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgWriteMemory(PVOID DestinationAddress, + DEBUGGER_EDIT_MEMORY_TYPE MemoryType, + UINT32 ProcessId, + PVOID SourceAddress, + UINT32 NumberOfBytes) +{ + UINT32 RequiredBytes = 0; + DEBUGGER_EDIT_MEMORY_BYTE_SIZE ByteSize; + UINT64 * TargetBuffer; + UINT32 FinalSize = 0; + BOOLEAN Result = FALSE; + BYTE * BufferToEdit = (BYTE *)SourceAddress; + + // + // Set the byte size to byte granularity + // + ByteSize = EDIT_BYTE; + + // + // Calculate the count of 64 chunks + // + RequiredBytes = NumberOfBytes * sizeof(UINT64); + + // + // Allocate structure + buffer + // + TargetBuffer = (UINT64 *)malloc(RequiredBytes); + + if (!TargetBuffer) + { + return FALSE; + } + + // + // Zero the buffer + // + ZeroMemory(TargetBuffer, FinalSize); + + // + // Copy requested memory in 64bit chunks + // + for (SIZE_T i = 0; i < NumberOfBytes; i++) + { + TargetBuffer[i] = BufferToEdit[i]; + } + + // + // Perform the write operation + // + Result = WriteMemoryContent((UINT64)DestinationAddress, + MemoryType, + ByteSize, + ProcessId, + NumberOfBytes, + TargetBuffer); + + // + // Free the malloc buffer + // + free(TargetBuffer); + + return Result; +} + +/** + * @brief !e* and e* commands handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandEditMemory(vector CommandTokens, string Command) +{ + UINT64 Address; + UINT64 * FinalBuffer; + vector ValuesToEdit; + DEBUGGER_EDIT_MEMORY_TYPE MemoryType; + DEBUGGER_EDIT_MEMORY_BYTE_SIZE ByteSize; + BOOL SetAddress = FALSE; + BOOL SetValue = FALSE; + BOOL SetProcId = FALSE; + BOOL NextIsProcId = FALSE; + UINT64 Value = 0; + UINT32 ProcId = 0; + UINT32 CountOfValues = 0; + UINT32 FinalSize = 0; + BOOLEAN IsFirstCommand = TRUE; + + // + // By default if the user-debugger is active, we use these commands + // on the memory layout of the debuggee process + // + if (g_ActiveProcessDebuggingState.IsActive) + { + ProcId = g_ActiveProcessDebuggingState.ProcessId; + } + + if (CommandTokens.size() <= 2) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandEditMemoryHelp(); + return; + } + + for (auto Section : CommandTokens) + { + if (IsFirstCommand) + { + if (CompareLowerCaseStrings(Section, "!eb")) + { + MemoryType = EDIT_PHYSICAL_MEMORY; + ByteSize = EDIT_BYTE; + } + else if (CompareLowerCaseStrings(Section, "!ed")) + { + MemoryType = EDIT_PHYSICAL_MEMORY; + ByteSize = EDIT_DWORD; + } + else if (CompareLowerCaseStrings(Section, "!eq")) + { + MemoryType = EDIT_PHYSICAL_MEMORY; + ByteSize = EDIT_QWORD; + } + else if (CompareLowerCaseStrings(Section, "eb")) + { + MemoryType = EDIT_VIRTUAL_MEMORY; + ByteSize = EDIT_BYTE; + } + else if (CompareLowerCaseStrings(Section, "ed")) + { + MemoryType = EDIT_VIRTUAL_MEMORY; + ByteSize = EDIT_DWORD; + } + else if (CompareLowerCaseStrings(Section, "eq")) + { + MemoryType = EDIT_VIRTUAL_MEMORY; + ByteSize = EDIT_QWORD; + } + else + { + // + // What's this? :( + // + ShowMessages("unknown error happened !\n\n"); + CommandEditMemoryHelp(); + return; + } + + IsFirstCommand = FALSE; + + continue; + } + + if (NextIsProcId) + { + // + // It's a process id + // + NextIsProcId = FALSE; + + if (!ConvertTokenToUInt32(Section, &ProcId)) + { + ShowMessages("please specify a correct hex process id\n\n"); + CommandEditMemoryHelp(); + return; + } + else + { + // + // Means that the proc id is set, next we should read value + // + continue; + } + } + + // + // Check if it's a process id or not + // + if (!SetProcId && CompareLowerCaseStrings(Section, "pid")) + { + NextIsProcId = TRUE; + continue; + } + + if (!SetAddress) + { + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &Address)) + { + ShowMessages("err, couldn't resolve error at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); + CommandEditMemoryHelp(); + return; + } + else + { + // + // Means that the address is set, next we should read value + // + SetAddress = TRUE; + continue; + } + } + + if (SetAddress) + { + // + // Remove the hex notations + // + std::string TargetVal = GetCaseSensitiveStringFromCommandToken(Section); + + if (TargetVal.rfind("0x", 0) == 0 || TargetVal.rfind("0X", 0) == 0 || + TargetVal.rfind("\\x", 0) == 0 || TargetVal.rfind("\\X", 0) == 0) + { + TargetVal = TargetVal.erase(0, 2); + } + else if (TargetVal.rfind('x', 0) == 0 || TargetVal.rfind('X', 0) == 0) + { + TargetVal = TargetVal.erase(0, 1); + } + + TargetVal.erase(remove(TargetVal.begin(), TargetVal.end(), '`'), TargetVal.end()); + + // + // Check if the value is valid based on byte counts + // + if (ByteSize == EDIT_BYTE && TargetVal.size() >= 3) + { + ShowMessages("please specify a byte (hex) value for 'eb' or '!eb'\n\n"); + return; + } + if (ByteSize == EDIT_DWORD && TargetVal.size() >= 9) + { + ShowMessages( + "please specify a dword (hex) value for 'ed' or '!ed'\n\n"); + return; + } + if (ByteSize == EDIT_QWORD && TargetVal.size() >= 17) + { + ShowMessages( + "please specify a qword (hex) value for 'eq' or '!eq'\n\n"); + return; + } + + // + // Qword is checked by the following function, no need to double + // check it above. + // + + if (!ConvertStringToUInt64(TargetVal, &Value)) + { + ShowMessages("please specify a correct hex value to change the memory " + "content\n\n"); + CommandEditMemoryHelp(); + return; + } + else + { + // + // Add it to the list + // + + ValuesToEdit.push_back(Value); + + // + // Keep track of values to modify + // + CountOfValues++; + + if (!SetValue) + { + // + // At least on value is there + // + SetValue = TRUE; + } + continue; + } + } + } + + // + // Check to prevent using process id in e* commands + // + if (g_IsSerialConnectedToRemoteDebuggee && ProcId != 0) + { + ShowMessages(ASSERT_MESSAGE_CANNOT_SPECIFY_PID); + return; + } + + // + // Only valid for VMI Mode + // + if (ProcId == 0) + { + ProcId = GetCurrentProcessId(); + } + + // + // Check if address and value are set or not + // + if (!SetAddress) + { + ShowMessages("please specify a correct hex address\n\n"); + CommandEditMemoryHelp(); + return; + } + if (!SetValue) + { + ShowMessages( + "please specify a correct hex value as the content to edit\n\n"); + CommandEditMemoryHelp(); + return; + } + if (NextIsProcId) + { + ShowMessages("please specify a correct hex value as the process id\n\n"); + CommandEditMemoryHelp(); + return; + } + + // + // Make the chunks for editing + // + FinalSize = (CountOfValues * sizeof(UINT64)); + + // + // Allocate structure + buffer + // + FinalBuffer = (UINT64 *)malloc(FinalSize); + + if (!FinalBuffer) + { + ShowMessages("unable to allocate memory\n\n"); + return; + } + + // + // Zero the buffer + // + ZeroMemory(FinalBuffer, FinalSize); + + // + // Put the values in 64 bit structures + // + std::copy(ValuesToEdit.begin(), ValuesToEdit.end(), FinalBuffer); + + // + // Perform the write operation + // + WriteMemoryContent(Address, + MemoryType, + ByteSize, + ProcId, + CountOfValues, + FinalBuffer); + + // + // Free the malloc buffer + // + free(FinalBuffer); +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/eval.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/eval.cpp similarity index 77% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/eval.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/eval.cpp index 94ec6492..202701cb 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/eval.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/eval.cpp @@ -11,12 +11,11 @@ */ #include "pch.h" -using namespace std; - // // Global Variables // -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; /** * @brief help of the ? command @@ -188,21 +187,18 @@ ErrorMessage: /** * @brief handler of ? command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandEval(vector SplitCommand, string Command) +CommandEval(vector CommandTokens, string Command) { - PVOID CodeBuffer; - UINT64 BufferAddress; - UINT32 BufferLength; - UINT32 Pointer; - - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { - ShowMessages("incorrect use of the '?'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandEvalHelp(); return; } @@ -215,7 +211,7 @@ CommandEval(vector SplitCommand, string Command) // // Remove the first command from it // - Command.erase(0, SplitCommand.at(0).size()); + Command.erase(0, GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).size()); // // Trim it again @@ -242,56 +238,25 @@ CommandEval(vector SplitCommand, string Command) return; } - if (g_IsSerialConnectedToRemoteDebuggee) + // + // Check if we're connected to a remote debuggee (kernel debugger) or the user debugger + // + if (g_IsSerialConnectedToRemoteDebuggee || g_ActiveProcessDebuggingState.IsActive) { // - // Send over serial + // Send data to the target user debugger or kernel debugger // - - // - // Run script engine handler - // - CodeBuffer = ScriptEngineParseWrapper((char *)Command.c_str(), TRUE); - - if (CodeBuffer == NULL) - { - // - // return to show that this item contains an script - // - return; - } - - // - // Print symbols (test) - // - // PrintSymbolBufferWrapper(CodeBuffer); - - // - // Set the buffer and length - // - BufferAddress = ScriptEngineWrapperGetHead(CodeBuffer); - BufferLength = ScriptEngineWrapperGetSize(CodeBuffer); - Pointer = ScriptEngineWrapperGetPointer(CodeBuffer); - - // - // Send it to the remote debuggee - // - KdSendScriptPacketToDebuggee(BufferAddress, BufferLength, Pointer, FALSE); - - // - // Remove the buffer of script engine interpreted code - // - ScriptEngineWrapperRemoveSymbolBuffer(CodeBuffer); + ScriptEngineExecuteSingleExpression((CHAR *)Command.c_str(), TRUE, FALSE); } else { // - // It's a test + // It's a test (simulated) run of the script-engine // - ShowMessages("this command should not be used while you're in VMI-Mode or not in debugger-mode, " - "the results that you see is a simulated result for TESTING script-engine " - "and is not based on the status of your system. You can use this command, " - "ONLY in debugger-mode\n\n"); + ShowMessages("this command should not be used while you're in VMI-Mode (not attached to the user debugger) " + "or not in the debugger mode, the results that you see is a simulated result for TESTING the script engine " + "and is not based on the status of your system. You can use this command, either in the debugger mode " + "(kernel debugger), or when you attached to a user debugger\n\n"); ShowMessages("test expression : %s \n", Command.c_str()); ScriptEngineWrapperTestParser(Command); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/events.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/events.cpp similarity index 90% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/events.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/events.cpp index 8620d375..27561c23 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/events.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/events.cpp @@ -18,6 +18,7 @@ extern LIST_ENTRY g_EventTrace; extern BOOLEAN g_EventTraceInitialized; extern BOOLEAN g_BreakPrintingOutput; extern BOOLEAN g_AutoFlush; +extern BOOLEAN g_IsVmmModuleLoaded; extern BOOLEAN g_IsConnectedToRemoteDebuggee; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; @@ -57,12 +58,13 @@ CommandEventsHelp() /** * @brief events command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandEvents(vector SplitCommand, string Command) +CommandEvents(vector CommandTokens, string Command) { DEBUGGER_MODIFY_EVENTS_TYPE RequestedAction; UINT64 RequestedTag; @@ -70,14 +72,15 @@ CommandEvents(vector SplitCommand, string Command) // // Validate the parameters (size) // - if (SplitCommand.size() != 1 && SplitCommand.size() != 3) + if (CommandTokens.size() != 1 && CommandTokens.size() != 3) { - ShowMessages("incorrect use of the '%s'\n\n", SplitCommand.at(0).c_str()); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandEventsHelp(); return; } - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { if (!g_EventTraceInitialized) { @@ -97,25 +100,25 @@ CommandEvents(vector SplitCommand, string Command) // Validate second argument as it's not just a simple // events without any parameter // - if (!SplitCommand.at(1).compare("e")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "e")) { RequestedAction = DEBUGGER_MODIFY_EVENTS_ENABLE; } - else if (!SplitCommand.at(1).compare("d")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "d")) { RequestedAction = DEBUGGER_MODIFY_EVENTS_DISABLE; } - else if (!SplitCommand.at(1).compare("c")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "c")) { RequestedAction = DEBUGGER_MODIFY_EVENTS_CLEAR; } - else if (!SplitCommand.at(1).compare("sc")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "sc")) { - if (!SplitCommand.at(2).compare("on")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "on")) { KdSendShortCircuitingEventToDebuggee(TRUE); } - else if (!SplitCommand.at(2).compare("off")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "off")) { KdSendShortCircuitingEventToDebuggee(FALSE); } @@ -137,7 +140,8 @@ CommandEvents(vector SplitCommand, string Command) // // unknown second command // - ShowMessages("incorrect use of the '%s'\n\n", SplitCommand.at(0).c_str()); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandEventsHelp(); return; } @@ -146,11 +150,11 @@ CommandEvents(vector SplitCommand, string Command) // Validate third argument as it's not just a simple // events without any parameter // - if (!SplitCommand.at(2).compare("all")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "all")) { RequestedTag = DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG; } - else if (!ConvertStringToUInt64(SplitCommand.at(2), &RequestedTag)) + else if (!ConvertTokenToUInt64(CommandTokens.at(2), &RequestedTag)) { ShowMessages( "please specify a correct hex value for tag id (event number)\n\n"); @@ -570,6 +574,19 @@ CommandEventsHandleModifiedEvent( } else { + // + // If HyperDbg is operating at the Debugger Mode, we'll indicate that + // the event will be cleared after continuing the debuggee + // + if (g_IsSerialConnectedToRemoteDebuggee) + { + ShowMessages("%s successfully cleared, but please note in the Debugger Mode (current mode), HyperDbg " + "cannot clear events instantly. Instead, it first disables the events, and when " + "you continue the debuggee (e.g., by pressing the 'g' command), the event will be cleared. " + "Reapplying the same event without first continuing the debuggee may result in undefined behavior\n", + Tag == DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG ? "events are" : "the event is"); + } + // // The action was applied successfully // @@ -681,9 +698,9 @@ CommandEventsModifyAndQueryEvents(UINT64 Tag, // // - // Check if debugger is loaded or not + // Check if the VMM module is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Fill the structure to send it to the kernel diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/exit.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/exit.cpp similarity index 68% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/exit.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/exit.cpp index 40b78fd3..b691c60b 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/exit.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/exit.cpp @@ -17,6 +17,8 @@ extern HANDLE g_DeviceHandle; extern BOOLEAN g_IsConnectedToHyperDbgLocally; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsVmmModuleLoaded; /** * @brief help of the exit command @@ -35,16 +37,18 @@ CommandExitHelp() /** * @brief exit command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandExit(vector SplitCommand, string Command) +CommandExit(vector CommandTokens, string Command) { - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the 'exit'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandExitHelp(); return; } @@ -56,11 +60,14 @@ CommandExit(vector SplitCommand, string Command) // // - // unload and exit if the vmm module is loaded + // unload and exit if the any module is loaded // if (g_DeviceHandle) { - HyperDbgUnloadVmm(); + // + // Unload all modules + // + HyperDbgUnloadAllModules(); } } else if (g_IsSerialConnectedToRemoteDebuggee) diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/flush.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/flush.cpp similarity index 84% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/flush.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/flush.cpp index dfc51942..c286207b 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/flush.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/flush.cpp @@ -14,6 +14,7 @@ // // Global Variables // +extern BOOLEAN g_IsKdModuleLoaded; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; /** @@ -45,16 +46,16 @@ CommandFlushRequestFlush() if (g_IsSerialConnectedToRemoteDebuggee) { // - // It's a debug-mode + // It's on a debugger mode // KdSendFlushPacketToDebuggee(); } else { // - // It's a vmi-mode + // It's on a local debugging mode // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); // // By the way, we don't need to send an input buffer @@ -101,16 +102,18 @@ CommandFlushRequestFlush() /** * @brief flush command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandFlush(vector SplitCommand, string Command) +CommandFlush(vector CommandTokens, string Command) { - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the 'flush'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandFlushHelp(); return; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/g.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/g.cpp similarity index 82% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/g.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/g.cpp index eba67d26..5530df30 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/g.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/g.cpp @@ -67,7 +67,7 @@ CommandGRequest() { if (g_ActiveProcessDebuggingState.IsPaused) { - UdContinueDebuggee(g_ActiveProcessDebuggingState.ProcessDebuggingToken); + UdContinueProcess(g_ActiveProcessDebuggingState.ProcessDebuggingToken); // // Target process is running @@ -76,7 +76,7 @@ CommandGRequest() } else { - ShowMessages("err, target process is already running\n"); + ShowMessages("the target process is already running\n"); } } } @@ -85,16 +85,18 @@ CommandGRequest() /** * @brief handler of g command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandG(vector SplitCommand, string Command) +CommandG(vector CommandTokens, string Command) { - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the 'g'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandGHelp(); return; } diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/gg.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/gg.cpp new file mode 100644 index 00000000..ca856e22 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/gg.cpp @@ -0,0 +1,58 @@ +/** + * @file gg.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief gg command + * @details + * @version 0.11 + * @date 2024-11-19 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief help of the g command + * + * @return VOID + */ +VOID +CommandGgHelp() +{ + ShowMessages("gg : shows and changes the operating processor.\n\n"); + + ShowMessages("syntax : \tgg\n"); + ShowMessages("syntax : \tgg [wp]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : gg \n"); + ShowMessages("\t\te.g : gg wp \n"); +} + +/** + * @brief gg command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandGg(vector CommandTokens, string Command) +{ + if (CommandTokens.size() == 1) + { + ShowMessages("Good Game! :)\n"); + } + else if (CommandTokens.size() == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "wp")) + { + ShowMessages("Good Game, Well Played! :)\n"); + } + else + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandGgHelp(); + return; + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/gu.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/gu.cpp similarity index 72% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/gu.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/gu.cpp index 17aac4c7..36362c21 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/gu.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/gu.cpp @@ -43,38 +43,35 @@ CommandGuHelp() /** * @brief handler of gu command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandGu(vector SplitCommand, string Command) +CommandGu(vector CommandTokens, string Command) { - UINT32 StepCount; - DEBUGGER_REMOTE_STEPPING_REQUEST RequestFormat; - BOOLEAN BreakOnNextInstruction = FALSE; + UINT32 StepCount; + BOOLEAN LastInstruction = FALSE; + BOOLEAN BreakOnNextInstruction = FALSE; // // Validate the commands // - if (SplitCommand.size() != 1 && SplitCommand.size() != 2) + if (CommandTokens.size() != 1 && CommandTokens.size() != 2) { - ShowMessages("incorrect use of the 'gu'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandGuHelp(); return; } - // - // Set type of request - // - RequestFormat = DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER_FOR_GU; - // // Check if the command has a counter parameter // - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { - if (!ConvertStringToUInt32(SplitCommand.at(1), &StepCount)) + if (!ConvertTokenToUInt32(CommandTokens.at(1), &StepCount)) { ShowMessages("please specify a correct hex value for [count]\n\n"); CommandGuHelp(); @@ -106,7 +103,7 @@ CommandGu(vector SplitCommand, string Command) // g_IsInstrumentingInstructions = TRUE; - for (size_t i = 0; i < StepCount; i++) + for (SIZE_T i = 0; i < StepCount; i++) { // // For logging purpose @@ -129,25 +126,13 @@ CommandGu(vector SplitCommand, string Command) // // It's the last instruction, so we gonna show the instruction // - RequestFormat = DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER_FOR_GU_LAST_INSTRUCTION; + LastInstruction = TRUE; } - if (g_IsSerialConnectedToRemoteDebuggee) - { - // - // It's stepping over serial connection in kernel debugger - // - KdSendStepPacketToDebuggee(RequestFormat); - } - else - { - // - // It's stepping over user debugger - // - UdSendStepPacketToDebuggee(g_ActiveProcessDebuggingState.ProcessDebuggingToken, - g_ActiveProcessDebuggingState.ThreadId, - RequestFormat); - } + // + // Perform a GU step + // + SteppingStepOverForGu(LastInstruction); // // Check if user pressed CTRL+C diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/i.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/i.cpp similarity index 81% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/i.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/i.cpp index f299fe99..29fdad73 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/i.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/i.cpp @@ -47,22 +47,23 @@ CommandIHelp() /** * @brief handler of i command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandI(vector SplitCommand, string Command) +CommandI(vector CommandTokens, string Command) { - UINT32 StepCount; - DEBUGGER_REMOTE_STEPPING_REQUEST RequestFormat; + UINT32 StepCount; // // Validate the commands // - if (SplitCommand.size() != 1 && SplitCommand.size() != 2) + if (CommandTokens.size() != 1 && CommandTokens.size() != 2) { - ShowMessages("incorrect use of the 'i'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandIHelp(); return; } @@ -76,17 +77,12 @@ CommandI(vector SplitCommand, string Command) return; } - // - // Set type of step - // - RequestFormat = DEBUGGER_REMOTE_STEPPING_REQUEST_INSTRUMENTATION_STEP_IN; - // // Check if the command has a counter parameter // - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { - if (!ConvertStringToUInt32(SplitCommand.at(1), &StepCount)) + if (!ConvertTokenToUInt32(CommandTokens.at(1), &StepCount)) { ShowMessages("please specify a correct hex value for [count]\n\n"); CommandIHelp(); @@ -108,7 +104,7 @@ CommandI(vector SplitCommand, string Command) // g_IsInstrumentingInstructions = TRUE; - for (size_t i = 0; i < StepCount; i++) + for (SIZE_T i = 0; i < StepCount; i++) { // // For logging purpose @@ -120,14 +116,15 @@ CommandI(vector SplitCommand, string Command) // // It's stepping over serial connection in kernel debugger // - KdSendStepPacketToDebuggee(RequestFormat); + SteppingInstrumentationStepIn(); - if (!SplitCommand.at(0).compare("ir")) + if (CompareLowerCaseStrings(CommandTokens.at(0), "ir")) { // // Show registers // - ShowAllRegisters(); + HyperDbgRegisterShowAll(); + if (i != StepCount - 1) { ShowMessages("\n"); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/k.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/k.cpp similarity index 72% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/k.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/k.cpp index 3ea810ec..9affccd8 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/k.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/k.cpp @@ -47,26 +47,24 @@ CommandKHelp() /** * @brief k command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandK(vector SplitCommand, string Command) +CommandK(vector CommandTokens, string Command) { - UINT64 BaseAddress = NULL; // Null base address means current RSP register - UINT32 Length = 0x100; // Default length - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - UINT32 IndexInCommandCaseSensitive = 0; - BOOLEAN IsFirstCommand = TRUE; - BOOLEAN IsNextBase = FALSE; - BOOLEAN IsNextLength = FALSE; + UINT64 BaseAddress = NULL; // Null base address means current RSP register + UINT32 Length = PAGE_SIZE; // Default length + BOOLEAN IsFirstCommand = TRUE; + BOOLEAN IsNextBase = FALSE; + BOOLEAN IsNextLength = FALSE; - string FirstCommand = SplitCommand.front(); - - if (SplitCommand.size() >= 6) + if (CommandTokens.size() >= 6) { - ShowMessages("incorrect use of the '%s'\n\n", FirstCommand.c_str()); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandKHelp(); return; } @@ -83,17 +81,15 @@ CommandK(vector SplitCommand, string Command) // if (g_IsRunningInstruction32Bit) { - Length = 0x100; + Length = PAGE_SIZE; } else { - Length = 0x200; + Length = PAGE_SIZE * 2; } - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - IndexInCommandCaseSensitive++; - if (IsFirstCommand) { IsFirstCommand = FALSE; @@ -101,14 +97,14 @@ CommandK(vector SplitCommand, string Command) } if (IsNextBase == TRUE) { - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1), + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &BaseAddress)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1).c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); return; } @@ -118,7 +114,7 @@ CommandK(vector SplitCommand, string Command) if (IsNextLength == TRUE) { - if (!ConvertStringToUInt32(Section, &Length)) + if (!ConvertTokenToUInt32(Section, &Length)) { ShowMessages("err, you should enter a valid length\n\n"); return; @@ -127,13 +123,13 @@ CommandK(vector SplitCommand, string Command) continue; } - if (!Section.compare("l")) + if (CompareLowerCaseStrings(Section, "l")) { IsNextLength = TRUE; continue; } - if (!Section.compare("base")) + if (CompareLowerCaseStrings(Section, "base")) { IsNextBase = TRUE; continue; @@ -143,7 +139,7 @@ CommandK(vector SplitCommand, string Command) // User inserts unexpected input // ShowMessages("err, incorrect use of the '%s' command\n\n", - FirstCommand.c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandKHelp(); return; @@ -151,7 +147,8 @@ CommandK(vector SplitCommand, string Command) if (IsNextLength || IsNextBase) { - ShowMessages("incorrect use of the '%s' command\n\n", FirstCommand.c_str()); + ShowMessages("incorrect use of the '%s' command\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandKHelp(); return; } @@ -160,21 +157,21 @@ CommandK(vector SplitCommand, string Command) // Send callstack request // - if (!FirstCommand.compare("k")) + if (CompareLowerCaseStrings(CommandTokens.at(0), "k")) { KdSendCallStackPacketToDebuggee(BaseAddress, Length, DEBUGGER_CALLSTACK_DISPLAY_METHOD_WITHOUT_PARAMS, g_IsRunningInstruction32Bit); } - else if (!FirstCommand.compare("kq")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "kq")) { KdSendCallStackPacketToDebuggee(BaseAddress, Length, DEBUGGER_CALLSTACK_DISPLAY_METHOD_WITH_PARAMS, FALSE); } - else if (!FirstCommand.compare("kd")) + else if (CompareLowerCaseStrings(CommandTokens.at(0), "kd")) { KdSendCallStackPacketToDebuggee(BaseAddress, Length, diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/lm.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/lm.cpp similarity index 83% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/lm.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/lm.cpp index bc4e0c5d..ce0cfb12 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/lm.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/lm.cpp @@ -16,6 +16,7 @@ using namespace std; // // Global Variables // +extern BOOLEAN g_IsKdModuleLoaded; extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; /** @@ -48,7 +49,7 @@ CommandLmHelp() * @return wstring */ std::wstring -CommandLmConvertWow64CompatibilityPaths(const wchar_t * LocalFilePath) +CommandLmConvertWow64CompatibilityPaths(const WCHAR * LocalFilePath) { std::wstring filePath(LocalFilePath); @@ -56,7 +57,7 @@ CommandLmConvertWow64CompatibilityPaths(const wchar_t * LocalFilePath) std::transform(filePath.begin(), filePath.end(), filePath.begin(), ::tolower); // Replace "\windows\system32" with "\windows\syswow64" - size_t pos = filePath.find(L":\\windows\\system32"); + SIZE_T pos = filePath.find(L":\\windows\\system32"); if (pos != std::string::npos) { filePath.replace(pos, 18, L":\\Windows\\SysWOW64"); @@ -80,7 +81,7 @@ CommandLmConvertWow64CompatibilityPaths(const wchar_t * LocalFilePath) * @return BOOLEAN */ BOOLEAN -CommandLmShowUserModeModule(UINT32 ProcessId, const char * SearchModule) +CommandLmShowUserModeModule(UINT32 ProcessId, const CHAR * SearchModule) { BOOLEAN Status; ULONG ReturnedLength; @@ -89,14 +90,14 @@ CommandLmShowUserModeModule(UINT32 ProcessId, const char * SearchModule) PUSERMODE_LOADED_MODULE_DETAILS ModuleDetailsRequest = NULL; PUSERMODE_LOADED_MODULE_SYMBOLS Modules = NULL; USERMODE_LOADED_MODULE_DETAILS ModuleCountRequest = {0}; - size_t CharSize = 0; - wchar_t * WcharBuff = NULL; + SIZE_T CharSize = 0; + WCHAR * WcharBuff = NULL; wstring SearchModuleString; // // Check if debugger is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Set the module details to get the details @@ -189,7 +190,7 @@ CommandLmShowUserModeModule(UINT32 ProcessId, const char * SearchModule) if (SearchModule != NULL) { CharSize = strlen(SearchModule) + 1; - WcharBuff = (wchar_t *)malloc(CharSize * 2); + WcharBuff = (WCHAR *)malloc(CharSize * 2); if (WcharBuff == NULL) { @@ -203,7 +204,7 @@ CommandLmShowUserModeModule(UINT32 ProcessId, const char * SearchModule) SearchModuleString.assign(WcharBuff, wcslen(WcharBuff)); } - for (size_t i = 0; i < ModulesCount; i++) + for (SIZE_T i = 0; i < ModulesCount; i++) { // // Check if we need to search for the module or not @@ -213,7 +214,7 @@ CommandLmShowUserModeModule(UINT32 ProcessId, const char * SearchModule) // // Convert FullPathName to string // - std::wstring FullPathName((wchar_t *)Modules[i].FilePath); + std::wstring FullPathName((WCHAR *)Modules[i].FilePath); if (FindCaseInsensitiveW(FullPathName, SearchModuleString, 0) == std::wstring::npos) { @@ -271,43 +272,14 @@ CommandLmShowUserModeModule(UINT32 ProcessId, const char * SearchModule) * @return BOOLEAN */ BOOLEAN -CommandLmShowKernelModeModule(const char * SearchModule) +CommandLmShowKernelModeModule(const CHAR * SearchModule) { - NTSTATUS Status = STATUS_UNSUCCESSFUL; - PRTL_PROCESS_MODULES ModulesInfo; - ULONG SysModuleInfoBufferSize = 0; + PRTL_PROCESS_MODULES ModulesInfo = NULL; string SearchModuleString; - // - // Get required size of "RTL_PROCESS_MODULES" buffer - // - Status = NtQuerySystemInformation(SystemModuleInformation, NULL, NULL, &SysModuleInfoBufferSize); - - // - // Allocate memory for the module list - // - ModulesInfo = (PRTL_PROCESS_MODULES)VirtualAlloc( - NULL, - SysModuleInfoBufferSize, - MEM_COMMIT | MEM_RESERVE, - PAGE_READWRITE); - - if (!ModulesInfo) + if (SymbolCheckAndAllocateModuleInformation(&ModulesInfo) == FALSE) { - ShowMessages("err, unable to allocate memory for module list (%x)\n", - GetLastError()); - return FALSE; - } - - Status = NtQuerySystemInformation(SystemModuleInformation, - ModulesInfo, - SysModuleInfoBufferSize, - NULL); - if (!NT_SUCCESS(Status)) - { - ShowMessages("err, unable to query module list (%x)\n", Status); - - VirtualFree(ModulesInfo, 0, MEM_RELEASE); + ShowMessages("err, unable get modules information\n"); return FALSE; } @@ -331,7 +303,7 @@ CommandLmShowKernelModeModule(const char * SearchModule) // // Convert FullPathName to string // - std::string FullPathName((char *)CurrentModule->FullPathName); + std::string FullPathName((CHAR *)CurrentModule->FullPathName); if (FindCaseInsensitive(FullPathName, SearchModuleString, 0) == std::string::npos) { @@ -346,7 +318,7 @@ CommandLmShowKernelModeModule(const char * SearchModule) ShowMessages("%x\t", CurrentModule->ImageSize); auto PathName = CurrentModule->FullPathName + CurrentModule->OffsetToFileName; - UINT32 PathNameLen = (UINT32)strlen((const char *)PathName); + UINT32 PathNameLen = (UINT32)strlen((const CHAR *)PathName); ShowMessages("%s\t", PathName); @@ -369,7 +341,7 @@ CommandLmShowKernelModeModule(const char * SearchModule) ShowMessages("%s\n", CurrentModule->FullPathName); } - VirtualFree(ModulesInfo, 0, MEM_RELEASE); + free(ModulesInfo); return TRUE; } @@ -377,12 +349,13 @@ CommandLmShowKernelModeModule(const char * SearchModule) /** * @brief handle lm command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandLm(vector SplitCommand, string Command) +CommandLm(vector CommandTokens, string Command) { BOOLEAN SetPid = FALSE; BOOLEAN SetSearchFilter = FALSE; @@ -390,35 +363,35 @@ CommandLm(vector SplitCommand, string Command) BOOLEAN OnlyShowKernelModules = FALSE; BOOLEAN OnlyShowUserModules = FALSE; UINT32 TargetPid = NULL; - char Search[MAX_PATH] = {0}; - char * SearchString = NULL; + CHAR Search[MAX_PATH] = {0}; + CHAR * SearchString = NULL; // // Interpret command specific details (if any) // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("lm")) + if (CompareLowerCaseStrings(Section, "lm")) { continue; } - else if (!Section.compare("pid") && !SetPid) + else if (CompareLowerCaseStrings(Section, "pid") && !SetPid) { SetPid = TRUE; } - else if (!Section.compare("m") && !SetSearchFilter) + else if (CompareLowerCaseStrings(Section, "m") && !SetSearchFilter) { SetSearchFilter = TRUE; } else if (SetPid) { - if (!ConvertStringToUInt32(Section, &TargetPid)) + if (!ConvertTokenToUInt32(Section, &TargetPid)) { // // couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n\n", - Section.c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandLmHelp(); return; } @@ -426,7 +399,7 @@ CommandLm(vector SplitCommand, string Command) } else if (SetSearchFilter) { - if (Section.length() >= MAX_PATH) + if (GetCaseSensitiveStringFromCommandToken(Section).length() >= MAX_PATH) { ShowMessages("err, string is too large for search, please enter " "smaller string\n"); @@ -435,11 +408,11 @@ CommandLm(vector SplitCommand, string Command) } SearchStringEntered = TRUE; - strcpy(Search, Section.c_str()); + strcpy(Search, GetLowerStringFromCommandToken(Section).c_str()); SetSearchFilter = FALSE; } - else if (!Section.compare("km")) + else if (CompareLowerCaseStrings(Section, "km")) { if (OnlyShowUserModules) { @@ -450,7 +423,7 @@ CommandLm(vector SplitCommand, string Command) OnlyShowKernelModules = TRUE; } - else if (!Section.compare("um")) + else if (CompareLowerCaseStrings(Section, "um")) { if (OnlyShowKernelModules) { @@ -467,7 +440,7 @@ CommandLm(vector SplitCommand, string Command) // Unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n\n", - Section.c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandLmHelp(); return; } diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/load.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/load.cpp new file mode 100644 index 00000000..3ea642c4 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/load.cpp @@ -0,0 +1,184 @@ +/** + * @file load.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief load command + * @details + * @version 0.1 + * @date 2020-05-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsConnectedToHyperDbgLocally; +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsVmmModuleLoaded; +extern BOOLEAN g_IsHyperTraceModuleLoaded; + +/** + * @brief help of the load command + * + * @return VOID + */ +VOID +CommandLoadHelp() +{ + ShowMessages("load : installs drivers and load modules.\n\n"); + + ShowMessages("syntax : \tload [ModuleNameOrAll (string)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : load vmm\n"); + ShowMessages("\t\te.g : load kd\n"); + ShowMessages("\t\te.g : load trace\n"); + ShowMessages("\t\te.g : load all\n"); +} + +/** + * @brief load command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandLoad(vector CommandTokens, string Command) +{ + if (CommandTokens.size() != 2) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandLoadHelp(); + return; + } + + if (!g_IsConnectedToHyperDbgLocally) + { + ShowMessages("you're not connected to any instance of HyperDbg, did you " + "use '.connect'? \n"); + return; + } + + // + // Check for the module + // + if (CompareLowerCaseStrings(CommandTokens.at(1), "all") || CompareLowerCaseStrings(CommandTokens.at(1), ".")) + { + // + // Load aa Modules + // + ShowMessages("loading the all modules\n"); + + if (HyperDbgInstallKdDriver() == 1 || HyperDbgLoadAllModules() == 1) + { + ShowMessages("failed to install or load drivers\n"); + return; + } + + // + // If in vmi-mode then initialize and load symbols (pdb) + // for previously downloaded symbols + // When the VMM module is loaded, we use the current + // process (HyperDbg's process) as the base for user-mode + // symbols + // + SymbolLocalReload(GetCurrentProcessId()); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "vmm") || + CompareLowerCaseStrings(CommandTokens.at(1), "vm")) + { + // + // Check to make sure that the driver is not already loaded + // + if (g_IsVmmModuleLoaded) + { + ShowMessages("the vmm module is already running, if you use 'load' before, please " + "first unload it using the 'unload' command\n"); + return; + } + + // + // Load the VMM Module + // + ShowMessages("loading the vmm module\n"); + + if (HyperDbgInstallKdDriver() == 1 || HyperDbgLoadVmmModule() == 1) + { + ShowMessages("failed to install or load the driver\n"); + return; + } + + // + // If in vmi-mode then initialize and load symbols (pdb) + // for previously downloaded symbols + // When the VMM module is loaded, we use the current + // process (HyperDbg's process) as the base for user-mode + // symbols + // + SymbolLocalReload(GetCurrentProcessId()); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "trace") || + CompareLowerCaseStrings(CommandTokens.at(1), "hypertrace")) + { + // + // Check to make sure that the driver is not already loaded + // + if (g_IsHyperTraceModuleLoaded) + { + ShowMessages("the trace module is already running, if you use 'load' before, please " + "first unload it using the 'unload' command\n"); + return; + } + + // + // Load the HyperTrace Module + // + ShowMessages("loading the trace module\n"); + + if (HyperDbgInstallKdDriver() == 1 || HyperDbgLoadHyperTraceModule() == 1) + { + ShowMessages("failed to install or load the driver\n"); + return; + } + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "kd") || + CompareLowerCaseStrings(CommandTokens.at(1), "dbg") || + CompareLowerCaseStrings(CommandTokens.at(1), "debugger") || + CompareLowerCaseStrings(CommandTokens.at(1), "debug") || + CompareLowerCaseStrings(CommandTokens.at(1), "kerneldebugger") || + CompareLowerCaseStrings(CommandTokens.at(1), "kerneldebug")) + { + // + // Check to make sure that the driver is not already loaded + // + if (g_IsKdModuleLoaded) + { + ShowMessages("the kd module is already running, if you use 'load' before, please " + "first unload it using the 'unload' command\n"); + return; + } + + // + // Load the KD Module + // + ShowMessages("loading the kd module\n"); + + if (HyperDbgInstallKdDriver() == 1 || HyperDbgLoadKdModule() == 1) + { + ShowMessages("failed to install or load the driver\n"); + return; + } + } + else + { + // + // Module not found + // + ShowMessages("err, module not found\n"); + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/output.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/output.cpp similarity index 86% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/output.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/output.cpp index 51a96c94..0fafc899 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/output.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/output.cpp @@ -28,12 +28,16 @@ CommandOutputHelp() ShowMessages("output : creates an output instance that can be used in event " "forwarding.\n\n"); - ShowMessages("syntax : \toutput [create Name (string)] [file|namedpipe|tcp Address (string)]\n"); + ShowMessages("syntax : \toutput\n"); + ShowMessages("syntax : \toutput [create Name (string)] [file|namedpipe|tcp|module Address (string)]\n"); ShowMessages("syntax : \toutput [open|close Name (string)]\n"); ShowMessages("\n"); + ShowMessages("\t\te.g : output\n"); ShowMessages("\t\te.g : output create MyOutputName1 file " "c:\\rev\\output.txt\n"); + ShowMessages("\t\te.g : output create MyOutputName1 file " + "\"c:\\rev\\output file.txt\"\n"); ShowMessages("\t\te.g : output create MyOutputName2 tcp 192.168.1.10:8080\n"); ShowMessages("\t\te.g : output create MyOutputName3 namedpipe " "\\\\.\\Pipe\\HyperDbgOutput\n"); @@ -46,12 +50,12 @@ CommandOutputHelp() /** * @brief output command handler * - * @param SplitCommand + * @param CommandTokens * @param Command * @return VOID */ VOID -CommandOutput(vector SplitCommand, string Command) +CommandOutput(vector CommandTokens, string Command) { PDEBUGGER_EVENT_FORWARDING EventForwardingObject; DEBUGGER_EVENT_FORWARDING_TYPE Type; @@ -63,11 +67,11 @@ CommandOutput(vector SplitCommand, string Command) HANDLE SourceHandle = INVALID_HANDLE_VALUE; SOCKET Socket = NULL; HMODULE Module = NULL; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - if (SplitCommand.size() <= 2) + if ((CommandTokens.size() != 1 && CommandTokens.size() <= 2) || CommandTokens.size() >= 6) { - ShowMessages("incorrect use of the 'output'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandOutputHelp(); return; } @@ -75,7 +79,7 @@ CommandOutput(vector SplitCommand, string Command) // // Check if the user needs a list of outputs or not // - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { IndexToShowList = 0; @@ -145,7 +149,7 @@ CommandOutput(vector SplitCommand, string Command) // // Check if it's a create, open, or close // - if (!SplitCommand.at(1).compare("create")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "create")) { // // It's a create @@ -154,9 +158,10 @@ CommandOutput(vector SplitCommand, string Command) // // check if the parameters are okay for a create or not // - if (SplitCommand.size() <= 4) + if (CommandTokens.size() <= 4) { - ShowMessages("incorrect use of the 'output'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandOutputHelp(); return; } @@ -164,26 +169,26 @@ CommandOutput(vector SplitCommand, string Command) // // Check for the type of the output source // - if (!SplitCommand.at(3).compare("file")) + if (CompareLowerCaseStrings(CommandTokens.at(3), "file")) { Type = EVENT_FORWARDING_FILE; } - else if (!SplitCommand.at(3).compare("namedpipe")) + else if (CompareLowerCaseStrings(CommandTokens.at(3), "namedpipe")) { Type = EVENT_FORWARDING_NAMEDPIPE; } - else if (!SplitCommand.at(3).compare("tcp")) + else if (CompareLowerCaseStrings(CommandTokens.at(3), "tcp")) { Type = EVENT_FORWARDING_TCP; } - else if (!SplitCommand.at(3).compare("module")) + else if (CompareLowerCaseStrings(CommandTokens.at(3), "module")) { Type = EVENT_FORWARDING_MODULE; } else { ShowMessages("incorrect type near '%s'\n\n", - SplitCommand.at(3).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)).c_str()); CommandOutputHelp(); return; } @@ -191,7 +196,7 @@ CommandOutput(vector SplitCommand, string Command) // // Check to make sure that the name doesn't exceed the maximum character // - if (SplitCommand.at(2).size() >= + if (GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).size() >= MAXIMUM_CHARACTERS_FOR_EVENT_FORWARDING_NAME) { ShowMessages("name of the output cannot exceed form %d characters\n\n", @@ -217,7 +222,7 @@ CommandOutput(vector SplitCommand, string Command) CONTAINING_RECORD(TempList, DEBUGGER_EVENT_FORWARDING, OutputSourcesList); if (strcmp(CurrentOutputSourceDetails->Name, - SplitCommandCaseSensitive.at(2).c_str()) == 0) + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()) == 0) { // // Indicate that we found this item @@ -245,9 +250,7 @@ CommandOutput(vector SplitCommand, string Command) // // try to open the source and get the handle // - DetailsOfSource = Command.substr(Command.find(SplitCommandCaseSensitive.at(3)) + - SplitCommandCaseSensitive.at(3).size() + 1, - Command.size()); + DetailsOfSource = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(4)); SourceHandle = ForwardingCreateOutputSource(Type, DetailsOfSource, &Socket, &Module); @@ -315,7 +318,8 @@ CommandOutput(vector SplitCommand, string Command) // // Move the name of the output source to the buffer // - strcpy_s(EventForwardingObject->Name, SplitCommandCaseSensitive.at(2).c_str()); + strcpy_s(EventForwardingObject->Name, + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()); // // Check if list is initialized or not @@ -332,7 +336,7 @@ CommandOutput(vector SplitCommand, string Command) InsertHeadList(&g_OutputSources, &(EventForwardingObject->OutputSourcesList)); } - else if (!SplitCommand.at(1).compare("open")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "open")) { // // It's an open @@ -359,7 +363,7 @@ CommandOutput(vector SplitCommand, string Command) OutputSourcesList); if (strcmp(CurrentOutputSourceDetails->Name, - SplitCommandCaseSensitive.at(2).c_str()) == 0) + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()) == 0) { // // Indicate that we found this item @@ -401,7 +405,7 @@ CommandOutput(vector SplitCommand, string Command) return; } } - else if (!SplitCommand.at(1).compare("close")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "close")) { // // It's a close @@ -428,7 +432,7 @@ CommandOutput(vector SplitCommand, string Command) OutputSourcesList); if (strcmp(CurrentOutputSourceDetails->Name, - SplitCommandCaseSensitive.at(2).c_str()) == 0) + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()) == 0) { // // Indicate that we found this item @@ -475,7 +479,8 @@ CommandOutput(vector SplitCommand, string Command) // // Invalid argument // - ShowMessages("incorrect option at '%s'\n\n", SplitCommand.at(1).c_str()); + ShowMessages("incorrect option at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandOutputHelp(); return; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/p.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/p.cpp similarity index 75% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/p.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/p.cpp index d4a0c86b..a50a41d2 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/p.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/p.cpp @@ -44,12 +44,13 @@ CommandPHelp() /** * @brief handler of p command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandP(vector SplitCommand, string Command) +CommandP(vector CommandTokens, string Command) { UINT32 StepCount; DEBUGGER_REMOTE_STEPPING_REQUEST RequestFormat; @@ -57,9 +58,10 @@ CommandP(vector SplitCommand, string Command) // // Validate the commands // - if (SplitCommand.size() != 1 && SplitCommand.size() != 2) + if (CommandTokens.size() != 1 && CommandTokens.size() != 2) { - ShowMessages("incorrect use of the 'p'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandPHelp(); return; } @@ -72,9 +74,9 @@ CommandP(vector SplitCommand, string Command) // // Check if the command has a counter parameter // - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { - if (!ConvertStringToUInt32(SplitCommand.at(1), &StepCount)) + if (!ConvertTokenToUInt32(CommandTokens.at(1), &StepCount)) { ShowMessages("please specify a correct hex value for [count]\n\n"); CommandPHelp(); @@ -106,7 +108,7 @@ CommandP(vector SplitCommand, string Command) // g_IsInstrumentingInstructions = TRUE; - for (size_t i = 0; i < StepCount; i++) + for (SIZE_T i = 0; i < StepCount; i++) { // // For logging purpose @@ -115,29 +117,18 @@ CommandP(vector SplitCommand, string Command) // (float)StepCount), i); // - if (g_IsSerialConnectedToRemoteDebuggee) - { - // - // It's stepping over serial connection in kernel debugger - // - KdSendStepPacketToDebuggee(RequestFormat); - } - else - { - // - // It's stepping over user debugger - // - UdSendStepPacketToDebuggee(g_ActiveProcessDebuggingState.ProcessDebuggingToken, - g_ActiveProcessDebuggingState.ThreadId, - RequestFormat); - } + // + // Perform Step-over + // + SteppingStepOver(); - if (!SplitCommand.at(0).compare("pr")) + if (CompareLowerCaseStrings(CommandTokens.at(0), "pr")) { // // Show registers // - ShowAllRegisters(); + HyperDbgRegisterShowAll(); + if (i != StepCount - 1) { ShowMessages("\n"); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/pause.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/pause.cpp similarity index 76% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/pause.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/pause.cpp index 8e70bfc7..5d2246e7 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/pause.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/pause.cpp @@ -54,28 +54,32 @@ CommandPauseRequest() } else if (g_ActiveProcessDebuggingState.IsActive && UdPauseProcess(g_ActiveProcessDebuggingState.ProcessDebuggingToken)) { - ShowMessages("please keep interacting with the process until all the " - "threads are intercepted and halted; whenever you execute " - "the first command, the thread interception will be stopped\n"); + ShowMessages("please keep interacting with the process until all the threads are intercepted " + "and halted; you can run the 'g' command to continue the debuggee\n"); } } /** * @brief pause command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandPause(vector SplitCommand, string Command) +CommandPause(vector CommandTokens, string Command) { - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the 'pause'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandPauseHelp(); return; } + // + // request to pause + // CommandPauseRequest(); } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/preactivate.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/preactivate.cpp similarity index 71% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/preactivate.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/preactivate.cpp index 21033c5e..ee88936d 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/preactivate.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/preactivate.cpp @@ -11,6 +11,12 @@ */ #include "pch.h" +// +// Global Variables +// +extern HANDLE g_DeviceHandle; +extern BOOLEAN g_IsVmmModuleLoaded; + /** * @brief help of the preactivate command * @@ -34,20 +40,22 @@ CommandPreactivateHelp() /** * @brief preactivate command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandPreactivate(vector SplitCommand, string Command) +CommandPreactivate(vector CommandTokens, string Command) { BOOL Status; ULONG ReturnedLength; - DEBUGGER_PREACTIVATE_COMMAND PreactivateRequest = {0}; + DEBUGGER_PREACTIVATE_COMMAND PreactivateRequest = {}; - if (SplitCommand.size() != 2) + if (CommandTokens.size() != 2) { - ShowMessages("incorrect use of the 'Preactivate'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandPreactivateHelp(); return; } @@ -55,7 +63,7 @@ CommandPreactivate(vector SplitCommand, string Command) // // Set the type of preactivation // - if (!SplitCommand.at(1).compare("mode") || !SplitCommand.at(1).compare("!mode")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "mode") || CompareLowerCaseStrings(CommandTokens.at(1), "!mode")) { PreactivateRequest.Type = DEBUGGER_PREACTIVATE_COMMAND_TYPE_MODE; } @@ -65,16 +73,16 @@ CommandPreactivate(vector SplitCommand, string Command) // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommand.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); return; } - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); // // Send IOCTL // - Status = DeviceIoControl( + Status = PlatformDeviceIoControl( g_DeviceHandle, // Handle to device IOCTL_PREACTIVATE_FUNCTIONALITY, // IO Control Code (IOCTL) &PreactivateRequest, // Input Buffer to driver. @@ -88,7 +96,7 @@ CommandPreactivate(vector SplitCommand, string Command) if (!Status) { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError()); return; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/prealloc.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/prealloc.cpp similarity index 73% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/prealloc.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/prealloc.cpp index 1f13b8cc..0bf9545b 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/prealloc.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/prealloc.cpp @@ -11,6 +11,11 @@ */ #include "pch.h" +// +// Global Variables +// +extern BOOLEAN g_IsKdModuleLoaded; + /** * @brief help of the prealloc command * @@ -46,57 +51,62 @@ CommandPreallocHelp() /** * @brief prealloc command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandPrealloc(vector SplitCommand, string Command) +CommandPrealloc(vector CommandTokens, string Command) { BOOL Status; ULONG ReturnedLength; UINT64 Count; - DEBUGGER_PREALLOC_COMMAND PreallocRequest = {0}; + DEBUGGER_PREALLOC_COMMAND PreallocRequest = {}; + string SecondParam; - if (SplitCommand.size() != 3) + if (CommandTokens.size() != 3) { - ShowMessages("incorrect use of the 'prealloc'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandPreallocHelp(); return; } + SecondParam = GetLowerStringFromCommandToken(CommandTokens.at(1)); + // // Set the type of pre-allocation // - if (!SplitCommand.at(1).compare("thread-interception")) + if (!SecondParam.compare("thread-interception")) { PreallocRequest.Type = DEBUGGER_PREALLOC_COMMAND_TYPE_THREAD_INTERCEPTION; } - else if (!SplitCommand.at(1).compare("monitor") || !SplitCommand.at(1).compare("!monitor")) + else if (!SecondParam.compare("monitor") || !SecondParam.compare("!monitor")) { PreallocRequest.Type = DEBUGGER_PREALLOC_COMMAND_TYPE_MONITOR; } - else if (!SplitCommand.at(1).compare("epthook") || !SplitCommand.at(1).compare("!epthook")) + else if (!SecondParam.compare("epthook") || !SecondParam.compare("!epthook")) { PreallocRequest.Type = DEBUGGER_PREALLOC_COMMAND_TYPE_EPTHOOK; } - else if (!SplitCommand.at(1).compare("epthook2") || !SplitCommand.at(1).compare("!epthook2")) + else if (!SecondParam.compare("epthook2") || !SecondParam.compare("!epthook2")) { PreallocRequest.Type = DEBUGGER_PREALLOC_COMMAND_TYPE_EPTHOOK2; } - else if (!SplitCommand.at(1).compare("regular-event")) + else if (!SecondParam.compare("regular-event")) { PreallocRequest.Type = DEBUGGER_PREALLOC_COMMAND_TYPE_REGULAR_EVENT; } - else if (!SplitCommand.at(1).compare("big-event")) + else if (!SecondParam.compare("big-event")) { PreallocRequest.Type = DEBUGGER_PREALLOC_COMMAND_TYPE_BIG_EVENT; } - else if (!SplitCommand.at(1).compare("regular-safe-buffer")) + else if (!SecondParam.compare("regular-safe-buffer")) { PreallocRequest.Type = DEBUGGER_PREALLOC_COMMAND_TYPE_REGULAR_SAFE_BUFFER; } - else if (!SplitCommand.at(1).compare("big-safe-buffer")) + else if (!SecondParam.compare("big-safe-buffer")) { PreallocRequest.Type = DEBUGGER_PREALLOC_COMMAND_TYPE_BIG_SAFE_BUFFER; } @@ -106,20 +116,20 @@ CommandPrealloc(vector SplitCommand, string Command) // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommand.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); return; } // // Get the count of needed pre-allocated buffers // - if (!SymbolConvertNameOrExprToAddress(SplitCommand.at(2), &Count)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)), &Count)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommand.at(2).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()); return; } @@ -128,12 +138,12 @@ CommandPrealloc(vector SplitCommand, string Command) // PreallocRequest.Count = (UINT32)Count; - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); // // Send IOCTL // - Status = DeviceIoControl( + Status = PlatformDeviceIoControl( g_DeviceHandle, // Handle to device IOCTL_RESERVE_PRE_ALLOCATED_POOLS, // IO Control Code (IOCTL) &PreallocRequest, // Input Buffer to driver. @@ -147,7 +157,7 @@ CommandPrealloc(vector SplitCommand, string Command) if (!Status) { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError()); return; } diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/print.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/print.cpp new file mode 100644 index 00000000..da7af0e0 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/print.cpp @@ -0,0 +1,77 @@ +/** + * @file print.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @author M.H. Gholamrezaei (mh@hyperdbg.org) + * @brief print command + * @details + * @version 0.1 + * @date 2020-10-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +using namespace std; + +/** + * @brief help of the print command + * + * @return VOID + */ +VOID +CommandPrintHelp() +{ + ShowMessages("print : evaluates expressions.\n\n"); + + ShowMessages("syntax : \tprint [Expression (string)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : print dq(poi(@rcx))\n"); +} + +/** + * @brief handler of print command + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandPrint(vector CommandTokens, string Command) +{ + if (CommandTokens.size() == 1) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandPrintHelp(); + return; + } + + // + // Trim the command + // + Trim(Command); + + // + // Remove print from it + // + Command.erase(0, GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).size()); + + // + // Trim it again + // + Trim(Command); + + // + // Prepend and append 'print(' and ')' + // + Command.insert(0, "print("); + Command.append(");"); + + // + // Execute the expression + // + ScriptEngineExecuteSingleExpression((CHAR *)Command.c_str(), TRUE, FALSE); +} diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/r.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/r.cpp new file mode 100644 index 00000000..ca0aaa73 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/r.cpp @@ -0,0 +1,574 @@ +/** + * @file r.cpp + * @author Alee Amini (alee@hyperdbg.org) + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief r command + * @details + * @version 0.1 + * @date 2021-02-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// using namespace std; + +// +// Global Variables +// +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; + +std::map RegistersMap = { + {"rax", REGISTER_RAX}, + {"eax", REGISTER_EAX}, + {"ax", REGISTER_AX}, + {"ah", REGISTER_AH}, + {"al", REGISTER_AL}, + {"rbx", REGISTER_RBX}, + {"ebx", REGISTER_EBX}, + {"bx", REGISTER_BX}, + {"bh", REGISTER_BH}, + {"bl", REGISTER_BL}, + {"rcx", REGISTER_RCX}, + {"ecx", REGISTER_ECX}, + {"cx", REGISTER_CX}, + {"ch", REGISTER_CH}, + {"cl", REGISTER_CL}, + {"rdx", REGISTER_RDX}, + {"edx", REGISTER_EDX}, + {"dx", REGISTER_DX}, + {"dh", REGISTER_DH}, + {"dl", REGISTER_DL}, + {"rsi", REGISTER_RSI}, + {"esi", REGISTER_ESI}, + {"si", REGISTER_SI}, + {"sil", REGISTER_SIL}, + {"rdi", REGISTER_RDI}, + {"edi", REGISTER_EDI}, + {"di", REGISTER_DI}, + {"dil", REGISTER_DIL}, + {"rbp", REGISTER_RBP}, + {"ebp", REGISTER_EBP}, + {"bp", REGISTER_BP}, + {"bpl", REGISTER_BPL}, + {"rsp", REGISTER_RSP}, + {"esp", REGISTER_ESP}, + {"sp", REGISTER_SP}, + {"spl", REGISTER_SPL}, + {"r8", REGISTER_R8}, + {"r8d", REGISTER_R8D}, + {"r8w", REGISTER_R8W}, + {"r8h", REGISTER_R8H}, + {"r8l", REGISTER_R8L}, + {"r9", REGISTER_R9}, + {"r9d", REGISTER_R9D}, + {"r9w", REGISTER_R9W}, + {"r9h", REGISTER_R9H}, + {"r9l", REGISTER_R9L}, + {"r10", REGISTER_R10}, + {"r10d", REGISTER_R10D}, + {"r10w", REGISTER_R10W}, + {"r10h", REGISTER_R10H}, + {"r10l", REGISTER_R10L}, + {"r11", REGISTER_R11}, + {"r11d", REGISTER_R11D}, + {"r11w", REGISTER_R11W}, + {"r11h", REGISTER_R11H}, + {"r11l", REGISTER_R11L}, + {"r12", REGISTER_R12}, + {"r12d", REGISTER_R12D}, + {"r12w", REGISTER_R12W}, + {"r12h", REGISTER_R12H}, + {"r12l", REGISTER_R12L}, + {"r13", REGISTER_R13}, + {"r13d", REGISTER_R13D}, + {"r13w", REGISTER_R13W}, + {"r13h", REGISTER_R13H}, + {"r13l", REGISTER_R13L}, + {"r14", REGISTER_R14}, + {"r14d", REGISTER_R14D}, + {"r14w", REGISTER_R14W}, + {"r14h", REGISTER_R14H}, + {"r14l", REGISTER_R14L}, + {"r15", REGISTER_R15}, + {"r15d", REGISTER_R15D}, + {"r15w", REGISTER_R15W}, + {"r15h", REGISTER_R15H}, + {"r15l", REGISTER_R15L}, + {"ds", REGISTER_DS}, + {"es", REGISTER_ES}, + {"fs", REGISTER_FS}, + {"gs", REGISTER_GS}, + {"cs", REGISTER_CS}, + {"ss", REGISTER_SS}, + {"rflags", REGISTER_RFLAGS}, + {"eflags", REGISTER_EFLAGS}, + {"flags", REGISTER_FLAGS}, + {"cf", REGISTER_CF}, + {"pf", REGISTER_PF}, + {"af", REGISTER_AF}, + {"zf", REGISTER_ZF}, + {"sf", REGISTER_SF}, + {"tf", REGISTER_TF}, + {"if", REGISTER_IF}, + {"df", REGISTER_DF}, + {"of", REGISTER_OF}, + {"iopl", REGISTER_IOPL}, + {"nt", REGISTER_NT}, + {"rf", REGISTER_RF}, + {"vm", REGISTER_VM}, + {"ac", REGISTER_AC}, + {"vif", REGISTER_VIF}, + {"vip", REGISTER_VIP}, + {"id", REGISTER_ID}, + {"idtr", REGISTER_IDTR}, + {"gdtr", REGISTER_GDTR}, + {"ldtr", REGISTER_LDTR}, + {"tr", REGISTER_TR}, + {"cr0", REGISTER_CR0}, + {"cr2", REGISTER_CR2}, + {"cr3", REGISTER_CR3}, + {"cr4", REGISTER_CR4}, + {"cr8", REGISTER_CR8}, + {"dr0", REGISTER_DR0}, + {"dr1", REGISTER_DR1}, + {"dr2", REGISTER_DR2}, + {"dr3", REGISTER_DR3}, + {"dr6", REGISTER_DR6}, + {"dr7", REGISTER_DR7}, + {"rip", REGISTER_RIP}, + {"eip", REGISTER_EIP}, + {"ip", REGISTER_IP}, +}; + +/** + * @brief help of the r command + * + * @return VOID + */ +VOID +CommandRHelp() +{ + ShowMessages("r : reads or modifies registers.\n\n"); + + ShowMessages("syntax : \tr\n"); + ShowMessages("syntax : \tr [Register (string)] [= Expr (string)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : r\n"); + ShowMessages("\t\te.g : r @rax\n"); + ShowMessages("\t\te.g : r rax\n"); + ShowMessages("\t\te.g : r rax = 0x55\n"); + ShowMessages("\t\te.g : r rax = @rbx + @rcx + 0n10\n"); +} + +/** + * @brief Read all registers + * @param GuestRegisters The guest registers + * @param ExtraRegisters The extra registers + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +HyperDbgReadAllRegisters(GUEST_REGS * GuestRegisters, GUEST_EXTRA_REGISTERS * ExtraRegisters) +{ + PGUEST_REGS Regs; + PGUEST_EXTRA_REGISTERS ExtraRegs; + DEBUGGEE_REGISTER_READ_DESCRIPTION * RegState = NULL; + UINT32 SizeOfRegState = 0; + + // + // Calculate the size of the register state + // + SizeOfRegState = sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) + sizeof(GUEST_REGS) + sizeof(GUEST_EXTRA_REGISTERS); + + // + // Allocate memory for the register state + // + RegState = (DEBUGGEE_REGISTER_READ_DESCRIPTION *)malloc(SizeOfRegState); + + // + // Check if the memory allocation was successful + // + if (RegState == NULL) + { + return FALSE; + } + + // + // Set the register ID to show all registers + // + RegState->RegisterId = DEBUGGEE_SHOW_ALL_REGISTERS; + + // + // Check whether a kernel debugger is connected or a user-mode debugger is active + // + if (g_IsSerialConnectedToRemoteDebuggee) + { + if (!KdSendReadRegisterPacketToDebuggee(RegState, SizeOfRegState)) + { + free(RegState); + return FALSE; + } + } + else if (g_ActiveProcessDebuggingState.IsActive && g_ActiveProcessDebuggingState.IsPaused) + { + // + // It's stepping over user debugger + // + if (!UdSendReadRegisterToUserDebugger(g_ActiveProcessDebuggingState.ProcessDebuggingToken, + g_ActiveProcessDebuggingState.ThreadId, + RegState, + SizeOfRegState)) + { + free(RegState); + return FALSE; + } + } + + if (RegState->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // + // Copy the registers and extra registers to the output + // + Regs = (GUEST_REGS *)(((CHAR *)RegState) + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION)); + ExtraRegs = (GUEST_EXTRA_REGISTERS *)(((CHAR *)RegState) + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) + sizeof(GUEST_REGS)); + + if (GuestRegisters != NULL) + { + memcpy(GuestRegisters, Regs, sizeof(GUEST_REGS)); + } + + if (ExtraRegisters != NULL) + { + memcpy(ExtraRegisters, ExtraRegs, sizeof(GUEST_EXTRA_REGISTERS)); + } + } + else + { + ShowErrorMessage(RegState->KernelStatus); + free(RegState); + return FALSE; + } + + free(RegState); + return TRUE; +} + +/** + * @brief Read target register + * @param RegisterId The register ID + * @param TargetRegister The value of the target register + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +HyperDbgReadTargetRegister(REGS_ENUM RegisterId, UINT64 * TargetRegister) +{ + DEBUGGEE_REGISTER_READ_DESCRIPTION RegState = {0}; + + // + // Set the register ID + // + RegState.RegisterId = (UINT32)RegisterId; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + if (!KdSendReadRegisterPacketToDebuggee(&RegState, sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION))) + { + return FALSE; + } + } + else if (g_ActiveProcessDebuggingState.IsActive && g_ActiveProcessDebuggingState.IsPaused) + { + // + // It's stepping over user debugger + // + if (!UdSendReadRegisterToUserDebugger(g_ActiveProcessDebuggingState.ProcessDebuggingToken, + g_ActiveProcessDebuggingState.ThreadId, + &RegState, + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION))) + { + return FALSE; + } + } + + if (RegState.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + if (TargetRegister != NULL) + { + *TargetRegister = RegState.Value; + } + } + else + { + ShowErrorMessage(RegState.KernelStatus); + return FALSE; + } + + return TRUE; +} + +/** + * @brief Write target register + * @param RegisterId The register ID + * @param Value The value of the target register + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +HyperDbgWriteTargetRegister(REGS_ENUM RegisterId, UINT64 Value) +{ + DEBUGGEE_REGISTER_WRITE_DESCRIPTION RegState = {0}; + + // + // Set the register ID + // + RegState.RegisterId = (UINT32)RegisterId; + RegState.Value = Value; + + if (!KdSendWriteRegisterPacketToDebuggee(&RegState)) + { + return FALSE; + } + + if (RegState.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + return TRUE; + } + else + { + ShowErrorMessage(RegState.KernelStatus); + return FALSE; + } +} + +/** + * @brief handler of r show all registers + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgRegisterShowAll() +{ + GUEST_REGS Regs = {0}; + GUEST_EXTRA_REGISTERS ExtraRegs = {0}; + RFLAGS Rflags = {0}; + + if (!HyperDbgReadAllRegisters(&Regs, &ExtraRegs)) + { + return FALSE; + } + + // + // Show the result of reading registers like rax=0000000000018b01 + // + Rflags.AsUInt = ExtraRegs.RFLAGS; + + ShowMessages( + "RAX=%016llx RBX=%016llx RCX=%016llx\n" + "RDX=%016llx RSI=% 016llx RDI=%016llx\n" + "RIP=%016llx RSP=%016llx RBP=%016llx\n" + "R8 =%016llx R9 =%016llx R10=%016llx\n" + "R11=%016llx R12=%016llx R13=%016llx\n" + "R14=%016llx R15=%016llx IOPL=%02x\n" + "%s %s %s %s\n%s %s %s %s\n" + "CS %04x SS %04x DS %04x ES %04x FS %04x GS %04x\n" + "RFLAGS=%016llx\n", + Regs.rax, + Regs.rbx, + Regs.rcx, + Regs.rdx, + Regs.rsi, + Regs.rdi, + ExtraRegs.RIP, + Regs.rsp, + Regs.rbp, + Regs.r8, + Regs.r9, + Regs.r10, + Regs.r11, + Regs.r12, + Regs.r13, + Regs.r14, + Regs.r15, + Rflags.IoPrivilegeLevel, + Rflags.OverflowFlag ? "OF 1" : "OF 0", + Rflags.DirectionFlag ? "DF 1" : "DF 0", + Rflags.InterruptEnableFlag ? "IF 1" : "IF 0", + Rflags.SignFlag ? "SF 1" : "SF 0", + Rflags.ZeroFlag ? "ZF 1" : "ZF 0", + Rflags.ParityFlag ? "PF 1" : "PF 0", + Rflags.CarryFlag ? "CF 1" : "CF 0", + Rflags.AuxiliaryCarryFlag ? "AXF 1" : "AXF 0", + ExtraRegs.CS, + ExtraRegs.SS, + ExtraRegs.DS, + ExtraRegs.ES, + ExtraRegs.FS, + ExtraRegs.GS, + ExtraRegs.RFLAGS); + + return TRUE; +} + +/** + * @brief handler of r show the target register + * @param RegisterId The register ID + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +HyperDbgRegisterShowTargetRegister(REGS_ENUM RegisterId) +{ + UINT64 TargetRegister = 0; + + // + // Read target register + // + if (!HyperDbgReadTargetRegister(RegisterId, &TargetRegister)) + { + return FALSE; + } + + ShowMessages("%s=%016llx\n", + RegistersNames[RegisterId], + TargetRegister); + + return TRUE; +} + +/** + * @brief handler of r command + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandR(vector CommandTokens, string Command) +{ + REGS_ENUM RegKind; + std::vector Tmp; + std::string SetRegisterValue; + + if (CommandTokens.size() == 1) + { + // + // show all registers + // + if (g_IsSerialConnectedToRemoteDebuggee || + (g_ActiveProcessDebuggingState.IsActive && g_ActiveProcessDebuggingState.IsPaused)) + { + HyperDbgRegisterShowAll(); + } + else + { + ShowMessages("err, reading registers (r) is not valid in the current " + "context, you should connect to a debuggee or attach to a process\n"); + } + + return; + } + + // + // clear additional space of the command string + // + + // + // if command does not contain a '=' means user wants to read it + // + if (Command.find('=', 0) == string::npos) + { + // + // erase '=' from the string now we have just the name of register + // + Command.erase(0, 1); + ReplaceAll(Command, "@", ""); + ReplaceAll(Command, " ", ""); + if (RegistersMap.find(Command) != RegistersMap.end()) + { + RegKind = RegistersMap[Command]; + } + else + { + // + // set the Reg to -1(invalid register) + // + RegKind = (REGS_ENUM)-1; + } + + if (RegKind != -1) + { + // + // send the request + // + if (g_IsSerialConnectedToRemoteDebuggee || + (g_ActiveProcessDebuggingState.IsActive && g_ActiveProcessDebuggingState.IsPaused)) + { + HyperDbgRegisterShowTargetRegister(RegKind); + } + else + { + ShowMessages("err, reading registers (r) is not valid in the current " + "context, you should connect to a debuggee or attach to a process\n"); + } + } + else + { + ShowMessages("err, invalid register\n"); + } + } + + // + // if command contains a '=' means user wants modify the register + // + else if (Command.find('=', 0) != string::npos) + { + Command.erase(0, 1); + Tmp = Split(Command, '='); + if (Tmp.size() == 2) + { + ReplaceAll(Tmp[0], " ", ""); + string tmp = Tmp[0]; + if (RegistersMap.find(Tmp[0]) != RegistersMap.end()) + { + RegKind = RegistersMap[Tmp[0]]; + } + else + { + ReplaceAll(tmp, "@", ""); + if (RegistersMap.find(tmp) != RegistersMap.end()) + { + RegKind = RegistersMap[tmp]; + } + else + { + RegKind = (REGS_ENUM)-1; + } + } + if (RegKind != -1) + { + // + // send the request + // + SetRegisterValue = "@" + tmp + '=' + Tmp[1] + "; "; + + // + // Send data to the target user debugger or kernel debugger + // + ScriptEngineExecuteSingleExpression((CHAR *)SetRegisterValue.c_str(), TRUE, FALSE); + } + else + { + // + // error + // + ShowMessages("err, invalid register\n"); + } + } + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/rdmsr.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/rdmsr.cpp similarity index 90% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/rdmsr.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/rdmsr.cpp index 566a2537..b5f948f5 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/rdmsr.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/rdmsr.cpp @@ -11,6 +11,11 @@ */ #include "pch.h" +// +// Global Variables +// +extern BOOLEAN g_IsKdModuleLoaded; + /** * @brief help of the rdmsr command * @@ -106,12 +111,13 @@ GetWindowsNumaNumberOfCores() /** * @brief rdmsr command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandRdmsr(vector SplitCommand, string Command) +CommandRdmsr(vector CommandTokens, string Command) { BOOL Status; SIZE_T NumCPU; @@ -123,14 +129,15 @@ CommandRdmsr(vector SplitCommand, string Command) UINT32 CoreNumer = DEBUGGER_READ_AND_WRITE_ON_MSR_APPLY_ALL_CORES; BOOLEAN IsFirstCommand = TRUE; - if (SplitCommand.size() >= 5) + if (CommandTokens.size() >= 5) { - ShowMessages("incorrect use of the 'rdmsr'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandRdmsrHelp(); return; } - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { if (IsFirstCommand == TRUE) { @@ -140,7 +147,7 @@ CommandRdmsr(vector SplitCommand, string Command) if (IsNextCoreId) { - if (!ConvertStringToUInt32(Section, &CoreNumer)) + if (!ConvertTokenToUInt32(Section, &CoreNumer)) { ShowMessages("please specify a correct hex value for core id\n\n"); CommandRdmsrHelp(); @@ -150,13 +157,13 @@ CommandRdmsr(vector SplitCommand, string Command) continue; } - if (!Section.compare("core")) + if (CompareLowerCaseStrings(Section, "core")) { IsNextCoreId = TRUE; continue; } - if (SetMsr || !ConvertStringToUInt64(Section, &Msr)) + if (SetMsr || !ConvertTokenToUInt64(Section, &Msr)) { ShowMessages("please specify a correct hex value to be read\n\n"); CommandRdmsrHelp(); @@ -181,7 +188,7 @@ CommandRdmsr(vector SplitCommand, string Command) return; } - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); MsrReadRequest.ActionType = DEBUGGER_MSR_READ; MsrReadRequest.Msr = Msr; diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/s.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/s.cpp similarity index 81% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/s.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/s.cpp index 7024074b..9c3eff59 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/s.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/s.cpp @@ -15,6 +15,7 @@ // Global Variables // extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsKdModuleLoaded; extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; /** @@ -62,6 +63,7 @@ VOID CommandSearchSendRequest(UINT64 * BufferToSendAsIoctl, UINT32 BufferToSendAsIoctlSize) { BOOL Status; + DWORD BytesReturned; UINT64 CurrentValue; PUINT64 ResultsBuffer = NULL; @@ -86,9 +88,9 @@ CommandSearchSendRequest(UINT64 * BufferToSendAsIoctl, UINT32 BufferToSendAsIoct BufferToSendAsIoctlSize, // Input buffer length ResultsBuffer, // Output Buffer from driver. MaximumSearchResults * - sizeof(UINT64), // Length of output buffer in bytes. - NULL, // Bytes placed in buffer. - NULL // synchronous call + sizeof(UINT64), // Length of output buffer in bytes. + &BytesReturned, // Bytes placed in buffer. + NULL // synchronous call ); if (!Status) @@ -102,7 +104,7 @@ CommandSearchSendRequest(UINT64 * BufferToSendAsIoctl, UINT32 BufferToSendAsIoct // // Show the results (if any) // - for (size_t i = 0; i < MaximumSearchResults; i++) + for (SIZE_T i = 0; i < MaximumSearchResults; i++) { CurrentValue = ResultsBuffer[i]; @@ -130,12 +132,13 @@ CommandSearchSendRequest(UINT64 * BufferToSendAsIoctl, UINT32 BufferToSendAsIoct /** * @brief !s* s* commands handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandSearchMemory(vector SplitCommand, string Command) +CommandSearchMemory(vector CommandTokens, string Command) { UINT64 Address; vector ValuesToEdit; @@ -152,9 +155,7 @@ CommandSearchMemory(vector SplitCommand, string Command) UINT32 CountOfValues = 0; UINT32 FinalSize = 0; UINT64 * FinalBuffer = NULL; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - UINT32 IndexInCommandCaseSensitive = 0; - BOOLEAN IsFirstCommand = TRUE; + BOOLEAN IsFirstCommand = TRUE; // // By default if the user-debugger is active, we use these commands @@ -165,45 +166,47 @@ CommandSearchMemory(vector SplitCommand, string Command) ProcId = g_ActiveProcessDebuggingState.ProcessId; } - if (SplitCommand.size() <= 4) + if (CommandTokens.size() <= 4) { - ShowMessages("incorrect use of the 's*'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandSearchMemoryHelp(); return; } - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - IndexInCommandCaseSensitive++; - if (IsFirstCommand == TRUE) { - if (!Section.compare("!sb")) + std::string FirstCommand = GetLowerStringFromCommandToken(Section); + + if (!FirstCommand.compare("!sb")) { SearchMemoryRequest.MemoryType = SEARCH_PHYSICAL_MEMORY; SearchMemoryRequest.ByteSize = SEARCH_BYTE; } - else if (!Section.compare("!sd")) + else if (!FirstCommand.compare("!sd")) { SearchMemoryRequest.MemoryType = SEARCH_PHYSICAL_MEMORY; SearchMemoryRequest.ByteSize = SEARCH_DWORD; } - else if (!Section.compare("!sq")) + else if (!FirstCommand.compare("!sq")) { SearchMemoryRequest.MemoryType = SEARCH_PHYSICAL_MEMORY; SearchMemoryRequest.ByteSize = SEARCH_QWORD; } - else if (!Section.compare("sb")) + else if (!FirstCommand.compare("sb")) { SearchMemoryRequest.MemoryType = SEARCH_VIRTUAL_MEMORY; SearchMemoryRequest.ByteSize = SEARCH_BYTE; } - else if (!Section.compare("sd")) + else if (!FirstCommand.compare("sd")) { SearchMemoryRequest.MemoryType = SEARCH_VIRTUAL_MEMORY; SearchMemoryRequest.ByteSize = SEARCH_DWORD; } - else if (!Section.compare("sq")) + else if (!FirstCommand.compare("sq")) { SearchMemoryRequest.MemoryType = SEARCH_VIRTUAL_MEMORY; SearchMemoryRequest.ByteSize = SEARCH_QWORD; @@ -213,7 +216,7 @@ CommandSearchMemory(vector SplitCommand, string Command) // // What's this? :( // - ShowMessages("unknown error happened !\n\n"); + ShowMessages("unknown error happened!\n\n"); CommandSearchMemoryHelp(); return; } @@ -230,7 +233,7 @@ CommandSearchMemory(vector SplitCommand, string Command) // NextIsProcId = FALSE; - if (!ConvertStringToUInt32(Section, &ProcId)) + if (!ConvertTokenToUInt32(Section, &ProcId)) { ShowMessages("please specify a correct hex process id\n\n"); CommandSearchMemoryHelp(); @@ -252,7 +255,7 @@ CommandSearchMemory(vector SplitCommand, string Command) // NextIsLength = FALSE; - if (!ConvertStringToUInt64(Section, &Length)) + if (!ConvertTokenToUInt64(Section, &Length)) { ShowMessages("please specify a correct hex length\n\n"); CommandSearchMemoryHelp(); @@ -271,7 +274,7 @@ CommandSearchMemory(vector SplitCommand, string Command) // // Check if it's a process id or not // - if (!SetProcId && !Section.compare("pid")) + if (!SetProcId && CompareLowerCaseStrings(Section, "pid")) { NextIsProcId = TRUE; continue; @@ -280,7 +283,7 @@ CommandSearchMemory(vector SplitCommand, string Command) // // Check if it's a length or not // - if (!SetLength && !Section.compare("l")) + if (!SetLength && CompareLowerCaseStrings(Section, "l")) { NextIsLength = TRUE; continue; @@ -288,10 +291,10 @@ CommandSearchMemory(vector SplitCommand, string Command) if (!SetAddress) { - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1), &Address)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &Address)) { ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1).c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandSearchMemoryHelp(); return; } @@ -310,36 +313,38 @@ CommandSearchMemory(vector SplitCommand, string Command) // // Remove the hex notations // - if (Section.rfind("0x", 0) == 0 || Section.rfind("0X", 0) == 0 || - Section.rfind("\\x", 0) == 0 || Section.rfind("\\X", 0) == 0) + std::string TargetVal = GetCaseSensitiveStringFromCommandToken(Section); + + if (TargetVal.rfind("0x", 0) == 0 || TargetVal.rfind("0X", 0) == 0 || + TargetVal.rfind("\\x", 0) == 0 || TargetVal.rfind("\\X", 0) == 0) { - Section = Section.erase(0, 2); + TargetVal = TargetVal.erase(0, 2); } - else if (Section.rfind('x', 0) == 0 || Section.rfind('X', 0) == 0) + else if (TargetVal.rfind('x', 0) == 0 || TargetVal.rfind('X', 0) == 0) { - Section = Section.erase(0, 1); + TargetVal = TargetVal.erase(0, 1); } - Section.erase(remove(Section.begin(), Section.end(), '`'), Section.end()); + + TargetVal.erase(remove(TargetVal.begin(), TargetVal.end(), '`'), TargetVal.end()); // // Check if the value is valid based on byte counts // - if (SearchMemoryRequest.ByteSize == SEARCH_BYTE && Section.size() >= 3) + if (SearchMemoryRequest.ByteSize == SEARCH_BYTE && TargetVal.size() >= 3) { ShowMessages("please specify a byte (hex) value for 'sb' or '!sb'\n\n"); return; } - if (SearchMemoryRequest.ByteSize == SEARCH_DWORD && Section.size() >= 9) + + if (SearchMemoryRequest.ByteSize == SEARCH_DWORD && TargetVal.size() >= 9) { - ShowMessages( - "please specify a dword (hex) value for 'sd' or '!sd'\n\n"); + ShowMessages("please specify a dword (hex) value for 'sd' or '!sd'\n\n"); return; } - if (SearchMemoryRequest.ByteSize == SEARCH_QWORD && - Section.size() >= 17) + + if (SearchMemoryRequest.ByteSize == SEARCH_QWORD && TargetVal.size() >= 17) { - ShowMessages( - "please specify a qword (hex) value for 'sq' or '!sq'\n\n"); + ShowMessages("please specify a qword (hex) value for 'sq' or '!sq'\n\n"); return; } @@ -347,7 +352,7 @@ CommandSearchMemory(vector SplitCommand, string Command) // Qword is checked by the following function, no need to double // check it above. // - if (!ConvertStringToUInt64(Section, &Value)) + if (!ConvertStringToUInt64(TargetVal, &Value)) { ShowMessages("please specify a correct hex value to search in the " "memory content\n\n"); @@ -369,7 +374,7 @@ CommandSearchMemory(vector SplitCommand, string Command) if (!SetValue) { // - // At least on walue is there + // At least one value is there // SetValue = TRUE; } @@ -451,7 +456,7 @@ CommandSearchMemory(vector SplitCommand, string Command) if (!g_IsSerialConnectedToRemoteDebuggee) { - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); } // diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/settings.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/settings.cpp similarity index 71% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/settings.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/settings.cpp index 8b11d1c3..c54c63d4 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/settings.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/settings.cpp @@ -267,13 +267,13 @@ CommandSettingsLoadDefaultValuesFromConfigFile() * @brief set the address conversion enabled and disabled * and query the status of this mode * - * @param SplitCommand + * @param CommandTokens * @return VOID */ VOID -CommandSettingsAddressConversion(vector SplitCommand) +CommandSettingsAddressConversion(vector CommandTokens) { - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { // // It's a query @@ -287,19 +287,19 @@ CommandSettingsAddressConversion(vector SplitCommand) ShowMessages("address conversion is disabled\n"); } } - else if (SplitCommand.size() == 3) + else if (CommandTokens.size() == 3) { // // The user tries to set a value as the autoflush // - if (!SplitCommand.at(2).compare("on")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "on")) { g_AddressConversion = TRUE; CommandSettingsSetValueFromConfigFile("AddrConv", "on"); ShowMessages("set address conversion to enabled\n"); } - else if (!SplitCommand.at(2).compare("off")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "off")) { g_AddressConversion = FALSE; CommandSettingsSetValueFromConfigFile("AddrConv", "off"); @@ -311,8 +311,10 @@ CommandSettingsAddressConversion(vector SplitCommand) // // Sth is incorrect // - ShowMessages("incorrect use of the 'settings', please use 'help settings' " - "for more details\n"); + ShowMessages("incorrect use of the '%s', please use 'help %s' for more information\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str(), + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + return; } } @@ -321,8 +323,9 @@ CommandSettingsAddressConversion(vector SplitCommand) // // Sth is incorrect // - ShowMessages("incorrect use of the 'settings', please use 'help settings' " - "for more details\n"); + ShowMessages("incorrect use of the '%s', please use 'help %s' for more information\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str(), + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); return; } } @@ -331,13 +334,13 @@ CommandSettingsAddressConversion(vector SplitCommand) * @brief set the auto-flush mode to enabled and disabled * and query the status of this mode * - * @param SplitCommand + * @param CommandTokens * @return VOID */ VOID -CommandSettingsAutoFlush(vector SplitCommand) +CommandSettingsAutoFlush(vector CommandTokens) { - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { // // It's a query @@ -351,19 +354,19 @@ CommandSettingsAutoFlush(vector SplitCommand) ShowMessages("auto-flush is disabled\n"); } } - else if (SplitCommand.size() == 3) + else if (CommandTokens.size() == 3) { // // The user tries to set a value as the autoflush // - if (!SplitCommand.at(2).compare("on")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "on")) { g_AutoFlush = TRUE; CommandSettingsSetValueFromConfigFile("AutoFlush", "on"); ShowMessages("set auto-flush to enabled\n"); } - else if (!SplitCommand.at(2).compare("off")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "off")) { g_AutoFlush = FALSE; CommandSettingsSetValueFromConfigFile("AutoFlush", "off"); @@ -375,8 +378,9 @@ CommandSettingsAutoFlush(vector SplitCommand) // // Sth is incorrect // - ShowMessages("incorrect use of the 'settings', please use 'help settings' " - "for more details\n"); + ShowMessages("incorrect use of the '%s', please use 'help %s' for more information\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str(), + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); return; } } @@ -385,8 +389,9 @@ CommandSettingsAutoFlush(vector SplitCommand) // // Sth is incorrect // - ShowMessages("incorrect use of the 'settings', please use 'help settings' " - "for more details\n"); + ShowMessages("incorrect use of the '%s', please use 'help %s' for more information\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str(), + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); return; } } @@ -394,13 +399,13 @@ CommandSettingsAutoFlush(vector SplitCommand) /** * @brief set auto-unpause mode to enabled or disabled * - * @param SplitCommand + * @param CommandTokens * @return VOID */ VOID -CommandSettingsAutoUpause(vector SplitCommand) +CommandSettingsAutoUpause(vector CommandTokens) { - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { // // It's a query @@ -414,19 +419,19 @@ CommandSettingsAutoUpause(vector SplitCommand) ShowMessages("auto-unpause is disabled\n"); } } - else if (SplitCommand.size() == 3) + else if (CommandTokens.size() == 3) { // // The user tries to set a value as the autounpause // - if (!SplitCommand.at(2).compare("on")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "on")) { g_AutoUnpause = TRUE; CommandSettingsSetValueFromConfigFile("AutoUnpause", "on"); ShowMessages("set auto-unpause to enabled\n"); } - else if (!SplitCommand.at(2).compare("off")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "off")) { g_AutoUnpause = FALSE; CommandSettingsSetValueFromConfigFile("AutoUnpause", "off"); @@ -438,8 +443,9 @@ CommandSettingsAutoUpause(vector SplitCommand) // // Sth is incorrect // - ShowMessages("incorrect use of the 'settings', please use 'help settings' " - "for more details\n"); + ShowMessages("incorrect use of the '%s', please use 'help %s' for more information\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str(), + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); return; } } @@ -448,8 +454,9 @@ CommandSettingsAutoUpause(vector SplitCommand) // // Sth is incorrect // - ShowMessages("incorrect use of the 'settings', please use 'help settings' " - "for more details\n"); + ShowMessages("incorrect use of the '%s', please use 'help %s' for more information\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str(), + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); return; } } @@ -457,13 +464,13 @@ CommandSettingsAutoUpause(vector SplitCommand) /** * @brief set the syntax of !u !u2 u u2 command * - * @param SplitCommand + * @param CommandTokens * @return VOID */ VOID -CommandSettingsSyntax(vector SplitCommand) +CommandSettingsSyntax(vector CommandTokens) { - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { // // It's a query @@ -485,27 +492,27 @@ CommandSettingsSyntax(vector SplitCommand) ShowMessages("unknown syntax\n"); } } - else if (SplitCommand.size() == 3) + else if (CommandTokens.size() == 3) { // // The user tries to set a value as the syntax // - if (!SplitCommand.at(2).compare("intel")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "intel")) { g_DisassemblerSyntax = 1; CommandSettingsSetValueFromConfigFile("AsmSyntax", "intel"); ShowMessages("set syntax to intel\n"); } - else if (!SplitCommand.at(2).compare("att") || - !SplitCommand.at(2).compare("at&t")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "att") || + CompareLowerCaseStrings(CommandTokens.at(2), "at&t")) { g_DisassemblerSyntax = 2; CommandSettingsSetValueFromConfigFile("AsmSyntax", "att"); ShowMessages("set syntax to at&t\n"); } - else if (!SplitCommand.at(2).compare("masm")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "masm")) { g_DisassemblerSyntax = 3; CommandSettingsSetValueFromConfigFile("AsmSyntax", "masm"); @@ -517,8 +524,9 @@ CommandSettingsSyntax(vector SplitCommand) // // Sth is incorrect // - ShowMessages("incorrect use of the 'settings', please use 'help settings' " - "for more details\n"); + ShowMessages("incorrect use of the '%s', please use 'help %s' for more information\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str(), + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); return; } } @@ -527,8 +535,9 @@ CommandSettingsSyntax(vector SplitCommand) // // Sth is incorrect // - ShowMessages("incorrect use of the 'settings', please use 'help settings' " - "for more details\n"); + ShowMessages("incorrect use of the '%s', please use 'help %s' for more information\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str(), + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); return; } } @@ -536,16 +545,17 @@ CommandSettingsSyntax(vector SplitCommand) /** * @brief settings command handler * - * @param SplitCommand + * @param CommandTokens * @param Command * @return VOID */ VOID -CommandSettings(vector SplitCommand, string Command) +CommandSettings(vector CommandTokens, string Command) { - if (SplitCommand.size() <= 1) + if (CommandTokens.size() <= 1) { - ShowMessages("incorrect use of the 'settings'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSettingsHelp(); return; } @@ -553,14 +563,14 @@ CommandSettings(vector SplitCommand, string Command) // // Interpret the field name // - if (!SplitCommand.at(1).compare("autounpause")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "autounpause")) { // // Handle it locally // - CommandSettingsAutoUpause(SplitCommand); + CommandSettingsAutoUpause(CommandTokens); } - else if (!SplitCommand.at(1).compare("syntax")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "syntax")) { // // If it's a remote debugger then we send it to the remote debugger @@ -575,10 +585,10 @@ CommandSettings(vector SplitCommand, string Command) // If it's a connection over serial or a local debugging then // we handle it locally // - CommandSettingsSyntax(SplitCommand); + CommandSettingsSyntax(CommandTokens); } } - else if (!SplitCommand.at(1).compare("autoflush")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "autoflush")) { // // If it's a remote debugger then we send it to the remote debugger @@ -593,10 +603,10 @@ CommandSettings(vector SplitCommand, string Command) // If it's a connection over serial or a local debugging then // we handle it locally // - CommandSettingsAutoFlush(SplitCommand); + CommandSettingsAutoFlush(CommandTokens); } } - else if (!SplitCommand.at(1).compare("addressconversion")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "addressconversion")) { // // If it's a remote debugger then we send it to the remote debugger @@ -611,16 +621,17 @@ CommandSettings(vector SplitCommand, string Command) // If it's a connection over serial or a local debugging then // we handle it locally // - CommandSettingsAddressConversion(SplitCommand); + CommandSettingsAddressConversion(CommandTokens); } } else { // - // optionm not found + // option not found // - ShowMessages("incorrect use of the 'settings', please use 'help settings' " - "for more details\n"); + ShowMessages("incorrect use of the '%s', please use 'help %s' for more information\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str(), + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); return; } } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/sleep.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/sleep.cpp similarity index 74% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/sleep.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/sleep.cpp index be4b9ceb..77062b5a 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/sleep.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/sleep.cpp @@ -29,23 +29,25 @@ CommandSleepHelp() /** * @brief sleep command help * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandSleep(vector SplitCommand, string Command) +CommandSleep(vector CommandTokens, string Command) { UINT32 MillisecondsTime = 0; - if (SplitCommand.size() != 2) + if (CommandTokens.size() != 2) { - ShowMessages("incorrect use of the 'sleep'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSleepHelp(); return; } - if (!ConvertStringToUInt32(SplitCommand.at(1), &MillisecondsTime)) + if (!ConvertTokenToUInt32(CommandTokens.at(1), &MillisecondsTime)) { ShowMessages( "please specify a correct hex value for time (milliseconds)\n\n"); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/t.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/t.cpp similarity index 68% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/t.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/t.cpp index 40e9950b..afc48d51 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/t.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/t.cpp @@ -44,37 +44,33 @@ CommandTHelp() /** * @brief handler of t command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandT(vector SplitCommand, string Command) +CommandT(vector CommandTokens, string Command) { - UINT32 StepCount; - DEBUGGER_REMOTE_STEPPING_REQUEST RequestFormat; + UINT32 StepCount; // // Validate the commands // - if (SplitCommand.size() != 1 && SplitCommand.size() != 2) + if (CommandTokens.size() != 1 && CommandTokens.size() != 2) { - ShowMessages("incorrect use of the 't'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandTHelp(); return; } - // - // Set type of step - // - RequestFormat = DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_IN; - // // Check if the command has a counter parameter // - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { - if (!ConvertStringToUInt32(SplitCommand.at(1), &StepCount)) + if (!ConvertTokenToUInt32(CommandTokens.at(1), &StepCount)) { ShowMessages("please specify a correct hex value for [count]\n\n"); CommandTHelp(); @@ -97,7 +93,7 @@ CommandT(vector SplitCommand, string Command) if (g_ActiveProcessDebuggingState.IsActive && !g_ActiveProcessDebuggingState.IsPaused) { ShowMessages("the target process is running, use the " - "'pause' command or press CTRL+C to pause the process\n"); + "'pause' command to pause the process\n"); return; } @@ -106,7 +102,7 @@ CommandT(vector SplitCommand, string Command) // g_IsInstrumentingInstructions = TRUE; - for (size_t i = 0; i < StepCount; i++) + for (SIZE_T i = 0; i < StepCount; i++) { // // For logging purpose @@ -115,29 +111,18 @@ CommandT(vector SplitCommand, string Command) // (float)StepCount), i); // - if (g_IsSerialConnectedToRemoteDebuggee) - { - // - // It's stepping over serial connection in kernel debugger - // - KdSendStepPacketToDebuggee(RequestFormat); - } - else - { - // - // It's stepping over user debugger - // - UdSendStepPacketToDebuggee(g_ActiveProcessDebuggingState.ProcessDebuggingToken, - g_ActiveProcessDebuggingState.ThreadId, - RequestFormat); - } + // + // Instrument (regular) the instruction + // + SteppingRegularStepIn(); - if (!SplitCommand.at(0).compare("tr")) + if (CompareLowerCaseStrings(CommandTokens.at(0), "tr")) { // // Show registers // - ShowAllRegisters(); + HyperDbgRegisterShowAll(); + if (i != StepCount - 1) { ShowMessages("\n"); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/test.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/test.cpp similarity index 67% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/test.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/test.cpp index 2a29a7d1..ffe824d8 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/test.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/test.cpp @@ -14,6 +14,7 @@ // // Global Variables // +extern BOOLEAN g_IsKdModuleLoaded; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; /** @@ -30,7 +31,6 @@ CommandTestHelp() ShowMessages("syntax : \ttest [Task (string)]\n"); ShowMessages("\n"); - ShowMessages("\t\te.g : test\n"); ShowMessages("\t\te.g : test query\n"); ShowMessages("\t\te.g : test trap-status\n"); ShowMessages("\t\te.g : test pool\n"); @@ -53,7 +53,7 @@ CommandTestPerformKernelTestsIoctl() ULONG ReturnedLength; DEBUGGER_PERFORM_KERNEL_TESTS KernelTestRequest = {0}; - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // By the way, we don't need to send an input buffer @@ -63,7 +63,7 @@ CommandTestPerformKernelTestsIoctl() // Status = DeviceIoControl( g_DeviceHandle, // Handle to device - IOCTL_PERFROM_KERNEL_SIDE_TESTS, // IO Control Code (IOCTL) + IOCTL_PERFORM_KERNEL_SIDE_TESTS, // IO Control Code (IOCTL) &KernelTestRequest, // Input Buffer to driver. SIZEOF_DEBUGGER_PERFORM_KERNEL_TESTS, // Input buffer length &KernelTestRequest, // Output Buffer from driver. @@ -97,39 +97,109 @@ CommandTestPerformKernelTestsIoctl() } /** - * @brief perform test on the remote process + * @brief perform test on for all functionalities * - * @param KernelSideInformation Information from kernel - * @param KernelSideInformationSize Information from kernel () + * @return VOID + */ +VOID +CommandTestAllFunctionalities() +{ + HANDLE ThreadHandle; + HANDLE ProcessHandle; + + // + // Test command parser + // + if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_MAIN_COMMAND_PARSER)) + { + ShowMessages("err, start HyperDbg test process for testing the main command parser\n"); + return; + } + + // + // Test PE parser helpers + // + if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_PE_PARSER)) + { + ShowMessages("err, start HyperDbg test process for testing the PE parser\n"); + return; + } + + // + // Test CodeView RSDS parser helpers + // + if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_CODEVIEW_RSDS_PARSER)) + { + ShowMessages("err, start HyperDbg test process for testing the CodeView RSDS parser\n"); + return; + } + + // + // Test script engine (script parser) using semantic tests + // + if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_SCRIPT_SEMANTIC_TEST_CASES)) + { + ShowMessages("err, start HyperDbg test process for testing semantic tests\n"); + return; + } +} + +/** + * @brief perform test for all functionalities of hwdbg + * + * @return VOID + */ +VOID +CommandTestAllHwdbg() +{ + HANDLE ThreadHandle; + HANDLE ProcessHandle; + + // + // Test hwdbg functionalities + // + if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_HWDBG_FUNCTIONALITIES)) + { + ShowMessages("err, start HyperDbg test process for testing hwdbg functionalities\n"); + return; + } +} + +/** + * @brief perform test on the remote process * * @return BOOLEAN returns true if the results was true and false if the results * was not ok */ BOOLEAN -CommandTestPerformTest(PDEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION KernelSideInformation, UINT32 KernelSideInformationSize) +CommandTestPerformTest() { BOOLEAN ResultOfTest = FALSE; HANDLE PipeHandle; HANDLE ThreadHandle; HANDLE ProcessHandle; UINT32 ReadBytes; - CHAR * Buffer = {0}; + CHAR * Buffer = NULL; // // Allocate memory // Buffer = (CHAR *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + + if (!Buffer) + { + ShowMessages("err, enable allocate communication buffer\n"); + return FALSE; + } + RtlZeroMemory(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); // // Create tests process to create a thread for us // - if (!CreateProcessAndOpenPipeConnection( - KernelSideInformation, - KernelSideInformationSize, - &PipeHandle, - &ThreadHandle, - &ProcessHandle)) + if (!CreateProcessAndOpenPipeConnection(&PipeHandle, + &ThreadHandle, + &ProcessHandle)) { ShowMessages("err, enable to connect to the test process\n"); @@ -146,11 +216,26 @@ CommandTestPerformTest(PDEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION KernelSideInfo // Wait for the result of test to be received // -WaitForResponse: +SendCommandAndWaitForResponse: + + CHAR TestCommand[] = "this is a test command"; + + BOOLEAN SentMessageResult = NamedPipeServerSendMessageToClient( + PipeHandle, + TestCommand, + (UINT32)strlen(TestCommand) + 1); + + if (!SentMessageResult) + { + // + // error in sending + // + return FALSE; + } RtlZeroMemory(Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); ReadBytes = - NamedPipeServerReadClientMessage(PipeHandle, (char *)Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + NamedPipeServerReadClientMessage(PipeHandle, (CHAR *)Buffer, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); if (!ReadBytes) { @@ -162,35 +247,7 @@ WaitForResponse: return FALSE; } - if (strcmp(Buffer, "perform-kernel-test") == 0) - { - // - // Send IOCTL to perform kernel tasks - // - CommandTestPerformKernelTestsIoctl(); - - goto WaitForResponse; - } - else if (strcmp(Buffer, "success") == 0) - { - ResultOfTest = TRUE; - } - else if (Buffer[0] == 'c' && - Buffer[1] == 'm' && - Buffer[2] == 'd' && - Buffer[3] == ':') - { - // - // It's a command as it starts with "cmd:" - // - ShowMessages("command is : %s\n", &Buffer[4]); - HyperDbgInterpreter(&Buffer[4]); - goto WaitForResponse; - } - else - { - ResultOfTest = FALSE; - } + goto SendCommandAndWaitForResponse; // // Close connection and remote process @@ -202,72 +259,6 @@ WaitForResponse: return ResultOfTest; } -/** - * @brief test command for VMI mode - * - * @return VOID - */ -VOID -CommandTestInVmiMode() -{ - BOOL Status; - ULONG ReturnedLength; - PDEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION - KernelSideTestInformationRequestArray; - - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); - - // - // *** Read kernel-side debugging information *** - // - KernelSideTestInformationRequestArray = (DEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - - RtlZeroMemory(KernelSideTestInformationRequestArray, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - - // - // Send Ioctl to the kernel - // - Status = DeviceIoControl( - g_DeviceHandle, // Handle to device - IOCTL_SEND_GET_KERNEL_SIDE_TEST_INFORMATION, // IO Control Code (IOCTL) - KernelSideTestInformationRequestArray, // Input Buffer to driver. - SIZEOF_DEBUGGEE_KERNEL_AND_USER_TEST_INFORMATION, // Input buffer - // length - KernelSideTestInformationRequestArray, // Output Buffer from driver. - TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE, // Length - // of - // output - // buffer - // in - // bytes. - &ReturnedLength, // Bytes placed in buffer. - NULL // synchronous call - ); - - if (!Status) - { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); - return; - } - - // - // Means to check just one command - // - if (CommandTestPerformTest(KernelSideTestInformationRequestArray, ReturnedLength)) - { - ShowMessages("all the tests were successful :)\n"); - } - else - { - ShowMessages("all or at least one of the tests failed :(\n"); - } - - // - // Free the kernel-side buffer - // - free(KernelSideTestInformationRequestArray); -} - /** * @brief test command for query the state * @@ -434,60 +425,62 @@ CommandTestSetDebugBreakState(BOOLEAN State) /** * @brief test command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandTest(vector SplitCommand, string Command) +CommandTest(vector CommandTokens, string Command) { UINT64 Context = NULL; - if (SplitCommand.size() == 1) + UINT32 CommandSize = (UINT32)CommandTokens.size(); + + if (CommandSize == 1) { - // - // For testing in vmi mode - // - CommandTestInVmiMode(); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandTestHelp(); } - else if (SplitCommand.size() == 2 && !SplitCommand.at(1).compare("query")) + else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "query")) { // // Query the state of debuggee in debugger mode // CommandTestQueryState(); } - else if (SplitCommand.size() == 2 && !SplitCommand.at(1).compare("trap-status")) + else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "trap-status")) { // // Query the state of trap flag in debugger mode // CommandTestQueryTrapState(); } - else if (SplitCommand.size() == 2 && !SplitCommand.at(1).compare("pool")) + else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "pool")) { // // Query the state of pre-allocated pools in debugger mode // CommandTestQueryPreAllocPoolsState(); } - else if (SplitCommand.size() == 2 && !SplitCommand.at(1).compare("sync-task")) + else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "sync-task")) { // // Send target task to the halted cores in debugger mode (synchronous) // CommandTestSetTargetTaskToHaltedCores(TRUE); } - else if (SplitCommand.size() == 2 && !SplitCommand.at(1).compare("async-task")) + else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "async-task")) { // // Send target task to the halted cores in debugger mode (asynchronous) // CommandTestSetTargetTaskToHaltedCores(FALSE); } - else if (SplitCommand.size() == 3 && !SplitCommand.at(1).compare("target-core-task")) + else if (CommandSize == 3 && CompareLowerCaseStrings(CommandTokens.at(1), "target-core-task")) { - if (!ConvertStringToUInt64(SplitCommand.at(2), &Context)) + if (!ConvertTokenToUInt64(CommandTokens.at(2), &Context)) { ShowMessages("err, you should enter a valid hex number as the core id\n\n"); return; @@ -498,47 +491,64 @@ CommandTest(vector SplitCommand, string Command) // CommandTestSetTargetTaskToTargetCore((UINT32)Context); } - else if (SplitCommand.size() == 3 && !SplitCommand.at(1).compare("breakpoint")) + else if (CommandSize == 3 && CompareLowerCaseStrings(CommandTokens.at(1), "breakpoint")) { // // Change breakpoint state // - if (!SplitCommand.at(2).compare("on")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "on")) { CommandTestSetBreakpointState(TRUE); } - else if (!SplitCommand.at(2).compare("off")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "off")) { CommandTestSetBreakpointState(FALSE); } else { - ShowMessages("err, couldn't resolve error at '%s'\n\n", SplitCommand.at(2).c_str()); + ShowMessages("err, couldn't resolve error at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()); return; } } - else if (SplitCommand.size() == 3 && !SplitCommand.at(1).compare("trap")) + else if (CommandSize == 3 && CompareLowerCaseStrings(CommandTokens.at(1), "trap")) { // // Change debug break state // - if (!SplitCommand.at(2).compare("on")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "on")) { CommandTestSetDebugBreakState(TRUE); } - else if (!SplitCommand.at(2).compare("off")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "off")) { CommandTestSetDebugBreakState(FALSE); } else { - ShowMessages("err, couldn't resolve error at '%s'\n\n", SplitCommand.at(2).c_str()); + ShowMessages("err, couldn't resolve error at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()); return; } } + else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "all")) + { + // + // For testing functionalities + // + CommandTestAllFunctionalities(); + } + else if (CommandSize == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "hwdbg")) + { + // + // For testing functionalities of hwdbg + // + CommandTestAllHwdbg(); + } else { - ShowMessages("incorrect use of the 'test'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandTestHelp(); return; } diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/unload.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/unload.cpp new file mode 100644 index 00000000..0738fc1b --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/unload.cpp @@ -0,0 +1,244 @@ +/** + * @file unload.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief unload command + * @details + * @version 0.1 + * @date 2020-05-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsConnectedToHyperDbgLocally; +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsVmmModuleLoaded; +extern BOOLEAN g_IsHyperTraceModuleLoaded; +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; + +/** + * @brief help of the unload command + * + * @return VOID + */ +VOID +CommandUnloadHelp() +{ + ShowMessages("unload : unloads the kernel modules and uninstalls drivers.\n\n"); + + ShowMessages("syntax : \tunload [ModuleNameOrAll (string)]\n"); + ShowMessages("syntax : \tunload [remove] [all]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : unload vmm\n"); + ShowMessages("\t\te.g : unload trace\n"); + ShowMessages("\t\te.g : unload kd\n"); + ShowMessages("\t\te.g : unload all\n"); + ShowMessages("\t\te.g : unload remove all\n"); +} + +/** + * @brief check the environment for unload command + * + * @return BOOLEAN + */ +BOOLEAN +CommandUnloadCheckEnvironment() +{ + if (!g_IsConnectedToHyperDbgLocally) + { + ShowMessages("you're not connected to any instance of HyperDbg, did you " + "use '.connect'? \n"); + return FALSE; + } + + // + // Check to avoid using this command in debugger-mode + // + if (g_IsSerialConnectedToRemoteDebuggee || g_IsSerialConnectedToRemoteDebugger) + { + ShowMessages("you're connected to a an instance of HyperDbg, please use " + "'.debug close' command\n"); + return FALSE; + } + + return TRUE; +} + +/** + * @brief unload command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandUnload(vector CommandTokens, string Command) +{ + if (CommandTokens.size() != 2 && CommandTokens.size() != 3) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandUnloadHelp(); + return; + } + + // + // Check for the module + // + if (CommandTokens.size() == 2 && + (CompareLowerCaseStrings(CommandTokens.at(1), "vmm") || CompareLowerCaseStrings(CommandTokens.at(1), "vm"))) + { + // + // Check the environment + // + if (!CommandUnloadCheckEnvironment()) + { + return; + } + + if (g_IsVmmModuleLoaded) + { + HyperDbgUnloadVmm(); + + HyperDbgUnloadKd(); // Test: Should be removed + } + else + { + ShowMessages("the vmm module is not loadedd\n"); + } + } + else if (CommandTokens.size() == 2 && + (CompareLowerCaseStrings(CommandTokens.at(1), "trace") || CompareLowerCaseStrings(CommandTokens.at(1), "hypertrace"))) + { + // + // Check the environment + // + if (!CommandUnloadCheckEnvironment()) + { + return; + } + + if (g_IsHyperTraceModuleLoaded) + { + HyperDbgUnloadHyperTrace(); + } + else + { + ShowMessages("the trace (hypertrace) module is not loadedd\n"); + } + } + else if (CommandTokens.size() == 2 && + (CompareLowerCaseStrings(CommandTokens.at(1), "kd") || CompareLowerCaseStrings(CommandTokens.at(1), "dbg") || + CompareLowerCaseStrings(CommandTokens.at(1), "debugger") || CompareLowerCaseStrings(CommandTokens.at(1), "debug") || + CompareLowerCaseStrings(CommandTokens.at(1), "kerneldebugger") || CompareLowerCaseStrings(CommandTokens.at(1), "kerneldebug"))) + { + // + // Check the environment + // + if (!CommandUnloadCheckEnvironment()) + { + return; + } + + if (g_IsKdModuleLoaded) + { + HyperDbgUnloadKd(); + } + else + { + ShowMessages("the kd (kernel debugger) module is not loadedd\n"); + } + } + else if (CommandTokens.size() == 2 && + (CompareLowerCaseStrings(CommandTokens.at(1), "all") || CompareLowerCaseStrings(CommandTokens.at(1), "."))) + { + // + // Check the environment + // + if (!CommandUnloadCheckEnvironment()) + { + return; + } + + // + // Check if any module is loaded + // + if (!HyperDbgIsAnyModuleLoaded()) + { + ShowMessages("no module is loaded\n"); + return; + } + + ShowMessages("unloading all modules\n"); + + // + // Unload all modules + // + if (HyperDbgUnloadAllModules() != 0) + { + ShowMessages("err, failed to unload all modules\n"); + return; + } + else + { + ShowMessages("all modules are unloaded\n"); + } + } + else if (CommandTokens.size() == 3 && CompareLowerCaseStrings(CommandTokens.at(1), "remove") && + (CompareLowerCaseStrings(CommandTokens.at(2), "all") || + CompareLowerCaseStrings(CommandTokens.at(2), ".") || + CompareLowerCaseStrings(CommandTokens.at(2), "vmm") || + CompareLowerCaseStrings(CommandTokens.at(2), "vm"))) + { + // + // Check the environment + // + if (!CommandUnloadCheckEnvironment()) + { + return; + } + + // + // Unload all modules before removing the driver + // + if (HyperDbgUnloadAllModules()) + { + ShowMessages("err, failed to unload all modules\n"); + return; + } + + // + // Stop the driver + // + if (HyperDbgStopKdDriver()) + { + ShowMessages("err, failed to stop driver\n"); + return; + } + + // + // Uninstall the driver + // + if (HyperDbgUninstallKdDriver()) + { + ShowMessages("err, failed to uninstall the driver\n"); + return; + } + + ShowMessages("all drivers are removed\n"); + } + else + { + // + // Module not found + // + ShowMessages("err, module not found\n"); + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/wrmsr.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/wrmsr.cpp similarity index 79% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/wrmsr.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/wrmsr.cpp index 1aff8ece..7e6fb434 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/wrmsr.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/wrmsr.cpp @@ -11,6 +11,11 @@ */ #include "pch.h" +// +// Global Variables +// +extern BOOLEAN g_IsKdModuleLoaded; + /** * @brief help of the wrmsr command * @@ -33,16 +38,17 @@ CommandWrmsrHelp() /** * @brief wrmsr command handler * - * @param SplitCommand + * @param CommandTokens * @param Command * * @return VOID */ VOID -CommandWrmsr(vector SplitCommand, string Command) +CommandWrmsr(vector CommandTokens, string Command) { BOOL Status; UINT64 Msr; + ULONG ReturnedLength; DEBUGGER_READ_AND_WRITE_ON_MSR MsrWriteRequest = {0}; BOOL IsNextCoreId = FALSE; BOOL SetMsr = FALSE; @@ -51,14 +57,15 @@ CommandWrmsr(vector SplitCommand, string Command) UINT32 CoreNumer = DEBUGGER_READ_AND_WRITE_ON_MSR_APPLY_ALL_CORES; BOOLEAN IsFirstCommand = TRUE; - if (SplitCommand.size() >= 6) + if (CommandTokens.size() >= 6) { - ShowMessages("incorrect use of the 'wrmsr'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandWrmsrHelp(); return; } - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { if (IsFirstCommand == TRUE) { @@ -68,7 +75,7 @@ CommandWrmsr(vector SplitCommand, string Command) if (IsNextCoreId) { - if (!ConvertStringToUInt32(Section, &CoreNumer)) + if (!ConvertTokenToUInt32(Section, &CoreNumer)) { ShowMessages("please specify a correct hex value for core id\n\n"); CommandWrmsrHelp(); @@ -79,7 +86,7 @@ CommandWrmsr(vector SplitCommand, string Command) continue; } - if (!Section.compare("core")) + if (CompareLowerCaseStrings(Section, "core")) { IsNextCoreId = TRUE; continue; @@ -87,7 +94,7 @@ CommandWrmsr(vector SplitCommand, string Command) if (!SetMsr) { - if (!ConvertStringToUInt64(Section, &Msr)) + if (!ConvertTokenToUInt64(Section, &Msr)) { ShowMessages("please specify a correct hex value to be read\n\n"); CommandWrmsrHelp(); @@ -105,7 +112,7 @@ CommandWrmsr(vector SplitCommand, string Command) if (SetMsr) { - if (!SymbolConvertNameOrExprToAddress(Section, &Value)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &Value)) { ShowMessages( "please specify a correct hex value or an expression to put on the msr\n\n"); @@ -144,7 +151,7 @@ CommandWrmsr(vector SplitCommand, string Command) return; } - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); MsrWriteRequest.ActionType = DEBUGGER_MSR_WRITE; MsrWriteRequest.Msr = Msr; @@ -156,9 +163,9 @@ CommandWrmsr(vector SplitCommand, string Command) IOCTL_DEBUGGER_READ_OR_WRITE_MSR, // IO Control Code (IOCTL) &MsrWriteRequest, // Input Buffer to driver. SIZEOF_DEBUGGER_READ_AND_WRITE_ON_MSR, // Input buffer length - NULL, // Output Buffer from driver. - NULL, // Length of output buffer in bytes. - NULL, // Bytes placed in buffer. + &MsrWriteRequest, // Output Buffer from driver. + SIZEOF_DEBUGGER_READ_AND_WRITE_ON_MSR, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. NULL // synchronous call ); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/x.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/x.cpp similarity index 66% rename from hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/x.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/x.cpp index 708d8527..e76ed716 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/x.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/x.cpp @@ -32,37 +32,24 @@ CommandXHelp() /** * @brief x command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandX(vector SplitCommand, string Command) +CommandX(vector CommandTokens, string Command) { - if (SplitCommand.size() == 1) + if (CommandTokens.size() != 2) { - ShowMessages("incorrect use of the 'x'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandXHelp(); return; } - // - // Trim the command - // - Trim(Command); - - // - // Remove x from it - // - Command.erase(0, SplitCommand.at(0).size()); - - // - // Trim it again - // - Trim(Command); - // // Search for mask // - ScriptEngineSearchSymbolForMaskWrapper(Command.c_str()); + ScriptEngineSearchSymbolForMaskWrapper(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); } diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp new file mode 100644 index 00000000..b68c93cb --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp @@ -0,0 +1,300 @@ +/** + * @file apic.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !apic command + * @details + * @version 0.11 + * @date 2024-11-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; + +/** + * @brief help of the !apic command + * + * @return VOID + */ +VOID +CommandApicHelp() +{ + ShowMessages("!apic : shows the details of Local APIC in both xAPIC and x2APIC modes.\n\n"); + + ShowMessages("syntax : \t!apic\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !apic\n"); +} + +/** + * @brief Send APIC requests + * + * @param ApicType + * @param ApicBuffer + * @param ExpectedRequestSize + * @param IsUsingX2APIC + * + * @return VOID + */ +BOOLEAN +CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, + PVOID ApicBuffer, + UINT32 ExpectedRequestSize, + PBOOLEAN IsUsingX2APIC) +{ + BOOL Status; + ULONG ReturnedLength; + PDEBUGGER_APIC_REQUEST ApicRequest; + UINT32 RequestSize = 0; + + RequestSize = SIZEOF_DEBUGGER_APIC_REQUEST + ExpectedRequestSize; + + // + // Allocate buffer to fill the request + // + ApicRequest = (PDEBUGGER_APIC_REQUEST)malloc(RequestSize); + + if (ApicRequest == NULL) + { + // + // Unable to allocate buffer + // + return FALSE; + } + + RtlZeroMemory(ApicRequest, RequestSize); + + // + // Set the APIC type to local apic + // Note that the APIC mode (xAPIC and x2APIC) is determined in the debugger + // + ApicRequest->ApicType = ApicType; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Send the request over serial kernel debugger + // + if (!KdSendApicActionPacketsToDebuggee(ApicRequest, RequestSize)) + { + free(ApicRequest); + return FALSE; + } + else + { + *IsUsingX2APIC = ApicRequest->IsUsingX2APIC; + RtlCopyMemory(ApicBuffer, (PVOID)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)), ExpectedRequestSize); + + free(ApicRequest); + return TRUE; + } + } + else + { + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // Send IOCTL + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_PERFORM_ACTIONS_ON_APIC, // IO Control Code (IOCTL) + ApicRequest, // Input Buffer to driver. + SIZEOF_DEBUGGER_APIC_REQUEST, // Input buffer length + ApicRequest, // Output Buffer from driver. + RequestSize, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + + free(ApicRequest); + return FALSE; + } + + if (ReturnedLength != RequestSize && ReturnedLength != SIZEOF_DEBUGGER_APIC_REQUEST) + { + // + // An err occurred + // + ShowMessages("err, apic request failed\n"); + + free(ApicRequest); + return FALSE; + } + + if (ApicRequest->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // + // Fill the request buffer + // + *IsUsingX2APIC = ApicRequest->IsUsingX2APIC; + RtlCopyMemory(ApicBuffer, (PVOID)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)), ExpectedRequestSize); + + free(ApicRequest); + return TRUE; + } + else + { + // + // An err occurred, no results + // + ShowErrorMessage(ApicRequest->KernelStatus); + + free(ApicRequest); + return FALSE; + } + } +} + +/** + * @brief Request to get Local APIC + * + * @param LocalApic + * @param IsUsingX2APIC + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic, PBOOLEAN IsUsingX2APIC) +{ + return CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC, + LocalApic, + sizeof(LAPIC_PAGE), + IsUsingX2APIC); +} + +/** + * @brief !apic command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandApic(vector CommandTokens, string Command) +{ + BOOLEAN IsUsingX2APIC = FALSE; + UINT8 i = 0, j = 0; + UINT32 k = 0; + UINT32 Reg = 0; + LAPIC_PAGE LocalApic = {0}; + + if (CommandTokens.size() != 1) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + + CommandApicHelp(); + return; + } + + // + // Get the local APIC results + // + if (HyperDbgGetLocalApic(&LocalApic, &IsUsingX2APIC) == FALSE) + { + return; + } + + // + // Show different fields of the Local APIC + // + ShowMessages("*** (%s Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s')\n" + " -> TPR = 0x%08x, PPR = 0x%08x\n" + " -> LDR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" + " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" + " -> LVT_CMCI = 0x%08x, LVT_PMCR = 0x%08x\n" + " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" + " -> LVT_ERR = 0x%08x\n" + " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", + IsUsingX2APIC ? "X2APIC" : "XAPIC", + LocalApic.Id >> 24, + LocalApic.Version, + (LocalApic.Version & 0xFF0000) >> 16, + (LocalApic.Version >> 24) & 1, + (LocalApic.SpuriousInterruptVector >> 12) & 1, + (LocalApic.SpuriousInterruptVector & LAPIC_SVR_FLAG_SW_ENABLE) != 0 ? "Enabled" : "Disabled", + LocalApic.TPR, + LocalApic.ProcessorPriority, + LocalApic.LogicalDestination, + LocalApic.SpuriousInterruptVector, + LocalApic.ErrorStatus, + LocalApic.LvtLINT0, + LocalApic.LvtLINT1, + LocalApic.LvtCmci, + LocalApic.LvtPerfMonCounters, + LocalApic.LvtTimer, + LocalApic.LvtThermalSensor, + LocalApic.LvtError, + LocalApic.InitialCount, + LocalApic.CurrentCount, + LocalApic.DivideConfiguration); + + // + // Print the ISR, TMR and IRR + // + ShowMessages("ISR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + Reg = (UINT32)LocalApic.ISR[i * 4]; + for (j = 0; j < 32; j++) + { + if (0 != (Reg & k)) + { + ShowMessages("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + ShowMessages("\n"); + + ShowMessages("TMR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + Reg = (UINT32)LocalApic.TMR[i * 4]; + for (j = 0; j < 32; j++) + { + if (Reg & k) + { + ShowMessages("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + + ShowMessages("\n"); + + ShowMessages("IRR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + Reg = (UINT32)LocalApic.IRR[i * 4]; + for (j = 0; j < 32; j++) + { + if (Reg & k) + { + ShowMessages("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + + ShowMessages("\n"); +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/cpuid.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/cpuid.cpp similarity index 81% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/cpuid.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/cpuid.cpp index 7b1b2676..5475401a 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/cpuid.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/cpuid.cpp @@ -24,25 +24,28 @@ CommandCpuidHelp() ShowMessages("syntax : \t!cpuid [Eax (hex)] [pid ProcessId (hex)] [core CoreId (hex)] " "[imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] " - "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [condition { Condition (hex) }] " - "[code { Code (hex) }] [output {OutputName (string)}]\n"); + "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [asm condition { Condition (assembly/hex) }] " + "[asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !cpuid\n"); ShowMessages("\t\te.g : !cpuid 1\n"); ShowMessages("\t\te.g : !cpuid pid 400\n"); ShowMessages("\t\te.g : !cpuid core 2 pid 400\n"); + ShowMessages("\t\te.g : !cpuid script { printf(\"CPUID instruction is executed with the 'eax' register equal to: %%llx\\n\", @eax); }\n"); + ShowMessages("\t\te.g : !cpuid asm code { nop; nop; nop }\n"); } /** * @brief !cpuid command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandCpuid(vector SplitCommand, string Command) +CommandCpuid(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -54,7 +57,6 @@ CommandCpuid(vector SplitCommand, string Command) UINT32 ActionBreakToDebuggerLength = 0; UINT32 ActionCustomCodeLength = 0; UINT32 ActionScriptLength = 0; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // @@ -62,8 +64,7 @@ CommandCpuid(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, CPUID_INSTRUCTION_EXECUTION, &Event, &EventLength, @@ -81,23 +82,24 @@ CommandCpuid(vector SplitCommand, string Command) // // Interpret command specific details (if any), of CPUID EAX index // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!cpuid")) + if (CompareLowerCaseStrings(Section, "!cpuid")) { continue; } else if (!GetEax) { // - // It's probably an msr + // It's probably an index of EAX // - if (!ConvertStringToUInt64(Section, &SpecialTarget)) + if (!ConvertTokenToUInt64(Section, &SpecialTarget)) { // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandCpuidHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -116,7 +118,9 @@ CommandCpuid(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); + CommandCpuidHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/crwrite.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/crwrite.cpp similarity index 80% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/crwrite.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/crwrite.cpp index b7d4a35f..c0403f5c 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/crwrite.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/crwrite.cpp @@ -24,24 +24,27 @@ CommandCrwriteHelp() ShowMessages("syntax : \t!crwrite [Cr (hex)] [mask Mask (hex)] [pid ProcessId (hex)] " "[core CoreId (hex)] [imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] " "[stage CallingStage (prepostall)] [buffer PreAllocatedBuffer (hex)] [script { Script (string) }] " - "[condition { Condition (hex) }] [code { Code (hex) }] [output {OutputName (string)}]\n"); + "[asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !crwrite 0\n"); ShowMessages("\t\te.g : !crwrite 0 0x10000\n"); ShowMessages("\t\te.g : !crwrite 4 pid 400\n"); ShowMessages("\t\te.g : !crwrite 4 core 2 pid 400\n"); + ShowMessages("\t\te.g : !crwrite 4 script { printf(\"4th control register is modified at: %%llx\\n\", @rip); }\n"); + ShowMessages("\t\te.g : !crwrite 4 asm code { nop; nop; nop }\n"); } /** * @brief !crwrite command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandCrwrite(vector SplitCommand, string Command) +CommandCrwrite(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -55,12 +58,12 @@ CommandCrwrite(vector SplitCommand, string Command) UINT64 MaskRegister = 0xFFFFFFFFFFFFFFFF; BOOLEAN GetRegister = FALSE; BOOLEAN GetMask = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; - if (SplitCommand.size() < 2) + if (CommandTokens.size() < 2) { - ShowMessages("incorrect use of the '!crwrite'\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandCrwriteHelp(); return; } @@ -70,8 +73,7 @@ CommandCrwrite(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, CONTROL_REGISTER_MODIFIED, &Event, &EventLength, @@ -89,9 +91,9 @@ CommandCrwrite(vector SplitCommand, string Command) // // Interpret command specific details (if any) // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!crwrite")) + if (CompareLowerCaseStrings(Section, "!crwrite")) { continue; } @@ -100,12 +102,13 @@ CommandCrwrite(vector SplitCommand, string Command) // // It's probably a CR // - if (!ConvertStringToUInt64(Section, &TargetRegister)) + if (!ConvertTokenToUInt64(Section, &TargetRegister)) { // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandCrwriteHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -118,12 +121,13 @@ CommandCrwrite(vector SplitCommand, string Command) } else if (!GetMask) { - if (!ConvertStringToUInt64(Section, &MaskRegister)) + if (!ConvertTokenToUInt64(Section, &MaskRegister)) { // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandCrwriteHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -139,7 +143,8 @@ CommandCrwrite(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandCrwriteHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/dr.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/dr.cpp similarity index 84% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/dr.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/dr.cpp index bab93969..b74a95cb 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/dr.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/dr.cpp @@ -23,24 +23,27 @@ CommandDrHelp() ShowMessages("syntax : \t!dr [pid ProcessId (hex)] [core CoreId (hex)] " "[imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] " - "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [condition { Condition (hex) }] " - "[code { Code (hex) }] [output {OutputName (string)}]\n"); + "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [asm condition { Condition (assembly/hex) }] " + "[asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !dr\n"); ShowMessages("\t\te.g : !dr pid 400\n"); ShowMessages("\t\te.g : !dr core 2 pid 400\n"); + ShowMessages("\t\te.g : !dr script { printf(\"debug register modified!\\n\"); }\n"); + ShowMessages("\t\te.g : !dr asm code { nop; nop; nop }\n"); } /** * @brief !dr command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandDr(vector SplitCommand, string Command) +CommandDr(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -50,7 +53,6 @@ CommandDr(vector SplitCommand, string Command) UINT32 ActionBreakToDebuggerLength = 0; UINT32 ActionCustomCodeLength = 0; UINT32 ActionScriptLength = 0; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // @@ -58,8 +60,7 @@ CommandDr(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, DEBUG_REGISTERS_ACCESSED, &Event, &EventLength, @@ -77,9 +78,10 @@ CommandDr(vector SplitCommand, string Command) // // Check for size // - if (SplitCommand.size() > 1) + if (CommandTokens.size() > 1) { - ShowMessages("incorrect use of the '!dr'\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandDrHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/epthook.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/epthook.cpp similarity index 83% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/epthook.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/epthook.cpp index 0e0a695d..6eb15d88 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/epthook.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/epthook.cpp @@ -24,7 +24,7 @@ CommandEptHookHelp() ShowMessages( "syntax : \t!epthook [Address (hex)] [pid ProcessId (hex)] [core CoreId (hex)] " "[imm IsImmediate (yesno)] [buffer PreAllocatedBuffer (hex)] [script { Script (string) }] " - "[condition { Condition (hex) }] [code { Code (hex) }] [output {OutputName (string)}]\n"); + "[asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !epthook nt!ExAllocatePoolWithTag\n"); @@ -32,17 +32,20 @@ CommandEptHookHelp() ShowMessages("\t\te.g : !epthook fffff801deadb000\n"); ShowMessages("\t\te.g : !epthook fffff801deadb000 pid 400\n"); ShowMessages("\t\te.g : !epthook fffff801deadb000 core 2 pid 400\n"); + ShowMessages("\t\te.g : !epthook fffff801deadb000 script { printf(\"hook triggered at: %%llx\\n\", $context); }\n"); + ShowMessages("\t\te.g : !epthook fffff801deadb000 asm code { nop; nop; nop }\n"); } /** * @brief !epthook command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandEptHook(vector SplitCommand, string Command) +CommandEptHook(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -54,13 +57,13 @@ CommandEptHook(vector SplitCommand, string Command) UINT32 ActionScriptLength = 0; BOOLEAN GetAddress = FALSE; UINT64 OptionalParam1 = 0; // Set the target address - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - UINT32 IndexInCommandCaseSensitive = 0; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; - if (SplitCommand.size() < 2) + if (CommandTokens.size() < 2) { - ShowMessages("incorrect use of the '!epthook'\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandEptHookHelp(); return; } @@ -69,8 +72,7 @@ CommandEptHook(vector SplitCommand, string Command) // Interpret and fill the general event and action fields // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, HIDDEN_HOOK_EXEC_CC, &Event, &EventLength, @@ -100,11 +102,9 @@ CommandEptHook(vector SplitCommand, string Command) // // Interpret command specific details (if any) // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - IndexInCommandCaseSensitive++; - - if (!Section.compare("!epthook")) + if (CompareLowerCaseStrings(Section, "!epthook")) { continue; } @@ -114,14 +114,14 @@ CommandEptHook(vector SplitCommand, string Command) // It's probably address // if (!SymbolConvertNameOrExprToAddress( - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1), + GetCaseSensitiveStringFromCommandToken(Section), &OptionalParam1)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1).c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandEptHookHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -137,7 +137,8 @@ CommandEptHook(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandEptHookHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/epthook2.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/epthook2.cpp similarity index 83% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/epthook2.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/epthook2.cpp index 9db12be7..73b3c0c6 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/epthook2.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/epthook2.cpp @@ -24,7 +24,7 @@ CommandEptHook2Help() ShowMessages( "syntax : \t!epthook2 [Address (hex)] [pid ProcessId (hex)] " "[core CoreId (hex)] [imm IsImmediate (yesno)] [buffer PreAllocatedBuffer (hex)] " - "[script { Script (string) }] [condition { Condition (hex) }] [code { Code (hex) }] " + "[script { Script (string) }] [asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] " "[output {OutputName (string)}]\n"); ShowMessages("\n"); @@ -33,17 +33,20 @@ CommandEptHook2Help() ShowMessages("\t\te.g : !epthook2 fffff801deadb000\n"); ShowMessages("\t\te.g : !epthook2 fffff801deadb000 pid 400\n"); ShowMessages("\t\te.g : !epthook2 fffff801deadb000 core 2 pid 400\n"); + ShowMessages("\t\te.g : !epthook2 fffff801deadb000 script { printf(\"hook triggered at: %%llx\\n\", $context); }\n"); + ShowMessages("\t\te.g : !epthook2 fffff801deadb000 asm code { nop; nop; nop }\n"); } /** * @brief !epthook2 command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandEptHook2(vector SplitCommand, string Command) +CommandEptHook2(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -55,13 +58,13 @@ CommandEptHook2(vector SplitCommand, string Command) UINT32 ActionScriptLength = 0; BOOLEAN GetAddress = FALSE; UINT64 OptionalParam1 = 0; // Set the target address - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - UINT32 IndexInCommandCaseSensitive = 0; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; - if (SplitCommand.size() < 2) + if (CommandTokens.size() < 2) { - ShowMessages("incorrect use of the '!epthook2'\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandEptHook2Help(); return; } @@ -70,8 +73,7 @@ CommandEptHook2(vector SplitCommand, string Command) // Interpret and fill the general event and action fields // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, HIDDEN_HOOK_EXEC_DETOURS, &Event, &EventLength, @@ -101,11 +103,9 @@ CommandEptHook2(vector SplitCommand, string Command) // // Interpret command specific details (if any) // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - IndexInCommandCaseSensitive++; - - if (!Section.compare("!epthook2")) + if (CompareLowerCaseStrings(Section, "!epthook2")) { continue; } @@ -115,14 +115,14 @@ CommandEptHook2(vector SplitCommand, string Command) // It's probably address // if (!SymbolConvertNameOrExprToAddress( - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1), + GetCaseSensitiveStringFromCommandToken(Section), &OptionalParam1)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1).c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandEptHook2Help(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -138,7 +138,8 @@ CommandEptHook2(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandEptHook2Help(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/exception.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/exception.cpp similarity index 84% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/exception.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/exception.cpp index ac341d1a..1e58bd95 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/exception.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/exception.cpp @@ -26,26 +26,29 @@ CommandExceptionHelp() "syntax : \t!exception [IdtIndex (hex)] [pid ProcessId (hex)] " "[core CoreId (hex)] [imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] " "[stage CallingStage (prepostall)] [buffer PreAllocatedBuffer (hex)] [script { Script (string) }] " - "[condition { Condition (hex) }] [code { Code (hex) }] [output {OutputName (string)}]\n"); + "[asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); - ShowMessages("\nnote: monitoring page-faults (entry 0xe) is implemented differently.\n"); + ShowMessages("\nnote: monitoring page-faults (entry 0xe) is implemented differently (for more information, check the documentation).\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !exception\n"); ShowMessages("\t\te.g : !exception 0xe\n"); ShowMessages("\t\te.g : !exception pid 400\n"); ShowMessages("\t\te.g : !exception core 2 pid 400\n"); + ShowMessages("\t\te.g : !exception 0xe stage post script { printf(\"page-fault occurred at: %%llx\\n\", @cr2); }\n"); + ShowMessages("\t\te.g : !exception asm code { nop; nop; nop }\n"); } /** * @brief !exception command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandException(vector SplitCommand, string Command) +CommandException(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -57,7 +60,6 @@ CommandException(vector SplitCommand, string Command) UINT32 ActionScriptLength = 0; UINT64 SpecialTarget = DEBUGGER_EVENT_EXCEPTIONS_ALL_FIRST_32_ENTRIES; BOOLEAN GetEntry = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // @@ -65,8 +67,7 @@ CommandException(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, EXCEPTION_OCCURRED, &Event, &EventLength, @@ -84,9 +85,9 @@ CommandException(vector SplitCommand, string Command) // // Interpret command specific details (if any) // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!exception")) + if (CompareLowerCaseStrings(Section, "!exception")) { continue; } @@ -95,12 +96,13 @@ CommandException(vector SplitCommand, string Command) // // It's probably an index // - if (!ConvertStringToUInt64(Section, &SpecialTarget)) + if (!ConvertTokenToUInt64(Section, &SpecialTarget)) { // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandExceptionHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -132,7 +134,8 @@ CommandException(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandExceptionHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/hide.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/hide.cpp new file mode 100644 index 00000000..1675d709 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/hide.cpp @@ -0,0 +1,492 @@ +/** + * @file hide.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @author jtaw5649 + * @brief !hide command + * @details + * @version 0.1 + * @date 2020-07-07 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsVmmModuleLoaded; +extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; + +/** + * @brief help of the !hide command + * + * @return VOID + */ +VOID +CommandHideHelp() +{ + ShowMessages("!hide : tries to make HyperDbg transparent from anti-debugging " + "and anti-hypervisor methods.\n\n"); + + ShowMessages("syntax : \t!hide\n"); + ShowMessages("syntax : \t!hide [pid ProcessId (hex)]\n"); + ShowMessages("syntax : \t!hide [name ProcessName (string)]\n"); + + ShowMessages("note : \tprocess names are case sensitive and you can use " + "this command multiple times.\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !hide\n"); + ShowMessages("\t\te.g : !hide pid b60 \n"); + ShowMessages("\t\te.g : !hide name procexp.exe\n"); +} + +/** + * @brief This function is called when the user wants to hide the fill system calls + * in the transparent mode based on current system call numbers + * + * @param SyscallNumberDetails + * @return BOOLEAN + */ +BOOLEAN +CommandHideFillSystemCalls(SYSTEM_CALL_NUMBERS_INFORMATION * SyscallNumberDetails) +{ + BOOLEAN Result = TRUE; + + // + // Get the syscall number of NtQuerySystemInformation + // + SyscallNumberDetails->SysNtQuerySystemInformation = PeGetSyscallNumber("NtQuerySystemInformation"); + + if (SyscallNumberDetails->SysNtQuerySystemInformation == 0) + { + ShowMessages("warning, failed to get NtQuerySystemInformation syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtQuerySystemInformationEx + // + SyscallNumberDetails->SysNtQuerySystemInformationEx = PeGetSyscallNumber("NtQuerySystemInformationEx"); + + if (SyscallNumberDetails->SysNtQuerySystemInformationEx == 0) + { + ShowMessages("warning, failed to get NtQuerySystemInformationEx syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtSystemDebugControl + // + SyscallNumberDetails->SysNtSystemDebugControl = PeGetSyscallNumber("NtSystemDebugControl"); + + if (SyscallNumberDetails->SysNtSystemDebugControl == 0) + { + ShowMessages("warning, failed to get NtSystemDebugControl syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtQueryAttributesFile + // + SyscallNumberDetails->SysNtQueryAttributesFile = PeGetSyscallNumber("NtQueryAttributesFile"); + + if (SyscallNumberDetails->SysNtQueryAttributesFile == 0) + { + ShowMessages("warning, failed to get NtQueryAttributesFile syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtOpenDirectoryObject + // + SyscallNumberDetails->SysNtOpenDirectoryObject = PeGetSyscallNumber("NtOpenDirectoryObject"); + + if (SyscallNumberDetails->SysNtOpenDirectoryObject == 0) + { + ShowMessages("warning, failed to get NtOpenDirectoryObject syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtQueryDirectoryObject + // + SyscallNumberDetails->SysNtQueryDirectoryObject = PeGetSyscallNumber("NtQueryDirectoryObject"); + + if (SyscallNumberDetails->SysNtQueryDirectoryObject == 0) + { + ShowMessages("warning, failed to get NtQueryDirectoryObject syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtQueryInformationProcess + // + SyscallNumberDetails->SysNtQueryInformationProcess = PeGetSyscallNumber("NtQueryInformationProcess"); + + if (SyscallNumberDetails->SysNtQueryInformationProcess == 0) + { + ShowMessages("warning, failed to get NtQueryInformationProcess syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtSetInformationProcess + // + SyscallNumberDetails->SysNtSetInformationProcess = PeGetSyscallNumber("NtSetInformationProcess"); + + if (SyscallNumberDetails->SysNtSetInformationProcess == 0) + { + ShowMessages("warning, failed to get NtSetInformationProcess syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtQueryInformationThread + // + SyscallNumberDetails->SysNtQueryInformationThread = PeGetSyscallNumber("NtQueryInformationThread"); + + if (SyscallNumberDetails->SysNtQueryInformationThread == 0) + { + ShowMessages("warning, failed to get NtQueryInformationThread syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtSetInformationThread + // + SyscallNumberDetails->SysNtSetInformationThread = PeGetSyscallNumber("NtSetInformationThread"); + + if (SyscallNumberDetails->SysNtSetInformationThread == 0) + { + ShowMessages("warning, failed to get NtSetInformationThread syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtOpenFile + // + SyscallNumberDetails->SysNtOpenFile = PeGetSyscallNumber("NtOpenFile"); + + if (SyscallNumberDetails->SysNtOpenFile == 0) + { + ShowMessages("warning, failed to get NtOpenFile syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtOpenKey + // + SyscallNumberDetails->SysNtOpenKey = PeGetSyscallNumber("NtOpenKey"); + + if (SyscallNumberDetails->SysNtOpenKey == 0) + { + ShowMessages("warning, failed to get NtOpenKey syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtOpenKeyEx + // + SyscallNumberDetails->SysNtOpenKeyEx = PeGetSyscallNumber("NtOpenKeyEx"); + + if (SyscallNumberDetails->SysNtOpenKeyEx == 0) + { + ShowMessages("warning, failed to get NtOpenKeyEx syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtQueryValueKey + // + SyscallNumberDetails->SysNtQueryValueKey = PeGetSyscallNumber("NtQueryValueKey"); + + if (SyscallNumberDetails->SysNtQueryValueKey == 0) + { + ShowMessages("warning, failed to get NtQueryValueKey syscall number for transparent-mode\n"); + Result = FALSE; + } + + // + // Get the syscall number of NtEnumerateKey + // + SyscallNumberDetails->SysNtEnumerateKey = PeGetSyscallNumber("NtEnumerateKey"); + + if (SyscallNumberDetails->SysNtEnumerateKey == 0) + { + ShowMessages("warning, failed to get NtEnumerateKey syscall number for transparent-mode\n"); + Result = FALSE; + } + + return Result; +} + +/** + * @brief Enable transparent mode + * @param ProcessId + * @param ProcessName + * @param IsProcessId + * @param EvadeMask + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgEnableTransparentModeEx(UINT32 ProcessId, CHAR * ProcessName, BOOLEAN IsProcessId, UINT32 EvadeMask) +{ + BOOLEAN Status; + ULONG ReturnedLength; + DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE HideRequest = {0}; + PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE FinalRequestBuffer = 0; + SIZE_T RequestBufferSize = 0; + UINT32 EffectiveEvadeMask = EvadeMask == 0 ? TRANSPARENT_EVADE_MASK_DEFAULT : EvadeMask; + + // + // Check if debugger is loaded or not + // + // AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // We wanna hide the debugger and make transparent vm-exits + // + if ((EffectiveEvadeMask & ~TRANSPARENT_EVADE_MASK_ALL) != 0) + { + ShowMessages("unknown transparent-mode evade mask bits\n"); + return FALSE; + } + + HideRequest.IsHide = TRUE; + HideRequest.EvadeMask = EffectiveEvadeMask; + + HideRequest.TrueIfProcessIdAndFalseIfProcessName = IsProcessId; + + if (IsProcessId) + { + // + // It's a process id + // + HideRequest.ProcId = (UINT32)ProcessId; + + RequestBufferSize = sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE); + } + else + { + // + // It's a process name + // + HideRequest.LengthOfProcessName = (UINT32)strlen(ProcessName) + 1; + RequestBufferSize = sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE) + HideRequest.LengthOfProcessName; + } + + if ((EffectiveEvadeMask & TRANSPARENT_EVADE_MASK_SYSCALL_HOOK) != 0 && + !CommandHideFillSystemCalls(&HideRequest.SystemCallNumbersInformation)) + { + ShowMessages("warning, failed to resolve one or more syscall numbers for transparent-mode\n"); + return FALSE; + } + + // + // Allocate the requested buffer + // + FinalRequestBuffer = (PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE)malloc(RequestBufferSize); + + if (FinalRequestBuffer == NULL) + { + ShowMessages("insufficient space\n"); + return FALSE; + } + + // + // Zero the memory + // + RtlZeroMemory(FinalRequestBuffer, RequestBufferSize); + + // + // Copy the buffer on the top of the final buffer + // to send the kernel + // + memcpy(FinalRequestBuffer, &HideRequest, sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE)); + + // + // If it's a name then we should add it to the end of the buffer + // + if (!IsProcessId) + { + CHAR * ProcName = ProcessName; + + memcpy(((UINT64 *)((UINT64)FinalRequestBuffer + sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE))), + ProcName, + HideRequest.LengthOfProcessName); + } + + // + // Send the request to the kernel + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_DEBUGGER_HIDE_AND_UNHIDE_TO_TRANSPARENT_THE_DEBUGGER, // IO Control + // code + FinalRequestBuffer, // Input Buffer to driver. + (DWORD)RequestBufferSize, // Input buffer length + FinalRequestBuffer, // Output Buffer from driver. + SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE, // Length of output + // buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + free(FinalRequestBuffer); + return FALSE; + } + + if (FinalRequestBuffer->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + ShowMessages("transparent debugging successfully enabled :)\n"); + } + else if (FinalRequestBuffer->KernelStatus == DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER) + { + ShowMessages("unable to hide the debugger (transparent-debugging) :(\n"); + free(FinalRequestBuffer); + return FALSE; + } + else + { + ShowMessages("unknown error occurred :(\n"); + free(FinalRequestBuffer); + return FALSE; + } + + // + // free the buffer + // + free(FinalRequestBuffer); + + // + // It means the transparent mode enabled successfully + // + return TRUE; +} + +/** + * @brief Enable transparent mode + * @param ProcessId + * @param ProcessName + * @param IsProcessId + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgEnableTransparentMode(UINT32 ProcessId, CHAR * ProcessName, BOOLEAN IsProcessId) +{ + return HyperDbgEnableTransparentModeEx(ProcessId, ProcessName, IsProcessId, 0); +} + +/** + * @brief !hide command handler + * + * @param CommandTokens + * @param Command + * @return VOID + */ +VOID +CommandHide(vector CommandTokens, string Command) +{ + UINT32 TargetPid; + BOOLEAN TrueIfProcessIdAndFalseIfProcessName; + +#if ActivateHyperEvadeProject != TRUE + + ShowMessages("warning, the !hide command (hyperevade project) is in the Beta phase and is not yet well-tested, " + "so it is disabled in this version. If you want to test, you can enable it " + "from the configuration file (set ActivateHyperEvadeProject to TRUE) and recompile HyperDbg\n\n"); + return; + +#endif + + if (CommandTokens.size() != 1 && CommandTokens.size() != 3) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandHideHelp(); + return; + } + + // + // Find out whether the user enters pid or name + // + if (CommandTokens.size() == 1) + { + if (g_ActiveProcessDebuggingState.IsActive) + { + TrueIfProcessIdAndFalseIfProcessName = TRUE; + TargetPid = g_ActiveProcessDebuggingState.ProcessId; + } + else + { + // + // There is no user-debugging process + // + ShowMessages("you're not attached to any user-mode process, " + "please explicitly specify the process id or process name\n\n"); + CommandHideHelp(); + return; + } + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "pid")) + { + TrueIfProcessIdAndFalseIfProcessName = TRUE; + + // + // Check for the user to not add extra arguments + // + if (CommandTokens.size() != 3) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandHideHelp(); + return; + } + + // + // It's just a pid for the process + // + if (!ConvertTokenToUInt32(CommandTokens.at(2), &TargetPid)) + { + ShowMessages("incorrect process id\n\n"); + return; + } + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "name")) + { + TrueIfProcessIdAndFalseIfProcessName = FALSE; + } + else + { + // + // Invalid argument for the second parameter to the command + // + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandHideHelp(); + return; + } + + // + // Enable the transparent mode + // + if (TrueIfProcessIdAndFalseIfProcessName) + { + HyperDbgEnableTransparentMode(TargetPid, + NULL, + TRUE); + } + else + { + HyperDbgEnableTransparentMode(NULL, + (CHAR *)GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str(), + FALSE); + } +} diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/idt.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/idt.cpp new file mode 100644 index 00000000..69e117fd --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/idt.cpp @@ -0,0 +1,238 @@ +/** + * @file idt.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !idt command + * @details + * @version 0.12 + * @date 2024-12-30 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_AddressConversion; + +/** + * @brief help of the !idt command + * + * @return VOID + */ +VOID +CommandIdtHelp() +{ + ShowMessages("!ioapic : shows entries of Interrupt Descriptor Table (IDT).\n\n"); + + ShowMessages("syntax : \t!idt [IdtEntry (hex)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !idt\n"); + ShowMessages("\t\te.g : !idt 1d\n"); +} + +/** + * @brief Send IDT entry requests + * + * @param IdtPacket + * + * @return VOID + */ +BOOLEAN +HyperDbgGetIdtEntry(INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS * IdtPacket) +{ + BOOL Status; + ULONG ReturnedLength; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Send the request over serial kernel debugger + // + if (!KdSendQueryIdtPacketsToDebuggee(IdtPacket)) + { + return FALSE; + } + else + { + return TRUE; + } + } + else + { + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // Send IOCTL + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_QUERY_IDT_ENTRY, // IO Control Code (IOCTL) + IdtPacket, // Input Buffer to driver. + SIZEOF_INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS, // Input buffer length (not used in this case) + IdtPacket, // Output Buffer from driver. + SIZEOF_INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + + return FALSE; + } + + if (IdtPacket->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + return TRUE; + } + else + { + // + // An err occurred, no results + // + ShowErrorMessage(IdtPacket->KernelStatus); + + return FALSE; + } + } +} + +/** + * @brief !idt command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandIdt(vector CommandTokens, string Command) +{ + UINT32 IdtEntry; + INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS * IdtPacket = NULL; + BOOLEAN ShowAllEntries = TRUE; + UINT64 UsedBaseAddress = NULL; + + // + // Check if the command should show all entries or just one entry + // + if (CommandTokens.size() == 1) + { + ShowAllEntries = TRUE; + } + else if (CommandTokens.size() == 2) + { + ShowAllEntries = FALSE; + + // + // Get the IDT entry number + // + if (ConvertTokenToUInt32(CommandTokens.at(1), &IdtEntry) == FALSE) + { + ShowMessages("err, invalid IDT entry number\n"); + return; + } + + if (IdtEntry > MAX_NUMBER_OF_IDT_ENTRIES) + { + ShowMessages("err, invalid IDT entry number\n"); + return; + } + } + else + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + + CommandIdtHelp(); + return; + } + + // + // Allocate buffer for IDT entry + // + IdtPacket = (INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS *)malloc(sizeof(INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS)); + + if (IdtPacket == NULL) + { + ShowMessages("err, allocating buffer for receiving IDT entries"); + } + + RtlZeroMemory(IdtPacket, sizeof(INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS)); + + // + // Get the IDT buffer + // + if (HyperDbgGetIdtEntry(IdtPacket) == TRUE) + { + // + // Show (dump) entries + // + if (ShowAllEntries) + { + ShowMessages("IDT Entries:\n\n"); + + for (UINT32 i = 0; i < MAX_NUMBER_OF_IDT_ENTRIES; i++) + { + ShowMessages("IDT[0x%x:%d]\t: %s\t", + i, + i, + SeparateTo64BitValue(IdtPacket->IdtEntry[i]).c_str()); + + // + // Apply addressconversion of settings here + // + if (g_AddressConversion) + { + // + // Showing function names here + // + if (SymbolShowFunctionNameBasedOnAddress(IdtPacket->IdtEntry[i], &UsedBaseAddress)) + { + // + // The symbol address is showed (nothing to do) + // + } + } + + ShowMessages("\n"); + } + } + else + { + ShowMessages("IDT[0x%x:%d] : %s\t", + IdtEntry, + IdtEntry, + SeparateTo64BitValue(IdtPacket->IdtEntry[IdtEntry]).c_str()); + + // + // Apply addressconversion of settings here + // + if (g_AddressConversion) + { + // + // Showing function names here + // + if (SymbolShowFunctionNameBasedOnAddress(IdtPacket->IdtEntry[IdtEntry], &UsedBaseAddress)) + { + // + // The symbol address is showed (nothing to do) + // + } + + ShowMessages("\n"); + } + } + } + + // + // Deallocate the buffer + // + free(IdtPacket); +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/interrupt.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/interrupt.cpp similarity index 86% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/interrupt.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/interrupt.cpp index 56f13a01..ddd475b7 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/interrupt.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/interrupt.cpp @@ -24,7 +24,7 @@ CommandInterruptHelp() ShowMessages("syntax : \t[IdtIndex (hex)] [pid ProcessId (hex)] " "[core CoreId (hex)] [imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] " "[stage CallingStage (prepostall)] [buffer PreAllocatedBuffer (hex)] [script { Script (string) }] " - "[condition { Condition (hex) }] [code { Code (hex) }] [output {OutputName (string)}]\n"); + "[asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\nnote : The index should be greater than 0x20 (32) and less " "than 0xFF (255) - starting from zero.\n"); @@ -33,17 +33,20 @@ CommandInterruptHelp() ShowMessages("\t\te.g : !interrupt 0x2f\n"); ShowMessages("\t\te.g : !interrupt 0x2f pid 400\n"); ShowMessages("\t\te.g : !interrupt 0x2f core 2 pid 400\n"); + ShowMessages("\t\te.g : !interrupt 0xd1 script { printf(\"clock interrupt received at the core: %%x\\n\", $core); }\n"); + ShowMessages("\t\te.g : !interrupt 0x2f asm code { nop; nop; nop }\n"); } /** * @brief !interrupt command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandInterrupt(vector SplitCommand, string Command) +CommandInterrupt(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -55,7 +58,6 @@ CommandInterrupt(vector SplitCommand, string Command) UINT32 ActionScriptLength = 0; UINT64 SpecialTarget = 0; BOOLEAN GetEntry = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // @@ -63,8 +65,7 @@ CommandInterrupt(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, EXTERNAL_INTERRUPT_OCCURRED, &Event, &EventLength, @@ -83,9 +84,9 @@ CommandInterrupt(vector SplitCommand, string Command) // Interpret command specific details (if any) // // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!interrupt")) + if (CompareLowerCaseStrings(Section, "!interrupt")) { continue; } @@ -94,12 +95,13 @@ CommandInterrupt(vector SplitCommand, string Command) // // It's probably an index // - if (!ConvertStringToUInt64(Section, &SpecialTarget)) + if (!ConvertTokenToUInt64(Section, &SpecialTarget)) { // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandInterruptHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -131,7 +133,8 @@ CommandInterrupt(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandInterruptHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/ioapic.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/ioapic.cpp new file mode 100644 index 00000000..ab1f18b4 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/ioapic.cpp @@ -0,0 +1,234 @@ +/** + * @file ioapic.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !ioapic command + * @details + * @version 0.11 + * @date 2024-11-18 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief help of the !ioapic command + * + * @return VOID + */ +VOID +CommandIoapicHelp() +{ + ShowMessages("!ioapic : shows the details of I/O APIC entries.\n\n"); + + ShowMessages("syntax : \t!ioapic\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !ioapic\n"); +} + +/** + * @brief Request to get I/O APIC + * + * @param IolApic + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgGetIoApic(IO_APIC_ENTRY_PACKETS * IoApic) +{ + BOOLEAN IsUsingX2APIC; // not used since I/O APIC is accessed through memory (not MSR) + + return CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE_READ_IO_APIC, + IoApic, + sizeof(IO_APIC_ENTRY_PACKETS), + &IsUsingX2APIC); +} + +/** + * @brief Show redirections + * + * @param Desc + * @param CommandReg + * @param DestSelf + * @param Lh + * @param Ll + * + * @return ULONG + */ +ULONG +CommandIoapicShowRedir(PUCHAR Desc, + BOOLEAN CommandReg, + BOOLEAN DestSelf, + ULONGLONG Lh, + ULONGLONG Ll) +{ + static PUCHAR DelMode[] = { + (PUCHAR) "FixedDel", + (PUCHAR) "LowestDl", + (PUCHAR) "res010 ", + (PUCHAR) "remoterd", + (PUCHAR) "NMI ", + (PUCHAR) "RESET ", + (PUCHAR) "res110 ", + (PUCHAR) "ExtINTA "}; + + static PUCHAR DesShDesc[] = {(PUCHAR) "", + (PUCHAR) " Dest=Self", + (PUCHAR) " Dest=ALL", + (PUCHAR) " Dest=Othrs"}; + + ULONG Del, Dest, Delstat, Rirr, Trig, Masked, Destsh; + + Del = (Ll >> 8) & 0x7; + Dest = (Ll >> 11) & 0x1; + Delstat = (Ll >> 12) & 0x1; + Rirr = (Ll >> 14) & 0x1; + Trig = (Ll >> 15) & 0x1; + Masked = (Ll >> 16) & 0x1; + Destsh = (Ll >> 18) & 0x3; + + if (CommandReg) + { + // + // command reg's don't have a mask + // + Masked = 0; + } + + ShowMessages("%s: %s Vec:%02X %s ", + Desc, + SeparateTo64BitValue(Ll).c_str(), + Ll & 0xff, + DelMode[Del]); + + if (DestSelf) + { + ShowMessages("%s", DesShDesc[1]); + } + else if (CommandReg && Destsh) + { + ShowMessages("%s", DesShDesc[Destsh]); + } + else + { + if (Dest) + { + ShowMessages("Lg:%08x", Lh); + } + else + { + ShowMessages("PhysDest:%02X", (Lh >> 56) & 0xFF); + } + } + + ShowMessages("%s %s %s %s\n", + Delstat ? "-Pend" : " ", + Trig ? "level" : "edge ", + Rirr ? "rirr" : " ", + Masked ? "masked" : " "); + + return 0; +} + +/** + * @brief Show I/O APIC + * @param IoApicPackets + * + * @return VOID + */ +VOID +CommandIoapicShowIoApicEntries(IO_APIC_ENTRY_PACKETS * IoApicPackets) +{ + UINT32 Index = 0; + UINT32 Max; + UCHAR Desc[40]; + UINT64 ll, lh; + + UINT64 ApicBasePa = IoApicPackets->ApicBasePa; + + ll = IoApicPackets->IoLl; + + Max = (ll >> 16) & 0xff; + + ShowMessages("IoApic @ %08x ID:%x (%x) Arb:%x\t I/O APIC VA: %s\n", + ApicBasePa, + IoApicPackets->IoIdReg >> 24, + ll & 0xFF, + IoApicPackets->IoArbIdReg, + SeparateTo64BitValue(IoApicPackets->ApicBaseVa).c_str()); + + // + // Dump inti table + // + Max *= 2; + + for (Index = 0; Index <= Max; Index += 2) + { + if (Index >= MAX_NUMBER_OF_IO_APIC_ENTRIES) + { + // + // The buffer is now invalid + // + ShowMessages("err, there are additional entries in the I/O APIC that are not fully displayed in the results"); + return; + } + + ll = IoApicPackets->LlLhData[Index]; + lh = IoApicPackets->LlLhData[Index + 1]; + + sprintf((CHAR *)Desc, "Inti%02X.", Index / 2); + CommandIoapicShowRedir(Desc, FALSE, FALSE, lh, ll); + } +} + +/** + * @brief !ioapic command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandIoapic(vector CommandTokens, string Command) +{ + IO_APIC_ENTRY_PACKETS * IoApicPackets = NULL; + + if (CommandTokens.size() != 1) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + + CommandIoapicHelp(); + return; + } + + // + // Allocate buffer for I/O APIC + // + IoApicPackets = (IO_APIC_ENTRY_PACKETS *)malloc(sizeof(IO_APIC_ENTRY_PACKETS)); + + if (IoApicPackets == NULL) + { + ShowMessages("err, allocating buffer for receiving I/O APIC"); + } + + RtlZeroMemory(IoApicPackets, sizeof(IO_APIC_ENTRY_PACKETS)); + + // + // Get the I/O APIC buffer + // + if (HyperDbgGetIoApic(IoApicPackets) == TRUE) + { + // + // Show (dump) entries + // + CommandIoapicShowIoApicEntries(IoApicPackets); + } + + // + // Deallocate the buffer + // + free(IoApicPackets); +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/ioin.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/ioin.cpp similarity index 82% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/ioin.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/ioin.cpp index 64010a3c..48ad9f72 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/ioin.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/ioin.cpp @@ -24,25 +24,28 @@ CommandIoinHelp() ShowMessages("syntax : \t!ioin [Port (hex)] [pid ProcessId (hex)] [core CoreId (hex)] " "[imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] " - "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [condition { Condition (hex) }] " - "[code { Code (hex) }] [output {OutputName (string)}]\n"); + "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [asm condition { Condition (assembly/hex) }] " + "[asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !ioin\n"); ShowMessages("\t\te.g : !ioin 0x64\n"); ShowMessages("\t\te.g : !ioin pid 400\n"); ShowMessages("\t\te.g : !ioin core 2 pid 400\n"); + ShowMessages("\t\te.g : !ioin script { printf(\"IN instruction is executed at port: %%llx\\n\", $context); }\n"); + ShowMessages("\t\te.g : !ioin asm code { nop; nop; nop }\n"); } /** * @brief !ioin command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandIoin(vector SplitCommand, string Command) +CommandIoin(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -54,15 +57,13 @@ CommandIoin(vector SplitCommand, string Command) UINT32 ActionScriptLength = 0; UINT64 SpecialTarget = DEBUGGER_EVENT_ALL_IO_PORTS; BOOLEAN GetPort = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // // Interpret and fill the general event and action fields // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, IN_INSTRUCTION_EXECUTION, &Event, &EventLength, @@ -80,9 +81,9 @@ CommandIoin(vector SplitCommand, string Command) // // Interpret command specific details (if any) // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!ioin")) + if (CompareLowerCaseStrings(Section, "!ioin")) { continue; } @@ -91,12 +92,13 @@ CommandIoin(vector SplitCommand, string Command) // // It's probably an I/O port // - if (!ConvertStringToUInt64(Section, &SpecialTarget)) + if (!ConvertTokenToUInt64(Section, &SpecialTarget)) { // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandIoinHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -112,7 +114,8 @@ CommandIoin(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandIoinHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/ioout.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/ioout.cpp similarity index 82% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/ioout.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/ioout.cpp index 2c9dae53..05bafd92 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/ioout.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/ioout.cpp @@ -25,24 +25,27 @@ CommandIooutHelp() ShowMessages("syntax : \t!ioout [Port (hex)] [pid ProcessId (hex)] " "[core CoreId (hex)] [imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] " "[stage CallingStage (prepostall)] [buffer PreAllocatedBuffer (hex)] [script { Script (string) }] " - "[condition { Condition (hex) }] [code { Code (hex) }] [output {OutputName (string)}]\n"); + "[asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !ioout\n"); ShowMessages("\t\te.g : !ioout 0x64\n"); ShowMessages("\t\te.g : !ioout pid 400\n"); ShowMessages("\t\te.g : !ioout core 2 pid 400\n"); + ShowMessages("\t\te.g : !ioout script { printf(\"OUT instruction is executed at port: %%llx\\n\", $context); }\n"); + ShowMessages("\t\te.g : !ioout asm code { nop; nop; nop }\n"); } /** * @brief !ioout command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandIoout(vector SplitCommand, string Command) +CommandIoout(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -54,7 +57,6 @@ CommandIoout(vector SplitCommand, string Command) UINT32 ActionScriptLength = 0; UINT64 SpecialTarget = DEBUGGER_EVENT_ALL_IO_PORTS; BOOLEAN GetPort = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // @@ -62,8 +64,7 @@ CommandIoout(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, OUT_INSTRUCTION_EXECUTION, &Event, &EventLength, @@ -82,9 +83,9 @@ CommandIoout(vector SplitCommand, string Command) // Interpret command specific details (if any) // // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!ioout")) + if (CompareLowerCaseStrings(Section, "!ioout")) { continue; } @@ -93,12 +94,13 @@ CommandIoout(vector SplitCommand, string Command) // // It's probably an I/O port // - if (!ConvertStringToUInt64(Section, &SpecialTarget)) + if (!ConvertTokenToUInt64(Section, &SpecialTarget)) { // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandIooutHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -114,7 +116,8 @@ CommandIoout(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandIooutHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/lbr.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/lbr.cpp new file mode 100644 index 00000000..3d2718e8 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/lbr.cpp @@ -0,0 +1,384 @@ +/** + * @file lbr.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !lbr command + * @details + * @version 0.19 + * @date 2026-04-05 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern HANDLE g_DeviceHandle; +extern BOOLEAN g_IsHyperTraceModuleLoaded; + +/** + * @brief help of the !lbr command + * + * @return VOID + */ +VOID +CommandLbrHelp() +{ + ShowMessages("!lbr : performs operation for Last Branch Record (LBR).\n"); + ShowMessages("for dumping LBR entries, you can use the '!lbrdump' command\n"); + + ShowMessages("syntax : \t!lbr [Function (string)]\n"); + ShowMessages("syntax : \t!lbr [filter FilterOptions (string)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !lbr enable\n"); + ShowMessages("\t\te.g : !lbr disable\n"); + ShowMessages("\t\te.g : !lbr flush\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !lbr filter\n"); + ShowMessages("\t\te.g : !lbr filter kernel jcc ind_jmp rel_jmp far\n"); + ShowMessages("\t\te.g : !lbr filter kernel jcc return ind_jmp rel_jmp far\n"); + ShowMessages("\t\te.g : !lbr filter kernel jcc ind_jmp rel_jmp\n"); + ShowMessages("\t\te.g : !lbr filter user rel_call ind_call return far\n"); + ShowMessages("\t\te.g : !lbr filter call_stack user\n"); + ShowMessages("\t\te.g : !lbr filter call_stack kernel\n"); + + ShowMessages("\nlist of filter options: \n"); + ShowMessages("\t kernel: do not capture at ring0\n"); + ShowMessages("\t user: do not capture at ring > 0\n"); + ShowMessages("\t jcc: do not capture conditional branches\n"); + ShowMessages("\t rel_call: do not capture relative calls\n"); + ShowMessages("\t ind_call: do not capture indirect calls\n"); + ShowMessages("\t return: do not capture near returns\n"); + ShowMessages("\t ind_jmp: do not capture indirect jumps\n"); + ShowMessages("\t rel_jmp: do not capture relative jumps\n"); + ShowMessages("\t far: do not capture far branches (only in legacy LBR. check docs for details)\n"); + ShowMessages("\t other_branches: do not capture jmp/call ptr*, jmp/call m*, ret (0c8h), sys*, interrupts,\n"); + ShowMessages("\t exceptions (other than debug exceptions), iret, int3, intn, into, tsx abort\n"); + ShowMessages("\t eenter, eresume, eexit, aex, init, sipi, rsm (only in ARCH LBR. check docs for details)\n"); + ShowMessages("\t call_stack: enable LBR stack to use LIFO filtering to capture call stack profile\n"); + ShowMessages("\t not available on CPUs older than Haswell. for this item you can only specify the 'user'\n"); + ShowMessages("\t or the 'kernel'. it prevents all types of branches except calls and rets\n"); + ShowMessages("\t (no option): capture everything (default option)\n"); + + ShowMessages("\nnote 1: LBR is usually not supported (or is emulated) in nested virtualization (VM) environments\n"); + ShowMessages("note 2: LBR will be disabled if there is a debug-break (#DB) condition, such as the trap flags or\n"); + ShowMessages(" hardware debug registers (to learn how to mitigate this, check the documentation)\n"); +} + +/** + * @brief Send LBR requests + * + * @param LbrRequest + * + * @return VOID + */ +BOOLEAN +CommandLbrSendRequest(HYPERTRACE_LBR_OPERATION_PACKETS * LbrRequest) +{ + BOOL Status; + ULONG ReturnedLength; + + AssertShowMessageReturnStmt(g_IsHyperTraceModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_HYPERTRACE_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // Send IOCTL + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_PERFORM_HYPERTRACE_LBR_OPERATION, // IO Control Code (IOCTL) + LbrRequest, // Input Buffer to driver. + SIZEOF_HYPERTRACE_LBR_OPERATION_PACKETS, // Input buffer length + LbrRequest, // Output Buffer from driver. + SIZEOF_HYPERTRACE_LBR_OPERATION_PACKETS, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + + return FALSE; + } + + if (LbrRequest->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief Request to perform an LBR operation + * + * @param LbrRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgPerformLbrOperation(HYPERTRACE_LBR_OPERATION_PACKETS * LbrRequest) +{ + return CommandLbrSendRequest(LbrRequest); +} +/** + * @brief Parses simple (no-argument) LBR operations: enable, disable, flush + * + * @param CommandTokens + * @param LbrRequest + * + * @return BOOLEAN TRUE if parsed successfully + */ +BOOLEAN +CommandLbrParseSimpleOperation(vector CommandTokens, HYPERTRACE_LBR_OPERATION_PACKETS * LbrRequest) +{ + if (CommandTokens.size() != 2) + { + return FALSE; + } + + if (CompareLowerCaseStrings(CommandTokens.at(1), "enable")) + { + LbrRequest->LbrOperationType = HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_ENABLE; + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "disable")) + { + LbrRequest->LbrOperationType = HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_DISABLE; + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "flush")) + { + LbrRequest->LbrOperationType = HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_FLUSH; + } + else + { + return FALSE; + } + + return TRUE; +} + +/** + * @brief Check validity of the filter options in case of call_stack mode + * + * @param LbrRequest + * @return BOOLEAN TRUE if the filter options are valid in case of call_stack mode + */ +BOOLEAN +CommandLbrValidateCallStackFilterOptions(HYPERTRACE_LBR_OPERATION_PACKETS * LbrRequest) +{ + if (LbrRequest->LbrFilterOptions & LBR_CALL_STACK) + { + // + // Call-stack mode should be used with branch type enabling configured to capture only CALLs (NEAR_REL_CALL and + // NEAR_IND_CALL) and RETs (NEAR_RET). if the user specifed LBR_REL_CALL | LBR_IND_CALL | LBR_RETURN then + // it is invalid + // + if ((LbrRequest->LbrFilterOptions & (LBR_REL_CALL | LBR_IND_CALL | LBR_RETURN))) + { + ShowMessages("err, invalid filter options for 'call_stack' mode. when the 'call_stack' is enabled," + " 'rel_call', 'ind_call', and 'return' could not be specified as filter options\n\n"); + return FALSE; + } + } + return TRUE; +} + +/** + * @brief Parses the LBR filter operation and accumulates filter option flags + * + * @param CommandTokens + * @param LbrRequest + * + * @return BOOLEAN TRUE if parsed successfully + */ +BOOLEAN +CommandLbrParseFilterOperation(vector CommandTokens, HYPERTRACE_LBR_OPERATION_PACKETS * LbrRequest) +{ + LbrRequest->LbrOperationType = HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_FILTER; + LbrRequest->LbrFilterOptions = 0; // no options = capture everything + + for (SIZE_T i = 2; i < CommandTokens.size(); i++) + { + if (CompareLowerCaseStrings(CommandTokens.at(i), "kernel")) + { + LbrRequest->LbrFilterOptions |= LBR_KERNEL; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "user")) + { + LbrRequest->LbrFilterOptions |= LBR_USER; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "jcc")) + { + LbrRequest->LbrFilterOptions |= LBR_JCC; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "rel_call")) + { + LbrRequest->LbrFilterOptions |= LBR_REL_CALL; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "ind_call")) + { + LbrRequest->LbrFilterOptions |= LBR_IND_CALL; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "return")) + { + LbrRequest->LbrFilterOptions |= LBR_RETURN; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "ind_jmp")) + { + LbrRequest->LbrFilterOptions |= LBR_IND_JMP; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "rel_jmp")) + { + LbrRequest->LbrFilterOptions |= LBR_REL_JMP; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "far") || + CompareLowerCaseStrings(CommandTokens.at(i), "other_branch") || + CompareLowerCaseStrings(CommandTokens.at(i), "other_branches")) + { + LbrRequest->LbrFilterOptions |= LBR_FAR_OTHER_BRANCHES; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "call_stack")) + { + LbrRequest->LbrFilterOptions |= LBR_CALL_STACK; + } + else + { + ShowMessages("unknown filter option '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + return FALSE; + } + } + + // + // Call-stack mode should be used with branch type enabling configured to capture only CALLs (NEAR_REL_CALL and + // NEAR_IND_CALL) and RETs (NEAR_RET). When configured in this manner, the LBR array emulates a call stack, + // where CALLs are "pushed" and RETs "pop" them off the stack. If other branch types (JCC, NEAR_*_JMP, or + // OTHER_BRANCH) are enabled for recording with call-stack mode, LBR behavior may be undefined, so we will + // mask out any branch type filters that are not CALLs or RETs when call-stack mode is requested to ensure + // we are correctly emulating a call stack and avoiding undefined behavior + // + + // + // If it is call_stack then we only keep the user and kernel bit and filter all branch types + // except calls and rets to ensure we are only capturing call stack profile + // + if (LbrRequest->LbrFilterOptions & LBR_CALL_STACK) + { + // + // Validate the filter options in case of call_stack mode + // + if (CommandLbrValidateCallStackFilterOptions(LbrRequest) == FALSE) + { + return FALSE; + } + + // + // Preserve only the user/kernel privilege bits from the original options, + // then apply the mandatory call stack base flags + // + LbrRequest->LbrFilterOptions = LBR_CALL_STACK_BASE_FLAGS | (LbrRequest->LbrFilterOptions & (LBR_KERNEL | LBR_USER)); + } + + return TRUE; +} + +/** + * @brief Displays the success message appropriate for the completed LBR operation + * + * @param LbrRequest + * + * @return VOID + */ +VOID +CommandLbrShowSuccessMessage(const HYPERTRACE_LBR_OPERATION_PACKETS * LbrRequest) +{ + switch (LbrRequest->LbrOperationType) + { + case HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_ENABLE: + ShowMessages("LBR enabled successfully\n"); + break; + case HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_DISABLE: + ShowMessages("LBR disabled successfully\n"); + break; + case HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_FLUSH: + ShowMessages("LBR branches are flushed\n"); + break; + case HYPERTRACE_LBR_OPERATION_REQUEST_TYPE_FILTER: + ShowMessages("LBR filter options are updated successfully\n"); + break; + default: + ShowMessages("unknown LBR operation type\n"); + break; + } +} + +/** + * @brief !lbr command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandLbr(vector CommandTokens, string Command) +{ + HYPERTRACE_LBR_OPERATION_PACKETS LbrRequest = {0}; + BOOLEAN ParseResult = FALSE; + + if (CommandTokens.size() == 1) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandLbrHelp(); + return; + } + + // + // Dispatch to the appropriate parser based on the subcommand + // + if (CompareLowerCaseStrings(CommandTokens.at(1), "enable") || + CompareLowerCaseStrings(CommandTokens.at(1), "disable") || + CompareLowerCaseStrings(CommandTokens.at(1), "flush")) + { + ParseResult = CommandLbrParseSimpleOperation(CommandTokens, &LbrRequest); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "filter")) + { + ParseResult = CommandLbrParseFilterOperation(CommandTokens, &LbrRequest); + } + else + { + ParseResult = FALSE; + } + + if (!ParseResult) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandLbrHelp(); + return; + } + + // + // Check if the HyperTrace module is loaded, as it is required for LBR operations + // + AssertShowMessageReturnStmt(g_IsHyperTraceModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_HYPERTRACE_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + + // + // Send the LBR operation request + // + if (CommandLbrSendRequest(&LbrRequest)) + { + CommandLbrShowSuccessMessage(&LbrRequest); + } + else + { + ShowErrorMessage(LbrRequest.KernelStatus); + } +} diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/lbrdump.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/lbrdump.cpp new file mode 100644 index 00000000..6df20e4a --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/lbrdump.cpp @@ -0,0 +1,351 @@ +/** + * @file lbrdump.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !lbrdump command + * @details + * @version 0.19 + * @date 2026-05-03 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsHyperTraceModuleLoaded; +extern BOOLEAN g_IsHyperTraceModuleLoaded; + +/** + * @brief Send LBR dump requests + * + * @param LbrdumpRequest + * + * @return VOID + */ +BOOLEAN +HyperDbgLbrdumpSendRequest(HYPERTRACE_LBR_DUMP_PACKETS * LbrdumpRequest) +{ + BOOL Status; + ULONG ReturnedLength; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Send the request over serial kernel debugger + // + if (!KdSendHyperTraceLbrdumpPacketsToDebuggee(LbrdumpRequest, SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS)) + { + return FALSE; + } + } + else + { + AssertShowMessageReturnStmt(g_IsHyperTraceModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_HYPERTRACE_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // Send IOCTL + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_PERFORM_HYPERTRACE_LBR_DUMP, // IO Control Code (IOCTL) + LbrdumpRequest, // Input Buffer to driver. + SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS, // Input buffer length + LbrdumpRequest, // Output Buffer from driver. + SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + + return FALSE; + } + } + + // + // Sending the request was successful + // + return TRUE; +} + +/** + * @brief help of the !lbrdump command + * + * @return VOID + */ +VOID +CommandLbrdumpHelp() +{ + ShowMessages("!lbrdump : dumps Last Branch Record (LBR).\n"); + ShowMessages("for using this command, you should configure it using the '!lbr' command\n"); + + ShowMessages("syntax : \t!lbrdump [core CoreId (hex)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !lbrdump\n"); + ShowMessages("\t\te.g : !lbrdump core 1\n"); +} + +/** + * @brief Get the branch type name based on the LBR branch type value (only applicable for architectural LBR) + * + * @details THIS FUNCTION IS ALSO IMPLEMENTED IN THE USER MODE + * + * @param BrType The raw branch type value from the LBR info MSR + * @param BrTypeName A character buffer to receive the branch type name string + * + * @return VOID + */ +VOID +CommandLbrdumpGetArchBranchTypet(UINT32 BrType, CHAR * BrTypeName) +{ + if (BrType == LBR_BR_TYPE_COND) + { + strncpy(BrTypeName, "COND ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType == LBR_BR_TYPE_JMP_INDIRECT) + { + strncpy(BrTypeName, "JMP Indirect ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType == LBR_BR_TYPE_JMP_DIRECT) + { + strncpy(BrTypeName, "JMP Direct ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType == LBR_BR_TYPE_CALL_INDIRECT) + { + strncpy(BrTypeName, "CALL Indirect", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType == LBR_BR_TYPE_CALL_DIRECT) + { + strncpy(BrTypeName, "CALL Direct ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType == LBR_BR_TYPE_RET) + { + strncpy(BrTypeName, "RET ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType >= LBR_BR_TYPE_RESERVED_MIN && BrType <= LBR_BR_TYPE_RESERVED_MAX) + { + strncpy(BrTypeName, "Reserved ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else if (BrType >= LBR_BR_TYPE_OTHER_MIN && BrType <= LBR_BR_TYPE_OTHER_MAX) + { + strncpy(BrTypeName, "Other Branch ", LBR_BR_TYPE_NAME_MAX_LEN); + } + else + { + strncpy(BrTypeName, "Unknown ", LBR_BR_TYPE_NAME_MAX_LEN); + } +} + +/** + * @brief Print collected LBR branches + * + * @param LbrdumpRequest + * + * @return VOID + */ +VOID +CommandLbrdumpPrint(HYPERTRACE_LBR_DUMP_PACKETS * LbrdumpRequest) +{ + ULONG CurrentIdx; + BOOLEAN IsCoreEmpty = TRUE; + CHAR BrTypeName[LBR_BR_TYPE_NAME_MAX_LEN] = {0}; + UINT32 BrType = 0; + + ShowMessages("LBR Chronological Trace on core: 0x%x\n\n", LbrdumpRequest->CoreId); + + for (ULONG i = 1; i <= LbrdumpRequest->CurrentLbrCapacity; i++) + { + if (LbrdumpRequest->ArchBasedLBR) + { + // + // In ARCH LBR, there is not TOS index and everything is in order + // + CurrentIdx = i - 1; + } + else + { + CurrentIdx = (ULONG)(LbrdumpRequest->LbrStack.Tos + i) % (ULONG)LbrdumpRequest->CurrentLbrCapacity; + } + + if (LbrdumpRequest->LbrStack.BranchEntry[CurrentIdx].From == 0) + { + continue; + } + + IsCoreEmpty = FALSE; + + if (LbrdumpRequest->ArchBasedLBR) + { + BrType = (UINT32)LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].BrType_OnlyArchLbr; + + // + // Get the branch type name for better readability when printing + // + CommandLbrdumpGetArchBranchTypet(BrType, BrTypeName); + + // + // Architectural LBR + // + ShowMessages("\t [%2u] Branch Mispredicted: %s, Branch type: %s, Cycle Count (Decimal): %04d (is valid? %s) - From: %016llx To: %016llx\n", + CurrentIdx, + LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].Mispred ? "true " : "false", + BrTypeName, + LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].CycleCount, + LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].CycCntValid_OnlyArchLbr ? "true " : "false", + LbrdumpRequest->LbrStack.BranchEntry[CurrentIdx].From, + LbrdumpRequest->LbrStack.BranchEntry[CurrentIdx].To); + } + else + { + // + // Legacy LBR + // + ShowMessages("\t [%2u] Branch Mispredicted: %s, Cycle Count (Decimal): %04d - From: %016llx To: %016llx\n", + CurrentIdx, + LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].Mispred ? "true " : "false", + LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].CycleCount, + LbrdumpRequest->LbrStack.BranchEntry[CurrentIdx].From, + LbrdumpRequest->LbrStack.BranchEntry[CurrentIdx].To); + } + } + + if (IsCoreEmpty) + { + ShowMessages("\t no LBR entries found for this core\n" + "\t you can use the 'lbr_save();' function in the script engine\n" + "\t on the target core to save the LBR entries before dumping\n\n" + "\t ===========================================================\n\n"); + } + else + { + ShowMessages("\n\t ===========================================================\n\n"); + } +} + +/** + * @brief !lbrdump command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandLbrdump(vector CommandTokens, string Command) +{ + HYPERTRACE_LBR_DUMP_PACKETS LbrdumpRequest = {0}; + UINT32 CoreId = 0; + BOOLEAN ContinueDumpingAllCores = TRUE; + + if (CommandTokens.size() != 1 && CommandTokens.size() != 3) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandLbrdumpHelp(); + return; + } + + // + // Check if the HyperTrace module is loaded, as it is required for LBR operations + // + AssertShowMessageReturnStmt(g_IsHyperTraceModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_HYPERTRACE_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + + if (CommandTokens.size() == 3) + { + if (CompareLowerCaseStrings(CommandTokens.at(1), "core")) + { + if (!ConvertTokenToUInt32(CommandTokens.at(2), &CoreId)) + { + // + // Unknown parameter + // + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandLbrdumpHelp(); + + return; + } + } + else + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandLbrdumpHelp(); + return; + } + } + else + { + // + // If no core is specified, we can set the CoreId to a special value (e.g., 0xFFFFFFFF) to indicate that the dump should be performed for all cores + // + CoreId = HYPERTRACE_LBR_DUMP_ALL_CORES; + } + + // + // If the CoreId is set to the special value for dumping all cores, + // we can set it to 0 to start dumping from the first core and rely on the NextCoreIsValid flag + // in the dump request structure to indicate whether there are more cores to be dumped or not in + // the driver response + // + if (CoreId == HYPERTRACE_LBR_DUMP_ALL_CORES) + { + LbrdumpRequest.CoreId = 0; + } + else + { + LbrdumpRequest.CoreId = CoreId; + } + + while (ContinueDumpingAllCores) + { + // + // Send the LBR dump request + // + if (HyperDbgLbrdumpSendRequest(&LbrdumpRequest)) + { + if (LbrdumpRequest.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // + // Show entries of the LBR stack in the request structure which are filled by the driver in response to the dump request + // + CommandLbrdumpPrint(&LbrdumpRequest); + + if (CoreId == HYPERTRACE_LBR_DUMP_ALL_CORES && LbrdumpRequest.NextCoreIsValid) + { + // + // If the NextCoreIsValid flag is set, it means there are more cores to be + // dumped in the case of dumping all cores, so we can update the CoreId + // in the dump request structure to the next core number for the next + // iteration of dumping + // + LbrdumpRequest.CoreId++; + } + else + { + // + // If the NextCoreIsValid flag is not set, it means there are no more + // cores to be dumped in the case of dumping all cores, so we can break the loop + // + ContinueDumpingAllCores = FALSE; + } + } + else + { + ShowErrorMessage(LbrdumpRequest.KernelStatus); + break; + } + } + else + { + ShowMessages("failed to send LBR dump request\n"); + break; + } + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/measure.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/measure.cpp similarity index 81% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/measure.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/measure.cpp index b6d44855..ec083438 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/measure.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/measure.cpp @@ -32,6 +32,8 @@ extern BOOLEAN g_TransparentResultsMeasured; VOID CommandMeasureHelp() { + ShowMessages( + "This command is deprecated, you should not use it anymore!\n\n"); ShowMessages( "!measure : measures the arguments needs for the '!hide' command.\n\n"); @@ -45,30 +47,36 @@ CommandMeasureHelp() /** * @brief !measure command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandMeasure(vector SplitCommand, string Command) +CommandMeasure(vector CommandTokens, string Command) { BOOLEAN DefaultMode = FALSE; - if (SplitCommand.size() >= 3) + ShowMessages("This command is deprecated, you should not use it anymore!\n"); + return; + + if (CommandTokens.size() >= 3) { - ShowMessages("incorrect use of the '!measure'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandMeasureHelp(); return; } - if (SplitCommand.size() == 2 && SplitCommand.at(1).compare("default")) + if (CommandTokens.size() == 2 && !CompareLowerCaseStrings(CommandTokens.at(1), "default")) { - ShowMessages("incorrect use of the '!measure'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandMeasureHelp(); return; } - else if (SplitCommand.size() == 2 && - !SplitCommand.at(1).compare("default")) + else if (CommandTokens.size() == 2 && + CompareLowerCaseStrings(CommandTokens.at(1), "default")) { DefaultMode = TRUE; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/mode.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/mode.cpp similarity index 85% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/mode.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/mode.cpp index cb115014..dc4aa99a 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/mode.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/mode.cpp @@ -23,13 +23,15 @@ CommandModeHelp() ShowMessages("syntax : \t!mode [Mode (string)] [pid ProcessId (hex)] [core CoreId (hex)] [imm IsImmediate (yesno)] " "[sc EnableShortCircuiting (onoff)] [buffer PreAllocatedBuffer (hex)] [script { Script (string) }] " - "[condition { Condition (hex) }] [code { Code (hex) }] [output {OutputName (string)}]\n"); + "[asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !mode u pid 1c0\n"); ShowMessages("\t\te.g : !mode k pid 1c0\n"); ShowMessages("\t\te.g : !mode ku pid 1c0\n"); ShowMessages("\t\te.g : !mode ku core 2 pid 400\n"); + ShowMessages("\t\te.g : !mode u pid 1c0 script { printf(\"kernel -> user transition occurred!\\n\"); }\n"); + ShowMessages("\t\te.g : !mode ku pid 1c0 asm code { nop; nop; nop }\n"); ShowMessages("\n"); ShowMessages("note: this event applies to the target process; thus, you need to specify the process id\n"); @@ -38,12 +40,13 @@ CommandModeHelp() /** * @brief !mode command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandMode(vector SplitCommand, string Command) +CommandMode(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -53,7 +56,6 @@ CommandMode(vector SplitCommand, string Command) UINT32 ActionBreakToDebuggerLength = 0; UINT32 ActionCustomCodeLength = 0; UINT32 ActionScriptLength = 0; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; BOOLEAN SetMode = FALSE; DEBUGGER_EVENT_MODE_TYPE TargetInterceptionMode = DEBUGGER_EVENT_MODE_TYPE_INVALID; @@ -63,8 +65,7 @@ CommandMode(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, TRAP_EXECUTION_MODE_CHANGED, &Event, &EventLength, @@ -94,9 +95,11 @@ CommandMode(vector SplitCommand, string Command) // // Check for size // - if (SplitCommand.size() > 2) + if (CommandTokens.size() > 2) { - ShowMessages("incorrect use of the '!mode'\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandModeHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -106,23 +109,23 @@ CommandMode(vector SplitCommand, string Command) // // Interpret command specific details (if any) // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!mode")) + if (CompareLowerCaseStrings(Section, "!mode")) { continue; } - else if (!Section.compare("u") && !SetMode) + else if (CompareLowerCaseStrings(Section, "u") && !SetMode) { TargetInterceptionMode = DEBUGGER_EVENT_MODE_TYPE_USER_MODE; SetMode = TRUE; } - else if (!Section.compare("k") && !SetMode) + else if (CompareLowerCaseStrings(Section, "k") && !SetMode) { TargetInterceptionMode = DEBUGGER_EVENT_MODE_TYPE_KERNEL_MODE; SetMode = TRUE; } - else if ((!Section.compare("uk") || !Section.compare("ku")) && !SetMode) + else if ((CompareLowerCaseStrings(Section, "uk") || CompareLowerCaseStrings(Section, "ku")) && !SetMode) { TargetInterceptionMode = DEBUGGER_EVENT_MODE_TYPE_USER_MODE_AND_KERNEL_MODE; SetMode = TRUE; @@ -133,7 +136,7 @@ CommandMode(vector SplitCommand, string Command) // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n\n", - Section.c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandModeHelp(); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/monitor.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/monitor.cpp similarity index 68% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/monitor.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/monitor.cpp index 84d72c0a..6936ad80 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/monitor.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/monitor.cpp @@ -21,40 +21,45 @@ CommandMonitorHelp() { ShowMessages("!monitor : monitors address range for read and writes.\n\n"); - ShowMessages("syntax : \t!monitor [Attribute (string)] [FromAddress (hex)] " + ShowMessages("syntax : \t!monitor [MemoryType (vapa)] [Attribute (string)] [FromAddress (hex)] " "[ToAddress (hex)] [pid ProcessId (hex)] [core CoreId (hex)] " "[imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] " - "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [condition { Condition (hex) }] " - "[code { Code (hex) }] [output {OutputName (string)}]\n"); + "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [asm condition { Condition (assembly/hex) }] " + "[asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); - ShowMessages("syntax : \t!monitor [Attribute (string)] [FromAddress (hex)] " + ShowMessages("syntax : \t!monitor [MemoryType (vapa)] [Attribute (string)] [FromAddress (hex)] " "[l Length (hex)] [pid ProcessId (hex)] [core CoreId (hex)] " "[imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] " - "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [condition { Condition (hex) }] " - "[code { Code (hex) }] [output {OutputName (string)}]\n"); + "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [asm condition { Condition (assembly/hex) }] " + "[asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !monitor rw fffff801deadb000 fffff801deadbfff\n"); ShowMessages("\t\te.g : !monitor rw fffff801deadb000 l 1000\n"); + ShowMessages("\t\te.g : !monitor pa rw c01000 l 1000\n"); ShowMessages("\t\te.g : !monitor rwx fffff801deadb000 fffff801deadbfff\n"); ShowMessages("\t\te.g : !monitor rwx fffff801deadb000 l 230d0\n"); ShowMessages("\t\te.g : !monitor rw nt!Kd_DEFAULT_Mask Kd_DEFAULT_Mask+5\n"); ShowMessages("\t\te.g : !monitor r fffff801deadb000 fffff801deadbfff pid 400\n"); ShowMessages("\t\te.g : !monitor w fffff801deadb000 fffff801deadbfff core 2 pid 400\n"); + ShowMessages("\t\te.g : !monitor w c01000 c01000+2500 core 2 pid 400\n"); ShowMessages("\t\te.g : !monitor x fffff801deadb000 fffff801deadbfff core 2 pid 400\n"); ShowMessages("\t\te.g : !monitor x fffff801deadb000 l 500 core 2 pid 400\n"); ShowMessages("\t\te.g : !monitor wx fffff801deadb000 fffff801deadbfff core 2 pid 400\n"); + ShowMessages("\t\te.g : !monitor rw fffff801deadb000 l 1000 script { printf(\"read/write occurred at the virtual address: %%llx\\n\", $context); }\n"); + ShowMessages("\t\te.g : !monitor rw fffff801deadb000 l 1000 asm code { nop; nop; nop }\n"); } /** * @brief !monitor command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandMonitor(vector SplitCommand, string Command) +CommandMonitor(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -65,20 +70,22 @@ CommandMonitor(vector SplitCommand, string Command) UINT32 ActionCustomCodeLength = 0; UINT32 ActionScriptLength = 0; UINT32 HookLength = 0; - UINT64 OptionalParam1 = 0; // Set the 'from' target address - UINT64 OptionalParam2 = 0; // Set the 'to' target address - BOOLEAN SetFrom = FALSE; - BOOLEAN SetTo = FALSE; - BOOLEAN IsNextLength = FALSE; - BOOLEAN LengthAlreadySet = FALSE; - BOOLEAN SetAttributes = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - UINT32 IndexInCommandCaseSensitive = 0; + UINT64 OptionalParam1 = 0; // Set the 'from' target address + UINT64 OptionalParam2 = 0; // Set the 'to' target address + BOOLEAN SetFrom = FALSE; + BOOLEAN SetTo = FALSE; + BOOLEAN IsNextLength = FALSE; + BOOLEAN LengthAlreadySet = FALSE; + BOOLEAN SetAttributes = FALSE; + BOOLEAN HookMemoryTypeSet = FALSE; + DEBUGGER_HOOK_MEMORY_TYPE HookMemoryType = DEBUGGER_MEMORY_HOOK_VIRTUAL_ADDRESS; // by default virtual address DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; - if (SplitCommand.size() < 4) + if (CommandTokens.size() < 4) { - ShowMessages("incorrect use of the '!monitor'\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandMonitorHelp(); return; } @@ -91,8 +98,7 @@ CommandMonitor(vector SplitCommand, string Command) // we are not sure what kind event the user need // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, HIDDEN_HOOK_READ_AND_WRITE_AND_EXECUTE, &Event, &EventLength, @@ -110,17 +116,15 @@ CommandMonitor(vector SplitCommand, string Command) // // Interpret command specific details (if any) // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - IndexInCommandCaseSensitive++; - - if (!Section.compare("!monitor")) + if (CompareLowerCaseStrings(Section, "!monitor")) { continue; } else if (IsNextLength) { - if (!ConvertStringToUInt32(Section, &HookLength)) + if (!ConvertTokenToUInt32(Section, &HookLength)) { ShowMessages("err, you should enter a valid length\n\n"); return; @@ -130,54 +134,66 @@ CommandMonitor(vector SplitCommand, string Command) LengthAlreadySet = TRUE; SetTo = TRUE; // No longer need a second address } - else if (!Section.compare("r") && !SetAttributes) + else if (CompareLowerCaseStrings(Section, "r") && !SetAttributes) { Event->EventType = HIDDEN_HOOK_READ; SetAttributes = TRUE; } - else if (!Section.compare("w") && !SetAttributes) + else if (CompareLowerCaseStrings(Section, "w") && !SetAttributes) { Event->EventType = HIDDEN_HOOK_WRITE; SetAttributes = TRUE; } - else if (!Section.compare("x") && !SetAttributes) + else if (CompareLowerCaseStrings(Section, "x") && !SetAttributes) { Event->EventType = HIDDEN_HOOK_EXECUTE; SetAttributes = TRUE; } - else if ((!Section.compare("rw") || !Section.compare("wr")) && !SetAttributes) + else if ((CompareLowerCaseStrings(Section, "rw") || CompareLowerCaseStrings(Section, "wr")) && !SetAttributes) { Event->EventType = HIDDEN_HOOK_READ_AND_WRITE; SetAttributes = TRUE; } - else if ((!Section.compare("rx") || !Section.compare("xr")) && + else if ((CompareLowerCaseStrings(Section, "rx") || CompareLowerCaseStrings(Section, "xr")) && !SetAttributes) { Event->EventType = HIDDEN_HOOK_READ_AND_EXECUTE; SetAttributes = TRUE; } - else if ((!Section.compare("wx") || !Section.compare("xw")) && + else if ((CompareLowerCaseStrings(Section, "wx") || CompareLowerCaseStrings(Section, "xw")) && !SetAttributes) { Event->EventType = HIDDEN_HOOK_WRITE_AND_EXECUTE; SetAttributes = TRUE; } - else if ((!Section.compare("rwx") || - !Section.compare("rxw") || - !Section.compare("wrx") || - !Section.compare("wxr") || - !Section.compare("xrw") || - !Section.compare("xwr")) && + else if ((CompareLowerCaseStrings(Section, "rwx") || + CompareLowerCaseStrings(Section, "rxw") || + CompareLowerCaseStrings(Section, "wrx") || + CompareLowerCaseStrings(Section, "wxr") || + CompareLowerCaseStrings(Section, "xrw") || + CompareLowerCaseStrings(Section, "xwr")) && !SetAttributes) { Event->EventType = HIDDEN_HOOK_READ_AND_WRITE_AND_EXECUTE; SetAttributes = TRUE; } - else if (!Section.compare("l") && !SetTo && !LengthAlreadySet) + else if (CompareLowerCaseStrings(Section, "l") && !SetTo && !LengthAlreadySet) { IsNextLength = TRUE; continue; } + else if (CompareLowerCaseStrings(Section, "va") && !HookMemoryTypeSet) + { + HookMemoryType = DEBUGGER_MEMORY_HOOK_VIRTUAL_ADDRESS; + HookMemoryTypeSet = TRUE; + continue; + } + else if (CompareLowerCaseStrings(Section, "pa") && !HookMemoryTypeSet) + { + HookMemoryType = DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS; + HookMemoryTypeSet = TRUE; + continue; + } else { // @@ -186,14 +202,14 @@ CommandMonitor(vector SplitCommand, string Command) if (!SetFrom) { if (!SymbolConvertNameOrExprToAddress( - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1), + GetCaseSensitiveStringFromCommandToken(Section), &OptionalParam1)) { // // couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1).c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandMonitorHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -204,14 +220,14 @@ CommandMonitor(vector SplitCommand, string Command) else if (!SetTo && !LengthAlreadySet) { if (!SymbolConvertNameOrExprToAddress( - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1), + GetCaseSensitiveStringFromCommandToken(Section), &OptionalParam2)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1).c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandMonitorHelp(); @@ -225,7 +241,8 @@ CommandMonitor(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandMonitorHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -286,6 +303,7 @@ CommandMonitor(vector SplitCommand, string Command) // Event->Options.OptionalParam1 = OptionalParam1; Event->Options.OptionalParam2 = OptionalParam2; + Event->Options.OptionalParam3 = HookMemoryType; // // Send the ioctl to the kernel for event registration diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/msrread.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/msrread.cpp similarity index 82% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/msrread.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/msrread.cpp index 50fae232..943dc9c9 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/msrread.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/msrread.cpp @@ -24,24 +24,27 @@ CommandMsrreadHelp() ShowMessages("syntax : \t!msrread [Msr (hex)] [pid ProcessId (hex)] " "[core CoreId (hex)] [imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] " "[stage CallingStage (prepostall)] [buffer PreAllocatedBuffer (hex)] [script { Script (string) }] " - "[condition { Condition (hex) }] [code { Code (hex) }] [output {OutputName (string)}]\n"); + "[asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !msrread\n"); ShowMessages("\t\te.g : !msrread 0xc0000082\n"); ShowMessages("\t\te.g : !msread pid 400\n"); ShowMessages("\t\te.g : !msrread core 2 pid 400\n"); + ShowMessages("\t\te.g : !msrread script { printf(\"msr read with the 'ecx' register equal to: %%llx\\n\", $context); }\n"); + ShowMessages("\t\te.g : !msrread asm code { nop; nop; nop }\n"); } /** * @brief !msrread command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandMsrread(vector SplitCommand, string Command) +CommandMsrread(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -53,7 +56,6 @@ CommandMsrread(vector SplitCommand, string Command) UINT32 ActionScriptLength = 0; UINT64 SpecialTarget = DEBUGGER_EVENT_MSR_READ_OR_WRITE_ALL_MSRS; BOOLEAN GetAddress = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // @@ -61,8 +63,7 @@ CommandMsrread(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, RDMSR_INSTRUCTION_EXECUTION, &Event, &EventLength, @@ -81,9 +82,9 @@ CommandMsrread(vector SplitCommand, string Command) // Interpret command specific details (if any), it is because we can use // special msr bitmap here // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!msrread") || !Section.compare("!msread")) + if (CompareLowerCaseStrings(Section, "!msrread") || CompareLowerCaseStrings(Section, "!msread")) { continue; } @@ -92,12 +93,13 @@ CommandMsrread(vector SplitCommand, string Command) // // It's probably an msr // - if (!ConvertStringToUInt64(Section, &SpecialTarget)) + if (!ConvertTokenToUInt64(Section, &SpecialTarget)) { // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandMsrreadHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -113,7 +115,8 @@ CommandMsrread(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandMsrreadHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/msrwrite.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/msrwrite.cpp similarity index 82% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/msrwrite.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/msrwrite.cpp index ce659473..ec870e52 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/msrwrite.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/msrwrite.cpp @@ -23,25 +23,28 @@ CommandMsrwriteHelp() ShowMessages("syntax : \t!msrwrite [Msr (hex)] [pid ProcessId (hex)] [core CoreId (hex)] " "[imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] " - "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [condition { Condition (hex) }] " - "[code { Code (hex) }] [output {OutputName (string)}]\n"); + "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [asm condition { Condition (assembly/hex) }] " + "[asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !msrwrite\n"); ShowMessages("\t\te.g : !msrwrite 0xc0000082\n"); ShowMessages("\t\te.g : !msrwrite pid 400\n"); ShowMessages("\t\te.g : !msrwrite core 2 pid 400\n"); + ShowMessages("\t\te.g : !msrwrite script { printf(\"msr write with the 'ecx' register equal to: %%llx\\n\", $context); }\n"); + ShowMessages("\t\te.g : !msrwrite asm code { nop; nop; nop }\n"); } /** * @brief !msrwrite command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandMsrwrite(vector SplitCommand, string Command) +CommandMsrwrite(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -53,7 +56,6 @@ CommandMsrwrite(vector SplitCommand, string Command) UINT32 ActionScriptLength = 0; UINT64 SpecialTarget = DEBUGGER_EVENT_MSR_READ_OR_WRITE_ALL_MSRS; BOOLEAN GetAddress = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // @@ -61,8 +63,7 @@ CommandMsrwrite(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, WRMSR_INSTRUCTION_EXECUTION, &Event, &EventLength, @@ -81,9 +82,9 @@ CommandMsrwrite(vector SplitCommand, string Command) // Interpret command specific details (if any), it is because we can use // special msr bitmap here // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!msrwrite")) + if (CompareLowerCaseStrings(Section, "!msrwrite")) { continue; } @@ -92,12 +93,13 @@ CommandMsrwrite(vector SplitCommand, string Command) // // It's probably an msr // - if (!ConvertStringToUInt64(Section, &SpecialTarget)) + if (!ConvertTokenToUInt64(Section, &SpecialTarget)) { // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandMsrwriteHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -113,7 +115,8 @@ CommandMsrwrite(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandMsrwriteHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/pa2va.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pa2va.cpp similarity index 75% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/pa2va.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pa2va.cpp index e02be713..30a09ad7 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/pa2va.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pa2va.cpp @@ -14,6 +14,7 @@ // // Global Variables // +extern BOOLEAN g_IsKdModuleLoaded; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; @@ -40,24 +41,25 @@ CommandPa2vaHelp() /** * @brief !pa2va command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandPa2va(vector SplitCommand, string Command) +CommandPa2va(vector CommandTokens, string Command) { BOOL Status; ULONG ReturnedLength; UINT64 TargetPa; UINT32 Pid = 0; DEBUGGER_VA2PA_AND_PA2VA_COMMANDS AddressDetails = {0}; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - if (SplitCommand.size() == 1 || SplitCommand.size() >= 5 || - SplitCommand.size() == 3) + if (CommandTokens.size() == 1 || CommandTokens.size() >= 5 || CommandTokens.size() == 3) { - ShowMessages("incorrect use of the '!pa2va'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandPa2vaHelp(); return; } @@ -71,18 +73,18 @@ CommandPa2va(vector SplitCommand, string Command) Pid = g_ActiveProcessDebuggingState.ProcessId; } - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { // // It's just a address for current process // - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(1), &TargetPa)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)), &TargetPa)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); return; } } @@ -91,36 +93,36 @@ CommandPa2va(vector SplitCommand, string Command) // // It might be address + pid // - if (!SplitCommand.at(1).compare("pid")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "pid")) { - if (!ConvertStringToUInt32(SplitCommand.at(2), &Pid)) + if (!ConvertTokenToUInt32(CommandTokens.at(2), &Pid)) { ShowMessages("incorrect address, please enter a valid process id\n"); return; } - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(3), &TargetPa)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)), &TargetPa)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(3).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)).c_str()); return; } } - else if (!SplitCommand.at(2).compare("pid")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "pid")) { - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(1), &TargetPa)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)), &TargetPa)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); return; } - if (!ConvertStringToUInt32(SplitCommand.at(3), &Pid)) + if (!ConvertTokenToUInt32(CommandTokens.at(3), &Pid)) { ShowMessages("incorrect address, please enter a valid process id\n"); return; @@ -128,7 +130,8 @@ CommandPa2va(vector SplitCommand, string Command) } else { - ShowMessages("incorrect use of the '!pa2va'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandPa2vaHelp(); return; } @@ -161,7 +164,7 @@ CommandPa2va(vector SplitCommand, string Command) } else { - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); if (Pid == 0) { diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pcicam.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pcicam.cpp new file mode 100644 index 00000000..31c520cb --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pcicam.cpp @@ -0,0 +1,374 @@ +/** + * @file pcicam.cpp + * @author Bj�rn Ruytenberg (bjorn@bjornweb.nl) + * @brief !pcicam command + * @details + * @version 0.13 + * @date 2024-12-17 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; + +/** + * @brief !pcicam command help + * + * @return VOID + */ +VOID +CommandPcicamHelp() +{ + ShowMessages("!pcicam : dumps the PCI configuration space (CAM) for a given device.\n\n"); + + ShowMessages("syntax : \t!pcicam [Bus (hex)] [Device (hex)] [Function (hex)]\n"); + ShowMessages("syntax : \t!pcicam [Bus (hex)] [Device (hex)] [Function (hex)] [Dump (string)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !pcicam 0 2 0\n"); + ShowMessages("\t\te.g : !pcicam 3 0 0 x\n"); +} + +/** + * @brief !pcicam command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandPcicam(vector CommandTokens, string Command) +{ + BOOL Status; + ULONG ReturnedLength; + DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET PcidevinfoPacket = {0}; + UINT32 TargetBus = 0; + UINT32 TargetDevice = 0; + UINT32 TargetFunction = 0; + + const CHAR * PciHeaderTypes[] = {"Endpoint", "PCI-to-PCI Bridge", "PCI-to-CardBus Bridge"}; + + if (CommandTokens.size() < 4 || CommandTokens.size() > 5) + { + ShowMessages("Incorrect use of '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandPcicamHelp(); + return; + } + + if (ConvertTokenToUInt32(CommandTokens.at(1), &TargetBus)) + { + if (TargetBus > BUS_MAX_NUM) + { + ShowMessages("Invalid bus number '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); + CommandPcicamHelp(); + return; + } + PcidevinfoPacket.DeviceInfo.Bus = (UINT8)TargetBus; + } + + if (ConvertTokenToUInt32(CommandTokens.at(2), &TargetDevice)) + { + if (TargetDevice > DEVICE_MAX_NUM) + { + ShowMessages("Invalid device number '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()); + CommandPcicamHelp(); + return; + } + PcidevinfoPacket.DeviceInfo.Device = (UINT8)TargetDevice; + } + + if (ConvertTokenToUInt32(CommandTokens.at(3), &TargetFunction)) + { + if (TargetFunction > FUNCTION_MAX_NUM) + { + ShowMessages("Invalid function number '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)).c_str()); + CommandPcicamHelp(); + return; + } + PcidevinfoPacket.DeviceInfo.Function = (UINT8)TargetFunction; + } + + if (CommandTokens.size() == 5) + { + if (strncmp(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(4)).c_str(), "x", 1) == 0) + { + PcidevinfoPacket.PrintRaw = TRUE; + } + else + { + ShowMessages("Invalid parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(4)).c_str()); + CommandPcicamHelp(); + return; + } + } + + // + // Send buffer + // + if (g_IsSerialConnectedToRemoteDebuggee) + { + KdSendPcidevinfoPacketToDebuggee(&PcidevinfoPacket); + } + else + { + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + + // + // Send IOCTL + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_PCIDEVINFO_ENUM, // IO Control Code (IOCTL) + &PcidevinfoPacket, // Input Buffer to driver. + SIZEOF_DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET, // Input buffer length + &PcidevinfoPacket, // Output Buffer from driver. + SIZEOF_DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET, // Length of output + // buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + return; + } + + if (PcidevinfoPacket.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // + // For some reason, MSVC refuses to initialize these at top of case + // + const CHAR * PciHeaderTypeAsString[] = {"Endpoint", "PCI-to-PCI Bridge", "PCI-to-CardBus Bridge"}; + const CHAR * PciMmioBarTypeAsString[] = {"32-bit Wide", + "Reserved", + "64-bit Wide", + "Reserved"}; + UINT8 BarNumOffset = 0; + + ShowMessages("PCI configuration space (CAM) for device %04x:%02x:%02x:%x\n", + 0, // TODO: Add support for domains beyond 0000 + PcidevinfoPacket.DeviceInfo.Bus, + PcidevinfoPacket.DeviceInfo.Device, + PcidevinfoPacket.DeviceInfo.Function); + + if (!PcidevinfoPacket.PrintRaw) + { + Vendor * CurrentVendor = GetVendorById(PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.VendorId); + CHAR * CurrentVendorName = (CHAR *)"N/A"; + CHAR * CurrentDeviceName = (CHAR *)"N/A"; + + if (CurrentVendor != NULL) + { + CurrentVendorName = CurrentVendor->VendorName; + Device * CurrentDevice = GetDeviceFromVendor(CurrentVendor, PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.DeviceId); + + if (CurrentDevice != NULL) + { + CurrentDeviceName = CurrentDevice->DeviceName; + } + } + + ShowMessages("\nCommon Header:\nVID:DID: %04x:%04x\nVendor Name: %-17.*s\nDevice Name: %.*s\nCommand: %04x\n", + PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.VendorId, + PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.DeviceId, + strnlen_s(CurrentVendorName, PCI_NAME_STR_LENGTH), + CurrentVendorName, + strnlen_s(CurrentDeviceName, PCI_NAME_STR_LENGTH), + CurrentDeviceName, + PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command); + + if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01) << 7 == 0) // Only applicable to endpoints + { + ShowMessages(" Memory Space: %u\n I/O Space: %u\n", + (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1, + (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x1)); + } + + ShowMessages("Status: %04x\nRevision ID: %02x\nClass Code: %06x\nCacheLineSize: %02x\nPrimaryLatencyTimer: %02x\nHeaderType: %s (%02x)\n Multi-function Device: %s\nBist: %02x\n", + PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Status, + PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.RevisionId, + PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.ClassCode, + PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.CacheLineSize, + PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.PrimaryLatencyTimer, + (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) < 2 ? PciHeaderTypeAsString[(PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x1)] : "Unknown", + PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType, + (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x1) ? "True" : "False", + PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Bist); + FreeVendor(CurrentVendor); + FreePciIdDatabase(); + + ShowMessages("\nDevice Header:\n"); + + if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01) << 7 == 0) // Endpoint + { + for (UINT8 i = 0; i < 5; i++) + { + // + // Memory I/O + // + if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x1) == 0) + { + // + // 64-bit BAR + // + if (((PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1) == 2) + { + UINT64 BarMsb = PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i + 1]; + UINT64 BarLsb = PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i]; + UINT64 ActualBar = ((BarMsb & 0xFFFFFFFF) << 32) + (BarLsb & 0xFFFFFFF0); + + ShowMessages("BAR%u %s\n BAR Type: MMIO\n MMIO BAR Type: %s (%02x)\n BAR MSB: %08x\n BAR LSB: %08x\n BAR (actual): %016llx\n Prefetchable: %s\n", + i - BarNumOffset, + ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1 == 0) || !PcidevinfoPacket.DeviceInfo.MmioBarInfo[i].IsEnabled ? "[disabled]" : "", + PciMmioBarTypeAsString[(PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1], + (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1, + BarMsb, + BarLsb, + ActualBar, + (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x8 >> 3) ? "True" : "False"); + + i++; + BarNumOffset++; + } + // + // 32-bit BAR + // + else + { + UINT32 ActualBar = (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0xFFFFFFF0); + + ShowMessages("BAR%u %s\n BAR Type: MMIO\n BAR: %08x\n BAR (actual): %08x\n Prefetchable: %s\n", + i - BarNumOffset, + ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1 == 0) || !PcidevinfoPacket.DeviceInfo.MmioBarInfo[i].IsEnabled ? "[disabled]" : "", + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i], + ActualBar, + (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x8 >> 3) ? "True" : "False"); + } + } + // + // Port I/O + // + else + { + // + // 32-bit BAR is the only flavor we have here + // + UINT32 ActualBar32 = PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0xFFFFFFFC; + + ShowMessages("BAR%u %s\n BAR Type: Port IO\n BAR: %08x\n BAR (actual): %08x\n Reserved: %u\n", + i - BarNumOffset, + ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x1) == 0) ? "[disabled]" : "", + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i], + ActualBar32, + (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x2) >> 1); + } + } + + ShowMessages("Cardbus CIS Pointer: %08x\nSubsystem Vendor ID: %04x\nSubsystem ID: %04x\nROM BAR: %08x\nCapabilities Pointer: %02x\nReserved (0xD): %06x\nReserved (0xE): %08x\nInterrupt Line: %02x\nInterrupt Pin: %02x\nMin Grant: %02x\nMax latency: %02x\n", + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.CardBusCISPtr, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.SubVendorId, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.SubSystemId, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.ROMBar, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.CapabilitiesPtr, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Reserved, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Reserved1, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.InterruptLine, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.InterruptPin, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.MinGnt, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.MaxLat); + } + else if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) == 1) // PCI-to-PCI Bridge + { + ShowMessages("BAR0: %08x\nBAR1: %08x\n", PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Bar[0], PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Bar[1]); + + ShowMessages("Primary Bus Number: %02x\nSecondary Bus Number: %02x\nSubordinate Bus Number: %02x\nSecondary Latency Timer: %02x\nI/O Base: %02x\nI/O Limit: %02x\nSecondary Status: %04x\nMemory Base: %04x\nMemory Limit: %04x\nPrefetchable Memory Base: %04x\nPrefetchable Memory Limit: %04x\nPrefetchable Base Upper 32 Bits: %08x\nPrefetchable Limit Upper 32 Bits: %08x\nI/O Base Upper 16 Bits: %04x\nI/O Limit Upper 16 Bits: %04x\nCapability Pointer: %02x\nReserved: %06x\nROM BAR: %08x\nInterrupt Line: %02x\nInterrupt Pin: %02x\nBridge Control: %04x\n", + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrimaryBusNumber, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SecondaryBusNumber, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SubordinateBusNumber, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SecondaryLatencyTimer, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoBase, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoLimit, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SecondaryStatus, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.MemoryBase, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.MemoryLimit, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableMemoryBase, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableMemoryLimit, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableBaseUpper32b, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableLimitUpper32b, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoLimitUpper16b, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoBaseUpper16b, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.CapabilityPtr, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Reserved, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.ROMBar, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.InterruptLine, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.InterruptPin, + PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.BridgeControl); + } + else if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) == 2) // PCI-to-CardBus Bridge + { + ShowMessages("Parsing header type %s (%02x) currently unsupported\n", PciHeaderTypeAsString[PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01], PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01); + } + else + { + ShowMessages("\nDevice Header:\nUnknown header type %02x\n", (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f)); + } + } + else + { + UINT32 * cs = (UINT32 *)&PcidevinfoPacket.DeviceInfo.ConfigSpace; // Overflows into .ConfigSpaceAdditional - no padding due to pack(0) + + ShowMessages(" 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"); + + for (UINT16 i = 0; i < CAM_CONFIG_SPACE_LENGTH; i += 16) + { + ShowMessages("%02x: ", i); + for (UINT8 j = 0; j < 16; j++) + { + ShowMessages("%02x ", *(((BYTE *)cs) + j)); + } + + // + // Print ASCII representation + // Replace non-printable characters with "." + // + for (UINT8 j = 0; j < 16; j++) + { + CHAR c = (CHAR) * (cs + j); + if (c >= 32 && c <= 126) + { + ShowMessages("%c", c); + } + else + { + ShowMessages("."); + } + } + ShowMessages("\n"); + cs += 4; + } + } + } + else + { + // + // An err occurred, no results + // + ShowMessages("An error occurred, no results:"); + + ShowErrorMessage(PcidevinfoPacket.KernelStatus); + } + } +} diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pcitree.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pcitree.cpp new file mode 100644 index 00000000..4084e25c --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pcitree.cpp @@ -0,0 +1,140 @@ +/** + * @file pcitree.cpp + * @author Bj�rn Ruytenberg (bjorn@bjornweb.nl) + * @brief !pcitree command + * @details + * @version 0.10.3 + * @date 2024-10-31 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; + +/** + * @brief help of the !pcitree command + * + * @return VOID + */ +VOID +CommandPcitreeHelp() +{ + ShowMessages("!pcitree : enumerates all PCIe endpoints on the debuggee.\n\n"); + + ShowMessages("syntax : \t!pcitree\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !pcitree\n"); +} + +/** + * @brief !pcitree command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandPcitree(vector CommandTokens, string Command) +{ + BOOL Status; + ULONG ReturnedLength; + DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET PcitreePacket = {0}; + + if (CommandTokens.size() != 1) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandPcitreeHelp(); + return; + } + + // + // Send buffer + // + if (g_IsSerialConnectedToRemoteDebuggee) + { + KdSendPcitreePacketToDebuggee(&PcitreePacket); + } + else + { + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + + // + // Send IOCTL + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_PCIE_ENDPOINT_ENUM, // IO Control Code (IOCTL) + &PcitreePacket, // Input Buffer to driver. + SIZEOF_DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET, // Input buffer length + &PcitreePacket, // Output Buffer from driver. + SIZEOF_DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET, // Length of output + // buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + return; + } + + if (PcitreePacket.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // + // Print PCI device tree + // + ShowMessages("%-12s | %-9s | %-17s | %s \n%s\n", "DBDF", "VID:DID", "Vendor Name", "Device Name", "----------------------------------------------------------------------"); + for (UINT8 i = 0; i < (PcitreePacket.DeviceInfoListNum < DEV_MAX_NUM ? PcitreePacket.DeviceInfoListNum : DEV_MAX_NUM); i++) + { + Vendor * CurrentVendor = GetVendorById(PcitreePacket.DeviceInfoList[i].ConfigSpace.VendorId); + CHAR * CurrentVendorName = (CHAR *)"N/A"; + CHAR * CurrentDeviceName = (CHAR *)"N/A"; + + if (CurrentVendor != NULL) + { + CurrentVendorName = CurrentVendor->VendorName; + Device * CurrentDevice = GetDeviceFromVendor(CurrentVendor, PcitreePacket.DeviceInfoList[i].ConfigSpace.DeviceId); + + if (CurrentDevice != NULL) + { + CurrentDeviceName = CurrentDevice->DeviceName; + } + } + + ShowMessages("%04x:%02x:%02x:%x | %04x:%04x | %-17.*s | %.*s\n", + 0, // TODO: Add support for domains beyond 0000 + PcitreePacket.DeviceInfoList[i].Bus, + PcitreePacket.DeviceInfoList[i].Device, + PcitreePacket.DeviceInfoList[i].Function, + PcitreePacket.DeviceInfoList[i].ConfigSpace.VendorId, + PcitreePacket.DeviceInfoList[i].ConfigSpace.DeviceId, + strnlen_s(CurrentVendorName, PCI_NAME_STR_LENGTH), + CurrentVendorName, + strnlen_s(CurrentDeviceName, PCI_NAME_STR_LENGTH), + CurrentDeviceName + + ); + + FreeVendor(CurrentVendor); + } + FreePciIdDatabase(); + } + else + { + // + // An err occurred, no results + // + ShowErrorMessage(PcitreePacket.KernelStatus); + } + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/pmc.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pmc.cpp similarity index 84% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/pmc.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pmc.cpp index dfbb93be..89942cad 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/pmc.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pmc.cpp @@ -23,24 +23,27 @@ CommandPmcHelp() ShowMessages("syntax : \t!pmc [pid ProcessId (hex)] [core CoreId (hex)] [imm IsImmediate (yesno)] " "[sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] [buffer PreAllocatedBuffer (hex)] " - "[script { Script (string) }] [condition { Condition (hex) }] [code { Code (hex) }] " + "[script { Script (string) }] [asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] " "[output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !pmc\n"); ShowMessages("\t\te.g : !pmc pid 400\n"); ShowMessages("\t\te.g : !pmc core 2 pid 400\n"); + ShowMessages("\t\te.g : !pmc script { printf(\"RDPMC instruction called at: %%llx\\n\", @rip); }\n"); + ShowMessages("\t\te.g : !pmc asm code { nop; nop; nop }\n"); } /** * @brief !pmc command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandPmc(vector SplitCommand, string Command) +CommandPmc(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -50,7 +53,6 @@ CommandPmc(vector SplitCommand, string Command) UINT32 ActionBreakToDebuggerLength = 0; UINT32 ActionCustomCodeLength = 0; UINT32 ActionScriptLength = 0; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // @@ -58,8 +60,7 @@ CommandPmc(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, PMC_INSTRUCTION_EXECUTION, &Event, &EventLength, @@ -77,9 +78,10 @@ CommandPmc(vector SplitCommand, string Command) // // Check for size // - if (SplitCommand.size() > 1) + if (CommandTokens.size() > 1) { - ShowMessages("incorrect use of the '!pmc'\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandPmcHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pt.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pt.cpp new file mode 100644 index 00000000..09a96caf --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pt.cpp @@ -0,0 +1,1610 @@ +/** + * @file pt.cpp + * @author Masoud Rahimi Jafari (Masoodrahimy1379@gmail.com) + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !pt command + * @details + * @version 0.19 + * @date 2026-04-29 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsHyperTraceModuleLoaded; +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; + +/** + * @brief help of the !pt command + * + * @return VOID + */ +VOID +CommandPtHelp() +{ + ShowMessages("!pt : enables, disables and configures Intel Processor Trace (PT).\n\n"); + + ShowMessages("syntax : \t!pt enable\n"); + ShowMessages("syntax : \t!pt enable [size BufferSize (hex)]\n"); + ShowMessages("syntax : \t!pt enable [pid ProcessId (hex)] [size BufferSize (hex)] [core CoreId (hex)]\n"); + ShowMessages("syntax : \t!pt enable [tid ThreadId (hex)] [size BufferSize (hex)] [core CoreId (hex)]\n"); + ShowMessages("syntax : \t!pt enable [pname ProcessName (string)] [size BufferSize (hex)] [core CoreId (hex)]\n"); + ShowMessages("syntax : \t!pt enable [path Path (string)] [size BufferSize (hex)] [core CoreId (hex)]\n"); + ShowMessages("syntax : \t!pt enable [cr3 Cr3Value (hex)] [size BufferSize (hex)]\n"); + ShowMessages("syntax : \t!pt disable\n"); + ShowMessages("syntax : \t!pt pause\n"); + ShowMessages("syntax : \t!pt resume\n"); + ShowMessages("syntax : \t!pt flush\n"); + ShowMessages("syntax : \t!pt dump print [type TypeOfDump (string)]\n"); + ShowMessages("syntax : \t!pt dump path [type TypeOfDump (string)]\n"); + ShowMessages("syntax : \t!pt filter [Mode (string)]\n"); + ShowMessages("syntax : \t!pt filter [range1 FromAddress (hex) ToAddress (hex)] [range2 FromAddress (hex) ToAddress (hex)] [range3 FromAddress (hex) ToAddress (hex)] [range4 FromAddress (hex) ToAddress (hex)]\n"); + ShowMessages("syntax : \t!pt filter [range1 module ModuleName (string)] [range2 module ModuleName (string)] [range3 module ModuleName (string)] [range4 module ModuleName (string)]\n"); + ShowMessages("syntax : \t!pt filter [stoprange1 FromAddress (hex) ToAddress (hex)] [stoprange2 FromAddress (hex) ToAddress (hex)] [stoprange3 FromAddress (hex) ToAddress (hex)] [stoprange4 FromAddress (hex) ToAddress (hex)]\n"); + ShowMessages("syntax : \t!pt filter [stoprange1 module ModuleName (string)] [stoprange2 module ModuleName (string)] [stoprange3 module ModuleName (string)] [stoprange4 module ModuleName (string)]\n"); + ShowMessages("syntax : \t!pt packet [PacketType (string)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !pt enable\n"); + ShowMessages("\t\te.g : !pt enable size 0x200000\n"); + ShowMessages("\t\te.g : !pt enable pid 0x4a8\n"); + ShowMessages("\t\te.g : !pt enable pname notepad.exe\n"); + ShowMessages("\t\te.g : !pt enable tid 0x1234 core 3\n"); + ShowMessages("\t\te.g : !pt enable cr3 0x1aabb000\n"); + ShowMessages("\t\te.g : !pt enable pid 0x4a8 size 0x200000\n"); + ShowMessages("\t\te.g : !pt enable path \"c:\\programs\\my exe file.exe\" size 0x200000 core 3\n"); + ShowMessages("\t\te.g : !pt disable\n"); + ShowMessages("\t\te.g : !pt pause\n"); + ShowMessages("\t\te.g : !pt resume\n"); + ShowMessages("\t\te.g : !pt flush\n"); + ShowMessages("\t\te.g : !pt dump print type instruction\n"); + ShowMessages("\t\te.g : !pt dump print type packet\n"); + ShowMessages("\t\te.g : !pt dump path C:\\trace.txt type instruction\n"); + ShowMessages("\t\te.g : !pt filter user\n"); + ShowMessages("\t\te.g : !pt filter user kernel\n"); + ShowMessages("\t\te.g : !pt filter range1 0x140001000 0x140002000\n"); + ShowMessages("\t\te.g : !pt filter range1 module main\n"); + ShowMessages("\t\te.g : !pt filter range1 module ntdll range2 module nt\n"); + ShowMessages("\t\te.g : !pt filter stoprange1 0x140003000 0x140004000\n"); + ShowMessages("\t\te.g : !pt packet psb pip tsc\n"); + + ShowMessages("\n"); + ShowMessages("Where:\n"); + ShowMessages("\t[Mode (string)] could be 'kernel' or/and 'user'\n"); + ShowMessages("\t[TypeOfDump (string)] could be 'instruction' or 'packet'\n"); + ShowMessages("\t[ModuleName (string)] could be 'main' (the main module of the process), 'nt', 'win32k', or any other module name\n"); + ShowMessages("\t[PacketType (string)] could be either or a combination of 'psb', 'pip', 'tsc', 'mtc', 'cyc', 'tnt', 'tip', 'fup', or 'mode'\n"); + ShowMessages("\n"); +} + +/** + * @brief Send PT requests + * + * @param PtRequest + * + * @return VOID + */ +BOOLEAN +CommandPtSendRequest(HYPERTRACE_PT_OPERATION_PACKETS * PtRequest) +{ + BOOL Status; + ULONG ReturnedLength; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Send the request over serial kernel debugger + // + if (!KdSendHyperTracePtPacketsToDebuggee(PtRequest, SIZEOF_HYPERTRACE_PT_OPERATION_PACKETS)) + { + return FALSE; + } + else + { + return TRUE; + } + } + else + { + AssertShowMessageReturnStmt(g_IsHyperTraceModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_HYPERTRACE_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // Send IOCTL + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_PERFORM_HYPERTRACE_PT_OPERATION, // IO Control Code (IOCTL) + PtRequest, // Input Buffer to driver. + SIZEOF_HYPERTRACE_PT_OPERATION_PACKETS, // Input buffer length + PtRequest, // Output Buffer from driver. + SIZEOF_HYPERTRACE_PT_OPERATION_PACKETS, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + + return FALSE; + } + + if (PtRequest->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + return TRUE; + } + else + { + return FALSE; + } + } +} + +/** + * @brief Request to perform an PT operation + * + * @param PtRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgPerformPtOperation(HYPERTRACE_PT_OPERATION_PACKETS * PtRequest) +{ + return CommandPtSendRequest(PtRequest); +} + +/** + * @brief Send pt enable command + * + * @return BOOLEAN + */ +static BOOLEAN +CommandPtSendEnable() +{ + HYPERTRACE_PT_OPERATION_PACKETS PtRequest = {}; + + // + // Set the PtRequest structure for the operation + // + PtRequest.PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_ENABLE; + + // + // Send the request to perform the operation + // + if (!HyperDbgPerformPtOperation(&PtRequest)) + { + return FALSE; + } + else + { + return TRUE; + } +} + +/** + * @brief Send pt disable command + * + * @return BOOLEAN + */ +static BOOLEAN +CommandPtSendDisable() +{ + HYPERTRACE_PT_OPERATION_PACKETS PtRequest = {}; + + // + // Set the PtRequest structure for the operation + // + PtRequest.PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_DISABLE; + + // + // Send the request to perform the operation + // + if (!HyperDbgPerformPtOperation(&PtRequest)) + { + return FALSE; + } + else + { + return TRUE; + } +} + +/** + * @brief Send pt pause command + * + * @return BOOLEAN + */ +static BOOLEAN +CommandPtSendPause() +{ + HYPERTRACE_PT_OPERATION_PACKETS PtRequest = {}; + + // + // Set the PtRequest structure for the operation + // + PtRequest.PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_PAUSE; + + // + // Send the request to perform the operation + // + if (!HyperDbgPerformPtOperation(&PtRequest)) + { + return FALSE; + } + else + { + return TRUE; + } +} + +/** + * @brief Send pt resume command + * + * @return BOOLEAN + */ +static BOOLEAN +CommandPtSendResume() +{ + HYPERTRACE_PT_OPERATION_PACKETS PtRequest = {}; + + // + // Set the PtRequest structure for the operation + // + PtRequest.PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_RESUME; + + // + // Send the request to perform the operation + // + if (!HyperDbgPerformPtOperation(&PtRequest)) + { + return FALSE; + } + else + { + return TRUE; + } +} + +/** + * @brief Send pt flush command + * + * @return BOOLEAN + */ +static BOOLEAN +CommandPtSendFlush() +{ + HYPERTRACE_PT_OPERATION_PACKETS PtRequest = {}; + + // + // Set the PtRequest structure for the operation + // + PtRequest.PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FLUSH; + + // + // Send the request to perform the operation + // + if (!HyperDbgPerformPtOperation(&PtRequest)) + { + return FALSE; + } + else + { + return TRUE; + } +} + +/** + * @brief Send pt filter command + * + * @return BOOLEAN + */ +static BOOLEAN +CommandPtSendFilterByPid(UINT32 ProcessId, + BOOLEAN IsUserMode, + BOOLEAN IsKernelMode, + UINT64 StartRange1, + UINT64 EndRange1, + UINT64 StartRange2, + UINT64 EndRange2, + UINT64 StartRange3, + UINT64 EndRange3, + UINT64 StartRange4, + UINT64 EndRange4) +{ + HYPERTRACE_PT_OPERATION_PACKETS Op = {}; + UINT8 NumberOfRanges = 0; + + // + // Set the Op structure for the operation + // + Op.PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FILTER; + + // + // Set execution modes + // + Op.FilterOptions.TraceUser = IsUserMode ? 1 : 0; + Op.FilterOptions.TraceKernel = IsKernelMode ? 1 : 0; + + // + // Set the process ID + // + Op.EnableOptions.Pid = ProcessId; + + // + // Set the first range if provided + // + if (StartRange1 != NULL && EndRange1 != NULL) + { + Op.FilterOptions.AddrRanges[NumberOfRanges].Start = StartRange1; + Op.FilterOptions.AddrRanges[NumberOfRanges].End = EndRange1; + NumberOfRanges++; + } + + // + // Set the second range if provided + // + if (StartRange2 != NULL && EndRange2 != NULL) + { + Op.FilterOptions.AddrRanges[NumberOfRanges].Start = StartRange2; + Op.FilterOptions.AddrRanges[NumberOfRanges].End = EndRange2; + NumberOfRanges++; + } + + // + // Set the third range if provided + // + if (StartRange3 != NULL && EndRange3 != NULL) + { + Op.FilterOptions.AddrRanges[NumberOfRanges].Start = StartRange3; + Op.FilterOptions.AddrRanges[NumberOfRanges].End = EndRange3; + NumberOfRanges++; + } + + // + // Set the fourth range if provided + // + if (StartRange4 != NULL && EndRange4 != NULL) + { + Op.FilterOptions.AddrRanges[NumberOfRanges].Start = StartRange4; + Op.FilterOptions.AddrRanges[NumberOfRanges].End = EndRange4; + NumberOfRanges++; + } + + // + // Set number of ranges + // + Op.FilterOptions.NumAddrRanges = NumberOfRanges; + + // + // Send the request to perform the operation + // + if (!HyperDbgPerformPtOperation(&Op)) + { + return FALSE; + } + else + { + ShowMessages("[+] PT Filter: cr3=0x%llx, pid=0x%x, user=%x, kernel=%x, ranges=%x\n", + Op.EnableOptions.Cr3, + Op.EnableOptions.Pid, + Op.FilterOptions.TraceUser, + Op.FilterOptions.TraceKernel, + Op.FilterOptions.NumAddrRanges); + + return TRUE; + } + + return TRUE; +} + +/** + * @brief Shared core: enable PT, wait for the target, decode and disable + * + * @details Called by the three specialised helpers after they have filled + * Process with a valid hProcess (and optionally hThread). + * Owns and closes all handles in Process before returning. + * + * @param Process Pointer to a PROCESS_INFORMATION whose hProcess (and + * optionally hThread) have already been opened/created + * @param Path Executable path used for symbol resolution, or NULL + * @param Function Symbol name to narrow the IP filter, or NULL + * @param Packets TRUE → decode raw packets; FALSE → decode instructions + * @param PinCore ≥ 0 → pin the target to that logical core; < 0 → free + * @param LaunchedNew TRUE → process was launched suspended here (will be + * resumed, and terminated on error); FALSE → the + * process was already running (never terminated) + * + * @return VOID + */ +static VOID +CommandPtRunAndTraceCore(PROCESS_INFORMATION * Process, + const CHAR * Path, + const CHAR * Function, + BOOLEAN Packets, + int PinCore, + BOOLEAN LaunchedNew) +{ + DWORD_PTR Mask; + HYPERTRACE_PT_MMAP_PACKETS Mmap = {}; + HYPERTRACE_PT_OPERATION_PACKETS Sizes = {}; + IMAGE_SYMBOL_CONTEXT Ctx = {}; + UINT64 TextStart = 0; + UINT64 TextEnd = 0; + UINT64 FilterStart = 0; + UINT64 FilterEnd = 0; + UINT64 Total = 0; + + if (PinCore < 0) + { + PinCore = PT_DEFAULT_PINNING_CORE; + } + + Mask = (DWORD_PTR)1 << PinCore; + + // + // Set process affinity to the specified core so that all PT trace will land on that core + // + if (SetProcessAffinityMask(Process->hProcess, Mask)) + { + ShowMessages("[+] pinned target to core %d (all trace should land on this core)\n", PinCore); + } + else + { + ShowMessages("[!] could not pin to core %d (error 0x%x); running unpinned\n", PinCore, GetLastError()); + } + + // + // Capture the .text section of the target process image for symbol resolution + // + if (!PtHelperCaptureImage(Process->hProcess, &TextStart, &TextEnd, &Ctx)) + { + ShowMessages("[-] cannot read target image / .text section\n"); + + if (LaunchedNew) + TerminateProcess(Process->hProcess, 1); + + goto Cleanup; + } + + ShowMessages("[+] image base 0x%llx, .text 0x%llx-0x%llx (%llu bytes)\n", + (UINT64)Ctx.ImageBase, + (UINT64)TextStart, + (UINT64)TextEnd, + (UINT64)Ctx.CodeSize); + + FilterStart = TextStart; + FilterEnd = TextEnd; + + // + // Narrow the IP filter to the specified function if possible + // + if (Function != NULL && Path != NULL && + PtHelperResolveFunction(Process->hProcess, Path, Function, Ctx.ImageBase, &FilterStart, &FilterEnd)) + { + ShowMessages("[+] IP filter narrowed to '%s' 0x%llx-0x%llx (%llu bytes)\n", + Function, + (UINT64)FilterStart, + (UINT64)FilterEnd, + (UINT64)(FilterEnd - FilterStart + 1)); + } + else + { + ShowMessages("[!] IP filter: whole .text (symbol '%s' not found or not applicable)\n", + Function ? Function : "(none)"); + } + + // + // Enable PT with the specified filter and wait for the target process to exit + // + if (!CommandPtSendFilterByPid(Process->dwProcessId, TRUE, FALSE, FilterStart, FilterEnd, NULL, NULL, NULL, NULL, NULL, NULL) || + !CommandPtSendEnable()) + { + ShowMessages("[-] cannot enable Intel PT\n"); + + if (LaunchedNew) + { + TerminateProcess(Process->hProcess, 1); + } + + goto Cleanup; + } + + // + // Request the PT buffers to be mapped into user space so that we can decode them after the target exits + // + if (!HyperDbgPtMmapSendRequest(&Mmap)) + { + ShowMessages("[-] MMAP failed\n"); + CommandPtSendDisable(); + if (LaunchedNew) + TerminateProcess(Process->hProcess, 1); + goto Cleanup; + } + + ShowMessages("[+] PT enabled, %u per-core buffers mapped\n", Mmap.NumCpus); + + if (LaunchedNew) + { + ShowMessages("[*] resuming target and waiting for it to exit...\n"); + ResumeThread(Process->hThread); + } + else + { + ShowMessages("[*] waiting for target process to exit...\n"); + } + + // + // Wait for the target process to exit before decoding the trace + // + WaitForSingleObject(Process->hProcess, INFINITE); + + ShowMessages("[+] target exited, decoding trace\n"); + + // + // Pause PT so that the buffers are not being written to while we decode them + // + CommandPtSendPause(); + + Sizes.PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_SIZE; + + // + // Request the sizes of the PT buffers for each core so that we know how much to decode + // + if (!CommandPtSendRequest(&Sizes)) + { + ShowMessages("[-] cannot query PT sizes\n"); + CommandPtSendDisable(); + goto Cleanup; + } + + // + // Decode the trace for each core that has a non-zero buffer size + // + for (UINT32 i = 0; i < Mmap.NumCpus; i++) + { + UINT32 Cpu = Mmap.Cpus[i].CpuId; + UINT64 Bytes = (Cpu < Sizes.NumCpus) ? Sizes.BytesPerCpu[Cpu] : 0; + + if (Bytes == 0) + continue; + + if (Bytes > Mmap.Cpus[i].Size) + Bytes = Mmap.Cpus[i].Size; + + ShowMessages("\n[*] core %u: %llu bytes of trace\n", Cpu, (UINT64)Bytes); + Total += Packets + ? PtHelperDecodeCorePackets(Cpu, (const UINT8 *)(ULONG_PTR)Mmap.Cpus[i].UserVa, Bytes, Ctx.ImageBase) + : PtHelperDecodeCore(Cpu, (const UINT8 *)(ULONG_PTR)Mmap.Cpus[i].UserVa, Bytes, &Ctx); + } + + ShowMessages("\n[+] decoded %llu %s total\n", (UINT64)Total, Packets ? "packet(s)" : "instruction(s)"); + + // + // Disable PT now that we are done decoding the trace + // + CommandPtSendDisable(); + +Cleanup: + + if (Ctx.Code != NULL) + { + free(Ctx.Code); + Ctx.Code = NULL; + } + + if (Process->hThread != NULL) + CloseHandle(Process->hThread); + if (Process->hProcess != NULL) + CloseHandle(Process->hProcess); +} + +/** + * @brief Launch an executable at Path as a suspended process, enable PT, and + * decode the trace after the process exits + * + * @param Path Full path to the executable to launch + * @param Function Symbol name to narrow the IP filter, or NULL for whole .text + * @param Packets TRUE → decode raw packets; FALSE → decode instructions + * @param PinCore ≥ 0 → pin to that logical core; < 0 → unpinned + * + * @return VOID + */ +static VOID +CommandPtRunAndTraceByPath(const CHAR * Path, const CHAR * Function, BOOLEAN Packets, int PinCore) +{ + STARTUPINFOA Startup = {}; + PROCESS_INFORMATION Process = {}; + + Startup.cb = sizeof(Startup); + + if (!CreateProcessA(Path, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &Startup, &Process)) + { + ShowMessages("[-] cannot launch '%s' (error 0x%x)\n", Path, GetLastError()); + return; + } + + ShowMessages("[+] launched '%s' (pid %u, suspended)\n", Path, Process.dwProcessId); + + CommandPtRunAndTraceCore(&Process, Path, Function, Packets, PinCore, TRUE); +} + +/** + * @brief Open an existing process by PID, enable PT, and decode the trace + * after the process exits + * + * @param ProcessId PID of the target process + * @param Function Symbol name to narrow the IP filter, or NULL for whole .text + * @param Packets TRUE → decode raw packets; FALSE → decode instructions + * @param PinCore ≥ 0 → pin to that logical core; < 0 → unpinned + * + * @return VOID + */ +static VOID +CommandPtRunAndTraceByPid(UINT32 ProcessId, const CHAR * Function, BOOLEAN Packets, int PinCore) +{ + PROCESS_INFORMATION Process = {}; + + Process.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)ProcessId); + + if (Process.hProcess == NULL) + { + ShowMessages("[-] cannot open process 0x%x (error 0x%x)\n", ProcessId, GetLastError()); + return; + } + + Process.dwProcessId = ProcessId; + + ShowMessages("[+] attached to pid 0x%x\n", ProcessId); + + CommandPtRunAndTraceCore(&Process, NULL, Function, Packets, PinCore, FALSE); +} + +/** + * @brief Open an existing thread by TID, derive its owning process, enable PT, + * and decode the trace after the process exits + * + * @param ThreadId TID of the target thread + * @param Function Symbol name to narrow the IP filter, or NULL for whole .text + * @param Packets TRUE → decode raw packets; FALSE → decode instructions + * @param PinCore ≥ 0 → pin to that logical core; < 0 → unpinned + * + * @return VOID + */ +static VOID +CommandPtRunAndTraceByTid(UINT32 ThreadId, const CHAR * Function, BOOLEAN Packets, int PinCore) +{ + PROCESS_INFORMATION Process = {}; + HANDLE ThreadHandle = NULL; + DWORD OwningPid = 0; + THREAD_BASIC_INFO_EX Tbi = {0}; + ULONG RetTid = 0; + HMODULE NtdllTid = GetModuleHandleA("ntdll.dll"); + PFN_NT_QIT NtQit = NtdllTid ? (PFN_NT_QIT)GetProcAddress(NtdllTid, "NtQueryInformationThread") : NULL; + + ThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD)ThreadId); + + if (ThreadHandle == NULL) + { + ShowMessages("[-] cannot open thread 0x%x (error 0x%x)\n", ThreadId, GetLastError()); + return; + } + + if (NtQit == NULL || NtQit(ThreadHandle, 0, &Tbi, sizeof(Tbi), &RetTid) < 0 || Tbi.ClientId.UniqueProcess == NULL) + { + ShowMessages("[-] cannot get owning PID for thread 0x%x\n", ThreadId); + CloseHandle(ThreadHandle); + return; + } + + OwningPid = (DWORD)(ULONG_PTR)Tbi.ClientId.UniqueProcess; + + if (OwningPid == 0) + { + ShowMessages("[-] cannot get owning PID for thread 0x%x\n", ThreadId); + CloseHandle(ThreadHandle); + return; + } + + Process.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, OwningPid); + + if (Process.hProcess == NULL) + { + ShowMessages("[-] cannot open process %u (error 0x%x)\n", OwningPid, GetLastError()); + CloseHandle(ThreadHandle); + return; + } + + Process.hThread = ThreadHandle; + Process.dwProcessId = OwningPid; + Process.dwThreadId = ThreadId; + + ShowMessages("[+] attached to tid 0x%x (owning pid %u)\n", ThreadId, OwningPid); + + CommandPtRunAndTraceCore(&Process, NULL, Function, Packets, PinCore, FALSE); +} + +/** + * @brief Wrapper: dispatch to the appropriate trace helper based on whichever + * selector (Path, ProcessId, ThreadId) is provided + * + * @param Path Executable path, or NULL + * @param Function Symbol name for IP filter, or NULL + * @param Packets TRUE → raw packets; FALSE → instructions + * @param PinCore Logical core to pin the target to, or < 0 for unpinned + * @param ProcessId PID of an existing process, or 0 + * @param ThreadId TID of an existing thread, or 0 + * + * @return VOID + */ +static VOID +CommandPtRunAndTrace(const CHAR * Path, const CHAR * Function, BOOLEAN Packets, int PinCore, UINT32 ProcessId, UINT32 ThreadId) +{ + if (Path != NULL) + CommandPtRunAndTraceByPath(Path, Function, Packets, PinCore); + else if (ThreadId != 0) + CommandPtRunAndTraceByTid(ThreadId, Function, Packets, PinCore); + else if (ProcessId != 0) + CommandPtRunAndTraceByPid(ProcessId, Function, Packets, PinCore); + else + ShowMessages("[-] no path, PID, or TID specified\n"); +} + +/** + * @brief Map the per-CPU PT output buffers into the current process + * + * @details On success MmapRequest->Cpus[0..NumCpus) hold one { UserVa, Size } + * per CPU, valid in this process until PT is disabled / flushed. + * Only meaningful in local (VMI) mode. + * + * @param MmapRequest + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgPtMmapSendRequest(HYPERTRACE_PT_MMAP_PACKETS * MmapRequest) +{ + BOOL Status; + ULONG ReturnedLength; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // The mmap surface maps into the caller's address space, which only + // makes sense in local mode (no remote-debuggee transport for it). + // + ShowMessages("err, PT mmap is only available in local (VMI) mode\n"); + return FALSE; + } + + AssertShowMessageReturnStmt(g_IsHyperTraceModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_HYPERTRACE_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_PERFORM_HYPERTRACE_PT_MMAP, // IO Control Code (IOCTL) + MmapRequest, // Input Buffer to driver. + SIZEOF_HYPERTRACE_PT_MMAP_PACKETS, // Input buffer length + MmapRequest, // Output Buffer from driver. + SIZEOF_HYPERTRACE_PT_MMAP_PACKETS, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + return FALSE; + } + + return MmapRequest->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL; +} + +/** + * @brief Parse and display enable options for !pt enable command + * + * @param CommandTokens The command tokens to parse + * @param PtRequest The PT request structure to fill with parsed options + * + * @return VOID + */ +static VOID +CommandPtParseEnable(vector & CommandTokens, HYPERTRACE_PT_OPERATION_PACKETS * PtRequest) +{ + BOOLEAN HasPid = FALSE; + BOOLEAN HasPname = FALSE; + BOOLEAN HasPath = FALSE; + BOOLEAN HasTid = FALSE; + BOOLEAN HasCr3 = FALSE; + BOOLEAN HasSize = FALSE; + BOOLEAN HasCore = FALSE; + UINT64 Pid = 0; + UINT64 Tid = 0; + UINT64 Cr3 = 0; + UINT64 Size = 0; + UINT32 Core = 0; + string Pname; + string Path; + + for (SIZE_T i = 2; i < CommandTokens.size(); i++) + { + if (CompareLowerCaseStrings(CommandTokens.at(i), "pid")) + { + if (i + 1 >= CommandTokens.size()) + { + ShowMessages("err, 'pid' expects a hex process ID\n\n"); + CommandPtHelp(); + return; + } + i++; + if (!ConvertTokenToUInt64(CommandTokens.at(i), &Pid)) + { + ShowMessages("err, '%s' is not a valid hex process ID\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + HasPid = TRUE; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "pname")) + { + if (i + 1 >= CommandTokens.size()) + { + ShowMessages("err, 'pname' expects a process name\n\n"); + CommandPtHelp(); + return; + } + i++; + Pname = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)); + HasPname = TRUE; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "path")) + { + if (i + 1 >= CommandTokens.size()) + { + ShowMessages("err, 'path' expects a process executable path\n\n"); + CommandPtHelp(); + return; + } + i++; + Path = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)); + HasPath = TRUE; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "tid")) + { + if (i + 1 >= CommandTokens.size()) + { + ShowMessages("err, 'tid' expects a hex thread ID\n\n"); + CommandPtHelp(); + return; + } + i++; + if (!ConvertTokenToUInt64(CommandTokens.at(i), &Tid)) + { + ShowMessages("err, '%s' is not a valid hex thread ID\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + HasTid = TRUE; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "cr3")) + { + if (i + 1 >= CommandTokens.size()) + { + ShowMessages("err, 'cr3' expects a hex CR3 value\n\n"); + CommandPtHelp(); + return; + } + i++; + if (!ConvertTokenToUInt64(CommandTokens.at(i), &Cr3)) + { + ShowMessages("err, '%s' is not a valid hex CR3 value\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + HasCr3 = TRUE; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "size")) + { + if (i + 1 >= CommandTokens.size()) + { + ShowMessages("err, 'size' expects a hex buffer size\n\n"); + CommandPtHelp(); + return; + } + i++; + if (!ConvertTokenToUInt64(CommandTokens.at(i), &Size)) + { + ShowMessages("err, '%s' is not a valid hex size\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + HasSize = TRUE; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "core")) + { + if (i + 1 >= CommandTokens.size()) + { + ShowMessages("err, 'core' expects a hex value as the core number\n\n"); + CommandPtHelp(); + return; + } + i++; + if (!ConvertTokenToUInt32(CommandTokens.at(i), &Core)) + { + ShowMessages("err, '%s' is not a valid hex size\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + HasCore = TRUE; + } + else + { + ShowMessages("err, unknown 'enable' option '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + } + + // + // pid, pname, tid, cr3 are mutually exclusive target selectors + // + INT32 SelectorCount = (HasPid ? 1 : 0) + (HasPname ? 1 : 0) + (HasPath ? 1 : 0) + (HasTid ? 1 : 0) + (HasCr3 ? 1 : 0); + if (SelectorCount > 1) + { + ShowMessages("err, only one of 'pid', 'pname', 'path', 'tid', 'cr3' may be specified at a time\n\n"); + CommandPtHelp(); + return; + } + + // + // Show parsed enable options + // + ShowMessages("PT enable:\n"); + + if (HasPid) + { + ShowMessages(" target pid : 0x%llx\n", Pid); + + PtRequest->EnableOptions.EnableByPid = 1; + PtRequest->EnableOptions.Pid = (UINT32)Pid; + } + else if (HasPname) + { + ShowMessages(" target pname : %s\n", Pname.c_str()); + + PtRequest->EnableOptions.EnableByCr3 = 1; + strcpy_s(PtRequest->EnableOptions.ProcessName, sizeof(PtRequest->EnableOptions.ProcessName), Pname.c_str()); + } + else if (HasPath) + { + ShowMessages(" target path : %s\n", Path.c_str()); + + PtRequest->EnableOptions.EnableByPid = 1; // Path is resolved to a PID + } + else if (HasTid) + { + ShowMessages(" target tid : 0x%llx\n", Tid); + + PtRequest->EnableOptions.EnableByTid = 1; + PtRequest->EnableOptions.Tid = (UINT32)Tid; + } + else if (HasCr3) + { + ShowMessages(" target cr3 : 0x%llx\n", Cr3); + + PtRequest->EnableOptions.EnableByCr3 = 1; + PtRequest->EnableOptions.Cr3 = Cr3; + } + else + { + ShowMessages(" target : all (no process/thread filter)\n"); + } + + // + // Check for size options + // + if (HasSize) + { + ShowMessages(" buffer size : 0x%llx bytes\n", Size); + + PtRequest->BufferSize = Size; + } + else + { + ShowMessages(" buffer size : default (%llx bytes)\n", PT_DEFAULT_BUFFER_SIZE); + + PtRequest->BufferSize = PT_DEFAULT_BUFFER_SIZE; + } + + // + // Check for core options + // + if (HasCore) + { + ShowMessages(" core : 0x%x\n", Core); + PtRequest->CoreId = Core; + } + else + { + ShowMessages(" core : default (0x%x)\n", PT_DEFAULT_PINNING_CORE); + PtRequest->CoreId = PT_DEFAULT_PINNING_CORE; + } + + // + // Fill the PtRequest structure with parsed options + // + PtRequest->PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_ENABLE; + + // + // Temporary workaround for testing: + // If a path, PID, or TID is specified, invoke CommandPtRunAndTrace directly + // to launch/attach and decode the trace in one step. + // TODO: Should be removed once the kernel-side enable/filter path is complete. + // + if (HasPath) + { + ShowMessages(" Running '%s' on core: %llx\n", Path.c_str(), PtRequest->CoreId); + CommandPtRunAndTrace(Path.c_str(), NULL, FALSE, PtRequest->CoreId, 0, 0); + } + else if (HasPid) + { + ShowMessages(" Tracing pid 0x%llx on core: %llx\n", Pid, PtRequest->CoreId); + CommandPtRunAndTrace(NULL, NULL, FALSE, PtRequest->CoreId, (UINT32)Pid, 0); + } + else if (HasTid) + { + ShowMessages(" Tracing tid 0x%llx on core: %llx\n", Tid, PtRequest->CoreId); + CommandPtRunAndTrace(NULL, NULL, FALSE, PtRequest->CoreId, 0, (UINT32)Tid); + } +} + +/** + * @brief Parse and display !pt dump parameters + * + * @param CommandTokens The command tokens to parse + * @param PtRequest The PT request structure to fill with parsed options + * + * @return VOID + */ +static VOID +CommandPtParseDump(vector & CommandTokens, HYPERTRACE_PT_OPERATION_PACKETS * PtRequest) +{ + if (CommandTokens.size() < 3) + { + ShowMessages("err, 'dump' requires additional options\n\n"); + CommandPtHelp(); + return; + } + + if (CompareLowerCaseStrings(CommandTokens.at(2), "print")) + { + // + // !pt dump print type + // + if (CommandTokens.size() != 5 || !CompareLowerCaseStrings(CommandTokens.at(3), "type")) + { + ShowMessages("err, syntax: !pt dump print type \n\n"); + CommandPtHelp(); + return; + } + + if (!CompareLowerCaseStrings(CommandTokens.at(4), "instruction") && + !CompareLowerCaseStrings(CommandTokens.at(4), "packet")) + { + ShowMessages("err, dump type must be 'instruction' or 'packet', got '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(4)).c_str()); + CommandPtHelp(); + return; + } + + ShowMessages("PT dump to console:\n"); + ShowMessages(" output : console (print)\n"); + ShowMessages(" format : %s\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(4)).c_str()); + } + else if (CompareLowerCaseStrings(CommandTokens.at(2), "path")) + { + // + // !pt dump path type + // + if (CommandTokens.size() != 6 || !CompareLowerCaseStrings(CommandTokens.at(4), "type")) + { + ShowMessages("err, syntax: !pt dump path type \n\n"); + CommandPtHelp(); + return; + } + + if (!CompareLowerCaseStrings(CommandTokens.at(5), "instruction") && + !CompareLowerCaseStrings(CommandTokens.at(5), "packet")) + { + ShowMessages("err, dump type must be 'instruction' or 'packet', got '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(5)).c_str()); + CommandPtHelp(); + return; + } + + ShowMessages("PT dump to file:\n"); + ShowMessages(" output : file\n"); + ShowMessages(" path : %s\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)).c_str()); + ShowMessages(" format : %s\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(5)).c_str()); + } + else + { + ShowMessages("err, unknown 'dump' sub-option '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()); + CommandPtHelp(); + } +} + +/** + * @brief Parse and display !pt filter parameters + * + * @param CommandTokens The command tokens to parse + * @param PtRequest The PT request structure to fill with parsed options + * + * @return VOID + */ +static VOID +CommandPtParseFilter(vector & CommandTokens, HYPERTRACE_PT_OPERATION_PACKETS * PtRequest) +{ + struct PtRangeEntry + { + BOOLEAN Active; + BOOLEAN IsModule; + UINT64 Start; + UINT64 End; + string ModuleName; + }; + + PtRangeEntry Ranges[4] = {}; + PtRangeEntry StopRanges[4] = {}; + BOOLEAN TraceUser = FALSE; + BOOLEAN TraceKernel = FALSE; + + for (SIZE_T i = 2; i < CommandTokens.size(); i++) + { + if (CompareLowerCaseStrings(CommandTokens.at(i), "user")) + { + TraceUser = TRUE; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "kernel")) + { + TraceKernel = TRUE; + } + else + { + // + // Resolve range1..range4 / stoprange1..stoprange4 + // + BOOLEAN IsStop = FALSE; + INT32 RangeIdx = -1; + + if (CompareLowerCaseStrings(CommandTokens.at(i), "range1")) + { + IsStop = FALSE; + RangeIdx = 0; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "range2")) + { + IsStop = FALSE; + RangeIdx = 1; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "range3")) + { + IsStop = FALSE; + RangeIdx = 2; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "range4")) + { + IsStop = FALSE; + RangeIdx = 3; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "stoprange1")) + { + IsStop = TRUE; + RangeIdx = 0; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "stoprange2")) + { + IsStop = TRUE; + RangeIdx = 1; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "stoprange3")) + { + IsStop = TRUE; + RangeIdx = 2; + } + else if (CompareLowerCaseStrings(CommandTokens.at(i), "stoprange4")) + { + IsStop = TRUE; + RangeIdx = 3; + } + else + { + ShowMessages("err, unknown filter option '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + + PtRangeEntry * Entry = IsStop ? &StopRanges[RangeIdx] : &Ranges[RangeIdx]; + + if (i + 1 >= CommandTokens.size()) + { + ShowMessages("err, '%s' expects or 'module '\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + + if (CompareLowerCaseStrings(CommandTokens.at(i + 1), "module")) + { + // + // range module + // + if (i + 2 >= CommandTokens.size()) + { + ShowMessages("err, 'module' expects a module name\n\n"); + CommandPtHelp(); + return; + } + i += 2; + Entry->IsModule = TRUE; + Entry->ModuleName = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)); + Entry->Active = TRUE; + } + else + { + // + // range + // + if (i + 2 >= CommandTokens.size()) + { + ShowMessages("err, '%s' expects \n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + i++; + if (!ConvertTokenToUInt64(CommandTokens.at(i), &Entry->Start)) + { + ShowMessages("err, '%s' is not a valid address\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + i++; + if (!ConvertTokenToUInt64(CommandTokens.at(i), &Entry->End)) + { + ShowMessages("err, '%s' is not a valid address\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + Entry->IsModule = FALSE; + Entry->Active = TRUE; + } + } + } + + // + // Show parsed filter options + // + ShowMessages("PT filter:\n"); + + if (TraceUser) + { + ShowMessages(" privilege : user (CPL > 0)\n"); + + PtRequest->FilterOptions.TraceUser = 1; + } + if (TraceKernel) + { + ShowMessages(" privilege : kernel (CPL == 0)\n"); + + PtRequest->FilterOptions.TraceKernel = 1; + } + if (!TraceUser && !TraceKernel) + { + ShowMessages(" privilege : (default - user + kernel)\n"); + + PtRequest->FilterOptions.TraceUser = 1; + PtRequest->FilterOptions.TraceKernel = 1; + } + + for (INT32 r = 0; r < 4; r++) + { + if (Ranges[r].Active) + { + if (Ranges[r].IsModule) + ShowMessages(" range%d : module '%s'\n", r + 1, Ranges[r].ModuleName.c_str()); + else + ShowMessages(" range%d : 0x%llx - 0x%llx\n", r + 1, Ranges[r].Start, Ranges[r].End); + } + + // + // Set the PtRequest structure for filter operation + // + PtRequest->FilterOptions.AddrRanges[r].IsStopRange = FALSE; + + PtRequest->FilterOptions.AddrRanges[r].Start = Ranges[r].Start; + PtRequest->FilterOptions.AddrRanges[r].End = Ranges[r].End; + } + + for (INT32 r = 0; r < 4; r++) + { + if (StopRanges[r].Active) + { + if (StopRanges[r].IsModule) + ShowMessages(" stoprange%d : module '%s'\n", r + 1, StopRanges[r].ModuleName.c_str()); + else + ShowMessages(" stoprange%d : 0x%llx - 0x%llx\n", r + 1, StopRanges[r].Start, StopRanges[r].End); + } + + // + // Set the PtRequest structure for filter operation + // + PtRequest->FilterOptions.AddrRanges[r].IsStopRange = TRUE; + + PtRequest->FilterOptions.AddrRanges[r].Start = Ranges[r].Start; + PtRequest->FilterOptions.AddrRanges[r].End = Ranges[r].End; + } + + // + // Set the PtRequest structure for filter operation + // + PtRequest->PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FILTER; +} + +/** + * @brief Parse and display !pt packet parameters + * @param CommandTokens The command tokens to parse + * @param PtRequest The PT request structure to fill with parsed options + * + * @return VOID + */ +static VOID +CommandPtParsePacket(vector & CommandTokens, HYPERTRACE_PT_OPERATION_PACKETS * PtRequest) +{ + if (CommandTokens.size() < 3) + { + ShowMessages("err, 'packet' requires at least one option\n\n"); + CommandPtHelp(); + return; + } + + BOOLEAN PktPsb = FALSE; + BOOLEAN PktPip = FALSE; + BOOLEAN PktTsc = FALSE; + BOOLEAN PktMtc = FALSE; + BOOLEAN PktCyc = FALSE; + BOOLEAN PktTnt = FALSE; + BOOLEAN PktTip = FALSE; + BOOLEAN PktFup = FALSE; + BOOLEAN PktMode = FALSE; + + for (SIZE_T i = 2; i < CommandTokens.size(); i++) + { + if (CompareLowerCaseStrings(CommandTokens.at(i), "psb")) + PktPsb = TRUE; + else if (CompareLowerCaseStrings(CommandTokens.at(i), "pip")) + PktPip = TRUE; + else if (CompareLowerCaseStrings(CommandTokens.at(i), "tsc")) + PktTsc = TRUE; + else if (CompareLowerCaseStrings(CommandTokens.at(i), "mtc")) + PktMtc = TRUE; + else if (CompareLowerCaseStrings(CommandTokens.at(i), "cyc")) + PktCyc = TRUE; + else if (CompareLowerCaseStrings(CommandTokens.at(i), "tnt")) + PktTnt = TRUE; + else if (CompareLowerCaseStrings(CommandTokens.at(i), "tip")) + PktTip = TRUE; + else if (CompareLowerCaseStrings(CommandTokens.at(i), "fup")) + PktFup = TRUE; + else if (CompareLowerCaseStrings(CommandTokens.at(i), "mode")) + PktMode = TRUE; + else + { + ShowMessages("err, unknown 'packet' option '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(i)).c_str()); + CommandPtHelp(); + return; + } + } + + // + // Show parsed packet options + // + ShowMessages("PT packet filter:\n"); + + if (PktPsb) + { + ShowMessages(" packet type: PSB (Packet Stream Boundary)\n"); + + PtRequest->PacketOptions.PSB = 1; + } + if (PktPip) + { + ShowMessages(" packet type: PIP (Paging Information Packet)\n"); + + PtRequest->PacketOptions.PIP = 1; + } + if (PktTsc) + { + ShowMessages(" packet type: TSC (Timestamp Counter)\n"); + + PtRequest->PacketOptions.TSC = 1; + } + if (PktMtc) + { + ShowMessages(" packet type: MTC (Mini Timestamp Counter)\n"); + + PtRequest->PacketOptions.MTC = 1; + } + if (PktCyc) + { + ShowMessages(" packet type: CYC (Cycle Counter)\n"); + + PtRequest->PacketOptions.CYC = 1; + } + if (PktTnt) + { + ShowMessages(" packet type: TNT (Taken/Not-Taken)\n"); + + PtRequest->PacketOptions.TNT = 1; + } + if (PktTip) + { + ShowMessages(" packet type: TIP (Target IP)\n"); + + PtRequest->PacketOptions.TNT = 1; + } + if (PktFup) + { + ShowMessages(" packet type: FUP (Flow Update Packet)\n"); + + PtRequest->PacketOptions.FUP = 1; + } + if (PktMode) + { + ShowMessages(" packet type: MODE (Mode packet)\n"); + + PtRequest->PacketOptions.MODE = 1; + } + + // + // Set the PtRequest structure for packet operation + // + PtRequest->PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_PACKET; +} + +/** + * @brief !pt command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandPt(vector CommandTokens, string Command) +{ + HYPERTRACE_PT_OPERATION_PACKETS PtRequest = {}; + + if (CommandTokens.size() == 1) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandPtHelp(); + return; + } + + // + // Parse subcommands + // + if (CompareLowerCaseStrings(CommandTokens.at(1), "enable")) + { + // + // Parse and display enable options for !pt enable command + // + CommandPtParseEnable(CommandTokens, &PtRequest); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "disable")) + { + if (CommandTokens.size() != 2) + { + ShowMessages("err, 'disable' takes no arguments\n\n"); + CommandPtHelp(); + return; + } + + // + // Parse and display disable options for !pt disable command + // + CommandPtSendDisable(); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "pause")) + { + if (CommandTokens.size() != 2) + { + ShowMessages("err, 'pause' takes no arguments\n\n"); + CommandPtHelp(); + return; + } + + // + // Parse and display pause options for !pt pause command + // + CommandPtSendPause(); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "resume")) + { + if (CommandTokens.size() != 2) + { + ShowMessages("err, 'resume' takes no arguments\n\n"); + CommandPtHelp(); + return; + } + + // + // Parse and display resume options for !pt resume command + // + CommandPtSendResume(); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "flush")) + { + if (CommandTokens.size() != 2) + { + ShowMessages("err, 'flush' takes no arguments\n\n"); + CommandPtHelp(); + return; + } + + // + // Parse and display flush options for !pt flush command + // + CommandPtSendFlush(); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "dump")) + { + // + // Parse and display dump options for !pt dump command + // + CommandPtParseDump(CommandTokens, &PtRequest); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "filter")) + { + // + // Parse and display filter options for !pt filter command + // + CommandPtParseFilter(CommandTokens, &PtRequest); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "packet")) + { + // + // Parse and display packet options for !pt packet command + // + CommandPtParsePacket(CommandTokens, &PtRequest); + } + else + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandPtHelp(); + } + + // + // Send the PT request to the debugger + // + CommandPtSendRequest(&PtRequest); +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/pte.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pte.cpp similarity index 79% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/pte.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pte.cpp index 88f4ac53..7618f598 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/pte.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pte.cpp @@ -14,6 +14,7 @@ // // Global Variables // +extern BOOLEAN g_IsKdModuleLoaded; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; @@ -83,24 +84,25 @@ CommandPteShowResults(UINT64 TargetVa, PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS /** * @brief !pte command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandPte(vector SplitCommand, string Command) +CommandPte(vector CommandTokens, string Command) { BOOL Status; ULONG ReturnedLength; UINT64 TargetVa; UINT32 Pid = 0; DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS AddressDetails = {0}; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - if (SplitCommand.size() == 1 || SplitCommand.size() >= 5 || - SplitCommand.size() == 3) + if (CommandTokens.size() == 1 || CommandTokens.size() >= 5 || + CommandTokens.size() == 3) { - ShowMessages("incorrect use of the '!pte'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandPteHelp(); return; } @@ -114,18 +116,18 @@ CommandPte(vector SplitCommand, string Command) Pid = g_ActiveProcessDebuggingState.ProcessId; } - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { // // It's just an address for current process // - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(1), &TargetVa)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)), &TargetVa)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); return; } } @@ -134,37 +136,37 @@ CommandPte(vector SplitCommand, string Command) // // It might be address + pid // - if (!SplitCommand.at(1).compare("pid")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "pid")) { - if (!ConvertStringToUInt32(SplitCommand.at(2), &Pid)) + if (!ConvertTokenToUInt32(CommandTokens.at(2), &Pid)) { ShowMessages("incorrect address, please enter a valid process id\n"); return; } - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(3), &TargetVa)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)), &TargetVa)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(3).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)).c_str()); return; } } - else if (!SplitCommand.at(2).compare("pid")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "pid")) { - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(1), &TargetVa)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)), &TargetVa)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommandCaseSensitive.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); return; } - if (!ConvertStringToUInt32(SplitCommand.at(3), &Pid)) + if (!ConvertTokenToUInt32(CommandTokens.at(3), &Pid)) { ShowMessages("incorrect address, please enter a valid process id\n"); return; @@ -172,7 +174,8 @@ CommandPte(vector SplitCommand, string Command) } else { - ShowMessages("incorrect use of the '!pte'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandPteHelp(); return; } @@ -204,7 +207,7 @@ CommandPte(vector SplitCommand, string Command) } else { - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); if (Pid == 0) { diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/rev.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/rev.cpp new file mode 100644 index 00000000..53c16ce4 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/rev.cpp @@ -0,0 +1,123 @@ +/** + * @file rev.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !rev command + * @details + * @version 0.2 + * @date 2023-03-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; +extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; + +/** + * @brief help of the !rev command + * + * @return VOID + */ +VOID +CommandRevHelp() +{ + ShowMessages("!rev : uses the reversing machine module in order to reconstruct the programmer/memory assumptions.\n\n"); + + ShowMessages("syntax : \t!rev [config] [pid ProcessId (hex)]\n"); + ShowMessages("syntax : \t!rev [path Path (string)] [Parameters (string)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !rev path c:\\reverse eng\\my_file.exe\n"); + ShowMessages("\t\te.g : !rev pattern\n"); + ShowMessages("\t\te.g : !rev reconstruct\n"); + ShowMessages("\t\te.g : !rev pattern pid 1c0\n"); + ShowMessages("\t\te.g : !rev reconstruct pid 1c0\n"); +} + +/** + * @brief !rev command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandRev(vector CommandTokens, string Command) +{ + REVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST RevRequest = {0}; + BOOLEAN SetPid = FALSE; + UINT32 TargetPid = NULL; + BOOLEAN IgnoreFirstCommand = TRUE; + REVERSING_MACHINE_RECONSTRUCT_MEMORY_MODE Mode = REVERSING_MACHINE_RECONSTRUCT_MEMORY_MODE_UNKNOWN; + REVERSING_MACHINE_RECONSTRUCT_MEMORY_TYPE Type = REVERSING_MACHINE_RECONSTRUCT_MEMORY_TYPE_UNKNOWN; + + // + // Interpret command specific details + // + for (auto Section : CommandTokens) + { + if (CompareLowerCaseStrings(Section, "!rev") && IgnoreFirstCommand) + { + IgnoreFirstCommand = FALSE; + continue; + } + else if (CompareLowerCaseStrings(Section, "pid") && !SetPid) + { + SetPid = TRUE; + } + else if (SetPid) + { + if (!ConvertTokenToUInt32(Section, &TargetPid)) + { + // + // couldn't resolve or unknown parameter + // + ShowMessages("err, couldn't resolve error at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); + CommandRevHelp(); + return; + } + SetPid = FALSE; + } + else if (CompareLowerCaseStrings(Section, "pattern")) + { + Type = REVERSING_MACHINE_RECONSTRUCT_MEMORY_TYPE_PATTERN; + } + else if (CompareLowerCaseStrings(Section, "reconstruct")) + { + Type = REVERSING_MACHINE_RECONSTRUCT_MEMORY_TYPE_RECONSTRUCT; + } + else + { + // + // Unknown parameter + // + ShowMessages("err, couldn't resolve error at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); + CommandRevHelp(); + return; + } + } + + if (SetPid) + { + ShowMessages("err, please enter a valid process id in hex format, " + "or if you want to use it in decimal format, add '0n' " + "prefix to the number\n"); + return; + } + + RevRequest.ProcessId = TargetPid; + + // ================================================================================ + + // + // Send the request to the hypervisor (kernel) + // + RevRequestService(&RevRequest); +} diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/smi.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/smi.cpp new file mode 100644 index 00000000..0efa6c41 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/smi.cpp @@ -0,0 +1,178 @@ +/** + * @file smi.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !smi command + * @details + * @version 0.15 + * @date 2025-08-02 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; + +/** + * @brief help of the !smi command + * + * @return VOID + */ +VOID +CommandSmiHelp() +{ + ShowMessages("!smi : shows details and triggers functionalities related to System Management Interrupt (SMI).\n"); + ShowMessages("Note : SMIs are triggered using APM I/O Decode Registers and SMI count are from MSR_SMI_COUNT MSR (0x34).\n\n"); + + ShowMessages("syntax : \t!smi [Function (string)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !smi count\n"); + ShowMessages("\t\te.g : !smi trigger\n"); +} + +/** + * @brief Send SMI requests + * + * @param SmiRequest + * + * @return VOID + */ +BOOLEAN +CommandSmiSendRequest(SMI_OPERATION_PACKETS * SmiOperationRequest) +{ + BOOL Status; + ULONG ReturnedLength; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Send the request over serial kernel debugger + // + if (!KdSendSmiPacketsToDebuggee(SmiOperationRequest, SIZEOF_SMI_OPERATION_PACKETS)) + { + return FALSE; + } + else + { + return TRUE; + } + } + else + { + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // Send IOCTL + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_PERFORM_SMI_OPERATION, // IO Control Code (IOCTL) + SmiOperationRequest, // Input Buffer to driver. + SIZEOF_SMI_OPERATION_PACKETS, // Input buffer length + SmiOperationRequest, // Output Buffer from driver. + SIZEOF_SMI_OPERATION_PACKETS, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + + return FALSE; + } + + if (SmiOperationRequest->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + return TRUE; + } + else + { + return FALSE; + } + } +} + +/** + * @brief Request to perform an SMI operation + * + * @param SmiOperation + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgPerformSmiOperation(SMI_OPERATION_PACKETS * SmiOperation) +{ + return CommandSmiSendRequest(SmiOperation); +} + +/** + * @brief !smi command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandSmi(vector CommandTokens, string Command) +{ + SMI_OPERATION_PACKETS SmiOperationRequest = {0}; + + if (CommandTokens.size() != 2) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + + CommandSmiHelp(); + return; + } + + if (CompareLowerCaseStrings(CommandTokens.at(1), "count")) + { + SmiOperationRequest.SmiOperationType = SMI_OPERATION_REQUEST_TYPE_READ_COUNT; + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "trigger")) + { + SmiOperationRequest.SmiOperationType = SMI_OPERATION_REQUEST_TYPE_TRIGGER_POWER_SMI; + } + else + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandSmiHelp(); + return; + } + + // + // Send the SMI operation request + // + if (CommandSmiSendRequest(&SmiOperationRequest)) + { + if (SmiOperationRequest.SmiOperationType == SMI_OPERATION_REQUEST_TYPE_READ_COUNT) + { + if (SmiOperationRequest.SmiCount == 0) + { + ShowMessages("SMI count: 0 (for security reasons, nested-virtualization environment (VMs) are unable to communicate with UEFI firmware)\n"); + } + else + { + ShowMessages("SMI count: 0x%x\n", SmiOperationRequest.SmiCount); + } + } + else if (SmiOperationRequest.SmiOperationType == SMI_OPERATION_REQUEST_TYPE_TRIGGER_POWER_SMI) + { + ShowMessages("power SMI triggered successfully (you can use '!smi count' to view the number of executed SMIs)\n"); + } + } + else + { + ShowErrorMessage(SmiOperationRequest.KernelStatus); + return; + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/syscall-sysret.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/syscall-sysret.cpp similarity index 81% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/syscall-sysret.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/syscall-sysret.cpp index 527e041f..4b3f887b 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/syscall-sysret.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/syscall-sysret.cpp @@ -26,12 +26,12 @@ CommandSyscallHelp() ShowMessages("syntax : \t!syscall [SyscallNumber (hex)] [pid ProcessId (hex)] [core CoreId (hex)] " "[imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] " - "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [condition { Condition (hex) }] " - "[code { Code (hex) }] [output {OutputName (string)}]\n"); + "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [asm condition { Condition (assembly/hex) }] " + "[asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("syntax : \t!syscall2 [SyscallNumber (hex)] [pid ProcessId (hex)] [core CoreId (hex)] " "[imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] " - "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [condition { Condition (hex) }] " - "[code { Code (hex) }] [output {OutputName (string)}]\n"); + "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [asm condition { Condition (assembly/hex) }] " + "[asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !syscall\n"); @@ -41,6 +41,8 @@ CommandSyscallHelp() ShowMessages("\t\te.g : !syscall 0x55 pid 400\n"); ShowMessages("\t\te.g : !syscall 0x55 core 2 pid 400\n"); ShowMessages("\t\te.g : !syscall2 0x55 core 2 pid 400\n"); + ShowMessages("\t\te.g : !syscall script { printf(\"system-call num: %%llx, at process id: %%x\\n\", @rax, $pid); }\n"); + ShowMessages("\t\te.g : !syscall asm code { nop; nop; nop }\n"); } /** @@ -58,7 +60,7 @@ CommandSysretHelp() ShowMessages("syntax : \t!sysret [pid ProcessId (hex)] [core CoreId (hex)] " "[imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] [buffer PreAllocatedBuffer (hex)] " - "[script { Script (string) }] [condition { Condition (hex) }] [code { Code (hex) }]\n"); + "[script { Script (string) }] [asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !sysret\n"); @@ -67,17 +69,20 @@ CommandSysretHelp() ShowMessages("\t\te.g : !sysret2 pid 400\n"); ShowMessages("\t\te.g : !sysret core 2 pid 400\n"); ShowMessages("\t\te.g : !sysret2 core 2 pid 400\n"); + ShowMessages("\t\te.g : !sysret script { printf(\"SYSRET instruction is executed at process id: %%x\\n\", $pid); }\n"); + ShowMessages("\t\te.g : !sysret asm code { nop; nop; nop }\n"); } /** * @brief !syscall, !syscall2 and !sysret, !sysret2 commands handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandSyscallAndSysret(vector SplitCommand, string Command) +CommandSyscallAndSysret(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -89,7 +94,6 @@ CommandSyscallAndSysret(vector SplitCommand, string Command) UINT32 ActionScriptLength = 0; UINT64 SpecialTarget = DEBUGGER_EVENT_SYSCALL_ALL_SYSRET_OR_SYSCALLS; BOOLEAN GetSyscallNumber = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; string Cmd; @@ -97,12 +101,12 @@ CommandSyscallAndSysret(vector SplitCommand, string Command) // Interpret and fill the general event and action fields // // - Cmd = SplitCommand.at(0); + Cmd = GetLowerStringFromCommandToken(CommandTokens.at(0)); + if (!Cmd.compare("!syscall") || !Cmd.compare("!syscall2")) { if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, SYSCALL_HOOK_EFER_SYSCALL, &Event, &EventLength, @@ -120,8 +124,7 @@ CommandSyscallAndSysret(vector SplitCommand, string Command) else { if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, SYSCALL_HOOK_EFER_SYSRET, &Event, &EventLength, @@ -149,12 +152,12 @@ CommandSyscallAndSysret(vector SplitCommand, string Command) // if (!Cmd.compare("!syscall") || !Cmd.compare("!syscall2")) { - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!syscall") || - !Section.compare("!syscall2") || - !Section.compare("!sysret") || - !Section.compare("!sysret2")) + if (CompareLowerCaseStrings(Section, "!syscall") || + CompareLowerCaseStrings(Section, "!syscall2") || + CompareLowerCaseStrings(Section, "!sysret") || + CompareLowerCaseStrings(Section, "!sysret2")) { continue; } @@ -164,12 +167,15 @@ CommandSyscallAndSysret(vector SplitCommand, string Command) // // It's probably a syscall address // - if (!ConvertStringToUInt64(Section, &SpecialTarget)) + if (!SymbolConvertNameOrExprToAddress( + GetCaseSensitiveStringFromCommandToken(Section), + &SpecialTarget)) { // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); if (!Cmd.compare("!syscall") || !Cmd.compare("!syscall2")) { @@ -193,7 +199,8 @@ CommandSyscallAndSysret(vector SplitCommand, string Command) // // Unknown parameter // - ShowMessages("unknown parameter '%s'\n\n", Section.c_str()); + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); if (!Cmd.compare("!syscall") || !Cmd.compare("!syscall2")) { diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/trace.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/trace.cpp similarity index 79% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/trace.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/trace.cpp index b4609d7f..9c62a9c1 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/trace.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/trace.cpp @@ -23,12 +23,13 @@ CommandTraceHelp() ShowMessages("syntax : \t!trace [TraceType (string)] [pid ProcessId (hex)] [core CoreId (hex)] [imm IsImmediate (yesno)] " "[sc EnableShortCircuiting (onoff)] [buffer PreAllocatedBuffer (hex)] [script { Script (string) }] " - "[condition { Condition (hex) }] [code { Code (hex) }] [output {OutputName (string)}]\n"); + "[asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !trace step-out\n"); ShowMessages("\t\te.g : !trace step-in pid 1c0\n"); ShowMessages("\t\te.g : !trace instrument-step core 2 pid 400\n"); + ShowMessages("\t\te.g : !trace instrument-step asm code { nop; nop; nop }\n"); ShowMessages("\n"); ShowMessages("valid trace types: \n"); @@ -41,12 +42,13 @@ CommandTraceHelp() /** * @brief !trace command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandTrace(vector SplitCommand, string Command) +CommandTrace(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -56,7 +58,6 @@ CommandTrace(vector SplitCommand, string Command) UINT32 ActionBreakToDebuggerLength = 0; UINT32 ActionCustomCodeLength = 0; UINT32 ActionScriptLength = 0; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; BOOLEAN SetTraceType = FALSE; DEBUGGER_EVENT_TRACE_TYPE TargetTrace = DEBUGGER_EVENT_TRACE_TYPE_INVALID; @@ -66,8 +67,7 @@ CommandTrace(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, TRAP_EXECUTION_INSTRUCTION_TRACE, &Event, &EventLength, @@ -85,9 +85,10 @@ CommandTrace(vector SplitCommand, string Command) // // Check for size // - if (SplitCommand.size() > 2) + if (CommandTokens.size() > 2) { - ShowMessages("incorrect use of the '!trace'\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandTraceHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); @@ -97,25 +98,25 @@ CommandTrace(vector SplitCommand, string Command) // // Interpret command specific details (if any) // - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - if (!Section.compare("!trace")) + if (CompareLowerCaseStrings(Section, "!trace")) { continue; } - else if ((!Section.compare("step-in") || !Section.compare("stepin") || !Section.compare("step")) && !SetTraceType) + else if ((CompareLowerCaseStrings(Section, "step-in") || CompareLowerCaseStrings(Section, "stepin") || CompareLowerCaseStrings(Section, "step")) && !SetTraceType) { TargetTrace = DEBUGGER_EVENT_TRACE_TYPE_STEP_IN; SetTraceType = TRUE; } - else if ((!Section.compare("step-out") || !Section.compare("stepout")) && !SetTraceType) + else if ((CompareLowerCaseStrings(Section, "step-out") || CompareLowerCaseStrings(Section, "stepout")) && !SetTraceType) { TargetTrace = DEBUGGER_EVENT_TRACE_TYPE_STEP_OUT; SetTraceType = TRUE; } - else if ((!Section.compare("step-instrument") || !Section.compare("instrument-step") || - !Section.compare("instrumentstep") || - !Section.compare("instrument-step-in")) && + else if ((CompareLowerCaseStrings(Section, "step-instrument") || CompareLowerCaseStrings(Section, "instrument-step") || + CompareLowerCaseStrings(Section, "instrumentstep") || + CompareLowerCaseStrings(Section, "instrument-step-in")) && !SetTraceType) { TargetTrace = DEBUGGER_EVENT_TRACE_TYPE_INSTRUMENTATION_STEP_IN; @@ -127,8 +128,7 @@ CommandTrace(vector SplitCommand, string Command) // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n\n", - Section.c_str()); - + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandTraceHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/track.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/track.cpp new file mode 100644 index 00000000..fee0841c --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/track.cpp @@ -0,0 +1,330 @@ +/** + * @file track.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !track command + * @details + * @version 0.3 + * @date 2023-05-05 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsInstrumentingInstructions; +extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; +extern BOOLEAN g_AddressConversion; + +// +// Local (global) variables +// +UINT32 NumberOfCallsIdentation = 0; +BOOLEAN IsCallInstructionVisited = FALSE; +BOOLEAN ShowRegs = FALSE; +volatile BOOLEAN RequestShowingRegs = FALSE; + +/** + * @brief help of the !track command + * + * @return VOID + */ +VOID +CommandTrackHelp() +{ + ShowMessages( + "!track : tracks instructions from user-mode to kernel-mode or kernel-mode to user-mode " + "to create call tree. Please note that it's highly recommended to configure symbols before " + "using this command as it maps addresses to corresponding function names.\n\n"); + + ShowMessages("syntax : \t!track [tree] [Count (hex)]\n"); + ShowMessages("syntax : \t!track [reg] [Count (hex)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !track tree 10000\n"); + ShowMessages("\t\te.g : !track reg 10000\n"); +} + +/** + * @brief handler of !track command + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandTrack(vector CommandTokens, string Command) +{ + UINT32 StepCount; + string SymbolServer; + + // + // Validate the commands + // + if (CommandTokens.size() >= 4) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandTrackHelp(); + return; + } + + // + // Check if we're in VMI mode + // + if (g_ActiveProcessDebuggingState.IsActive) + { + ShowMessages("the tracking mechanism is only supported in Debugger Mode\n"); + return; + } + + // + // Show recommendation + // + if (!CommandSettingsGetValueFromConfigFile("SymbolServer", SymbolServer)) + { + ShowMessages("it is recommended to configure the symbol path '.sympath' and load " + "symbols before using the '!track' command command to obtain results with function " + "names\n"); + } + + // + // Reset the details of indentation and regs + // + NumberOfCallsIdentation = 0; + IsCallInstructionVisited = FALSE; + ShowRegs = FALSE; + RequestShowingRegs = FALSE; + + // + // Set default of stepping (tracking) + // + StepCount = DEBUGGER_REMOTE_TRACKING_DEFAULT_COUNT_OF_STEPPING; + + // + // Check parameters + // + for (auto Section : CommandTokens) + { + if (CompareLowerCaseStrings(Section, "!track") || CompareLowerCaseStrings(Section, "track")) + { + continue; + } + + // + // check if the second param is a number + // + if (ConvertTokenToUInt32(Section, &StepCount)) + { + continue; + } + else if (CompareLowerCaseStrings(Section, "tree")) + { + // + // Default + // + ShowRegs = FALSE; + } + else if (CompareLowerCaseStrings(Section, "reg")) + { + ShowRegs = TRUE; + } + else + { + ShowMessages("err, couldn't resolve error at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); + return; + } + } + + // + // Check if the remote serial debuggee or user debugger are paused or not + // + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Indicate that we're instrumenting + // + g_IsInstrumentingInstructions = TRUE; + + for (SIZE_T i = 0; i < StepCount; i++) + { + // + // For logging purpose + // + // ShowMessages("percentage : %f %% (%x)\n", 100.0 * (i / + // (float)StepCount), i); + // + + // + // It's stepping over serial connection in kernel debugger + // + SteppingInstrumentationStepInForTracking(); + + if (ShowRegs && RequestShowingRegs) + { + RequestShowingRegs = FALSE; + + // + // Show registers + // + HyperDbgRegisterShowAll(); + + ShowMessages("\n"); + } + + // + // Check if user pressed CTRL+C + // + if (!g_IsInstrumentingInstructions) + { + break; + } + } + + // + // We're not instrumenting instructions anymore + // + g_IsInstrumentingInstructions = FALSE; + } + else + { + ShowMessages("err, tracking is not valid in the current context, you " + "should connect to a debuggee\n"); + } +} + +/** + * @brief Handle received 'call' or 'ret' + * + * @param BufferToDisassemble + * @param BuffLength + * @param Isx86_64 + * @param RipAddress + * + * @return VOID + */ +VOID +CommandTrackHandleReceivedInstructions(UCHAR * BufferToDisassemble, + UINT32 BuffLength, + BOOLEAN Isx86_64, + UINT64 RipAddress) +{ + BOOLEAN IsRet = FALSE; + + // + // By calling this function, it acts as a callback that in case of the 'call' and the 'ret' instructions + // the callbacks will be called + // + HyperDbgCheckWhetherTheCurrentInstructionIsCallOrRet(BufferToDisassemble, RipAddress, BuffLength, Isx86_64, &IsRet); +} + +/** + * @brief Handle received 'call' + * + * @param NameOfFunctionFromSymbols + * @param ComputedAbsoluteAddress + * + * @return VOID + */ +VOID +CommandTrackHandleReceivedCallInstructions(const CHAR * NameOfFunctionFromSymbols, + UINT64 ComputedAbsoluteAddress) +{ + // + // One 'call' instruction is visited + // + IsCallInstructionVisited = TRUE; + + CHAR Utf8String1[] = "\xE2\x94\x82\x20\x20"; + + for (SIZE_T i = 0; i < NumberOfCallsIdentation; i++) + { + PlatformWriteConsole(Utf8String1, sizeof(Utf8String1) - 1); + } + + // + // Write the UTF-8 encoded character sequence to the console + // + // CHAR Utf8String[] = "\xE2\x94\x9C\xE2\x94\x80\xE2\x94\x80"; + CHAR Utf8String[] = "\xE2\x94\x8C\xE2\x94\x80\xE2\x94\x80"; + PlatformWriteConsole(Utf8String, sizeof(Utf8String) - 1); + + if (NameOfFunctionFromSymbols != NULL) + { + ShowMessages(" %s (%s)\n", NameOfFunctionFromSymbols, SeparateTo64BitValue(ComputedAbsoluteAddress).c_str()); + } + else + { + ShowMessages(" %s\n", SeparateTo64BitValue(ComputedAbsoluteAddress).c_str()); + } + + if (ShowRegs) + { + RequestShowingRegs = TRUE; + } + + NumberOfCallsIdentation++; +} + +/** + * @brief Handle received 'ret' + * + * @param CurrentRip + * + * @return VOID + */ +VOID +CommandTrackHandleReceivedRetInstructions(UINT64 CurrentRip) +{ + UINT64 UsedBaseAddress = NULL; + BOOLEAN IsNameShowed = FALSE; + + if (IsCallInstructionVisited) + { + if (NumberOfCallsIdentation != 0) + { + NumberOfCallsIdentation--; + } + } + + CHAR Utf8String1[] = "\xE2\x94\x82\x20\x20"; + + for (SIZE_T i = 0; i < NumberOfCallsIdentation; i++) + { + PlatformWriteConsole(Utf8String1, sizeof(Utf8String1) - 1); + } + + // + // Write the UTF-8 encoded character sequence to the console + // + CHAR Utf8String[] = "\xE2\x94\x94\xE2\x94\x80\xE2\x94\x80\x20"; + PlatformWriteConsole(Utf8String, sizeof(Utf8String) - 1); + + // + // Apply addressconversion of settings here + // + if (g_AddressConversion) + { + // + // Showing function names here + // + if (SymbolShowFunctionNameBasedOnAddress(CurrentRip, &UsedBaseAddress)) + { + // + // The symbol address is showed + // + IsNameShowed = TRUE; + ShowMessages(" (%s)\n", SeparateTo64BitValue(CurrentRip).c_str()); + } + } + + if (!IsNameShowed) + { + ShowMessages("%s \n", SeparateTo64BitValue(CurrentRip).c_str()); + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/tsc.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/tsc.cpp similarity index 84% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/tsc.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/tsc.cpp index 09833add..44c2706e 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/tsc.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/tsc.cpp @@ -23,24 +23,27 @@ CommandTscHelp() ShowMessages("syntax : \t!tsc [pid ProcessId (hex)] [core CoreId (hex)] [imm IsImmediate (yesno)] " "[sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] [buffer PreAllocatedBuffer (hex)] " - "[script { Script (string) }] [condition { Condition (hex) }] [code { Code (hex) }] " + "[script { Script (string) }] [asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] " "[output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !tsc\n"); ShowMessages("\t\te.g : !tsc pid 400\n"); ShowMessages("\t\te.g : !tsc core 2 pid 400\n"); + ShowMessages("\t\te.g : !tsc script { printf(\"RDTSC/P instruction called at: %%llx\\n\", @rip); }\n"); + ShowMessages("\t\te.g : !tsc asm code { nop; nop; nop }\n"); } /** * @brief handler of !tsc command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandTsc(vector SplitCommand, string Command) +CommandTsc(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -50,7 +53,6 @@ CommandTsc(vector SplitCommand, string Command) UINT32 ActionBreakToDebuggerLength = 0; UINT32 ActionCustomCodeLength = 0; UINT32 ActionScriptLength = 0; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // @@ -58,8 +60,7 @@ CommandTsc(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, TSC_INSTRUCTION_EXECUTION, &Event, &EventLength, @@ -77,9 +78,11 @@ CommandTsc(vector SplitCommand, string Command) // // Check for size // - if (SplitCommand.size() > 1) + if (CommandTokens.size() > 1) { - ShowMessages("incorrect use of the '!tsc'\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandTscHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/unhide.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/unhide.cpp similarity index 72% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/unhide.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/unhide.cpp index 0f2c796a..7ede211d 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/unhide.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/unhide.cpp @@ -11,6 +11,11 @@ */ #include "pch.h" +// +// Global Variables +// +extern BOOLEAN g_IsVmmModuleLoaded; + /** * @brief help of the !unhide command * @@ -19,7 +24,7 @@ VOID CommandUnhideHelp() { - ShowMessages("!unhide : reverts the transparency measures of the '!hide' command.\n\n"); + ShowMessages("!unhide : reverts the transparency measures of the '!hide' command and exits the transparent mode.\n\n"); ShowMessages("syntax : \t!unhide\n"); @@ -28,30 +33,21 @@ CommandUnhideHelp() } /** - * @brief !unhide command handler + * @brief Disable transparent mode * - * @param SplitCommand - * @param Command - * @return VOID + * @return BOOLEAN */ -VOID -CommandUnhide(vector SplitCommand, string Command) +BOOLEAN +HyperDbgDisableTransparentMode() { BOOLEAN Status; ULONG ReturnedLength; DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE UnhideRequest = {0}; - if (SplitCommand.size() >= 2) - { - ShowMessages("incorrect use of the '!unhide'\n\n"); - CommandUnhideHelp(); - return; - } - // // Check if debugger is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // We don't wanna hide the debugger and make transparent vm-exits @@ -77,20 +73,43 @@ CommandUnhide(vector SplitCommand, string Command) if (!Status) { ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); - return; + return FALSE; } if (UnhideRequest.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) { ShowMessages("transparent debugging successfully disabled :)\n"); - } - else if (UnhideRequest.KernelStatus == - DEBUGGER_ERROR_DEBUGGER_ALREADY_UHIDE) - { - ShowMessages("debugger is not in transparent-mode\n"); + return TRUE; } else { - ShowMessages("unknown error occurred :(\n"); + ShowErrorMessage(UnhideRequest.KernelStatus); + return FALSE; } } + +/** + * @brief !unhide command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandUnhide(vector CommandTokens, string Command) +{ + if (CommandTokens.size() >= 2) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + + CommandUnhideHelp(); + return; + } + + // + // Disable transparent mode + // + HyperDbgDisableTransparentMode(); +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/va2pa.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/va2pa.cpp similarity index 75% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/va2pa.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/va2pa.cpp index 189fc739..795462de 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/va2pa.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/va2pa.cpp @@ -14,6 +14,7 @@ // // Global Variables // +extern BOOLEAN g_IsKdModuleLoaded; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; @@ -41,24 +42,24 @@ CommandVa2paHelp() /** * @brief !va2pa command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandVa2pa(vector SplitCommand, string Command) +CommandVa2pa(vector CommandTokens, string Command) { BOOL Status; ULONG ReturnedLength; UINT64 TargetVa; UINT32 Pid = 0; DEBUGGER_VA2PA_AND_PA2VA_COMMANDS AddressDetails = {0}; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - if (SplitCommand.size() == 1 || SplitCommand.size() >= 5 || - SplitCommand.size() == 3) + if (CommandTokens.size() == 1 || CommandTokens.size() >= 5 || CommandTokens.size() == 3) { - ShowMessages("incorrect use of the '!va2pa'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandVa2paHelp(); return; } @@ -72,18 +73,18 @@ CommandVa2pa(vector SplitCommand, string Command) Pid = g_ActiveProcessDebuggingState.ProcessId; } - if (SplitCommand.size() == 2) + if (CommandTokens.size() == 2) { // // It's just an address for current process // - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(1), &TargetVa)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)), &TargetVa)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); return; } } @@ -92,37 +93,37 @@ CommandVa2pa(vector SplitCommand, string Command) // // It might be address + pid // - if (!SplitCommand.at(1).compare("pid")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "pid")) { - if (!ConvertStringToUInt32(SplitCommand.at(2), &Pid)) + if (!ConvertTokenToUInt32(CommandTokens.at(2), &Pid)) { ShowMessages("incorrect address, please enter a valid process id\n"); return; } - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(3), &TargetVa)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)), &TargetVa)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(3).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)).c_str()); return; } } - else if (!SplitCommand.at(2).compare("pid")) + else if (CompareLowerCaseStrings(CommandTokens.at(2), "pid")) { - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(1), &TargetVa)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)), &TargetVa)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); return; } - if (!ConvertStringToUInt32(SplitCommand.at(3), &Pid)) + if (!ConvertTokenToUInt32(CommandTokens.at(3), &Pid)) { ShowMessages("incorrect address, please enter a valid process id\n"); return; @@ -130,7 +131,8 @@ CommandVa2pa(vector SplitCommand, string Command) } else { - ShowMessages("incorrect use of the '!va2pa'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandVa2paHelp(); return; } @@ -163,7 +165,7 @@ CommandVa2pa(vector SplitCommand, string Command) } else { - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); if (Pid == 0) { diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/vmcall.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/vmcall.cpp similarity index 84% rename from hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/vmcall.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/vmcall.cpp index 1267d6e6..52e81720 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/extension-commands/vmcall.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/vmcall.cpp @@ -23,24 +23,27 @@ CommandVmcallHelp() ShowMessages("syntax : \t!vmcall [pid ProcessId (hex)] [core CoreId (hex)] [imm IsImmediate (yesno)] " "[sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] [buffer PreAllocatedBuffer (hex)] " - "[script { Script (string) }] [condition { Condition (hex) }] [code { Code (hex) }] " + "[script { Script (string) }] [asm condition { Condition (assembly/hex) }] [asm code { Code (assembly/hex) }] " "[output {OutputName (string)}]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : !vmcall\n"); ShowMessages("\t\te.g : !vmcall pid 400\n"); ShowMessages("\t\te.g : !vmcall core 2 pid 400\n"); + ShowMessages("\t\te.g : !vmcall script { printf(\"VMCALL executed with context: %%llx\\n\", $context); }\n"); + ShowMessages("\t\te.g : !vmcall asm code { nop; nop; nop }\n"); } /** * @brief !vmcall command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandVmcall(vector SplitCommand, string Command) +CommandVmcall(vector CommandTokens, string Command) { PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; @@ -50,7 +53,6 @@ CommandVmcall(vector SplitCommand, string Command) UINT32 ActionBreakToDebuggerLength = 0; UINT32 ActionCustomCodeLength = 0; UINT32 ActionScriptLength = 0; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; // @@ -58,8 +60,7 @@ CommandVmcall(vector SplitCommand, string Command) // // if (!InterpretGeneralEventAndActionsFields( - &SplitCommand, - &SplitCommandCaseSensitive, + &CommandTokens, VMCALL_INSTRUCTION_EXECUTION, &Event, &EventLength, @@ -77,9 +78,10 @@ CommandVmcall(vector SplitCommand, string Command) // // Check for size // - if (SplitCommand.size() > 1) + if (CommandTokens.size() > 1) { - ShowMessages("incorrect use of the '!vmcall'\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandVmcallHelp(); FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/xsetbv.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/xsetbv.cpp new file mode 100644 index 00000000..ab5d5ca0 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/xsetbv.cpp @@ -0,0 +1,171 @@ +/** + * @file xsetbv.cpp + * @author unrustled.jimmies + * @brief !xsetbv command + * @details This command + * @version 0.16 + * @date 2025-08-20 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief help of the !xsetbv command + * + * @return VOID + */ +VOID +CommandXsetbvHelp() +{ + ShowMessages("!xsetbv : monitors execution of xsetbv instructions.\n\n"); + + ShowMessages("syntax : \t!xsetbv [Xcr (hex)] [pid ProcessId (hex)] [core CoreId (hex)] " + "[imm IsImmediate (yesno)] [sc EnableShortCircuiting (onoff)] [stage CallingStage (prepostall)] " + "[buffer PreAllocatedBuffer (hex)] [script { Script (string) }] [asm condition { Condition (assembly/hex) }] " + "[asm code { Code (assembly/hex) }] [output {OutputName (string)}]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !xsetbv\n"); + ShowMessages("\t\te.g : !xsetbv 0\n"); + ShowMessages("\t\te.g : !xsetbv pid 400\n"); + ShowMessages("\t\te.g : !xsetbv core 2 pid 400\n"); + ShowMessages("\t\te.g : !xsetbv script { printf(\"XSETBV instruction is executed with XCR index: %%llx\\n\", @rcx); }\n"); + ShowMessages("\t\te.g : !xsetbv asm code { nop; nop; nop }\n"); +} + +/** + * @brief !xsetbv command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandXsetbv(vector CommandTokens, string Command) +{ + PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; + PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; + PDEBUGGER_GENERAL_ACTION ActionCustomCode = NULL; + PDEBUGGER_GENERAL_ACTION ActionScript = NULL; + BOOLEAN GetXcr = FALSE; + UINT32 EventLength; + UINT64 SpecialTarget = 0; + UINT32 ActionBreakToDebuggerLength = 0; + UINT32 ActionCustomCodeLength = 0; + UINT32 ActionScriptLength = 0; + DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; + + // + // Interpret and fill the general event and action fields + // + if (!InterpretGeneralEventAndActionsFields( + &CommandTokens, + XSETBV_INSTRUCTION_EXECUTION, + &Event, + &EventLength, + &ActionBreakToDebugger, + &ActionBreakToDebuggerLength, + &ActionCustomCode, + &ActionCustomCodeLength, + &ActionScript, + &ActionScriptLength, + &EventParsingErrorCause)) + { + return; + } + + // + // Interpret command specific details (if any), of XCR index + // + for (auto Section : CommandTokens) + { + if (CompareLowerCaseStrings(Section, "!xsetbv")) + { + continue; + } + else if (!GetXcr) + { + // + // It's probably an XCR index + // + if (!ConvertTokenToUInt64(Section, &SpecialTarget)) + { + // + // Unknown parameter + // + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); + CommandXsetbvHelp(); + + FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); + return; + } + else + { + // + // A special XCR is set + // + GetXcr = TRUE; + } + } + else + { + // + // Unknown parameter + // + ShowMessages("unknown parameter '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); + + CommandXsetbvHelp(); + + FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); + return; + } + } + + // + // Set the target XCR (if not specific then it means all XCRs) + // + Event->Options.OptionalParam1 = GetXcr; + + if (GetXcr) + { + Event->Options.OptionalParam2 = SpecialTarget; + } + + // + // Send the ioctl to the kernel for event registration + // + if (!SendEventToKernel(Event, EventLength)) + { + // + // There was an error, probably the handle was not initialized + // we have to free the Action before exit, it is because, we + // already freed the Event and string buffers + // + + FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); + return; + } + + // + // Add the event to the kernel + // + if (!RegisterActionToEvent(Event, + ActionBreakToDebugger, + ActionBreakToDebuggerLength, + ActionCustomCode, + ActionCustomCodeLength, + ActionScript, + ActionScriptLength)) + { + // + // There was an error + // + FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); + return; + } +} diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/hwdbg-commands/hw.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/hwdbg-commands/hw.cpp new file mode 100644 index 00000000..036355e9 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/hwdbg-commands/hw.cpp @@ -0,0 +1,80 @@ +/** + * @file hw.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !hw command + * @details + * @version 0.11 + * @date 2024-09-29 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_HwdbgInstanceInfoIsValid; + +/** + * @brief help of the !hw command + * + * @return VOID + */ +VOID +CommandHwHelp() +{ + ShowMessages("!hw : runs a hardware script in the target device.\n\n"); + + ShowMessages("syntax : \t!hw script [script { Script (string) }]\n"); + ShowMessages("syntax : \t!hw script [unload]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !hw script { @hw_pin1 = 0; }\n"); + ShowMessages("\t\te.g : !hw unload\n"); +} + +/** + * @brief !hw command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandHw(vector CommandTokens, string Command) +{ + if (CommandTokens.size() >= 2 && CompareLowerCaseStrings(CommandTokens.at(1), "script")) + { + // + // Perform test with default file path and initial BRAM buffer size + // + HwdbgScriptRunScript(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str(), + HWDBG_TEST_READ_INSTANCE_INFO_PATH, + HWDBG_TEST_WRITE_SCRIPT_BUFFER_PATH, + DEFAULT_INITIAL_BRAM_BUFFER_SIZE); + } + else if (CommandTokens.size() >= 2 && + (CompareLowerCaseStrings(CommandTokens.at(1), "eval") || CompareLowerCaseStrings(CommandTokens.at(1), "evaluation"))) + { + // + // Perform test evaluation + // + ScriptEngineWrapperTestParserForHwdbg(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2))); + } + else if (CommandTokens.size() == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "unload")) + { + // + // Unload the script + // + g_HwdbgInstanceInfoIsValid = FALSE; + } + else + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandHwHelp(); + return; + } +} diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/hwdbg-commands/hw_clk.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/hwdbg-commands/hw_clk.cpp new file mode 100644 index 00000000..d6d5f588 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/hwdbg-commands/hw_clk.cpp @@ -0,0 +1,174 @@ +/** + * @file hw_clk.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !hw_clk command + * @details + * @version 0.9 + * @date 2024-05-29 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern HWDBG_INSTANCE_INFORMATION g_HwdbgInstanceInfo; + +/** + * @brief help of the !hw_clk command + * + * @return VOID + */ +VOID +CommandHwClkHelp() +{ + ShowMessages("!hw_clk : performs actions related to hwdbg hardware debugging events for each clock cycle.\n\n"); + + ShowMessages("syntax : \t!hw_clk [script { Script (string) }]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !hw_clk script { @hw_pin1 = 0; }\n"); +} + +/** + * @brief !hw_clk perform test + * + * @param CommandTokens + * @param InstanceFilePathToRead + * @param InstanceFilePathToSave + * @param HardwareScriptFilePathToSave + * @param InitialBramBufferSize + * + * @return BOOLEAN + */ +BOOLEAN +CommandHwClkPerformTest(vector CommandTokens, + const TCHAR * InstanceFilePathToRead, + const TCHAR * InstanceFilePathToSave, + const TCHAR * HardwareScriptFilePathToSave, + UINT32 InitialBramBufferSize) +{ + UINT32 EventLength; + DEBUGGER_EVENT_PARSING_ERROR_CAUSE EventParsingErrorCause; + PDEBUGGER_GENERAL_EVENT_DETAIL Event = NULL; + PDEBUGGER_GENERAL_ACTION ActionBreakToDebugger = NULL; + PDEBUGGER_GENERAL_ACTION ActionCustomCode = NULL; + PDEBUGGER_GENERAL_ACTION ActionScript = NULL; + UINT32 ActionBreakToDebuggerLength = 0; + UINT32 ActionCustomCodeLength = 0; + UINT32 ActionScriptLength = 0; + CHAR * ScriptBuffer = NULL; + BOOLEAN Result = FALSE; + + // + // Load the instance info + // + if (!HwdbgLoadInstanceInfo(InstanceFilePathToRead, InitialBramBufferSize)) + { + // + // No need for freeing memory so return directly + // + return FALSE; + } + + // + // Interpret and fill the general event and action fields for the target script + // + if (!InterpretGeneralEventAndActionsFields( + &CommandTokens, + (VMM_EVENT_TYPE_ENUM)NULL, // not an event + &Event, + &EventLength, + &ActionBreakToDebugger, + &ActionBreakToDebuggerLength, + &ActionCustomCode, + &ActionCustomCodeLength, + &ActionScript, + &ActionScriptLength, + &EventParsingErrorCause)) + { + // + // No need for freeing memory so return directly + // + return FALSE; + } + + // + // Print the actual script + // + ScriptBuffer = (CHAR *)((UINT64)ActionScript + sizeof(DEBUGGER_GENERAL_ACTION)); + HwdbgScriptPrintScriptBuffer(ScriptBuffer, ActionScript->ScriptBufferSize); + + // + // Create hwdbg script + // + if (!HwdbgScriptCreateHwdbgScript(ScriptBuffer, + ActionScript->ScriptBufferSize, + HardwareScriptFilePathToSave)) + { + ShowMessages("err, unable to create hwdbg script\n"); + Result = FALSE; + goto FreeAndReturnResult; + } + + // + // Write an additional updated test instance info request into a file + // + if (!HwdbgWriteTestInstanceInfoRequestIntoFile(&g_HwdbgInstanceInfo, + InstanceFilePathToSave)) + { + ShowMessages("err, unable to write instance info request\n"); + Result = FALSE; + goto FreeAndReturnResult; + } + + // + // The test is performed successfully + // + Result = TRUE; + +FreeAndReturnResult: + + // + // Free the allocated memory + // + FreeEventsAndActionsMemory(Event, ActionBreakToDebugger, ActionCustomCode, ActionScript); + + // + // Return the result + // + return Result; +} + +/** + * @brief !hw_clk command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandHwClk(vector CommandTokens, string Command) +{ + if (CommandTokens.size() >= 2) + { + // + // Perform test with default file path and initial BRAM buffer size + // + CommandHwClkPerformTest(CommandTokens, + HWDBG_TEST_READ_INSTANCE_INFO_PATH, + HWDBG_TEST_WRITE_INSTANCE_INFO_PATH, + HWDBG_TEST_WRITE_SCRIPT_BUFFER_PATH, + DEFAULT_INITIAL_BRAM_BUFFER_SIZE); + } + else + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandHwClkHelp(); + return; + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/attach.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/attach.cpp similarity index 75% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/attach.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/attach.cpp index f01538a0..24f2ede8 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/attach.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/attach.cpp @@ -14,7 +14,6 @@ // // Global Variables // -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; /** @@ -36,12 +35,13 @@ CommandAttachHelp() /** * @brief .attach command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandAttach(vector SplitCommand, string Command) +CommandAttach(vector CommandTokens, string Command) { UINT32 TargetPid = 0; BOOLEAN NextIsPid = FALSE; @@ -67,25 +67,15 @@ CommandAttach(vector SplitCommand, string Command) // // It's a attach to a target PID // - if (SplitCommand.size() >= 4) + if (CommandTokens.size() >= 4) { - ShowMessages("incorrect use of the '.attach'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandAttachHelp(); return; } - // - // .attach and .detach commands are only supported in VMI Mode - // - if (g_IsSerialConnectedToRemoteDebuggee) - { - ShowMessages("err, '.attach', and '.detach' commands are only usable " - "in VMI Mode, you can use the '.process', or the '.thread' " - "in Debugger Mode\n"); - return; - } - - for (auto item : SplitCommand) + for (auto Section = CommandTokens.begin() + 1; Section != CommandTokens.end(); Section++) { // // Find out whether the user enters pid or not @@ -94,20 +84,27 @@ CommandAttach(vector SplitCommand, string Command) { NextIsPid = FALSE; - if (!ConvertStringToUInt32(item, &TargetPid)) + if (!ConvertTokenToUInt32(*Section, &TargetPid)) { ShowMessages("please specify a correct hex value for process id\n\n"); CommandAttachHelp(); return; } } - else if (!item.compare("pid")) + else if (CompareLowerCaseStrings(*Section, "pid")) { // // next item is a pid for the process // NextIsPid = TRUE; } + else + { + ShowMessages("unknown parameter at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(*Section).c_str()); + CommandAttachHelp(); + return; + } } // @@ -123,5 +120,6 @@ CommandAttach(vector SplitCommand, string Command) // // Perform attach to target process // + ShowMessages("Attaching to process 0x%llx (%lld)...\n\n", TargetPid, TargetPid); UdAttachToProcess(TargetPid, NULL, NULL, FALSE); } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/cls.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/cls.cpp similarity index 60% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/cls.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/cls.cpp index 2422d976..6439e867 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/cls.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/cls.cpp @@ -17,7 +17,7 @@ * @return VOID */ VOID -CommandClearScreenHelp() +CommandClsHelp() { ShowMessages(".cls : clears the screen.\n\n"); @@ -27,12 +27,21 @@ CommandClearScreenHelp() /** * @brief .cls command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandClearScreen(vector SplitCommand, string Command) +CommandCls(vector CommandTokens, string Command) { + if (CommandTokens.size() != 1) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandClsHelp(); + return; + } + system("cls"); } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/connect.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/connect.cpp similarity index 56% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/connect.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/connect.cpp index 097c0ed4..3cd72a66 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/connect.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/connect.cpp @@ -42,17 +42,72 @@ CommandConnectHelp() } /** - * @brief .connect command handler + * @brief Connect to local debugger * - * @param SplitCommand - * @param Command * @return VOID */ VOID -CommandConnect(vector SplitCommand, string Command) +ConnectLocalDebugger() { - string ip; - string port; + g_IsConnectedToHyperDbgLocally = TRUE; +} + +/** + * @brief Connect to remote debugger + * + * @return BOOLEAN + */ +BOOLEAN +ConnectRemoteDebugger(const CHAR * Ip, const CHAR * Port) +{ + // + // Validate IP and Port + + if (!ValidateIP(Ip)) + { + return FALSE; + } + + if (Port != NULL) + { + if (!IsNumber(Port) || stoi(Port) > 65535 || stoi(Port) < 0) + { + return FALSE; + } + + // + // connect to remote debugger + // + g_ServerIp = Ip; + g_ServerPort = Port; + RemoteConnectionConnect(Ip, Port); + } + else + { + // + // connect to remote debugger (default port) + // + g_ServerIp = Ip; + g_ServerPort = DEFAULT_PORT; + RemoteConnectionConnect(Ip, DEFAULT_PORT); + } + + return TRUE; +} + +/** + * @brief .connect command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandConnect(vector CommandTokens, string Command) +{ + string Ip; + string Port; if (g_IsConnectedToHyperDbgLocally || g_IsConnectedToRemoteDebuggee || g_IsConnectedToRemoteDebugger) @@ -70,32 +125,35 @@ CommandConnect(vector SplitCommand, string Command) return; } - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { // // Means that user entered just a connect so we have to // ask to connect to what ? // - ShowMessages("incorrect use of the '.connect'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandConnectHelp(); return; } - else if (SplitCommand.at(1) == "local" && SplitCommand.size() == 2) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "local") && CommandTokens.size() == 2) { // // connect to local debugger // ShowMessages("local debugging (vmi-mode)\n"); - g_IsConnectedToHyperDbgLocally = TRUE; + + ConnectLocalDebugger(); + return; } - else if (SplitCommand.size() == 3 || SplitCommand.size() == 2) + else if (CommandTokens.size() == 3 || CommandTokens.size() == 2) { - ip = SplitCommand.at(1); + Ip = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)); - if (SplitCommand.size() == 3) + if (CommandTokens.size() == 3) { - port = SplitCommand.at(2); + Port = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)); } // @@ -103,15 +161,15 @@ CommandConnect(vector SplitCommand, string Command) // system, let's first check the if the parameters are // valid // - if (!ValidateIP(ip)) + if (!ValidateIP(Ip)) { ShowMessages("incorrect ip address\n"); return; } - if (SplitCommand.size() == 3) + if (CommandTokens.size() == 3) { - if (!IsNumber(port) || stoi(port) > 65535 || stoi(port) < 0) + if (!IsNumber(Port) || stoi(Port) > 65535 || stoi(Port) < 0) { ShowMessages("incorrect port\n"); return; @@ -120,23 +178,20 @@ CommandConnect(vector SplitCommand, string Command) // // connect to remote debugger // - g_ServerIp = ip; - g_ServerPort = port; - RemoteConnectionConnect(ip.c_str(), port.c_str()); + ConnectRemoteDebugger(Ip.c_str(), Port.c_str()); } else { // // connect to remote debugger (default port) // - g_ServerIp = ip; - g_ServerPort = DEFAULT_PORT; - RemoteConnectionConnect(ip.c_str(), DEFAULT_PORT); + ConnectRemoteDebugger(Ip.c_str(), NULL); } } else { - ShowMessages("incorrect use of the '.connect'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandConnectHelp(); return; } diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/debug.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/debug.cpp new file mode 100644 index 00000000..42e9fb4e --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/debug.cpp @@ -0,0 +1,439 @@ +/** + * @file debug.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief .debug command + * @details + * @version 0.1 + * @date 2020-12-19 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; + +/** + * @brief help of the .debug command + * + * @return VOID + */ +VOID +CommandDebugHelp() +{ + ShowMessages( + ".debug : debugs a target machine or makes this machine a debuggee.\n\n"); + + ShowMessages( + "syntax : \t.debug [remote] [serial|namedpipe] [pause] [Baudrate (decimal)] [Address (string)]\n"); + ShowMessages( + "syntax : \t.debug [prepare] [serial] [Baudrate (decimal)] [Address (string)]\n"); + ShowMessages("syntax : \t.debug [close]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : .debug remote serial 115200 com2\n"); + ShowMessages("\t\te.g : .debug remote pause serial 115200 com2\n"); + ShowMessages("\t\te.g : .debug remote namedpipe \\\\.\\pipe\\HyperDbgPipe\n"); + ShowMessages("\t\te.g : .debug remote pause namedpipe \\\\.\\pipe\\HyperDbgPipe\n"); + ShowMessages("\t\te.g : .debug remote namedpipe \"\\\\.\\pipe\\HyperDbg Pipe\"\n"); + ShowMessages("\t\te.g : .debug prepare serial 115200 com1\n"); + ShowMessages("\t\te.g : .debug prepare serial 115200 com2\n"); + ShowMessages("\t\te.g : .debug close\n"); + + ShowMessages( + "\nvalid baud rates (decimal) : 110, 300, 600, 1200, 2400, 4800, 9600, " + "14400, 19200, 38400, 56000, 57600, 115200, 128000, 256000\n"); + ShowMessages("valid COM ports : COM1, COM2, COM3, COM4 \n"); +} + +/** + * @brief Check if COM port is valid or not + * + * @param ComPort + * @return BOOLEAN + */ +BOOLEAN +CommandDebugCheckComPort(const CHAR * ComPort, UINT32 * Port) +{ + if (_stricmp(ComPort, "com1") == 0) + { + *Port = COM1_PORT; + return TRUE; + } + else if (_stricmp(ComPort, "com2") == 0) + { + *Port = COM2_PORT; + return TRUE; + } + else if (_stricmp(ComPort, "com3") == 0) + { + *Port = COM3_PORT; + return TRUE; + } + else if (_stricmp(ComPort, "com4") == 0) + { + *Port = COM4_PORT; + return TRUE; + } + + return FALSE; +} + +/** + * @brief Check if baud rate is valid or not + * + * @param Baudrate + * @return BOOLEAN + */ +BOOLEAN +CommandDebugCheckBaudrate(DWORD Baudrate) +{ + if (Baudrate == CBR_110 || Baudrate == CBR_300 || Baudrate == CBR_600 || + Baudrate == CBR_1200 || Baudrate == CBR_2400 || Baudrate == CBR_4800 || + Baudrate == CBR_9600 || Baudrate == CBR_14400 || Baudrate == CBR_19200 || + Baudrate == CBR_38400 || Baudrate == CBR_56000 || Baudrate == CBR_57600 || + Baudrate == CBR_115200 || Baudrate == CBR_128000 || + Baudrate == CBR_256000) + { + return TRUE; + } + return FALSE; +} + +/** + * @brief Connect to a remote serial device (Debugger) + * + * @param PortName + * @param Baudrate + * @param PauseAfterConnection + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgDebugRemoteDeviceUsingComPort(const CHAR * PortName, DWORD Baudrate, BOOLEAN PauseAfterConnection) +{ + UINT32 Port; + + // + // Check if baudrate is valid or not + // + if (!CommandDebugCheckBaudrate(Baudrate)) + { + // + // Baud-rate is invalid + // + return FALSE; + } + + // + // check if com port address is valid or not + // + if (!CommandDebugCheckComPort(PortName, &Port)) + { + // + // com port is invalid + // + return FALSE; + } + + // + // Everything is okay, connect to the remote machine to send (debugger) + // + return KdPrepareAndConnectDebugPort(PortName, Baudrate, Port, FALSE, FALSE, PauseAfterConnection); +} + +/** + * @brief Connect to a remote named pipe (Debugger) + * + * @param NamedPipe + * @param PauseAfterConnection + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgDebugRemoteDeviceUsingNamedPipe(const CHAR * NamedPipe, BOOLEAN PauseAfterConnection) +{ + return KdPrepareAndConnectDebugPort(NamedPipe, NULL, NULL, FALSE, TRUE, PauseAfterConnection); +} + +/** + * @brief Connect to a remote serial device (Debuggee) + * + * @param PortName + * @param Baudrate + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgDebugCurrentDeviceUsingComPort(const CHAR * PortName, DWORD Baudrate) +{ + UINT32 Port; + + // + // Check if baudrate is valid or not + // + if (!CommandDebugCheckBaudrate(Baudrate)) + { + // + // Baud-rate is invalid + // + return FALSE; + } + + // + // check if com port address is valid or not + // + if (!CommandDebugCheckComPort(PortName, &Port)) + { + // + // com port is invalid + // + return FALSE; + } + + // + // Everything is okay, connect to the remote machine to send (debuggee) + // Note: Pause after connect is set to FALSE, because it doesn't make sense for the + // deubuggee to pause after connecting to the debugger + // + return KdPrepareAndConnectDebugPort(PortName, Baudrate, Port, TRUE, FALSE, FALSE); +} + +/** + * @brief Connect to a remote serial device (Debuggee) + * + * @return BOOLEAN + */ +BOOLEAN +HyperDbgDebugCloseRemoteDebugger() +{ + // + // Check if the debugger is attached to a debuggee + // + if (g_IsSerialConnectedToRemoteDebuggee) + { + KdCloseConnection(); + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief .debug command handler + * + * @param CommandTokens + * @param Command + * @return VOID + */ +VOID +CommandDebug(vector CommandTokens, string Command) +{ + UINT32 Baudrate; + UINT32 Port; + BOOLEAN IsFirstCommand = TRUE; + BOOLEAN IsRemote = FALSE; + BOOLEAN IsPrepare = FALSE; + BOOLEAN IsSerial = FALSE; + BOOLEAN IsNamedPipe = FALSE; + BOOLEAN IsPause = FALSE; + BOOLEAN IsNamedPipeAddressKnown = FALSE; + string NamedPipeAddress; + BOOLEAN IsComPortAddressKnown = FALSE; + string ComAddress; + BOOLEAN IsComPortBaudrateKnown = FALSE; + + if (CommandTokens.size() == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "close")) + { + // + // Check if the debugger is attached to a debuggee + // + if (!HyperDbgDebugCloseRemoteDebugger()) + { + ShowMessages("err, debugger is not attached to any instance of debuggee\n"); + } + + return; + } + else if (CommandTokens.size() <= 3) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandDebugHelp(); + return; + } + + for (auto Section : CommandTokens) + { + if (IsFirstCommand) + { + IsFirstCommand = FALSE; + continue; + } + else if (!IsRemote && CompareLowerCaseStrings(Section, "remote")) + { + IsRemote = TRUE; + continue; + } + else if (!IsPrepare && CompareLowerCaseStrings(Section, "prepare")) + { + IsPrepare = TRUE; + continue; + } + else if (!IsSerial && CompareLowerCaseStrings(Section, "serial")) + { + IsSerial = TRUE; + continue; + } + else if (!IsNamedPipe && CompareLowerCaseStrings(Section, "namedpipe")) + { + IsNamedPipe = TRUE; + continue; + } + else if (!IsPause && CompareLowerCaseStrings(Section, "pause")) + { + IsPause = TRUE; + continue; + } + else if (!IsNamedPipeAddressKnown && IsNamedPipe) + { + IsNamedPipeAddressKnown = TRUE; + NamedPipeAddress = GetCaseSensitiveStringFromCommandToken(Section); + continue; + } + else if (!IsComPortBaudrateKnown && IsSerial && IsNumber(GetCaseSensitiveStringFromCommandToken(Section))) + { + IsComPortBaudrateKnown = TRUE; + Baudrate = stoi(GetCaseSensitiveStringFromCommandToken(Section)); + + // + // Check if baudrate is valid or not + // + if (!CommandDebugCheckBaudrate(Baudrate)) + { + // + // Baud-rate is invalid + // + ShowMessages("err, baud rate is invalid\n\n"); + CommandDebugHelp(); + return; + } + + continue; + } + else if (!IsComPortAddressKnown && IsSerial) + { + IsComPortAddressKnown = TRUE; + ComAddress = GetCaseSensitiveStringFromCommandToken(Section); + + // + // check if com port address is valid or not + // + if (!CommandDebugCheckComPort(ComAddress.c_str(), &Port)) + { + // + // com port is invalid + // + ShowMessages("err, COM port is invalid\n\n"); + CommandDebugHelp(); + return; + } + + continue; + } + else + { + ShowMessages("err, couldn't resolve error at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Section).c_str()); + CommandDebugHelp(); + return; + } + } + + // + // Validate parameters + // + if (IsRemote && IsPrepare) + { + ShowMessages("err, both 'remote' and 'prepare' can't be used together\n\n"); + CommandDebugHelp(); + return; + } + + if (!IsRemote && !IsPrepare) + { + ShowMessages("err, either 'remote' or 'prepare' should be used\n\n"); + CommandDebugHelp(); + return; + } + + // + // Prepare cannot be specified with the 'pause' + // + if (IsPrepare && IsPause) + { + ShowMessages("err, 'pause' cannot be used with 'prepare'\n\n"); + CommandDebugHelp(); + return; + } + + // + // Named pipe cannot be used with the 'prepare' + // + if (IsNamedPipe && IsPrepare) + { + ShowMessages("err, named pipe cannot be used with 'prepare'\n\n"); + CommandDebugHelp(); + return; + } + + // + // Check if named pipe is empty or not if it's a named pipe + // + if (IsNamedPipe && NamedPipeAddress.empty()) + { + ShowMessages("err, named pipe address is empty\n\n"); + CommandDebugHelp(); + return; + } + + // + // If it's serial, COM address and bausrate should be known + // + if (IsSerial && (!IsComPortAddressKnown || !IsComPortBaudrateKnown)) + { + ShowMessages("err, COM port address or baudrate is unknown\n\n"); + CommandDebugHelp(); + return; + } + + // + // Perform connecting to the remote machine or prepare to send + // + if (IsPrepare) + { + // + // Everything is okay, prepare to send (debuggee) + // + HyperDbgDebugCurrentDeviceUsingComPort(ComAddress.c_str(), Baudrate); + } + else + { + // + // Everything is okay, connect to the remote machine to send (debugger) + // + if (IsNamedPipe) + { + HyperDbgDebugRemoteDeviceUsingNamedPipe(NamedPipeAddress.c_str(), IsPause); + } + else if (IsSerial) + { + HyperDbgDebugRemoteDeviceUsingComPort(ComAddress.c_str(), Baudrate, IsPause); + } + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/detach.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/detach.cpp similarity index 66% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/detach.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/detach.cpp index 9cebdfec..565957ed 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/detach.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/detach.cpp @@ -14,8 +14,8 @@ // // Global Variables // +extern BOOLEAN g_IsVmmModuleLoaded; extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; /** * @brief help of the .detach command @@ -43,7 +43,7 @@ DetachFromProcess() // // Check if debugger is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); // // Check if we attached to a process or not @@ -63,31 +63,22 @@ DetachFromProcess() /** * @brief .detach command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandDetach(vector SplitCommand, string Command) +CommandDetach(vector CommandTokens, string Command) { - if (SplitCommand.size() >= 2) + if (CommandTokens.size() >= 2) { - ShowMessages("incorrect use of the '.detach'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandDetachHelp(); return; } - // - // .attach and .detach commands are only supported in VMI Mode - // - if (g_IsSerialConnectedToRemoteDebuggee) - { - ShowMessages("err, '.attach', and '.detach' commands are only usable " - "in VMI Mode, you can use the '.process', or the '.thread' " - "in Debugger Mode\n"); - return; - } - // // Perform detach from the process // diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/disconnect.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/disconnect.cpp similarity index 89% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/disconnect.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/disconnect.cpp index 84254241..7a28df0b 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/disconnect.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/disconnect.cpp @@ -36,16 +36,18 @@ CommandDisconnectHelp() /** * @brief .disconnect command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandDisconnect(vector SplitCommand, string Command) +CommandDisconnect(vector CommandTokens, string Command) { - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the '.disconnect'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandDisconnectHelp(); return; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/dump.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/dump.cpp similarity index 79% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/dump.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/dump.cpp index 5c6883ec..2ac5bc92 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/dump.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/dump.cpp @@ -54,12 +54,12 @@ CommandDumpHelp() /** * @brief .dump command handler * - * @param SplitCommand + * @param CommandTokens * @param Command * @return VOID */ VOID -CommandDump(vector SplitCommand, string Command) +CommandDump(vector CommandTokens, string Command) { wstring Filepath; UINT32 ActualLength; @@ -74,10 +74,10 @@ CommandDump(vector SplitCommand, string Command) BOOLEAN IsTheFirstAddr = FALSE; BOOLEAN IsTheSecondAddr = FALSE; BOOLEAN IsDumpPathSpecified = FALSE; - string FirstCommand = SplitCommand.front(); + string FirstCommand = GetLowerStringFromCommandToken(CommandTokens.front()); DEBUGGER_READ_MEMORY_TYPE MemoryType = DEBUGGER_READ_VIRTUAL_ADDRESS; - if (SplitCommand.size() <= 4) + if (CommandTokens.size() <= 4) { ShowMessages("err, incorrect use of the '.dump' command\n\n"); CommandDumpHelp(); @@ -93,7 +93,7 @@ CommandDump(vector SplitCommand, string Command) Pid = g_ActiveProcessDebuggingState.ProcessId; } - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { if (IsFirstCommand == TRUE) { @@ -102,7 +102,7 @@ CommandDump(vector SplitCommand, string Command) } else if (NextIsProcId) { - if (!ConvertStringToUInt32(Section, &Pid)) + if (!ConvertTokenToUInt32(Section, &Pid)) { ShowMessages("please specify a correct hex value for process id\n\n"); CommandDumpHelp(); @@ -116,17 +116,17 @@ CommandDump(vector SplitCommand, string Command) // // Convert path to wstring // - StringToWString(Filepath, Section); + StringToWString(Filepath, GetCaseSensitiveStringFromCommandToken(Section)); IsDumpPathSpecified = TRUE; NextIsPath = FALSE; } - else if (!Section.compare("pid")) + else if (CompareLowerCaseStrings(Section, "pid")) { NextIsProcId = TRUE; continue; } - else if (!Section.compare("path")) + else if (CompareLowerCaseStrings(Section, "path")) { NextIsPath = TRUE; continue; @@ -134,14 +134,16 @@ CommandDump(vector SplitCommand, string Command) // // Check the 'From' address // - else if (!IsTheFirstAddr && SymbolConvertNameOrExprToAddress(Section, &StartAddress)) + else if (!IsTheFirstAddr && + SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &StartAddress)) { IsTheFirstAddr = TRUE; } // // Check the 'To' address // - else if (!IsTheSecondAddr && SymbolConvertNameOrExprToAddress(Section, &EndAddress)) + else if (!IsTheSecondAddr && + SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &EndAddress)) { IsTheSecondAddr = TRUE; } @@ -151,7 +153,7 @@ CommandDump(vector SplitCommand, string Command) // invalid input // ShowMessages("err, couldn't resolve error at '%s'\n\n", - Section.c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); CommandDumpHelp(); return; @@ -210,7 +212,7 @@ CommandDump(vector SplitCommand, string Command) // // Default process we read from current process // - Pid = GetCurrentProcessId(); + Pid = PlatformGetCurrentProcessId(); } // @@ -224,14 +226,19 @@ CommandDump(vector SplitCommand, string Command) // // Create or open the file for writing the dump file // - DumpFileHandle = CreateFileW( - Filepath.c_str(), - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); + // TEMPORARY LINUX SHIM (same as in pe.cpp): std::wstring stores native + // wchar_t (4 bytes on Linux), but the HyperDbg WCHAR type is 2 bytes + // (UINT16) and PlatformOpenFileForWriting takes a const WCHAR *. On Linux + // the cast is a bogus 2-byte reinterpretation, acceptable only because + // Linux file I/O is still stubbed (the path is never opened). On Windows + // WCHAR == wchar_t, so it is a plain correct pointer. TODO(Linux): remove + // once real file I/O lands and convert wchar_t -> 2-byte WCHAR properly. + // +#ifdef __linux__ + DumpFileHandle = PlatformOpenFileForWriting((const WCHAR *)Filepath.c_str()); +#else + DumpFileHandle = PlatformOpenFileForWriting(Filepath.c_str()); +#endif if (DumpFileHandle == INVALID_HANDLE_VALUE) { @@ -247,7 +254,7 @@ CommandDump(vector SplitCommand, string Command) ActualLength = NULL; Iterator = Length / PAGE_SIZE; - for (size_t i = 0; i <= Iterator; i++) + for (SIZE_T i = 0; i <= Iterator; i++) { UINT64 Address = StartAddress + (i * PAGE_SIZE); @@ -266,7 +273,7 @@ CommandDump(vector SplitCommand, string Command) { // ShowMessages("address: 0x%llx | actual length: 0x%llx\n", Address, ActualLength); - HyperDbgReadMemoryAndDisassemble( + HyperDbgShowMemoryOrDisassemble( DEBUGGER_SHOW_COMMAND_DUMP, Address, MemoryType, @@ -282,7 +289,7 @@ CommandDump(vector SplitCommand, string Command) // if (DumpFileHandle != NULL) { - CloseHandle(DumpFileHandle); + PlatformCloseFile(DumpFileHandle); DumpFileHandle = NULL; } @@ -300,8 +307,6 @@ CommandDump(vector SplitCommand, string Command) VOID CommandDumpSaveIntoFile(PVOID Buffer, UINT32 Length) { - DWORD BytesWritten; - // // Check if handle is valid // @@ -314,11 +319,11 @@ CommandDumpSaveIntoFile(PVOID Buffer, UINT32 Length) // // Write the buffer into the dump file // - if (!WriteFile(DumpFileHandle, Buffer, Length, &BytesWritten, NULL)) + if (!PlatformWriteFile(DumpFileHandle, Buffer, Length)) { ShowMessages("err, unable to write buffer into the dump\n"); - CloseHandle(DumpFileHandle); + PlatformCloseFile(DumpFileHandle); DumpFileHandle = NULL; return; diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/formats.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/formats.cpp similarity index 82% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/formats.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/formats.cpp index e41c6601..65a83280 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/formats.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/formats.cpp @@ -42,10 +42,10 @@ CommandFormatsHelp() VOID CommandFormatsShowResults(UINT64 U64Value) { - time_t t; - struct tm * tmp; - char MY_TIME[50]; - unsigned int Character; + time_t t; + struct tm * tmp; + CHAR MY_TIME[50]; + UINT32 Character; time(&t); @@ -75,10 +75,10 @@ CommandFormatsShowResults(UINT64 U64Value) // // iterate through 8, 8 bits (8*6) // - unsigned char * TempCharacter = (unsigned char *)&U64Value; - for (size_t j = 0; j < sizeof(UINT64); j++) + UCHAR * TempCharacter = (UCHAR *)&U64Value; + for (SIZE_T j = 0; j < sizeof(UINT64); j++) { - Character = (unsigned int)TempCharacter[j]; + Character = (UINT32)TempCharacter[j]; if (isprint(Character)) { @@ -97,19 +97,21 @@ CommandFormatsShowResults(UINT64 U64Value) /** * @brief handler of .formats command * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandFormats(vector SplitCommand, string Command) +CommandFormats(vector CommandTokens, string Command) { UINT64 ConstantValue = 0; BOOLEAN HasError = TRUE; - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { - ShowMessages("incorrect use of the '.formats'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandFormatsHelp(); return; } @@ -122,7 +124,7 @@ CommandFormats(vector SplitCommand, string Command) // // Remove .formats from it // - Command.erase(0, SplitCommand.at(0).size()); + Command.erase(0, GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).size()); // // Trim it again diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/help.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/help.cpp similarity index 100% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/help.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/help.cpp diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/kill.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/kill.cpp similarity index 84% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/kill.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/kill.cpp index 26f5a38b..7c8af91d 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/kill.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/kill.cpp @@ -33,16 +33,18 @@ CommandKillHelp() /** * @brief .kill command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandKill(vector SplitCommand, string Command) +CommandKill(vector CommandTokens, string Command) { - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the '.kill'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandKillHelp(); return; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/listen.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/listen.cpp similarity index 76% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/listen.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/listen.cpp index 78986b1d..d303c18e 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/listen.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/listen.cpp @@ -45,21 +45,23 @@ CommandListenHelp() /** * @brief listen command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandListen(vector SplitCommand, string Command) +CommandListen(vector CommandTokens, string Command) { - string port; + string Port; - if (SplitCommand.size() >= 3) + if (CommandTokens.size() >= 3) { // // Means that user entered invalid parameters // - ShowMessages("incorrect use of the '.listen'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandListenHelp(); return; } @@ -82,7 +84,7 @@ CommandListen(vector SplitCommand, string Command) return; } - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { // // listen on default port @@ -92,16 +94,16 @@ CommandListen(vector SplitCommand, string Command) return; } - else if (SplitCommand.size() == 2) + else if (CommandTokens.size() == 2) { - port = SplitCommand.at(1); + Port = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)); // // means that probably wants to listen // on a specific port, let's see if the // port is valid or not // - if (!IsNumber(port) || stoi(port) > 65535 || stoi(port) < 0) + if (!IsNumber(Port) || stoi(Port) > 65535 || stoi(Port) < 0) { ShowMessages("incorrect port\n"); return; @@ -110,12 +112,13 @@ CommandListen(vector SplitCommand, string Command) // // listen on the port // - ShowMessages("listening on %s ...\n", port.c_str()); - RemoteConnectionListen(port.c_str()); + ShowMessages("listening on %s ...\n", Port.c_str()); + RemoteConnectionListen(Port.c_str()); } else { - ShowMessages("incorrect use of the '.listen'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandListenHelp(); return; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/logclose.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/logclose.cpp similarity index 83% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/logclose.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/logclose.cpp index 32cf6148..c3069afe 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/logclose.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/logclose.cpp @@ -33,16 +33,18 @@ CommandLogcloseHelp() /** * @brief .logclose command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandLogclose(vector SplitCommand, string Command) +CommandLogclose(vector CommandTokens, string Command) { - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the '.logclose'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandLogcloseHelp(); return; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/logopen.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/logopen.cpp similarity index 68% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/logopen.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/logopen.cpp index 84fe62e9..abb0ea31 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/logopen.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/logopen.cpp @@ -30,21 +30,27 @@ CommandLogopenHelp() ShowMessages(".logopen : saves commands and results in a file.\n\n"); ShowMessages("syntax : \t.logopen [FilePath (string)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : .logopen c:\\users\\sina\\desktop\\log.txt\n"); + ShowMessages("\t\te.g : .logopen \"c:\\users\\sina\\desktop\\log with space.txt\"\n"); } /** * @brief .logopen command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandLogopen(vector SplitCommand, string Command) +CommandLogopen(vector CommandTokens, string Command) { - if (SplitCommand.size() == 1) + if (CommandTokens.size() != 2) { - ShowMessages("please specify a file\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandLogopenHelp(); return; } @@ -56,25 +62,10 @@ CommandLogopen(vector SplitCommand, string Command) return; } - // - // Trim the command - // - Trim(Command); - - // - // Remove .logopen from it - // - Command.erase(0, SplitCommand.at(0).size()); - - // - // Trim it again - // - Trim(Command); - // // Try to open it as file // - g_LogOpenFile.open(Command.c_str()); + g_LogOpenFile.open(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); // // Check if it's okay @@ -94,7 +85,7 @@ CommandLogopen(vector SplitCommand, string Command) ShowMessages("save commands and results into file : %s (%d-%02d-%02d " "%02d:%02d:%02d)\n", - Command.c_str(), + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str(), tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, @@ -104,7 +95,7 @@ CommandLogopen(vector SplitCommand, string Command) } else { - ShowMessages("unable to open file : %s\n", Command.c_str()); + ShowMessages("unable to open file : %s\n", GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); return; } } @@ -116,7 +107,7 @@ CommandLogopen(vector SplitCommand, string Command) * @return VOID */ VOID -LogopenSaveToFile(const char * Text) +LogopenSaveToFile(const CHAR * Text) { g_LogOpenFile << Text; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/pagein.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/pagein.cpp similarity index 83% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/pagein.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/pagein.cpp index b25d7e26..a01aec56 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/pagein.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/pagein.cpp @@ -15,6 +15,7 @@ // Global Variables // extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsVmmModuleLoaded; extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; /** @@ -81,10 +82,10 @@ BOOLEAN CommandPageinCheckAndInterpretModeString(const std::string & ModeString, PAGE_FAULT_EXCEPTION * PageFaultErrorCode) { - std::unordered_set AllowedChars = {'p', 'w', 'u', 'f', 'k', 's', 'h', 'g'}; - std::unordered_set FoundChars; + std::unordered_set AllowedChars = {'p', 'w', 'u', 'f', 'k', 's', 'h', 'g'}; + std::unordered_set FoundChars; - for (char c : ModeString) + for (CHAR c : ModeString) { if (AllowedChars.count(c) == 0) { @@ -99,7 +100,7 @@ CommandPageinCheckAndInterpretModeString(const std::string & ModeString, // // Found a character more than once // - return false; + return FALSE; } FoundChars.insert(c); @@ -108,7 +109,7 @@ CommandPageinCheckAndInterpretModeString(const std::string & ModeString, // // All checks passed, let's interpret the page-fault code // - for (char c : ModeString) + for (CHAR c : ModeString) { if (c == 'p') { @@ -203,7 +204,7 @@ CommandPageinRequest(UINT64 TargetVirtualAddrFrom, } else { - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); // // For know, the support for the '.pagein' command is excluded from @@ -215,14 +216,14 @@ CommandPageinRequest(UINT64 TargetVirtualAddrFrom, if (Pid == 0) { - Pid = GetCurrentProcessId(); + Pid = PlatformGetCurrentProcessId(); PageFaultRequest.ProcessId = Pid; } // // Send IOCTL // - Status = DeviceIoControl( + Status = PlatformDeviceIoControl( g_DeviceHandle, // Handle to device IOCTL_DEBUGGER_BRING_PAGES_IN, // IO Control Code (IOCTL) &PageFaultRequest, // Input Buffer to driver. @@ -236,7 +237,7 @@ CommandPageinRequest(UINT64 TargetVirtualAddrFrom, if (!Status) { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError()); return; } @@ -256,23 +257,22 @@ CommandPageinRequest(UINT64 TargetVirtualAddrFrom, /** * @brief .pagein command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandPagein(vector SplitCommand, string Command) +CommandPagein(vector CommandTokens, string Command) { - UINT32 Pid = 0; - UINT64 Length = 0; - UINT64 TargetAddressFrom = NULL; - UINT64 TargetAddressTo = NULL; - BOOLEAN IsNextProcessId = FALSE; - BOOLEAN IsFirstCommand = TRUE; - BOOLEAN IsNextLength = FALSE; - vector SplitCommandCaseSensitive {Split(Command, ' ')}; - UINT32 IndexInCommandCaseSensitive = 0; - PAGE_FAULT_EXCEPTION PageFaultErrorCode = {0}; + UINT32 Pid = 0; + UINT64 Length = 0; + UINT64 TargetAddressFrom = NULL; + UINT64 TargetAddressTo = NULL; + BOOLEAN IsNextProcessId = FALSE; + BOOLEAN IsFirstCommand = TRUE; + BOOLEAN IsNextLength = FALSE; + PAGE_FAULT_EXCEPTION PageFaultErrorCode = {0}; // // By default if the user-debugger is active, we use these commands @@ -283,20 +283,19 @@ CommandPagein(vector SplitCommand, string Command) Pid = g_ActiveProcessDebuggingState.ProcessId; } - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { // // Means that user entered one command without any parameter // - ShowMessages("incorrect use of the '.pagein' command\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandPageinHelp(); return; } - for (auto Section : SplitCommand) + for (auto Section : CommandTokens) { - IndexInCommandCaseSensitive++; - if (IsFirstCommand) { IsFirstCommand = FALSE; @@ -304,7 +303,7 @@ CommandPagein(vector SplitCommand, string Command) } if (IsNextProcessId == TRUE) { - if (!ConvertStringToUInt32(Section, &Pid)) + if (!ConvertTokenToUInt32(Section, &Pid)) { ShowMessages("err, you should enter a valid process id\n\n"); return; @@ -315,7 +314,7 @@ CommandPagein(vector SplitCommand, string Command) if (IsNextLength == TRUE) { - if (!SymbolConvertNameOrExprToAddress(Section, &Length)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &Length)) { ShowMessages("err, you should enter a valid length\n\n"); return; @@ -324,13 +323,13 @@ CommandPagein(vector SplitCommand, string Command) continue; } - if (!Section.compare("l")) + if (CompareLowerCaseStrings(Section, "l")) { IsNextLength = TRUE; continue; } - // if (!Section.compare("pid")) + // if (CompareLowerCaseStrings(Section, "pid")) // { // IsNextProcessId = TRUE; // continue; @@ -340,20 +339,20 @@ CommandPagein(vector SplitCommand, string Command) // Probably it's address or mode string // - if (CommandPageinCheckAndInterpretModeString(Section, &PageFaultErrorCode)) + if (CommandPageinCheckAndInterpretModeString(GetLowerStringFromCommandToken(Section), &PageFaultErrorCode)) { continue; } else if (TargetAddressFrom == 0) { - if (!SymbolConvertNameOrExprToAddress(SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1), + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &TargetAddressFrom)) { // // Couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommandCaseSensitive.at(IndexInCommandCaseSensitive - 1).c_str()); + GetCaseSensitiveStringFromCommandToken(Section).c_str()); return; } } @@ -381,7 +380,8 @@ CommandPagein(vector SplitCommand, string Command) if (IsNextLength || IsNextProcessId) { - ShowMessages("incorrect use of the '.pagein' command\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandPageinHelp(); return; } diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/pe.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/pe.cpp new file mode 100644 index 00000000..1d9fe58e --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/pe.cpp @@ -0,0 +1,153 @@ +/** + * @file pe.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief .pe command + * @details + * @version 0.1 + * @date 2021-12-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief help of the .pe command + * + * @return VOID + */ +VOID +CommandPeHelp() +{ + ShowMessages(".pe : parses portable executable (PE) files, displays header metadata, and dumps sections.\n\n"); + + ShowMessages("syntax : \t.pe [header] [FilePath (string)]\n"); + ShowMessages("syntax : \t.pe [section] [SectionName (string)] [FilePath (string)]\n"); + ShowMessages("\n.pe section dumps are capped at 1 MiB per matching section and 4 MiB total.\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : .pe header c:\\reverse\\myfile.exe\n"); + ShowMessages("\t\te.g : .pe section .text \"c:\\reverse files\\myfile.exe\"\n"); + ShowMessages("\t\te.g : .pe section .rdata \"c:\\reverse files\\myfile.exe\"\n"); +} + +/** + * @brief .pe command handler + * + * @param CommandTokens + * @param Command + * @return VOID + */ +VOID +CommandPe(vector CommandTokens, string Command) +{ + BOOLEAN Is32Bit = FALSE; + wstring Filepath; + string TempFilePath; + BOOLEAN ShowDumpOfSection = FALSE; + + if (CommandTokens.size() <= 2) + { + ShowMessages("err, incorrect use of the '%s' command\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandPeHelp(); + return; + } + + // + // Check for first option + // + if (CompareLowerCaseStrings(CommandTokens.at(1), "section")) + { + if (CommandTokens.size() == 3) + { + ShowMessages("err, incorrect use of the '%s' command\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandPeHelp(); + return; + } + + if (CommandTokens.size() != 4) + { + ShowMessages("err, incorrect use of the '%s' command\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandPeHelp(); + return; + } + ShowDumpOfSection = TRUE; + TempFilePath = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)); + } + else if (CompareLowerCaseStrings(CommandTokens.at(1), "header")) + { + if (CommandTokens.size() != 3) + { + ShowMessages("err, incorrect use of the '%s' command\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandPeHelp(); + return; + } + + ShowDumpOfSection = FALSE; + TempFilePath = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)); + } + else + { + // + // Couldn't resolve or unknown parameter + // + ShowMessages("err, couldn't resolve error at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); + CommandPeHelp(); + return; + } + + // + // Convert path to wstring + // + StringToWString(Filepath, TempFilePath); + + // + // TEMPORARY LINUX SHIM: + // std::wstring stores native wchar_t, which is 4 bytes on Linux, but the + // HyperDbg WCHAR type is 2 bytes (UINT16) and the PE-parser path APIs take + // a const WCHAR *. The cast below exists ONLY so the project compiles on + // Linux. On Linux it produces a bogus 2-byte reinterpretation of the 4-byte + // buffer; that is acceptable for now only because Linux file I/O is still + // stubbed (the path is never actually opened). On Windows WCHAR == wchar_t, + // so it is a plain, correct pointer with no reinterpretation. + // + // TODO (Linux): remove this cast once real Linux file I/O lands. The proper + // fix is to convert the 4-byte wchar_t path into a 2-byte WCHAR/UTF-16 + // buffer (e.g. a std::wstring -> WCHAR helper) and pass that, so the PE + // parser receives a valid path. The same conversion is needed by + // PlatformMapFileReadOnly / PlatformOpenFileForWriting. + // +#ifdef __linux__ + const WCHAR * FilepathW = (const WCHAR *)Filepath.c_str(); +#else + const WCHAR * FilepathW = Filepath.c_str(); +#endif + + // + // Detect whether PE is 32-bit or 64-bit + // + if (!PeIsPE32BitOr64Bit(FilepathW, &Is32Bit)) + { + // + // File was invalid, the error message is shown in the above function + // + return; + } + + // + // Parse PE file + // + if (!ShowDumpOfSection) + { + PeShowSectionInformationAndDump(FilepathW, NULL, Is32Bit); + } + else + { + PeShowSectionInformationAndDump(FilepathW, GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str(), Is32Bit); + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/process.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/process.cpp similarity index 88% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/process.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/process.cpp index 077c96f6..746c08ea 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/process.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/process.cpp @@ -48,12 +48,13 @@ CommandProcessHelp() /** * @brief .process command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandProcess(vector SplitCommand, string Command) +CommandProcess(vector CommandTokens, string Command) { UINT32 TargetProcessId = 0; UINT64 TargetProcess = 0; @@ -65,14 +66,15 @@ CommandProcess(vector SplitCommand, string Command) BOOLEAN IsSetByClkIntr = FALSE; DEBUGGEE_PROCESS_LIST_NEEDED_DETAILS ProcessListNeededItems = {0}; - if (SplitCommand.size() >= 4) + if (CommandTokens.size() >= 4) { - ShowMessages("incorrect use of the '.process'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandProcessHelp(); return; } - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { // // Check if it's connected to a remote debuggee or not @@ -96,9 +98,9 @@ CommandProcess(vector SplitCommand, string Command) NULL); } } - else if (SplitCommand.size() == 2) + else if (CommandTokens.size() == 2) { - if (!SplitCommand.at(1).compare("list")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "list")) { // // Query for nt!_EPROCESS.ImageFileName, nt!_EPROCESS.UniqueProcessId, @@ -161,12 +163,12 @@ CommandProcess(vector SplitCommand, string Command) { ShowMessages( "err, unknown parameter at '%s'\n\n", - SplitCommand.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); CommandProcessHelp(); return; } } - else if (SplitCommand.size() == 3) + else if (CommandTokens.size() == 3) { // // Check if it's connected to a remote debuggee or not @@ -179,9 +181,9 @@ CommandProcess(vector SplitCommand, string Command) return; } - if (!SplitCommand.at(1).compare("pid")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "pid")) { - if (!ConvertStringToUInt32(SplitCommand.at(2), &TargetProcessId)) + if (!ConvertTokenToUInt32(CommandTokens.at(2), &TargetProcessId)) { ShowMessages( "please specify a correct hex value for the process id that you " @@ -190,9 +192,9 @@ CommandProcess(vector SplitCommand, string Command) return; } } - else if (!SplitCommand.at(1).compare("process")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "process")) { - if (!SymbolConvertNameOrExprToAddress(SplitCommand.at(2), &TargetProcess)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)), &TargetProcess)) { ShowMessages( "please specify a correct hex value for the process (nt!_EPROCESS) that you " @@ -205,7 +207,7 @@ CommandProcess(vector SplitCommand, string Command) { ShowMessages( "err, unknown parameter at '%s'\n\n", - SplitCommand.at(2).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()); CommandProcessHelp(); return; } @@ -213,7 +215,7 @@ CommandProcess(vector SplitCommand, string Command) // // Check for switching method // - if (!SplitCommand.at(0).compare(".process2")) + if (CompareLowerCaseStrings(CommandTokens.at(0), ".process2")) { IsSetByClkIntr = FALSE; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/restart.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/restart.cpp similarity index 58% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/restart.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/restart.cpp index f14beae0..626856b7 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/restart.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/restart.cpp @@ -38,16 +38,18 @@ CommandRestartHelp() /** * @brief .restart command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandRestart(vector SplitCommand, string Command) +CommandRestart(vector CommandTokens, string Command) { - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the '.restart'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandRestartHelp(); return; } @@ -87,15 +89,33 @@ CommandRestart(vector SplitCommand, string Command) // if (g_StartCommandPathAndArguments.empty()) { + // + // TEMPORARY LINUX SHIM (same as in pe.cpp/dump.cpp): the path is a + // std::wstring of native wchar_t (4 bytes on Linux), but UdAttachToProcess + // takes a 2-byte HyperDbg WCHAR * (UINT16). The cast is a bogus 2-byte + // reinterpretation on Linux, acceptable only because the user-debugger + // path is still stubbed there. On Windows WCHAR == wchar_t, so it is a + // plain correct pointer. TODO(Linux): convert wchar_t -> 2-byte WCHAR + // properly once the Linux user-debugger path is real. + // UdAttachToProcess(NULL, - g_StartCommandPath.c_str(), + (WCHAR *)g_StartCommandPath.c_str(), NULL, FALSE); } else { + // + // TEMPORARY LINUX SHIM (same as in pe.cpp/dump.cpp): the path/arguments + // are std::wstring of native wchar_t (4 bytes on Linux), but + // UdAttachToProcess takes 2-byte HyperDbg WCHAR * (UINT16). The casts are + // a bogus 2-byte reinterpretation on Linux, acceptable only because the + // user-debugger path is still stubbed there. On Windows WCHAR == wchar_t, + // so they are plain correct pointers. TODO(Linux): convert wchar_t -> + // 2-byte WCHAR properly once the Linux user-debugger path is real. + // UdAttachToProcess(NULL, - g_StartCommandPath.c_str(), + (WCHAR *)g_StartCommandPath.c_str(), (WCHAR *)g_StartCommandPathAndArguments.c_str(), FALSE); } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/script.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/script.cpp similarity index 82% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/script.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/script.cpp index 159336f4..f594ff37 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/script.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/script.cpp @@ -47,9 +47,9 @@ CommandScriptHelp() VOID CommandScriptRunCommand(std::string Input, vector PathAndArgs) { - int CommandExecutionResult = 0; - char * LineContent = NULL; - int i = 0; + INT CommandExecutionResult = 0; + CHAR * LineContent = NULL; + INT i = 0; // // Replace the $arg*s @@ -69,12 +69,7 @@ CommandScriptRunCommand(std::string Input, vector PathAndArgs) // // Convert script to char* // - LineContent = (char *)Input.c_str(); - - // - // Check if the it's a command or not - // - InterpreterRemoveComments(LineContent); + LineContent = (CHAR *)Input.c_str(); if (IsEmptyString(LineContent)) { @@ -114,7 +109,7 @@ HyperDbgScriptReadFileAndExecuteCommand(std::vector & PathAndArgs) { std::string Line; BOOLEAN IsOpened = FALSE; - bool Reset = false; + BOOLEAN Reset = FALSE; string CommandToExecute = ""; string PathOfScriptFile = ""; @@ -139,14 +134,14 @@ HyperDbgScriptReadFileAndExecuteCommand(std::vector & PathAndArgs) // // Reset multiline command // - Reset = true; + Reset = TRUE; while (std::getline(File, Line)) { // // Check for multiline commands // - if (HyperDbgCheckMultilineCommand((char *)Line.c_str(), Reset)) + if (CheckMultilineCommand((char *)Line.c_str(), Reset)) { // // if the reset is true, we should make the saving buffer empty @@ -159,7 +154,7 @@ HyperDbgScriptReadFileAndExecuteCommand(std::vector & PathAndArgs) // // The command is expected to be continued // - Reset = false; + Reset = FALSE; // // Append to the previous command @@ -173,7 +168,7 @@ HyperDbgScriptReadFileAndExecuteCommand(std::vector & PathAndArgs) // // Reset for the next commands round // - Reset = true; + Reset = TRUE; // // Append this line too @@ -221,18 +216,20 @@ HyperDbgScriptReadFileAndExecuteCommand(std::vector & PathAndArgs) /** * @brief Parsing the command line options for scripts + * @param argc + * @param argv * - * @return int + * @return INT */ -int -HyperDbgScriptReadFileAndExecuteCommandline(int argc, char * argv[]) +INT +HyperDbgScriptReadFileAndExecuteCommandline(INT argc, CHAR * argv[]) { vector Args; // // Convert it to the array // - for (size_t i = 2; i < argc; i++) + for (SIZE_T i = 2; i < argc; i++) { std::string TempStr(argv[i]); Args.push_back(TempStr); @@ -258,53 +255,36 @@ HyperDbgScriptReadFileAndExecuteCommandline(int argc, char * argv[]) /** * @brief .script command handler * - * @param SplitCommand + * @param CommandTokens * @param Command * @return VOID */ VOID -CommandScript(vector SplitCommand, string Command) +CommandScript(vector CommandTokens, string Command) { vector PathAndArgs; + BOOLEAN IsFirstCommand = FALSE; - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { - ShowMessages("please specify a file\n"); + ShowMessages("please specify a file\n\n"); CommandScriptHelp(); return; } - // - // Trim the command - // - Trim(Command); - - // - // Remove .script from it - // - Command.erase(0, SplitCommand.at(0).size()); - - // - // Trim it again - // - Trim(Command); - - // - // Split Path and args - // - SplitPathAndArgs(PathAndArgs, Command); - - /* - - for (auto item : PathAndArgs) + for (auto Section : CommandTokens) { - // - // The first argument is the path - // - ShowMessages("Arg : %s\n", item.c_str()); - } + if (!IsFirstCommand) + { + IsFirstCommand = TRUE; + continue; + } - */ + // + // Add the path and the arguments + // + PathAndArgs.push_back(GetCaseSensitiveStringFromCommandToken(Section)); + } // // Parse the file and the possible arguments diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/start.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/start.cpp new file mode 100644 index 00000000..c628cdb2 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/start.cpp @@ -0,0 +1,190 @@ +/** + * @file start.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief .start command + * @details + * @version 0.1 + * @date 2022-01-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern std::wstring g_StartCommandPath; +extern std::wstring g_StartCommandPathAndArguments; +extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; + +/** + * @brief help of the .start command + * + * @return VOID + */ +VOID +CommandStartHelp() +{ + ShowMessages(".start : runs a user-mode process.\n\n"); + + ShowMessages("syntax : \t.start [path Path (string)] [Parameters (string)]\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : .start path c:\\reverse_eng\\my_file.exe\n"); + ShowMessages("\t\te.g : .start path \"c:\\reverse eng\\my_file.exe\"\n"); + ShowMessages("\t\te.g : .start path \"c:\\reverse eng\\my_file.exe\" \"arg1\" 2 \"arg 3\"\n"); +} + +/** + * @brief .start command handler + * + * @param CommandTokens + * @param Command + * @return VOID + */ +VOID +CommandStart(vector CommandTokens, string Command) +{ + vector PathAndArgs; + string Arguments = ""; + BOOLEAN IsFirstCommand = FALSE; + BOOLEAN PathIgnored = FALSE; + BOOLEAN IsNextPath = FALSE; + + if (CommandTokens.size() <= 2) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + CommandStartHelp(); + return; + } + +// +// Disable user-mode debugger in this version +// +#if ActivateUserModeDebugger == FALSE + + if (!g_IsSerialConnectedToRemoteDebugger) + { + ShowMessages("the user-mode debugger in VMI Mode is still in the beta version and not stable. " + "we decided to exclude it from this release and release it in future versions. " + "if you want to test the user-mode debugger in VMI Mode, you should build " + "HyperDbg with special instructions. But starting processes is fully supported " + "in the Debugger Mode.\n" + "(it's not recommended to use it in VMI Mode yet!)\n"); + return; + } + +#endif // !ActivateUserModeDebugger + + // + // Check if the first token is 'path' + // + if (!CompareLowerCaseStrings(CommandTokens.at(1), "path")) + { + ShowMessages("err, couldn't resolve error at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); + CommandStartHelp(); + return; + } + + // + // *** It's a run of target PE file *** + // + + for (auto Section : CommandTokens) + { + // + // Skip first two parameters + // + if (!IsFirstCommand) + { + IsFirstCommand = TRUE; + continue; + } + + // + // Skip the path + // + if (!PathIgnored) + { + PathIgnored = TRUE; + IsNextPath = TRUE; + continue; + } + + // + // Check if the next token is the actual path + // + if (IsNextPath) + { + IsNextPath = FALSE; + + // + // Convert path to wstring + // + StringToWString(g_StartCommandPath, GetCaseSensitiveStringFromCommandToken(Section)); + + continue; + } + + // + // Append the arguments and check if arguments contain spaces then add quotes + // + if (GetCaseSensitiveStringFromCommandToken(Section).find(' ') != std::string::npos) + { + Arguments += "\"" + GetCaseSensitiveStringFromCommandToken(Section) + "\" "; + } + else + { + Arguments += GetCaseSensitiveStringFromCommandToken(Section) + " "; + } + } + + // + // Perform run of the target file + // + if (Arguments.empty()) + { + // + // TEMPORARY LINUX SHIM (same as in pe.cpp/dump.cpp): the path is a + // std::wstring of native wchar_t (4 bytes on Linux), but UdAttachToProcess + // takes a 2-byte HyperDbg WCHAR * (UINT16). The cast is a bogus 2-byte + // reinterpretation on Linux, acceptable only because the user-debugger + // path is still stubbed there. On Windows WCHAR == wchar_t, so it is a + // plain correct pointer. TODO(Linux): convert wchar_t -> 2-byte WCHAR + // properly once the Linux user-debugger path is real. + // + UdAttachToProcess(NULL, + (WCHAR *)g_StartCommandPath.c_str(), + NULL, + FALSE); + } + else + { + // + // Remove the last space + // + Arguments.pop_back(); + + // + // Convert arguments to wstring if it's not empty + // + StringToWString(g_StartCommandPathAndArguments, Arguments); + + // + // TEMPORARY LINUX SHIM (same as in pe.cpp/dump.cpp): the path/arguments + // are std::wstring of native wchar_t (4 bytes on Linux), but + // UdAttachToProcess takes 2-byte HyperDbg WCHAR * (UINT16). The casts are + // a bogus 2-byte reinterpretation on Linux, acceptable only because the + // user-debugger path is still stubbed there. On Windows WCHAR == wchar_t, + // so they are plain correct pointers. TODO(Linux): convert wchar_t -> + // 2-byte WCHAR properly once the Linux user-debugger path is real. + // + UdAttachToProcess(NULL, + (WCHAR *)g_StartCommandPath.c_str(), + (WCHAR *)g_StartCommandPathAndArguments.c_str(), + FALSE); + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/status.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/status.cpp similarity index 90% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/status.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/status.cpp index d57816f1..dfebdc1f 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/status.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/status.cpp @@ -42,16 +42,18 @@ CommandStatusHelp() /** * @brief .status and status command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandStatus(vector SplitCommand, string Command) +CommandStatus(vector CommandTokens, string Command) { - if (SplitCommand.size() != 1) + if (CommandTokens.size() != 1) { - ShowMessages("incorrect use of the '.status'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandStatusHelp(); } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/switch.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/switch.cpp similarity index 65% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/switch.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/switch.cpp index cf961898..65bf33ea 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/switch.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/switch.cpp @@ -11,12 +11,6 @@ */ #include "pch.h" -// -// Global Variables -// -extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; - /** * @brief help of the .switch command * @@ -33,6 +27,7 @@ CommandSwitchHelp() ShowMessages("syntax : \t.switch [tid ThreadId (hex)]\n"); ShowMessages("\n"); + ShowMessages("\t\te.g : .switch\n"); ShowMessages("\t\te.g : .switch list\n"); ShowMessages("\t\te.g : .switch pid b60 \n"); ShowMessages("\t\te.g : .switch tid b60 \n"); @@ -41,43 +36,34 @@ CommandSwitchHelp() /** * @brief .switch command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandSwitch(vector SplitCommand, string Command) +CommandSwitch(vector CommandTokens, string Command) { UINT32 PidOrTid = NULL; - if (SplitCommand.size() > 3 || SplitCommand.size() == 2) + if (CommandTokens.size() > 3) { - ShowMessages("incorrect use of the '.switch'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSwitchHelp(); return; } - // - // .attach and .detach commands are only supported in VMI Mode - // - if (g_IsSerialConnectedToRemoteDebuggee) - { - ShowMessages("err, the '.switch' command is only usable in VMI Mode, " - "you can use the '.process', or the '.thread' " - "in Debugger Mode\n"); - return; - } - // // Perform switching or listing the threads // - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1 || (CommandTokens.size() == 2 && CompareLowerCaseStrings(CommandTokens.at(1), "list"))) { UdShowListActiveDebuggingProcessesAndThreads(); } - else if (!SplitCommand.at(1).compare("pid")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "pid")) { - if (!ConvertStringToUInt32(SplitCommand.at(2), &PidOrTid)) + if (!ConvertTokenToUInt32(CommandTokens.at(2), &PidOrTid)) { ShowMessages("please specify a correct hex value for process id\n\n"); return; @@ -91,9 +77,9 @@ CommandSwitch(vector SplitCommand, string Command) ShowMessages("switched to process id: %x\n", PidOrTid); } } - else if (!SplitCommand.at(1).compare("tid")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "tid")) { - if (!ConvertStringToUInt32(SplitCommand.at(2), &PidOrTid)) + if (!ConvertTokenToUInt32(CommandTokens.at(2), &PidOrTid)) { ShowMessages("please specify a correct hex value for thread id\n\n"); return; @@ -110,7 +96,7 @@ CommandSwitch(vector SplitCommand, string Command) else { ShowMessages("err, couldn't resolve error at '%s'\n", - SplitCommand.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); return; } } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/sym.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/sym.cpp similarity index 64% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/sym.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/sym.cpp index 04c4c508..0f9c1f5b 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/sym.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/sym.cpp @@ -37,40 +37,45 @@ CommandSymHelp() ShowMessages("\n"); ShowMessages("\t\te.g : .sym table\n"); ShowMessages("\t\te.g : .sym reload\n"); + ShowMessages("\t\te.g : .sym reload pid 3a24\n"); ShowMessages("\t\te.g : .sym load\n"); ShowMessages("\t\te.g : .sym download\n"); ShowMessages("\t\te.g : .sym add base fffff8077356000 path c:\\symbols\\my_dll.pdb\n"); + ShowMessages("\t\te.g : .sym add base fffff8077356000 path \"c:\\symbols files\\my_dll.pdb\"\n"); ShowMessages("\t\te.g : .sym unload\n"); } /** * @brief .sym command handler * - * @param SplitCommand + * @param CommandTokens * @param Command * @return VOID */ VOID -CommandSym(vector SplitCommand, string Command) +CommandSym(vector CommandTokens, string Command) { UINT64 BaseAddress = NULL; UINT32 UserProcessId = NULL; + string PathToPdb; - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { - ShowMessages("incorrect use of the '.sym'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSymHelp(); return; } - if (!SplitCommand.at(1).compare("table")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "table")) { // // Validate params // - if (SplitCommand.size() != 2) + if (CommandTokens.size() != 2) { - ShowMessages("incorrect use of the '.sym'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSymHelp(); return; } @@ -80,14 +85,15 @@ CommandSym(vector SplitCommand, string Command) // SymbolBuildAndShowSymbolTable(); } - else if (!SplitCommand.at(1).compare("load") || !SplitCommand.at(1).compare("download")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "load") || CompareLowerCaseStrings(CommandTokens.at(1), "download")) { // // Validate params // - if (SplitCommand.size() != 2) + if (CommandTokens.size() != 2) { - ShowMessages("incorrect use of the '.sym'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSymHelp(); return; } @@ -95,23 +101,24 @@ CommandSym(vector SplitCommand, string Command) // // Load and download available symbols // - if (!SplitCommand.at(1).compare("load")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "load")) { SymbolLoadOrDownloadSymbols(FALSE, FALSE); } - else if (!SplitCommand.at(1).compare("download")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "download")) { SymbolLoadOrDownloadSymbols(TRUE, FALSE); } } - else if (!SplitCommand.at(1).compare("reload")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "reload")) { // // Validate params // - if (SplitCommand.size() != 2 && SplitCommand.size() != 4) + if (CommandTokens.size() != 2 && CommandTokens.size() != 4) { - ShowMessages("incorrect use of the '.sym'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSymHelp(); return; } @@ -119,24 +126,25 @@ CommandSym(vector SplitCommand, string Command) // // Check for process id // - if (SplitCommand.size() == 4) + if (CommandTokens.size() == 4) { - if (!SplitCommand.at(2).compare("pid")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "pid")) { - if (!ConvertStringToUInt32(SplitCommand.at(3), &UserProcessId)) + if (!ConvertTokenToUInt32(CommandTokens.at(3), &UserProcessId)) { // // couldn't resolve or unknown parameter // ShowMessages("err, couldn't resolve error at '%s'\n\n", - SplitCommand.at(3).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)).c_str()); CommandSymHelp(); return; } } else { - ShowMessages("incorrect use of the '.sym'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSymHelp(); return; } @@ -184,14 +192,15 @@ CommandSym(vector SplitCommand, string Command) } } } - else if (!SplitCommand.at(1).compare("unload")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "unload")) { // // Validate params // - if (SplitCommand.size() != 2) + if (CommandTokens.size() != 2) { - ShowMessages("incorrect use of the '.sym'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSymHelp(); return; } @@ -207,23 +216,22 @@ CommandSym(vector SplitCommand, string Command) // // ScriptEngineUnloadModuleSymbolWrapper((char *)SplitCommand.at(2).c_str()); } - else if (!SplitCommand.at(1).compare("add")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "add")) { // // Validate params // - if (SplitCommand.size() < 6) + if (CommandTokens.size() < 6) { - ShowMessages("incorrect use of the '.sym'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSymHelp(); return; } - if (!SplitCommand.at(2).compare("base")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "base")) { - string Delimiter = ""; - string PathToPdb = ""; - if (!ConvertStringToUInt64(SplitCommand.at(3), &BaseAddress)) + if (!ConvertTokenToUInt64(CommandTokens.at(3), &BaseAddress)) { ShowMessages("please add a valid hex address to be used as the base address\n\n"); CommandSymHelp(); @@ -233,9 +241,10 @@ CommandSym(vector SplitCommand, string Command) // // Base address is now valid, check if next parameter is path // - if (SplitCommand.at(4).compare("path")) + if (!CompareLowerCaseStrings(CommandTokens.at(4), "path")) { - ShowMessages("incorrect use of the '.sym'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSymHelp(); return; } @@ -243,8 +252,7 @@ CommandSym(vector SplitCommand, string Command) // // The rest of command is pdb path // - Delimiter = "path "; - PathToPdb = Command.substr(Command.find(Delimiter) + 5, Command.size()); + PathToPdb = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(5)); // // Check if pdb file exists or not @@ -265,14 +273,16 @@ CommandSym(vector SplitCommand, string Command) } else { - ShowMessages("incorrect use of the '.sym'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandSymHelp(); return; } } else { - ShowMessages("unknown parameter at '%s'\n\n", SplitCommand.at(1).c_str()); + ShowMessages("unknown parameter at '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); CommandSymHelp(); return; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/sympath.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/sympath.cpp similarity index 71% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/sympath.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/sympath.cpp index 872fadc0..b413cf8a 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/sympath.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/sympath.cpp @@ -30,23 +30,24 @@ CommandSympathHelp() ShowMessages("\n"); ShowMessages("\t\te.g : .sympath\n"); - ShowMessages("\t\te.g : .sympath SRV*c:\\Symbols*https://msdl.microsoft.com/download/symbols \n"); + ShowMessages("\t\te.g : .sympath \"SRV*c:\\Symbols*https://msdl.microsoft.com/download/symbols\" \n"); } /** * @brief .sympath command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandSympath(vector SplitCommand, string Command) +CommandSympath(vector CommandTokens, string Command) { string SymbolServer = ""; string Token; - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { // // Show the current symbol path @@ -66,6 +67,13 @@ CommandSympath(vector SplitCommand, string Command) // Save the symbol path // + // + // Because technically, the "https://" is containing characters that resemble the command token, + // it's better to use the symbol server in quotes, but due to the fact that for compatibility reasons, + // with the previous versions, we should support the old syntax, we should check if the symbol server + // is in quotes or not to support both syntaxes + // + // // Trim the command // @@ -74,13 +82,24 @@ CommandSympath(vector SplitCommand, string Command) // // Remove .sympath from it // - Command.erase(0, SplitCommand.at(0).size()); + Command.erase(0, GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).size()); // // Trim it again // Trim(Command); + // + // Check if the symbol server starts with quotes + // + if (Command.at(0) == '\"') + { + // + // Means that the symbol server is in quotes + // + Command = GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)); + } + // // *** validate the symbols *** // @@ -88,7 +107,7 @@ CommandSympath(vector SplitCommand, string Command) // // Check if the string contains '*' // - char Delimiter = '*'; + CHAR Delimiter = '*'; if (Command.find(Delimiter) != std::string::npos) { // diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/thread.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/thread.cpp similarity index 85% rename from hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/thread.cpp rename to hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/thread.cpp index 8cde0d6e..53800e8d 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/thread.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/meta-commands/thread.cpp @@ -111,26 +111,28 @@ CommandThreadListThreads(UINT64 Eprocess) /** * @brief .thread command handler * - * @param SplitCommand + * @param CommandTokens * @param Command + * * @return VOID */ VOID -CommandThread(vector SplitCommand, string Command) +CommandThread(vector CommandTokens, string Command) { UINT32 TargetThreadId = 0; UINT64 TargetThread = 0; UINT64 TargetProcess = 0; BOOLEAN CheckByClkIntr = FALSE; - if (SplitCommand.size() >= 5) + if (CommandTokens.size() >= 5) { - ShowMessages("incorrect use of the '.thread'\n\n"); + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandThreadHelp(); return; } - if (SplitCommand.size() == 1) + if (CommandTokens.size() == 1) { // // Check if it's connected to a remote debuggee or not @@ -151,9 +153,9 @@ CommandThread(vector SplitCommand, string Command) NULL); } } - else if (SplitCommand.size() == 2) + else if (CommandTokens.size() == 2) { - if (!SplitCommand.at(1).compare("list")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "list")) { // // Sending null as the nt!_EPROCESS indicates that the target process is @@ -171,12 +173,12 @@ CommandThread(vector SplitCommand, string Command) { ShowMessages( "err, unknown parameter at '%s'\n\n", - SplitCommand.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); CommandThreadHelp(); return; } } - else if (SplitCommand.size() == 3) + else if (CommandTokens.size() == 3) { // // Check if it's connected to a remote debuggee or not @@ -189,9 +191,9 @@ CommandThread(vector SplitCommand, string Command) return; } - if (!SplitCommand.at(1).compare("tid")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "tid")) { - if (!ConvertStringToUInt32(SplitCommand.at(2), &TargetThreadId)) + if (!ConvertTokenToUInt32(CommandTokens.at(2), &TargetThreadId)) { ShowMessages( "please specify a correct hex value for the thread id that you " @@ -200,9 +202,9 @@ CommandThread(vector SplitCommand, string Command) return; } } - else if (!SplitCommand.at(1).compare("thread")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "thread")) { - if (!SymbolConvertNameOrExprToAddress(SplitCommand.at(2), &TargetThread)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)), &TargetThread)) { ShowMessages( "please specify a correct hex value for the thread (nt!_ETHREAD) that you " @@ -211,7 +213,7 @@ CommandThread(vector SplitCommand, string Command) return; } } - else if (!SplitCommand.at(1).compare("list") && !SplitCommand.at(2).compare("process")) + else if (CompareLowerCaseStrings(CommandTokens.at(1), "list") && CompareLowerCaseStrings(CommandTokens.at(2), "process")) { ShowMessages( "please specify a hex value for the process\n\n"); @@ -222,12 +224,12 @@ CommandThread(vector SplitCommand, string Command) { ShowMessages( "err, unknown parameter at '%s'\n\n", - SplitCommand.at(2).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()); CommandThreadHelp(); return; } - if (!SplitCommand.at(0).compare(".thread2")) + if (CompareLowerCaseStrings(CommandTokens.at(0), ".thread2")) { // // Check by changes to gs:[188] @@ -251,13 +253,13 @@ CommandThread(vector SplitCommand, string Command) CheckByClkIntr, NULL); } - else if (SplitCommand.size() == 4) + else if (CommandTokens.size() == 4) { - if (!SplitCommand.at(1).compare("list")) + if (CompareLowerCaseStrings(CommandTokens.at(1), "list")) { - if (!SplitCommand.at(2).compare("process")) + if (CompareLowerCaseStrings(CommandTokens.at(2), "process")) { - if (!SymbolConvertNameOrExprToAddress(SplitCommand.at(3), &TargetProcess)) + if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)), &TargetProcess)) { ShowMessages( "please specify a correct hex value for the process (nt!_EPROCESS) that you " @@ -281,7 +283,7 @@ CommandThread(vector SplitCommand, string Command) { ShowMessages( "err, unknown parameter at '%s'\n\n", - SplitCommand.at(2).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str()); CommandThreadHelp(); return; } @@ -290,7 +292,7 @@ CommandThread(vector SplitCommand, string Command) { ShowMessages( "err, unknown parameter at '%s'\n\n", - SplitCommand.at(1).c_str()); + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str()); CommandThreadHelp(); return; } diff --git a/hyperdbg/hprdbgctrl/code/debugger/communication/forwarding.cpp b/hyperdbg/libhyperdbg/code/debugger/communication/forwarding.cpp similarity index 98% rename from hyperdbg/hprdbgctrl/code/debugger/communication/forwarding.cpp rename to hyperdbg/libhyperdbg/code/debugger/communication/forwarding.cpp index 6ec387e1..b6d3d940 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/communication/forwarding.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/communication/forwarding.cpp @@ -211,7 +211,7 @@ ForwardingCloseOutputSource(PDEBUGGER_EVENT_FORWARDING SourceDescriptor) * * @return HANDLE returns handle of the source */ -VOID * +PVOID ForwardingCreateOutputSource(DEBUGGER_EVENT_FORWARDING_TYPE SourceType, const string & Description, SOCKET * Socket, @@ -232,7 +232,7 @@ ForwardingCreateOutputSource(DEBUGGER_EVENT_FORWARDING_TYPE SourceType, // The handle might be INVALID_HANDLE_VALUE which will be // checked by the caller // - return (void *)FileHandle; + return (PVOID)FileHandle; } else if (SourceType == EVENT_FORWARDING_MODULE) { @@ -260,7 +260,7 @@ ForwardingCreateOutputSource(DEBUGGER_EVENT_FORWARDING_TYPE SourceType, // // The handle is the location of the hyperdbg_event_forwarding function // - return (void *)hyperdbg_event_forwarding; + return (PVOID)hyperdbg_event_forwarding; } else if (SourceType == EVENT_FORWARDING_NAMEDPIPE) { @@ -274,7 +274,7 @@ ForwardingCreateOutputSource(DEBUGGER_EVENT_FORWARDING_TYPE SourceType, return INVALID_HANDLE_VALUE; } - return (void *)PipeHandle; + return (PVOID)PipeHandle; } else if (SourceType == EVENT_FORWARDING_TCP) { @@ -287,7 +287,7 @@ ForwardingCreateOutputSource(DEBUGGER_EVENT_FORWARDING_TYPE SourceType, // Split the ip and port by : delimiter // IpPortDelimiter = ':'; - size_t find = Description.find(IpPortDelimiter); + SIZE_T find = Description.find(IpPortDelimiter); Ip = Description.substr(0, find); Port = Description.substr(find + 1, find + Description.size()); @@ -302,7 +302,7 @@ ForwardingCreateOutputSource(DEBUGGER_EVENT_FORWARDING_TYPE SourceType, // because this functionality doesn't work with handlers; however, // send 1 or TRUE is a valid handle // - return (void *)TRUE; + return (PVOID)TRUE; } else { @@ -347,7 +347,7 @@ ForwardingPerformEventForwarding(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetail, BOOLEAN Result = FALSE; PLIST_ENTRY TempList = 0; - for (size_t i = 0; i < DebuggerOutputSourceMaximumRemoteSourceForSingleEvent; i++) + for (SIZE_T i = 0; i < DebuggerOutputSourceMaximumRemoteSourceForSingleEvent; i++) { // // Check whether we reached to the end of the events diff --git a/hyperdbg/hprdbgctrl/code/debugger/communication/namedpipe.cpp b/hyperdbg/libhyperdbg/code/debugger/communication/namedpipe.cpp similarity index 94% rename from hyperdbg/hprdbgctrl/code/debugger/communication/namedpipe.cpp rename to hyperdbg/libhyperdbg/code/debugger/communication/namedpipe.cpp index b2e75899..a52fca2c 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/communication/namedpipe.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/communication/namedpipe.cpp @@ -68,9 +68,9 @@ NamedPipeServerWaitForClientConntection(HANDLE PipeHandle) // // Wait for the client to connect // - BOOL bClientConnected = ConnectNamedPipe(PipeHandle, NULL); + BOOL ClientConnected = ConnectNamedPipe(PipeHandle, NULL); - if (FALSE == bClientConnected) + if (FALSE == ClientConnected) { ShowMessages("err, occurred while connecting to the client (%x)\n", GetLastError()); @@ -93,7 +93,7 @@ NamedPipeServerWaitForClientConntection(HANDLE PipeHandle) * @return UINT32 */ UINT32 -NamedPipeServerReadClientMessage(HANDLE PipeHandle, char * BufferToSave, int MaximumReadBufferLength) +NamedPipeServerReadClientMessage(HANDLE PipeHandle, CHAR * BufferToSave, INT MaximumReadBufferLength) { DWORD cbBytes; @@ -129,8 +129,8 @@ NamedPipeServerReadClientMessage(HANDLE PipeHandle, char * BufferToSave, int Max BOOLEAN NamedPipeServerSendMessageToClient(HANDLE PipeHandle, - char * BufferToSend, - int BufferSize) + CHAR * BufferToSend, + INT BufferSize) { DWORD cbBytes; @@ -289,7 +289,7 @@ NamedPipeClientCreatePipeOverlappedIo(LPCSTR PipeName) * @return BOOLEAN */ BOOLEAN -NamedPipeClientSendMessage(HANDLE PipeHandle, char * BufferToSend, int BufferSize) +NamedPipeClientSendMessage(HANDLE PipeHandle, CHAR * BufferToSend, INT BufferSize) { // // We are done connecting to the server pipe, @@ -328,7 +328,7 @@ NamedPipeClientSendMessage(HANDLE PipeHandle, char * BufferToSend, int BufferSiz // Read the count of read buffer // UINT32 -NamedPipeClientReadMessage(HANDLE PipeHandle, char * BufferToRead, int MaximumSizeOfBuffer) +NamedPipeClientReadMessage(HANDLE PipeHandle, CHAR * BufferToRead, INT MaximumSizeOfBuffer) { DWORD cbBytes; @@ -376,17 +376,17 @@ NamedPipeClientClosePipe(HANDLE PipeHandle) /** * @brief and example of how to use named pipe as a server * - * @return int + * @return INT */ -int +INT NamedPipeServerExample() { HANDLE PipeHandle; BOOLEAN SentMessageResult; UINT32 ReadBytes; - const int BufferSize = 1024; - char BufferToRead[BufferSize] = {0}; - char BufferToSend[BufferSize] = "test message to send from server !!!"; + const INT BufferSize = 1024; + CHAR BufferToRead[BufferSize] = {0}; + CHAR BufferToSend[BufferSize] = "test message to send from server !!!"; PipeHandle = NamedPipeServerCreatePipe("\\\\.\\Pipe\\HyperDbgTests", BufferSize, @@ -447,16 +447,16 @@ NamedPipeServerExample() /** * @brief and example of how to use named pipe as a client * - * @return int + * @return INT */ -int +INT NamedPipeClientExample() { HANDLE PipeHandle; BOOLEAN SentMessageResult; UINT32 ReadBytes; - const int BufferSize = 1024; - char Buffer[BufferSize] = "test message to send from client !!!"; + const INT BufferSize = 1024; + CHAR Buffer[BufferSize] = "test message to send from client !!!"; PipeHandle = NamedPipeClientCreatePipe("\\\\.\\Pipe\\HyperDbgTests"); diff --git a/hyperdbg/hprdbgctrl/code/debugger/communication/remote-connection.cpp b/hyperdbg/libhyperdbg/code/debugger/communication/remote-connection.cpp similarity index 93% rename from hyperdbg/hprdbgctrl/code/debugger/communication/remote-connection.cpp rename to hyperdbg/libhyperdbg/code/debugger/communication/remote-connection.cpp index f0a3022e..75198438 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/communication/remote-connection.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/communication/remote-connection.cpp @@ -39,7 +39,7 @@ extern HANDLE g_EndOfMessageReceivedEvent; VOID RemoteConnectionListen(PCSTR Port) { - char recvbuf[COMMUNICATION_BUFFER_SIZE] = {0}; + CHAR recvbuf[COMMUNICATION_BUFFER_SIZE] = {0}; // // Check if the debugger or debuggee is already active @@ -75,7 +75,7 @@ RemoteConnectionListen(PCSTR Port) // // Check whether the signature of debuggee and debugger match or not // - if (strcmp((const char *)BuildSignature, recvbuf) != 0) + if (strcmp((const CHAR *)BuildSignature, recvbuf) != 0) { // // Build version not matched @@ -154,12 +154,12 @@ RemoteConnectionListen(PCSTR Port) // // Execute the command // - int CommandExecutionResult = HyperDbgInterpreter(recvbuf); + INT CommandExecutionResult = HyperDbgInterpreter(recvbuf); // // Send end of buffer // - RemoteConnectionSendResultsToHost((const char *)g_EndOfBufferCheckTcp, sizeof(g_EndOfBufferCheckTcp)); + RemoteConnectionSendResultsToHost((const CHAR *)g_EndOfBufferCheckTcp, sizeof(g_EndOfBufferCheckTcp)); // // if the debugger encounters an exit state then the return will be 1 @@ -191,7 +191,7 @@ RemoteConnectionListen(PCSTR Port) // // Indicate that we're not in remote debugger anymore // - ShowMessages("closing the conntection...\n"); + ShowMessages("closing the connection...\n"); // // Close the connection @@ -210,7 +210,7 @@ RemoteConnectionListen(PCSTR Port) DWORD WINAPI RemoteConnectionThreadListeningToDebuggee(LPVOID lpParam) { - char RecvBuf[COMMUNICATION_BUFFER_SIZE + TCP_END_OF_BUFFER_CHARS_COUNT] = {0}; + CHAR RecvBuf[COMMUNICATION_BUFFER_SIZE + TCP_END_OF_BUFFER_CHARS_COUNT] = {0}; UINT32 BuffLenReceived = 0; while (g_IsConnectedToRemoteDebuggee) @@ -229,7 +229,7 @@ RemoteConnectionThreadListeningToDebuggee(LPVOID lpParam) // // Check if it's end of the buffer // - for (size_t i = 0; i < BuffLenReceived; i++) + for (SIZE_T i = 0; i < BuffLenReceived; i++) { if (RecvBuf[i] == g_EndOfBufferCheckTcp[0] && RecvBuf[i + 1] == g_EndOfBufferCheckTcp[1] && @@ -364,7 +364,7 @@ RemoteConnectionConnect(PCSTR Ip, PCSTR Port) // // Check to see whether the version of debugger and debuggee matches together or not // - if (CommunicationClientSendMessage(g_ClientConnectSocket, (const char *)BuildSignature, sizeof(BuildSignature)) != 0) + if (CommunicationClientSendMessage(g_ClientConnectSocket, (const CHAR *)BuildSignature, sizeof(BuildSignature)) != 0) { // // Failed @@ -388,7 +388,7 @@ RemoteConnectionConnect(PCSTR Ip, PCSTR Port) // // Check if the handshake was successful or not // - if (strcmp((const char *)"OK", Recv) != 0) + if (strcmp((const CHAR *)"OK", Recv) != 0) { // // Build version not matched @@ -438,11 +438,11 @@ RemoteConnectionConnect(PCSTR Ip, PCSTR Port) * * @param sendbuf address of message buffer * @param len length of buffer - * @return int returning 0 means that there was no error in + * @return INT returning 0 means that there was no error in * executing the function and 1 shows there was an error */ -int -RemoteConnectionSendCommand(const char * sendbuf, int len) +INT +RemoteConnectionSendCommand(const CHAR * sendbuf, INT len) { // // Send Message @@ -474,11 +474,11 @@ RemoteConnectionSendCommand(const char * sendbuf, int len) * * @param sendbuf buffer address * @param len length of buffer - * @return int returning 0 means that there was no error in + * @return INT returning 0 means that there was no error in * executing the function and 1 shows there was an error */ -int -RemoteConnectionSendResultsToHost(const char * sendbuf, int len) +INT +RemoteConnectionSendResultsToHost(const CHAR * sendbuf, INT len) { // // Send the message @@ -497,10 +497,10 @@ RemoteConnectionSendResultsToHost(const char * sendbuf, int len) /** * @brief Close the connect from client side to the debuggee * - * @return int returning 0 means that there was no error in + * @return INT returning 0 means that there was no error in * executing the function and 1 shows there was an error */ -int +INT RemoteConnectionCloseTheConnectionWithDebuggee() { CommunicationClientShutdownConnection(g_ClientConnectSocket); diff --git a/hyperdbg/hprdbgctrl/code/debugger/communication/tcpclient.cpp b/hyperdbg/libhyperdbg/code/debugger/communication/tcpclient.cpp similarity index 86% rename from hyperdbg/hprdbgctrl/code/debugger/communication/tcpclient.cpp rename to hyperdbg/libhyperdbg/code/debugger/communication/tcpclient.cpp index b601f3f9..831b361c 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/communication/tcpclient.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/communication/tcpclient.cpp @@ -17,23 +17,23 @@ * @param Ip * @param Port * @param ConnectSocketArg - * @return int + * @return INT */ -int +INT CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketArg) { WSADATA wsaData; SOCKET ConnectSocket = INVALID_SOCKET; struct addrinfo *result = NULL, *ptr = NULL, hints; - int iResult; + INT IResult; // // Initialize Winsock // - iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (iResult != 0) + IResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (IResult != 0) { - ShowMessages("err, WSAStartup failed (%x)\n", iResult); + ShowMessages("err, WSAStartup failed (%x)\n", IResult); return 1; } @@ -45,10 +45,10 @@ CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketA // // Resolve the server address and port // - iResult = getaddrinfo(Ip, Port, &hints, &result); - if (iResult != 0) + IResult = getaddrinfo(Ip, Port, &hints, &result); + if (IResult != 0) { - ShowMessages("getaddrinfo failed (%x)\n", iResult); + ShowMessages("getaddrinfo failed (%x)\n", IResult); WSACleanup(); return 1; } @@ -72,8 +72,8 @@ CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketA // // Connect to server. // - iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); - if (iResult == SOCKET_ERROR) + IResult = connect(ConnectSocket, ptr->ai_addr, (INT)ptr->ai_addrlen); + if (IResult == SOCKET_ERROR) { closesocket(ConnectSocket); ConnectSocket = INVALID_SOCKET; @@ -105,18 +105,18 @@ CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketA * @param ConnectSocket * @param sendbuf * @param buflen - * @return int + * @return INT */ -int -CommunicationClientSendMessage(SOCKET ConnectSocket, const char * sendbuf, int buflen) +INT +CommunicationClientSendMessage(SOCKET ConnectSocket, const CHAR * sendbuf, INT buflen) { - int iResult; + INT IResult; // // Send an initial buffer // - iResult = send(ConnectSocket, sendbuf, buflen, 0); - if (iResult == SOCKET_ERROR) + IResult = send(ConnectSocket, sendbuf, buflen, 0); + if (IResult == SOCKET_ERROR) { ShowMessages("err, send failed (%x)\n", WSAGetLastError()); closesocket(ConnectSocket); @@ -131,18 +131,18 @@ CommunicationClientSendMessage(SOCKET ConnectSocket, const char * sendbuf, int b * @brief shutdown the connection as a client * * @param ConnectSocket - * @return int + * @return INT */ -int +INT CommunicationClientShutdownConnection(SOCKET ConnectSocket) { - int iResult; + INT IResult; // // shutdown the connection since no more data will be sent // - iResult = shutdown(ConnectSocket, SD_SEND); - if (iResult == SOCKET_ERROR) + IResult = shutdown(ConnectSocket, SD_SEND); + if (IResult == SOCKET_ERROR) { // // We comment this line because the connection might be removed; @@ -167,12 +167,12 @@ CommunicationClientShutdownConnection(SOCKET ConnectSocket) * @param RecvBuf * @param MaxBuffLen * @param BuffLenRecvd - * @return int + * @return INT */ -int +INT CommunicationClientReceiveMessage(SOCKET ConnectSocket, CHAR * RecvBuf, UINT32 MaxBuffLen, PUINT32 BuffLenRecvd) { - int Result; + INT Result; // // Receive until the peer closes the connection @@ -210,9 +210,9 @@ CommunicationClientReceiveMessage(SOCKET ConnectSocket, CHAR * RecvBuf, UINT32 M * @brief cleanup the connection as client * * @param ConnectSocket - * @return int + * @return INT */ -int +INT CommunicationClientCleanup(SOCKET ConnectSocket) { // diff --git a/hyperdbg/hprdbgctrl/code/debugger/communication/tcpserver.cpp b/hyperdbg/libhyperdbg/code/debugger/communication/tcpserver.cpp similarity index 83% rename from hyperdbg/hprdbgctrl/code/debugger/communication/tcpserver.cpp rename to hyperdbg/libhyperdbg/code/debugger/communication/tcpserver.cpp index 764ff0eb..19129e29 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/communication/tcpserver.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/communication/tcpserver.cpp @@ -27,13 +27,13 @@ * @param ListenSocketArg * @return int */ -int +INT CommunicationServerCreateServerAndWaitForClient(PCSTR Port, SOCKET * ClientSocketArg, SOCKET * ListenSocketArg) { WSADATA wsaData; - int iResult; + INT IResult; SOCKET ListenSocket = INVALID_SOCKET; SOCKET ClientSocket = INVALID_SOCKET; @@ -44,10 +44,10 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port, // // Initialize Winsock // - iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (iResult != 0) + IResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (IResult != 0) { - ShowMessages("err, WSAStartup failed (%x)\n", iResult); + ShowMessages("err, WSAStartup failed (%x)\n", IResult); return 1; } @@ -60,10 +60,10 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port, // // Resolve the server address and port // - iResult = getaddrinfo(NULL, Port, &hints, &result); - if (iResult != 0) + IResult = getaddrinfo(NULL, Port, &hints, &result); + if (IResult != 0) { - ShowMessages("err, getaddrinfo failed (%x)\n", iResult); + ShowMessages("err, getaddrinfo failed (%x)\n", IResult); WSACleanup(); return 1; } @@ -84,8 +84,8 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port, // // Setup the TCP listening socket // - iResult = ::bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); - if (iResult == SOCKET_ERROR) + IResult = ::bind(ListenSocket, result->ai_addr, (INT)result->ai_addrlen); + if (IResult == SOCKET_ERROR) { ShowMessages("err, bind failed (%x)\n", WSAGetLastError()); freeaddrinfo(result); @@ -96,8 +96,8 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port, freeaddrinfo(result); - iResult = listen(ListenSocket, SOMAXCONN); - if (iResult == SOCKET_ERROR) + IResult = listen(ListenSocket, SOMAXCONN); + if (IResult == SOCKET_ERROR) { ShowMessages("err, listen failed (%x)\n", WSAGetLastError()); closesocket(ListenSocket); @@ -109,9 +109,9 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port, // Accept a client socket // sockaddr_in name = {0}; - int addrlen = sizeof(name); + INT AddrLen = sizeof(name); - ClientSocket = accept(ListenSocket, (struct sockaddr *)&name, &addrlen); + ClientSocket = accept(ListenSocket, (struct sockaddr *)&name, &AddrLen); if (ClientSocket == INVALID_SOCKET) { @@ -141,24 +141,24 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port, * @param ClientSocket * @param recvbuf * @param recvbuflen - * @return int + * @return INT */ -int -CommunicationServerReceiveMessage(SOCKET ClientSocket, char * recvbuf, int recvbuflen) +INT +CommunicationServerReceiveMessage(SOCKET ClientSocket, CHAR * recvbuf, INT recvbuflen) { - int iResult; + INT IResult; // // Receive until the peer shuts down the connection // - iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); - if (iResult > 0) + IResult = recv(ClientSocket, recvbuf, recvbuflen, 0); + if (IResult > 0) { // // ShowMessages("bytes received: %d\n", iResult); // } - else if (iResult == 0) + else if (IResult == 0) { // // ShowMessages("connection closing...\n"); @@ -182,18 +182,18 @@ CommunicationServerReceiveMessage(SOCKET ClientSocket, char * recvbuf, int recvb * @param ClientSocket * @param sendbuf * @param length - * @return int + * @return INT */ -int -CommunicationServerSendMessage(SOCKET ClientSocket, const char * sendbuf, int length) +INT +CommunicationServerSendMessage(SOCKET ClientSocket, const CHAR * sendbuf, INT length) { - int iSendResult; + INT ISendResult; // // Echo the buffer back to the sender // - iSendResult = send(ClientSocket, sendbuf, length, 0); - if (iSendResult == SOCKET_ERROR) + ISendResult = send(ClientSocket, sendbuf, length, 0); + if (ISendResult == SOCKET_ERROR) { /* ShowMessages("err, send failed (%x)\n", WSAGetLastError()); @@ -210,13 +210,13 @@ CommunicationServerSendMessage(SOCKET ClientSocket, const char * sendbuf, int le * * @param ClientSocket * @param ListenSocket - * @return int + * @return INT */ -int +INT CommunicationServerShutdownAndCleanupConnection(SOCKET ClientSocket, SOCKET ListenSocket) { - int iResult; + INT IResult; // // No longer need server socket @@ -226,8 +226,8 @@ CommunicationServerShutdownAndCleanupConnection(SOCKET ClientSocket, // // shutdown the connection since we're done // - iResult = shutdown(ClientSocket, SD_SEND); - if (iResult == SOCKET_ERROR) + IResult = shutdown(ClientSocket, SD_SEND); + if (IResult == SOCKET_ERROR) { // // We comment this line because the connection might be removed; @@ -295,7 +295,7 @@ CommunicationServerShutdownAndCleanupConnection(SOCKET ClientSocket, // } // } // -// ShowMessages("close conntection\n"); +// ShowMessages("close connection\n"); // // // // // Close the connection diff --git a/hyperdbg/hprdbgctrl/code/debugger/core/break-control.cpp b/hyperdbg/libhyperdbg/code/debugger/core/break-control.cpp similarity index 81% rename from hyperdbg/hprdbgctrl/code/debugger/core/break-control.cpp rename to hyperdbg/libhyperdbg/code/debugger/core/break-control.cpp index 00e835d7..a703ac8c 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/core/break-control.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/core/break-control.cpp @@ -1,5 +1,5 @@ /** - * @file breakcontrol.cpp + * @file break-control.cpp * @author Sina Karvandi (sina@hyperdbg.org) * @brief break control is the handler for CTRL+C and CTRL+BREAK Signals * @details @@ -15,7 +15,7 @@ // Global Variables // extern BOOLEAN g_BreakPrintingOutput; -extern BOOLEAN g_IsDebuggerModulesLoaded; +extern BOOLEAN g_IsKdModuleLoaded; extern BOOLEAN g_AutoUnpause; extern BOOLEAN g_IsConnectedToRemoteDebuggee; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; @@ -76,10 +76,10 @@ BreakController(DWORD CtrlType) } else { - KdBreakControlCheckAndPauseDebugger(); + KdBreakControlCheckAndPauseDebugger(TRUE); } } - else if (!g_IsDebuggerModulesLoaded && !g_IsConnectedToRemoteDebuggee) + else if (!g_IsKdModuleLoaded && !g_IsConnectedToRemoteDebuggee) { // // vmm module is not loaded here @@ -116,18 +116,19 @@ BreakController(DWORD CtrlType) if (g_AutoUnpause) { ShowMessages( - "\npausing...\nauto-unpause mode is enabled, " + "\npausing...%s\nauto-unpause mode is enabled, " "debugger will automatically continue when you run a new " "event command, if you want to change this behaviour then " - "run run 'settings autounpause off'\n\n"); + "run run 'settings autounpause off'\n\n", + g_ActiveProcessDebuggingState.IsActive ? PAUSE_MESSAGE_IN_USER_DEBUGGER : ""); } else { ShowMessages( - "\npausing...\nauto-unpause mode is disabled, you " + "\npausing...%s\nauto-unpause mode is disabled, you " "should run 'g' when you want to continue, otherwise run " - "'settings " - "autounpause on'\n\n"); + "'settings autounpause on'\n\n", + g_ActiveProcessDebuggingState.IsActive ? PAUSE_MESSAGE_IN_USER_DEBUGGER : ""); } // @@ -135,10 +136,13 @@ BreakController(DWORD CtrlType) // HyperDbgShowSignature(); - if (g_ActiveProcessDebuggingState.IsActive) - { - UdPauseProcess(g_ActiveProcessDebuggingState.ProcessDebuggingToken); - } + // + // Not pause the process if CTRL+C is pressed (Commented) + // + // if (g_ActiveProcessDebuggingState.IsActive) + // { + // UdPauseProcess(g_ActiveProcessDebuggingState.ProcessDebuggingToken); + // } } } } diff --git a/hyperdbg/hprdbgctrl/code/debugger/core/debugger.cpp b/hyperdbg/libhyperdbg/code/debugger/core/debugger.cpp similarity index 71% rename from hyperdbg/hprdbgctrl/code/debugger/core/debugger.cpp rename to hyperdbg/libhyperdbg/code/debugger/core/debugger.cpp index 69340976..de827e8c 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/core/debugger.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/core/debugger.cpp @@ -15,6 +15,7 @@ // Global Variables // extern UINT64 g_EventTag; +extern UINT64 g_KernelBaseAddress; extern LIST_ENTRY g_EventTrace; extern BOOLEAN g_EventTraceInitialized; extern BOOLEAN g_BreakPrintingOutput; @@ -25,6 +26,8 @@ extern BOOLEAN g_IsConnectedToRemoteDebuggee; extern BOOLEAN g_IsConnectedToRemoteDebugger; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsVmmModuleLoaded; extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; /** @@ -64,7 +67,10 @@ ShowErrorMessage(UINT32 Error) break; case DEBUGGER_ERROR_INVALID_ADDRESS: - ShowMessages("err, invalid address (%x)\n", + + ShowMessages("err, invalid address (%x)\n" + "address may be paged-out or unavailable on the page table due to 'demand paging'\n" + "please refer to https://docs.hyperdbg.org/tips-and-tricks/considerations/accessing-invalid-address for further information\n", Error); break; @@ -84,12 +90,12 @@ ShowErrorMessage(UINT32 Error) break; case DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER: - ShowMessages("err, unable to hide or unhide debugger (%x)\n", + ShowMessages("err, unable to hide or unhide debugger and entr the transparent mode (%x)\n", Error); break; - case DEBUGGER_ERROR_DEBUGGER_ALREADY_UHIDE: - ShowMessages("err, debugger already unhide (%x)\n", + case DEBUGGER_ERROR_DEBUGGER_ALREADY_HIDE: + ShowMessages("err, debugger already hidden in the transparent mode (%x)\n", Error); break; @@ -101,7 +107,9 @@ ShowErrorMessage(UINT32 Error) case DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS: ShowMessages("err, edit memory request has invalid address based on " "current process layout, the address might be valid but not " - "present in the ram (%x)\n", + "present in the ram (%x)\n" + "address may be paged-out or unavailable on the page table due to 'demand paging'\n" + "please refer to https://docs.hyperdbg.org/tips-and-tricks/considerations/accessing-invalid-address for further information\n", Error); break; @@ -222,7 +230,9 @@ ShowErrorMessage(UINT32 Error) case DEBUGGER_ERROR_MAXIMUM_BREAKPOINT_FOR_A_SINGLE_PAGE_IS_HIT: ShowMessages("err, the maximum breakpoint for a single page is hit, " - "you cannot apply more breakpoints in this page (%x)\n", + "you cannot apply more breakpoints in this page (%x)\n" + "please refer to https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/number-of-ept-hooks-in-one-page" + " for further information\n", Error); break; @@ -235,7 +245,8 @@ ShowErrorMessage(UINT32 Error) break; case DEBUGGER_ERROR_EPT_COULD_NOT_SPLIT_THE_LARGE_PAGE_TO_4KB_PAGES: - ShowMessages("err, could not convert 2MB large page to 4KB pages (%x)\n", + ShowMessages("err, could not convert 2MB large page to 4KB pages " + "(maybe pre-allocated buffers are empty?) (%x)\n", Error); break; @@ -487,15 +498,14 @@ ShowErrorMessage(UINT32 Error) break; case DEBUGGER_ERROR_THE_MODE_EXEC_TRAP_IS_NOT_INITIALIZED: - ShowMessages("err, the '!mode' event command cannot be directly initialized in the Debugger Mode. " - "To avoid wasting system resources and performance issues we decided to use another " - "command to initialize it first then use it. You can use the 'preactivate mode' command " - "to preactivate this mechanism after that, you can use the '!mode' event (%x)\n", + ShowMessages("err, for performance reasons, the '!mode' event command cannot be directly initialized in the Debugger Mode. " + "You can use the 'preactivate mode' command to preactivate this mechanism after that, " + "you can use the '!mode' event (%x)\n", Error); break; case DEBUGGER_ERROR_THE_TARGET_EVENT_IS_DISABLED_BUT_CANNOT_BE_CLEARED_PRIRITY_BUFFER_IS_FULL: - ShowMessages("err, The event(s) that you've requested are disabled, yet HyperDbg cannot remove (clear) them in " + ShowMessages("err, the event(s) that you've requested are disabled, yet HyperDbg cannot remove (clear) them in " "the subsequent run due to the user-mode priority buffers being at full capacity. " "This typically occurs when you attempt to clear numerous events without resuming the debuggee. " "Since these unserviced events remain in the queue, HyperDbg is unable to clear them. " @@ -506,6 +516,128 @@ ShowErrorMessage(UINT32 Error) Error); break; + case DEBUGGER_ERROR_NOT_ALL_CORES_ARE_LOCKED_FOR_APPLYING_INSTANT_EVENT: + ShowMessages("err, the event cannot be applied since not all cores are locked! " + "If you are using the instant-event mechanism or switching between cores, this will likely halt the system. " + "This may be caused by a race condition, but continuing and halting the debugger might resolve it. " + "If the problem persists, please open an issue and provide steps to reproduce it (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_TARGET_SWITCHING_CORE_IS_NOT_LOCKED: + ShowMessages("err, target core is not locked! " + "This may be caused by a race condition, continuing and halting the debugger might resolve it. " + "If the problem persists, please open an issue and provide steps to reproduce it (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_INVALID_PHYSICAL_ADDRESS: + ShowMessages("err, invalid physical address (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_APIC_ACTIONS_ERROR: + ShowMessages("err, could not perform APIC actions (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_DEBUGGER_ALREADY_UNHIDE: + ShowMessages("err, debugger was not in the hidden transparent-mode (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_DEBUGGER_NOT_INITIALIZED: + ShowMessages("err, the user debugger cannot be initialized (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_CANNOT_PUT_EPT_HOOKS_ON_PHYSICAL_ADDRESS_ABOVE_512_GB: + ShowMessages("err, putting EPT hooks on physical address above 512 GB is not supported (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_INVALID_SMI_OPERATION_PARAMETERS: + ShowMessages("err, invalid SMI operation parameter(s) are specified (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_UNABLE_TO_TRIGGER_SMI: + ShowMessages("err, unable to trigger SMI, are you running on a nested-virtualization environment? (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_UNABLE_TO_APPLY_COMMAND_TO_THE_TARGET_THREAD: + ShowMessages("err, unable to apply command to the target thread (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_HYPERTRACE_NOT_INITIALIZED: + ShowMessages("err, the hypertrace module is not loaded and initialized, " + "use the 'load trace' command to load the hypertrace module (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_INVALID_HYPERTRACE_OPERATION_TYPE: + ShowMessages("err, invalid hypertrace operation type is specified (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_LBR_ALREADY_ENABLED: + ShowMessages("err, LBR is already enabled, you can disable it using the '!lbr' command (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_LBR_ALREADY_DISABLED: + ShowMessages("err, LBR is already disabled, you can enable it using the '!lbr' command (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_LBR_NOT_SUPPORTED: + ShowMessages("err, LBR is not supported on this processor, this is likely caused by running inside " + "a nested virtualization (VM) environment that masks and removes LBR CPU flags (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_LBR_NOT_SUPPORTED_ON_VMCS: + ShowMessages("err, LBR is not supported on VMCS (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_PT_ALREADY_ENABLED: + ShowMessages("err, PT is already enabled (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_PT_ALREADY_DISABLED: + ShowMessages("err, PT is already disabled (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_PT_NOT_SUPPORTED: + ShowMessages("err, PT is not supported on this processor (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_VMM_CANNOT_BE_INITIALIZED_IF_HYPERTRACE_IS_LOADED: + ShowMessages("err, hypertrace is already loaded, please unload hypertrace module using the " + "'unload' command and then load the 'VMM' module. Then you can load hypertrace " + "after loading the VMM as it is because hypertrace behaves differently to sync " + "with VMM modules; it needs to have this notion that it is running within the " + "hypervisor, so that is why it needs to be initialized again if the VMM module " + "is loaded (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_VMM_CANNOT_BE_INITIALIZED_IF_DEBUGGER_IS_NOT_LOADED: + ShowMessages("err, the VMM module cannot be initialized because the debugger is not loaded (%x)\n", + Error); + break; + + case DEBUGGER_ERROR_CANNOT_INITIALIZE_DEBUGGER: + ShowMessages("err, cannot initialize the debugger (%x)\n", + Error); + break; + default: ShowMessages("err, error not found (%x)\n", Error); @@ -524,28 +656,19 @@ ShowErrorMessage(UINT32 Error) UINT64 DebuggerGetNtoskrnlBase() { - NTSTATUS Status = STATUS_UNSUCCESSFUL; - UINT64 NtoskrnlBase = NULL; - PRTL_PROCESS_MODULES Modules = NULL; - ULONG SysModuleInfoBufferSize = 0; +#ifdef _WIN32 + UINT64 NtoskrnlBase = NULL; + PRTL_PROCESS_MODULES Modules = NULL; - // - // Get required size of "RTL_PROCESS_MODULES" buffer - // - Status = NtQuerySystemInformation(SystemModuleInformation, NULL, NULL, &SysModuleInfoBufferSize); - - Modules = (PRTL_PROCESS_MODULES)malloc(SysModuleInfoBufferSize); - - if (Modules == NULL) + if (SymbolCheckAndAllocateModuleInformation(&Modules) == FALSE) { + ShowMessages("err, unable to get the module list for getting ntoskrnl base address\n"); return NULL64_ZERO; } - NtQuerySystemInformation(SystemModuleInformation, Modules, SysModuleInfoBufferSize, NULL); - for (UINT32 i = 0; i < Modules->NumberOfModules; i++) { - if (!strcmp((const char *)Modules->Modules[i].FullPathName + Modules->Modules[i].OffsetToFileName, + if (!strcmp((const CHAR *)Modules->Modules[i].FullPathName + Modules->Modules[i].OffsetToFileName, "ntoskrnl.exe")) { NtoskrnlBase = (UINT64)Modules->Modules[i].ImageBase; @@ -556,6 +679,37 @@ DebuggerGetNtoskrnlBase() free(Modules); return NtoskrnlBase; +#else + // + // TODO(Linux): NT-style system module enumeration (PRTL_PROCESS_MODULES via + // NtQuerySystemInformation) has no Linux analog. The kernel-module base lookup + // will need a Linux-specific mechanism once the kernel side exists. + // + return NULL64_ZERO; +#endif +} + +/** + * @brief Get the base address of the kernel module + * + * @return UINT64 + */ +UINT64 +DebuggerGetKernelBase() +{ + UINT64 KernelBase = NULL; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + KernelBase = g_KernelBaseAddress; + } + else + { + KernelBase = DebuggerGetNtoskrnlBase(); + g_KernelBaseAddress = KernelBase; + } + + return KernelBase; } /** @@ -574,7 +728,7 @@ DebuggerPauseDebuggee() // // Send a pause IOCTL // - StatusIoctl = DeviceIoControl(g_DeviceHandle, // Handle to device + StatusIoctl = PlatformDeviceIoControl(g_DeviceHandle, // Handle to device IOCTL_PAUSE_PACKET_RECEIVED, // IO Control Code (IOCTL) &PauseRequest, // Input Buffer to driver. SIZEOF_DEBUGGER_PAUSE_PACKET_RECEIVED, // Input buffer @@ -588,7 +742,7 @@ DebuggerPauseDebuggee() if (!StatusIoctl) { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError()); return FALSE; } @@ -702,8 +856,7 @@ IsTagExist(UINT64 Tag) * script in this command split and the details are returned in the * input structure * - * @param SplitCommand the initialized command that are split by space - * @param SplitCommandCaseSensitive case sensitive split command + * @param CommandTokens command tokens * @param BufferAddress the address that the allocated buffer will be saved on * it * @param BufferLength the length of the buffer @@ -711,241 +864,46 @@ IsTagExist(UINT64 Tag) * successful (false) */ BOOLEAN -InterpretScript(vector * SplitCommand, - vector * SplitCommandCaseSensitive, - PBOOLEAN ScriptSyntaxErrors, - PUINT64 BufferAddress, - PUINT32 BufferLength, - PUINT32 Pointer, - PUINT64 ScriptCodeBuffer) +InterpretScript(vector * CommandTokens, + PBOOLEAN ScriptSyntaxErrors, + PUINT64 BufferAddress, + PUINT32 BufferLength, + PUINT32 Pointer, + PUINT64 ScriptCodeBuffer) { - BOOLEAN IsTextVisited = FALSE; - BOOLEAN IsInState = FALSE; - BOOLEAN IsEnded = FALSE; - string AppendedFinalBuffer; - vector SaveBuffer; - vector IndexesToRemove; - UINT32 Index = 0; - UINT32 NewIndexToRemove = 0; - UINT32 OpenBracket = 0; - UINT32 CountOfOpenBrackets; - UINT32 CountOfCloseBrackets; - UINT32 IndexInCommandCaseSensitive = 0; - vector SplitCommandCaseSensitiveInstance = *SplitCommandCaseSensitive; - string TempStr; + BOOLEAN IsTextVisited = FALSE; + string TargetBracketString = ""; + + vector IndexesToRemove; + UINT32 Index = 0; + UINT32 NewIndexToRemove = 0; // // Indicate that there is an error at first // *ScriptSyntaxErrors = TRUE; - for (auto Section : *SplitCommand) + for (auto Section : *CommandTokens) { - IndexInCommandCaseSensitive++; Index++; - if (IsInState) - { - if (OpenBracket == 0 && Section.find('{') == string::npos) - { - // - // Check if the buffer is ended or not - // - if (!Section.compare("}")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - IsEnded = TRUE; - break; - } - - // - // Check if the script is end or not - // - if (HasEnding(Section, "}")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - // - // remove the last character and append it to the ConditionBuffer - // - TempStr = SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - - IsEnded = TRUE; - break; - } - } - - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - // - // Check if script contains bracket "{" - // - if (Section.find('{') != string::npos) - { - // - // We find a { between the script - // - - // - // Check the count of brackets in the string and add it to OpenBracket - // - UINT32 CountOfBrackets = (UINT32)count(Section.begin(), Section.end(), '{'); - - // - // Add it to the open brackets - // - OpenBracket += CountOfBrackets; - } - - // - // Check if script contains bracket "}" - // - if (Section.find('}') != string::npos) - { - // - // We find a } between the script - // - - // - // Check the count of brackets in the string and add it to OpenBracket - // - UINT32 CountOfBrackets = (UINT32)count(Section.begin(), Section.end(), '}'); - - // - // Add it to the open brackets - // - OpenBracket -= CountOfBrackets; - - if (OpenBracket < 0) - { - OpenBracket = 0; - IsEnded = TRUE; - TempStr = SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - break; - } - } - - // - // Add the text as the script screen - // - SaveBuffer.push_back(SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1)); - - // - // We want to stay in this condition - // - continue; - } - - if (IsTextVisited && !Section.compare("{")) + if (IsTextVisited && IsTokenBracketString(Section)) { // // Save to remove this string from the command // IndexesToRemove.push_back(Index); - IsInState = TRUE; + // + // Fill the bracket string + // + TargetBracketString = GetCaseSensitiveStringFromCommandToken(Section); + + IsTextVisited = FALSE; continue; } - if (IsTextVisited && Section.rfind('{', 0) == 0) - { - // - // Section starts with { - // - - // - // Check if script contains bracket "{" - // - if (Section.find('{') != string::npos) - { - // - // We find a { between the script - // - - // - // Check the count of brackets in the string and add it to OpenBracket - // - UINT32 CountOfBrackets = (UINT32)count(Section.begin(), Section.end(), '{'); - - // - // Add it to the open brackets (-1 because script starts with { which - // is not related to our interpretation of script) - // - OpenBracket += CountOfBrackets - 1; - } - - // - // Check if it ends with } - // - if (OpenBracket == 0 && HasEnding(Section, "}")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - TempStr = SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1).erase(0, 1); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - - IsEnded = TRUE; - break; - } - - // - // Check if script contains bracket "}" - // - if (Section.find('}') != string::npos) - { - // - // We find a } between the script - // - - // - // Check the count of brackets in the string and add it to OpenBracket - // - UINT32 CountOfBrackets = (UINT32)count(Section.begin(), Section.end(), '}'); - - // - // Add it to the open brackets - // - OpenBracket -= CountOfBrackets; - - if (OpenBracket < 0) - { - OpenBracket = 0; - IsEnded = TRUE; - TempStr = SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - break; - } - } - - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - SaveBuffer.push_back(SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1).erase(0, 1)); - - IsInState = TRUE; - continue; - } - - // - // Check if it's a script - // - if (!Section.compare("script")) + if (CompareLowerCaseStrings(Section, "script")) { // // Save to remove this string from the command @@ -955,157 +913,30 @@ InterpretScript(vector * SplitCommand, IsTextVisited = TRUE; continue; } - - // - // Check if it's a script with script{ - // - if (!Section.compare("script{")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - IsTextVisited = TRUE; - IsInState = TRUE; - continue; - } - - // - // It's a script - // - if (Section.rfind("script{", 0) == 0) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - IsTextVisited = TRUE; - IsInState = TRUE; - CountOfOpenBrackets = (UINT32)count(Section.begin(), Section.end(), '{'); - CountOfCloseBrackets = (UINT32)count(Section.begin(), Section.end(), '}'); - - // - // Check if script contains bracket "{" - // - if (Section.find('{') != string::npos) - { - // - // We find a { between the script - // - - // - // Add it to the open brackets (-1 because script starts with { which - // is not related to our interpretation of script) - // - OpenBracket += CountOfOpenBrackets - 1; - } - - if (CountOfOpenBrackets == CountOfCloseBrackets || (OpenBracket == 0 && HasEnding(Section, "}"))) - { - // - // remove the last character and first character append it to the - // ConditionBuffer - // - TempStr = SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1).erase(0, 7); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - - IsEnded = TRUE; - OpenBracket = 0; - break; - } - else - { - // - // Section starts with script{ - // - SaveBuffer.push_back(SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1).erase(0, 7)); - - // - // Check if script contains bracket "}" - // - if (Section.find('}') != string::npos) - { - // - // We find a } between the script - // - - // - // Check the count of brackets in the string and add it to OpenBracket - // - UINT32 CountOfBrackets = (UINT32)count(Section.begin(), Section.end(), '}'); - - // - // Add it to the open brackets - // - OpenBracket -= CountOfBrackets; - - if (OpenBracket < 0) - { - OpenBracket = 0; - IsEnded = TRUE; - } - } - - continue; - } - } } // - // Now we have everything in script buffer + // Now we have everything in buffer // Check to see if it is empty or not // - if (SaveBuffer.size() == 0) + if (TargetBracketString.length() == 0) { // - // Nothing in condition buffer, return zero + // Nothing in output buffer, return zero // return FALSE; } - // - // Check if we see that all the '{' ended with '}' or not - // - if (OpenBracket != 0) - { - // - // Not all open brackets close with a } - // - return FALSE; - } - - // - // Check if we see '}' at the end - // - if (!IsEnded) - { - // - // Nothing in condition buffer, return zero - // - return FALSE; - } - - // - // If we reach here then there is sth in script buffer - // - for (auto Section : SaveBuffer) - { - AppendedFinalBuffer.append(Section); - AppendedFinalBuffer.append(" "); - } - - if (AppendedFinalBuffer.rfind("file:", 0) == 0) + if (TargetBracketString.rfind("file:", 0) == 0) { // // It's a file script // - std::ifstream t(AppendedFinalBuffer.erase(0, 5).c_str()); + std::ifstream t(TargetBracketString.erase(0, 5).c_str()); std::stringstream buffer; buffer << t.rdbuf(); - AppendedFinalBuffer = buffer.str(); - if (AppendedFinalBuffer.empty()) + TargetBracketString = buffer.str(); + if (TargetBracketString.empty()) { ShowMessages("err, either script file is not found or it's empty\n"); @@ -1121,12 +952,12 @@ InterpretScript(vector * SplitCommand, } } - // ShowMessages("script : %s\n", AppendedFinalBuffer.c_str()); + // ShowMessages("script : %s\n", TargetBracketString.c_str()); // // Run script engine handler // - PVOID CodeBuffer = ScriptEngineParseWrapper((char *)AppendedFinalBuffer.c_str(), TRUE); + PVOID CodeBuffer = ScriptEngineParseWrapper((CHAR *)TargetBracketString.c_str(), TRUE); if (CodeBuffer == NULL) { @@ -1170,8 +1001,7 @@ InterpretScript(vector * SplitCommand, { NewIndexToRemove++; - SplitCommand->erase(SplitCommand->begin() + (IndexToRemove - NewIndexToRemove)); - SplitCommandCaseSensitive->erase(SplitCommandCaseSensitive->begin() + (IndexToRemove - NewIndexToRemove)); + CommandTokens->erase(CommandTokens->begin() + (IndexToRemove - NewIndexToRemove)); } return TRUE; @@ -1183,9 +1013,7 @@ InterpretScript(vector * SplitCommand, * or code buffer in this command split and the details are returned in the * input structure * - * @param SplitCommand the initialized command that are split by space - * @param SplitCommandCaseSensitive the initialized command that are split - * by space case sensitive + * @param CommandTokens command tokens * @param IsConditionBuffer is it a condition buffer or a custom code buffer * @param BufferAddress the address that the allocated buffer will be saved on * it @@ -1194,264 +1022,82 @@ InterpretScript(vector * SplitCommand, * successful (false) */ BOOLEAN -InterpretConditionsAndCodes(vector * SplitCommand, - vector * SplitCommandCaseSensitive, - BOOLEAN IsConditionBuffer, - PUINT64 BufferAddress, - PUINT32 BufferLength) +InterpretConditionsAndCodes(vector * CommandTokens, + BOOLEAN IsConditionBuffer, + PUINT64 BufferAddress, + PUINT32 BufferLength) { - BOOLEAN IsTextVisited = FALSE; - BOOLEAN IsInState = FALSE; - BOOLEAN IsEnded = FALSE; - string Temp; - string TempStr; - string AppendedFinalBuffer; - vector SaveBuffer; - vector ParsedBytes; - vector IndexesToRemove; - UCHAR * FinalBuffer; - int NewIndexToRemove = 0; - int Index = 0; + BOOLEAN IsAsm = FALSE; + BOOLEAN IsTextVisited = FALSE; + string TargetBracketString = ""; - for (auto Section : *SplitCommand) + string Temp; + vector ParsedBytes; + vector IndexesToRemove; + UCHAR * FinalBuffer; + UINT32 AssembledByteCount; + INT NewIndexToRemove = 0; + INT Index = 0; + + for (auto Section : *CommandTokens) { Index++; - if (IsInState) - { - // - // Check if the buffer is ended or not - // - if (!Section.compare("}")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - IsEnded = TRUE; - break; - } - - // - // Check if the condition is end or not - // - if (HasEnding(Section, "}")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - // - // remove the last character and append it to the ConditionBuffer - // - SaveBuffer.emplace_back(Section.begin(), Section.begin() + Section.size() - 1); - - IsEnded = TRUE; - break; - } - - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - // - // Add the codes into condition bi - // - SaveBuffer.push_back(Section); - - // - // We want to stay in this condition - // - continue; - } - - if (IsTextVisited && !Section.compare("{")) + if (IsTextVisited && IsTokenBracketString(Section)) { // // Save to remove this string from the command // IndexesToRemove.push_back(Index); - IsInState = TRUE; + // + // Fill the bracket string + // + TargetBracketString = GetCaseSensitiveStringFromCommandToken(Section); + + IsTextVisited = FALSE; continue; } - if (IsTextVisited && Section.rfind('{', 0) == 0) + if (!IsConditionBuffer && CompareLowerCaseStrings(Section, "code")) { - // - // Section starts with { - // - - // - // Check if it ends with } - // - if (HasEnding(Section, "}")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - TempStr = Section.erase(0, 1); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - - IsEnded = TRUE; - break; - } - // // Save to remove this string from the command // IndexesToRemove.push_back(Index); - SaveBuffer.push_back(Section.erase(0, 1)); - - IsInState = TRUE; + IsTextVisited = TRUE; continue; } - if (IsConditionBuffer) - { - if (!Section.compare("condition")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - IsTextVisited = TRUE; - continue; - } - } - else + if (IsConditionBuffer && CompareLowerCaseStrings(Section, "condition")) { // - // It's code + // Save to remove this string from the command // - if (!Section.compare("code")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); + IndexesToRemove.push_back(Index); - IsTextVisited = TRUE; - continue; - } + IsTextVisited = TRUE; + continue; } - if (IsConditionBuffer) - { - if (!Section.compare("condition{")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - IsTextVisited = TRUE; - IsInState = TRUE; - continue; - } - } - else + if (CompareLowerCaseStrings(Section, "asm")) { // - // It's code + // Save to remove this string from the command // - if (!Section.compare("code{")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); + IndexesToRemove.push_back(Index); - IsTextVisited = TRUE; - IsInState = TRUE; - continue; - } - } - - if (IsConditionBuffer) - { - if (Section.rfind("condition{", 0) == 0) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - IsTextVisited = TRUE; - IsInState = TRUE; - - if (!HasEnding(Section, "}")) - { - // - // Section starts with condition{ - // - SaveBuffer.push_back(Section.erase(0, 10)); - continue; - } - else - { - // - // remove the last character and first character append it to the - // ConditionBuffer - // - TempStr = Section.erase(0, 10); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - - IsEnded = TRUE; - break; - } - } - } - else - { - // - // It's a code - // - if (Section.rfind("code{", 0) == 0) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - IsTextVisited = TRUE; - IsInState = TRUE; - - if (!HasEnding(Section, "}")) - { - // - // Section starts with code{ - // - SaveBuffer.push_back(Section.erase(0, 5)); - continue; - } - else - { - // - // remove the last character and first character append it to the - // ConditionBuffer - // - TempStr = Section.erase(0, 5); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - - IsEnded = TRUE; - break; - } - } + IsAsm = TRUE; + continue; } } // - // Now we have everything in condition buffer + // Now we have everything in condition/code buffer // Check to see if it is empty or not // - if (SaveBuffer.size() == 0) + if (TargetBracketString.length() == 0) { // // Nothing in condition buffer, return zero @@ -1460,40 +1106,75 @@ InterpretConditionsAndCodes(vector * SplitCommand, } // - // Check if we see '}' at the end + // Check if asm code was provided instead of hex // - if (!IsEnded) + if (IsAsm) { - // - // Nothing in condition buffer, return zero - // - return FALSE; - } + AssembleData AssembleData; + AssembleData.AsmRaw = TargetBracketString; // by now, it should only have one element + AssembleData.ParseAssemblyData(); - // - // Append a 'ret' at the end of the buffer - // - SaveBuffer.push_back("c3"); + // + // Append a 'ret' at the end of asm code + // + AssembleData.AsmFixed += "; ret"; - // - // If we reach here then there is sth in condition buffer - // - for (auto Section : SaveBuffer) - { - // - // Check if the section is started with '0x' - // - if (Section.rfind("0x", 0) == 0 || Section.rfind("0X", 0) == 0 || Section.rfind("\\x", 0) == 0 || Section.rfind("\\X", 0) == 0) + if (AssembleData.Assemble(0)) // we just want the hex bytes, so NULL instead of Start_Address { - Temp = Section.erase(0, 2); - } - else if (Section.rfind('x', 0) == 0 || Section.rfind('X', 0) == 0) - { - Temp = Section.erase(0, 1); + ShowMessages("err, assemble error code: '%u'\n\n", AssembleData.KsErr); + return FALSE; } else { - Temp = std::move(Section); + // + // Get the BytesCount; for readability. + // + AssembledByteCount = (UINT32)AssembleData.BytesCount; + + // + // * FinalBuffer * + // + FinalBuffer = (UCHAR *)malloc(AssembledByteCount); + + if (FinalBuffer == NULL) + { + return FALSE; + } + + memcpy(FinalBuffer, AssembleData.EncodedBytes, AssembledByteCount); + + // + // Set the buffer and length + // + *BufferAddress = (UINT64)FinalBuffer; + *BufferLength = AssembledByteCount; + } + } + else + { + // + // Append a 'ret' at the end of the buffer + // + TargetBracketString += "c3"; + + // + // If we reach here then there is sth in condition buffer + // + + // + // Check if the TargetBracketString is started with '0x' + // + if (TargetBracketString.rfind("0x", 0) == 0 || TargetBracketString.rfind("0X", 0) == 0 || TargetBracketString.rfind("\\x", 0) == 0 || TargetBracketString.rfind("\\X", 0) == 0) + { + Temp = TargetBracketString.erase(0, 2); + } + else if (TargetBracketString.rfind('x', 0) == 0 || TargetBracketString.rfind('X', 0) == 0) + { + Temp = TargetBracketString.erase(0, 1); + } + else + { + Temp = std::move(TargetBracketString); } // @@ -1517,26 +1198,31 @@ InterpretConditionsAndCodes(vector * SplitCommand, ShowMessages("please enter condition code in a hex notation\n"); return FALSE; } - AppendedFinalBuffer.append(Temp); + + // + // Convert it to vectored bytes + // + ParsedBytes = HexToBytes(Temp); + + // + // Convert to a contigues buffer + // + FinalBuffer = (UCHAR *)malloc(ParsedBytes.size()); + + if (FinalBuffer == NULL) + { + return FALSE; + } + + std::copy(ParsedBytes.begin(), ParsedBytes.end(), FinalBuffer); + + // + // Set the buffer and length + // + *BufferAddress = (UINT64)FinalBuffer; + *BufferLength = (UINT32)ParsedBytes.size(); } - // - // Convert it to vectored bytes - // - ParsedBytes = HexToBytes(AppendedFinalBuffer); - - // - // Convert to a contigues buffer - // - FinalBuffer = (unsigned char *)malloc(ParsedBytes.size()); - std::copy(ParsedBytes.begin(), ParsedBytes.end(), FinalBuffer); - - // - // Set the buffer and length - // - *BufferAddress = (UINT64)FinalBuffer; - *BufferLength = (UINT32)ParsedBytes.size(); - // // Removing the code or condition indexes from the command // @@ -1545,8 +1231,7 @@ InterpretConditionsAndCodes(vector * SplitCommand, { NewIndexToRemove++; - SplitCommand->erase(SplitCommand->begin() + (IndexToRemove - NewIndexToRemove)); - SplitCommandCaseSensitive->erase(SplitCommandCaseSensitive->begin() + (IndexToRemove - NewIndexToRemove)); + CommandTokens->erase(CommandTokens->begin() + (IndexToRemove - NewIndexToRemove)); } return TRUE; @@ -1558,9 +1243,7 @@ InterpretConditionsAndCodes(vector * SplitCommand, * input that needs to be considered for this event (other than just printing) * like sending over network, save to file, and send over a namedpipe * - * @param SplitCommand the initialized command that are split by space - * @param SplitCommandCaseSensitive the initialized command that are split - * by space case sensitive + * @param CommandTokens command tokens * @param BufferAddress the address that the allocated buffer will be saved on * it * @param BufferLength the length of the buffer @@ -1568,127 +1251,40 @@ InterpretConditionsAndCodes(vector * SplitCommand, * successful (false) */ BOOLEAN -InterpretOutput(vector * SplitCommand, - vector * SplitCommandCaseSensitive, - vector & InputSources) +InterpretOutput(vector * CommandTokens, + vector & InputSources) { - BOOLEAN IsTextVisited = FALSE; - BOOLEAN IsInState = FALSE; - BOOLEAN IsEnded = FALSE; - string AppendedFinalBuffer; - vector SaveBuffer; - vector IndexesToRemove; - string Token; - string TempStr; - int NewIndexToRemove = 0; - int Index = 0; - char Delimiter = ','; - size_t Pos = 0; - vector SplitCommandCaseSensitiveInstance = *SplitCommandCaseSensitive; - UINT32 IndexInCommandCaseSensitive = 0; + BOOLEAN IsTextVisited = FALSE; + string TargetBracketString = ""; - for (auto Section : *SplitCommand) + vector IndexesToRemove; + string Token; + INT NewIndexToRemove = 0; + INT Index = 0; + CHAR Delimiter = ','; + SIZE_T Pos = 0; + + for (auto Section : *CommandTokens) { - IndexInCommandCaseSensitive++; Index++; - if (IsInState) - { - // - // Check if the buffer is ended or not - // - if (!Section.compare("}")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - IsEnded = TRUE; - break; - } - - // - // Check if the output is end or not - // - if (HasEnding(Section, "}")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - // - // remove the last character and append it to the output buffer - // - TempStr = SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - - IsEnded = TRUE; - break; - } - - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - // - // Add the codes into buffer buffer - // - SaveBuffer.push_back(SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1)); - - // - // We want to stay in this condition - // - continue; - } - - if (IsTextVisited && !Section.compare("{")) + if (IsTextVisited && IsTokenBracketString(Section)) { // // Save to remove this string from the command // IndexesToRemove.push_back(Index); - IsInState = TRUE; + // + // Fill the bracket string + // + TargetBracketString = GetCaseSensitiveStringFromCommandToken(Section); + + IsTextVisited = FALSE; continue; } - if (IsTextVisited && Section.rfind('{', 0) == 0) - { - // - // Section starts with { - // - - // - // Check if it ends with } - // - if (HasEnding(Section, "}")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - TempStr = SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1).erase(0, 1); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - - IsEnded = TRUE; - break; - } - - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - SaveBuffer.push_back(SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1).erase(0, 1)); - - IsInState = TRUE; - continue; - } - - if (!Section.compare("output")) + if (CompareLowerCaseStrings(Section, "output")) { // // Save to remove this string from the command @@ -1698,57 +1294,13 @@ InterpretOutput(vector * SplitCommand, IsTextVisited = TRUE; continue; } - - if (!Section.compare("output{")) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - IsTextVisited = TRUE; - IsInState = TRUE; - continue; - } - - if (Section.rfind("output{", 0) == 0) - { - // - // Save to remove this string from the command - // - IndexesToRemove.push_back(Index); - - IsTextVisited = TRUE; - IsInState = TRUE; - - if (!HasEnding(Section, "}")) - { - // - // Section starts with output{ - // - SaveBuffer.push_back(SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1).erase(0, 7)); - continue; - } - else - { - // - // remove the last character and first character append it to the - // Output - // - TempStr = SplitCommandCaseSensitiveInstance.at(IndexInCommandCaseSensitive - 1).erase(0, 7); - SaveBuffer.emplace_back(TempStr.begin(), TempStr.begin() + TempStr.size() - 1); - - IsEnded = TRUE; - break; - } - } } // - // Now we have everything in buffer buffer + // Now we have everything in buffer // Check to see if it is empty or not // - if (SaveBuffer.size() == 0) + if (TargetBracketString.length() == 0) { // // Nothing in output buffer, return zero @@ -1756,37 +1308,17 @@ InterpretOutput(vector * SplitCommand, return FALSE; } - // - // Check if we see '}' at the end - // - if (!IsEnded) - { - // - // Nothing in output buffer, return zero - // - return FALSE; - } - - // - // If we reach here then there is sth in condition buffer - // - for (auto Section : SaveBuffer) - { - AppendedFinalBuffer.append(Section); - AppendedFinalBuffer.append(" "); - } - // // Check if we see multiple sources or it's just one single output // - if (AppendedFinalBuffer.find(Delimiter) != std::string::npos) + if (TargetBracketString.find(Delimiter) != std::string::npos) { // // Delimiter found ! // - while ((Pos = AppendedFinalBuffer.find(Delimiter)) != string::npos) + while ((Pos = TargetBracketString.find(Delimiter)) != string::npos) { - Token = AppendedFinalBuffer.substr(0, Pos); + Token = TargetBracketString.substr(0, Pos); Trim(Token); if (!Token.empty()) @@ -1794,12 +1326,12 @@ InterpretOutput(vector * SplitCommand, InputSources.push_back(Token); } - AppendedFinalBuffer.erase(0, Pos + sizeof(Delimiter) / sizeof(char)); + TargetBracketString.erase(0, Pos + sizeof(Delimiter) / sizeof(char)); } - if (!AppendedFinalBuffer.empty()) + if (!TargetBracketString.empty()) { - InputSources.push_back(AppendedFinalBuffer); + InputSources.push_back(TargetBracketString); } } else @@ -1807,19 +1339,17 @@ InterpretOutput(vector * SplitCommand, // // Delimiter not found ! // - InputSources.push_back(AppendedFinalBuffer); + InputSources.push_back(TargetBracketString); } // - // Removing the code or condition indexes from the command + // Removing indexes from the command // NewIndexToRemove = 0; for (auto IndexToRemove : IndexesToRemove) { NewIndexToRemove++; - - SplitCommand->erase(SplitCommand->begin() + (IndexToRemove - NewIndexToRemove)); - SplitCommandCaseSensitive->erase(SplitCommandCaseSensitive->begin() + (IndexToRemove - NewIndexToRemove)); + CommandTokens->erase(CommandTokens->begin() + (IndexToRemove - NewIndexToRemove)); } return TRUE; @@ -1864,14 +1394,13 @@ SendEventToKernel(PDEBUGGER_GENERAL_EVENT_DETAIL Event, // // It's either a debuggee or a local debugging instance // - - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Send IOCTL // - Status = DeviceIoControl(g_DeviceHandle, // Handle to device + Status = PlatformDeviceIoControl(g_DeviceHandle, // Handle to device IOCTL_DEBUGGER_REGISTER_EVENT, // IO Control Code (IOCTL) Event, // Input Buffer to driver. EventBufferLength, // Input buffer length @@ -1888,7 +1417,7 @@ SendEventToKernel(PDEBUGGER_GENERAL_EVENT_DETAIL Event, if (!Status) { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError()); return FALSE; } } @@ -2027,10 +1556,9 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event, else { // - // It's either a local debugger to in vmi-mode remote conntection + // It's either a local debugger to in vmi-mode remote connection // - - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Send IOCTLs @@ -2041,7 +1569,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event, // if (ActionBreakToDebugger != NULL) { - Status = DeviceIoControl( + Status = PlatformDeviceIoControl( g_DeviceHandle, // Handle to device IOCTL_DEBUGGER_ADD_ACTION_TO_EVENT, // IO Control Code (IOCTL) ActionBreakToDebugger, // Input Buffer to driver. @@ -2059,7 +1587,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event, if (!Status) { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError()); return FALSE; } } @@ -2069,7 +1597,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event, // if (ActionCustomCode != NULL) { - Status = DeviceIoControl( + Status = PlatformDeviceIoControl( g_DeviceHandle, // Handle to device IOCTL_DEBUGGER_ADD_ACTION_TO_EVENT, // IO Control Code (IOCTL) ActionCustomCode, // Input Buffer to driver. @@ -2087,7 +1615,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event, if (!Status) { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError()); return FALSE; } } @@ -2097,7 +1625,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event, // if (ActionScript != NULL) { - Status = DeviceIoControl( + Status = PlatformDeviceIoControl( g_DeviceHandle, // Handle to device IOCTL_DEBUGGER_ADD_ACTION_TO_EVENT, // IO Control Code (IOCTL) ActionScript, // Input Buffer to driver. @@ -2115,7 +1643,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event, if (!Status) { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError()); return FALSE; } } @@ -2189,9 +1717,7 @@ FreeEventsAndActionsMemory(PDEBUGGER_GENERAL_EVENT_DETAIL Event, /** * @brief Interpret general event fields * - * @param SplitCommand the commands that was split by space - * @param SplitCommandCaseSensitive the commands that was split by space - * case sensitive + * @param CommandTokens the command tokens * @param EventType type of event * @param EventDetailsToFill a pointer address that will be filled * by event detail buffer @@ -2208,8 +1734,7 @@ FreeEventsAndActionsMemory(PDEBUGGER_GENERAL_EVENT_DETAIL Event, */ BOOLEAN InterpretGeneralEventAndActionsFields( - vector * SplitCommand, - vector * SplitCommandCaseSensitive, + vector * CommandTokens, VMM_EVENT_TYPE_ENUM EventType, PDEBUGGER_GENERAL_EVENT_DETAIL * EventDetailsToFill, PUINT32 EventBufferLength, @@ -2260,17 +1785,17 @@ InterpretGeneralEventAndActionsFields( UINT32 RequestBuffer = 0; PLIST_ENTRY TempList; BOOLEAN OutputSourceFound; - vector IndexesToRemove; + vector IndexesToRemove; vector ListOfValidSourceTags; - int NewIndexToRemove = 0; - int Index = 0; + INT NewIndexToRemove = 0; + INT Index = 0; // // Create a command string to show in the history // - for (auto Section : *SplitCommandCaseSensitive) + for (auto Section : *CommandTokens) { - CommandString.append(Section); + CommandString.append(GetCaseSensitiveStringFromCommandToken(Section)); CommandString.append(" "); } @@ -2284,7 +1809,7 @@ InterpretGeneralEventAndActionsFields( // PVOID BufferOfCommandString = malloc(BufferOfCommandStringLength); - RtlZeroMemory(BufferOfCommandString, BufferOfCommandStringLength); + PlatformZeroMemory(BufferOfCommandString, BufferOfCommandStringLength); // // Copy the string to the buffer @@ -2294,16 +1819,14 @@ InterpretGeneralEventAndActionsFields( // // Check if there is a condition buffer in the command // - if (!InterpretConditionsAndCodes(SplitCommand, SplitCommandCaseSensitive, TRUE, &ConditionBufferAddress, &ConditionBufferLength)) + if (!InterpretConditionsAndCodes(CommandTokens, TRUE, &ConditionBufferAddress, &ConditionBufferLength)) { // // Indicate condition is not available // HasConditionBuffer = FALSE; - // - // ShowMessages("\nNo condition!\n"); - // + /* ShowMessages("\nNo condition!\n"); */ } else { @@ -2323,7 +1846,7 @@ InterpretGeneralEventAndActionsFields( // // Disassemble the buffer // - HyperDbgDisassembler64((unsigned char *)ConditionBufferAddress, 0x0, + HyperDbgDisassembler64((UCHAR *)ConditionBufferAddress, 0x0, ConditionBufferLength); ShowMessages("}\n\n"); @@ -2336,7 +1859,7 @@ InterpretGeneralEventAndActionsFields( // // Check if there is a code buffer in the command // - if (!InterpretConditionsAndCodes(SplitCommand, SplitCommandCaseSensitive, FALSE, &CodeBufferAddress, &CodeBufferLength)) + if (!InterpretConditionsAndCodes(CommandTokens, FALSE, &CodeBufferAddress, &CodeBufferLength)) { // // Indicate code is not available @@ -2363,7 +1886,7 @@ InterpretGeneralEventAndActionsFields( // // Disassemble the buffer // - HyperDbgDisassembler64((unsigned char *)CodeBufferAddress, 0x0, + HyperDbgDisassembler64((UCHAR *)CodeBufferAddress, 0x0, CodeBufferLength); ShowMessages("}\n\n"); @@ -2376,8 +1899,7 @@ InterpretGeneralEventAndActionsFields( // // Check if there is a Script block in the command // - if (!InterpretScript(SplitCommand, - SplitCommandCaseSensitive, + if (!InterpretScript(CommandTokens, &HasScriptSyntaxError, &ScriptBufferAddress, &ScriptBufferLength, @@ -2414,7 +1936,7 @@ InterpretGeneralEventAndActionsFields( // // Check if there is a output path in the command // - if (!InterpretOutput(SplitCommand, SplitCommandCaseSensitive, ListOfOutputSources)) + if (!InterpretOutput(CommandTokens, ListOfOutputSources)) { // // Indicate output is not available @@ -2592,7 +2114,7 @@ InterpretGeneralEventAndActionsFields( LengthOfEventBuffer = sizeof(DEBUGGER_GENERAL_EVENT_DETAIL) + ConditionBufferLength; TempEvent = (PDEBUGGER_GENERAL_EVENT_DETAIL)malloc(LengthOfEventBuffer); - RtlZeroMemory(TempEvent, LengthOfEventBuffer); + PlatformZeroMemory(TempEvent, LengthOfEventBuffer); // // Check if buffer is available @@ -2626,7 +2148,7 @@ InterpretGeneralEventAndActionsFields( ShowMessages("notice: as you're debugging a user-mode application, " "this event will only trigger on your current debugging process " "(pid:%x). If you want the event from the entire system, " - "add 'pid all' to the event\n", + "add 'pid all' to the event\n\n", g_ActiveProcessDebuggingState.ProcessId); TempEvent->ProcessId = g_ActiveProcessDebuggingState.ProcessId; @@ -2641,11 +2163,6 @@ InterpretGeneralEventAndActionsFields( // TempEvent->EventType = EventType; - // - // Get the current time - // - TempEvent->CreationTime = time(0); - // // Set buffer string command // @@ -2679,7 +2196,7 @@ InterpretGeneralEventAndActionsFields( TempActionCustomCode = (PDEBUGGER_GENERAL_ACTION)malloc(LengthOfCustomCodeActionBuffer); - RtlZeroMemory(TempActionCustomCode, LengthOfCustomCodeActionBuffer); + PlatformZeroMemory(TempActionCustomCode, LengthOfCustomCodeActionBuffer); memcpy( (PVOID)((UINT64)TempActionCustomCode + sizeof(DEBUGGER_GENERAL_ACTION)), @@ -2718,7 +2235,7 @@ InterpretGeneralEventAndActionsFields( LengthOfScriptActionBuffer = sizeof(DEBUGGER_GENERAL_ACTION) + ScriptBufferLength; TempActionScript = (PDEBUGGER_GENERAL_ACTION)malloc(LengthOfScriptActionBuffer); - RtlZeroMemory(TempActionScript, LengthOfScriptActionBuffer); + PlatformZeroMemory(TempActionScript, LengthOfScriptActionBuffer); memcpy((PVOID)((UINT64)TempActionScript + sizeof(DEBUGGER_GENERAL_ACTION)), (PVOID)ScriptBufferAddress, @@ -2764,7 +2281,7 @@ InterpretGeneralEventAndActionsFields( TempActionBreak = (PDEBUGGER_GENERAL_ACTION)malloc(LengthOfBreakActionBuffer); - RtlZeroMemory(TempActionBreak, LengthOfBreakActionBuffer); + PlatformZeroMemory(TempActionBreak, LengthOfBreakActionBuffer); // // Set the action Tag @@ -2785,12 +2302,13 @@ InterpretGeneralEventAndActionsFields( // // Interpret rest of the command // - for (auto Section : *SplitCommand) + for (auto Section : *CommandTokens) { Index++; + if (IsNextCommandBufferSize) { - if (!ConvertStringToUInt32(Section, &RequestBuffer)) + if (!ConvertTokenToUInt32(Section, &RequestBuffer)) { ShowMessages("err, buffer size is invalid\n"); *ReasonForErrorInParsing = DEBUGGER_EVENT_PARSING_ERROR_CAUSE_FORMAT_ERROR; @@ -2826,11 +2344,11 @@ InterpretGeneralEventAndActionsFields( if (IsNextCommandImmediateMessaging) { - if (!Section.compare("yes")) + if (CompareLowerCaseStrings(Section, "yes")) { ImmediateMessagePassing = TRUE; } - else if (!Section.compare("no")) + else if (CompareLowerCaseStrings(Section, "no")) { ImmediateMessagePassing = FALSE; } @@ -2857,15 +2375,15 @@ InterpretGeneralEventAndActionsFields( if (IsNextCommandExecutionStage) { - if (!Section.compare("pre")) + if (CompareLowerCaseStrings(Section, "pre")) { CallingStage = VMM_CALLBACK_CALLING_STAGE_PRE_EVENT_EMULATION; } - else if (!Section.compare("post")) + else if (CompareLowerCaseStrings(Section, "post")) { CallingStage = VMM_CALLBACK_CALLING_STAGE_POST_EVENT_EMULATION; } - else if (!Section.compare("all")) + else if (CompareLowerCaseStrings(Section, "all")) { CallingStage = VMM_CALLBACK_CALLING_STAGE_ALL_EVENT_EMULATION; } @@ -2892,11 +2410,11 @@ InterpretGeneralEventAndActionsFields( if (IsNextCommandSc) { - if (!Section.compare("on")) + if (CompareLowerCaseStrings(Section, "on")) { IsAShortCircuitingEventByDefault = TRUE; } - else if (!Section.compare("off")) + else if (CompareLowerCaseStrings(Section, "off")) { IsAShortCircuitingEventByDefault = FALSE; } @@ -2923,11 +2441,11 @@ InterpretGeneralEventAndActionsFields( if (IsNextCommandPid) { - if (!Section.compare("all")) + if (CompareLowerCaseStrings(Section, "all")) { TempEvent->ProcessId = DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES; } - else if (!ConvertStringToUInt32(Section, &ProcessId)) + else if (!ConvertTokenToUInt32(Section, &ProcessId)) { ShowMessages("err, pid is invalid\n"); *ReasonForErrorInParsing = DEBUGGER_EVENT_PARSING_ERROR_CAUSE_FORMAT_ERROR; @@ -2954,7 +2472,7 @@ InterpretGeneralEventAndActionsFields( if (IsNextCommandCoreId) { - if (!ConvertStringToUInt32(Section, &CoreId)) + if (!ConvertTokenToUInt32(Section, &CoreId)) { ShowMessages("err, core id is invalid\n"); *ReasonForErrorInParsing = DEBUGGER_EVENT_PARSING_ERROR_CAUSE_FORMAT_ERROR; @@ -2977,7 +2495,7 @@ InterpretGeneralEventAndActionsFields( continue; } - if (!Section.compare("pid")) + if (CompareLowerCaseStrings(Section, "pid")) { IsNextCommandPid = TRUE; @@ -2988,7 +2506,7 @@ InterpretGeneralEventAndActionsFields( continue; } - if (!Section.compare("core")) + if (CompareLowerCaseStrings(Section, "core")) { IsNextCommandCoreId = TRUE; @@ -3000,7 +2518,7 @@ InterpretGeneralEventAndActionsFields( continue; } - if (!Section.compare("imm")) + if (CompareLowerCaseStrings(Section, "imm")) { // // the next command is immediate messaging indicator @@ -3015,7 +2533,7 @@ InterpretGeneralEventAndActionsFields( continue; } - if (!Section.compare("stage")) + if (CompareLowerCaseStrings(Section, "stage")) { // // the next command is execution mode (pre- and post-events) @@ -3030,7 +2548,7 @@ InterpretGeneralEventAndActionsFields( continue; } - if (!Section.compare("sc")) + if (CompareLowerCaseStrings(Section, "sc")) { // // the next command is the default short-circuiting state @@ -3045,7 +2563,7 @@ InterpretGeneralEventAndActionsFields( continue; } - if (!Section.compare("buffer")) + if (CompareLowerCaseStrings(Section, "buffer")) { IsNextCommandBufferSize = TRUE; @@ -3137,10 +2655,12 @@ InterpretGeneralEventAndActionsFields( if (!g_IsSerialConnectedToRemoteDebuggee && TempActionBreak != NULL) { ShowMessages( - "err, it's not possible to break to the debugger in VMI Mode. " - "You should operate in Debugger Mode to break and get the " - "full control of the system. Still, you can use 'script' and run " - "'custom code' in your local debugging (VMI Mode)\n"); + "err, the script or assembly code is either not found or invalid. " + "As a result, the default action is to break. " + "However, breaking to the debugger is not possible in the VMI Mode. " + "To achieve full control of the system, you can switch to the Debugger Mode. " + "In the VMI Mode, you can still use scripts and run custom code for local debugging." + "For more information, please check: https://docs.hyperdbg.org/using-hyperdbg/prerequisites/operation-modes\n"); *ReasonForErrorInParsing = DEBUGGER_EVENT_PARSING_ERROR_CAUSE_ATTEMPT_TO_BREAK_ON_VMI_MODE; @@ -3243,8 +2763,7 @@ InterpretGeneralEventAndActionsFields( for (auto IndexToRemove : IndexesToRemove) { NewIndexToRemove++; - SplitCommand->erase(SplitCommand->begin() + (IndexToRemove - NewIndexToRemove)); - SplitCommandCaseSensitive->erase(SplitCommandCaseSensitive->begin() + (IndexToRemove - NewIndexToRemove)); + CommandTokens->erase(CommandTokens->begin() + (IndexToRemove - NewIndexToRemove)); } // diff --git a/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp b/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp new file mode 100644 index 00000000..edc0ab52 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp @@ -0,0 +1,1652 @@ +/** + * @file interpreter.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief The hyperdbg command interpreter and driver connector + * @details + * @version 0.1 + * @date 2020-04-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; +extern CommandType g_CommandsList; +extern BOOLEAN g_ShouldPreviousCommandBeContinued; +extern BOOLEAN g_IsCommandListInitialized; +extern BOOLEAN g_LogOpened; +extern BOOLEAN g_ExecutingScript; +extern BOOLEAN g_IsConnectedToRemoteDebuggee; +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_BreakPrintingOutput; +extern BOOLEAN g_IsInterpreterOnString; +extern BOOLEAN g_IsInterpreterPreviousCharacterABackSlash; +extern BOOLEAN g_RtmSupport; +extern UINT32 g_VirtualAddressWidth; +extern UINT32 g_InterpreterCountOfOpenCurlyBrackets; +extern ULONG g_CurrentRemoteCore; +extern string g_ServerPort; +extern string g_ServerIp; + +class CommandParser +{ +public: + /** + * @brief Parse the input string (commands) + * @param input + * + * @return std::vector + */ + std::vector Parse(const std::string & ConstInput) + { + std::vector tokens; + std::string current; + BOOLEAN InQuotes = FALSE; + INT IdxBracket = 0; + + // + // mainly for removing \ from escaped chars + // + std::string input = ConstInput; + for (SIZE_T i = 0; i < input.length(); ++i) + { + CHAR c = input[i]; + + if (c == '/') // start comment parse + { + // + // if we're in a script bracket, should we skip? it'll be handled later? + // + if (!InQuotes) + { + SIZE_T j = i; + CHAR c2 = input[++j]; + + if (c2 == '/') // start to look for comments + { + // + // to solve cases like: //"}" + // + SIZE_T StrLitEnd = 0; + SIZE_T StrLitBeg = input.find("\"", i); + if (StrLitBeg != std::string::npos) + { + if (i) + { + if (input[i - 1] != '\\') // if not escaped + { + StrLitEnd = input.find("\"", StrLitBeg + 1); + if (StrLitEnd != std::string::npos) + { + std::string StrLit(input.substr(i, StrLitEnd - i + 1)); + } + } + } + else + { + StrLitEnd = input.find("\"", StrLitBeg + 1); + if (StrLitEnd != std::string::npos) + { + std::string StrLit(input.substr(i, StrLitEnd - i + 1)); + } + } + } + + // + // assuming " }" as the end of a line comment aka //, if we are within {} + // + BOOLEAN CmntEndBrkt = FALSE; + SIZE_T CloseBrktPos = 0; + if (IdxBracket) + { + // + // loop for escaped } + // + auto pos = (StrLitEnd > i) ? StrLitEnd : i; + for (CloseBrktPos = input.find("}", pos); CloseBrktPos != std::string::npos;) + { + CloseBrktPos = input.find("}", CloseBrktPos); + if (input[CloseBrktPos - 1] == '\\') + { + input.erase(CloseBrktPos - 1, 1); + CloseBrktPos += 1; + } + else + { + break; + } + } + } + else + { + CloseBrktPos = std::string::npos; + } + + SIZE_T NewLineSrtPos = input.find("\\n", i); // "\\n" entered by user + if (StrLitBeg && StrLitBeg <= NewLineSrtPos && NewLineSrtPos <= StrLitEnd) // is it within the string literal? + { + NewLineSrtPos = std::string::npos; + } + SIZE_T NewLineChrPos = input.find('\n', i); + + std::vector PosVec = {CloseBrktPos, NewLineSrtPos, NewLineChrPos}; + + auto min = *(min_element(PosVec.begin(), PosVec.end())); // see which one occurs first + + if (min != std::string::npos && input[min - 1] != '\\') + { + // + // here we could get the comment but for now we just skip + // + std::string comment(input.substr(i, min - i)); + + // + // append comments to be passed to script engine + // + if (IdxBracket) + { + current += comment; + } + + // + // forward the buffer + // + auto diff = (min > i) ? (min - i) : (i - min); + i = i + diff - 1; + + continue; + } + else + { + BOOLEAN IsNewLineEsc = FALSE; + if (NewLineSrtPos != std::string::npos) + { + IsNewLineEsc = input[NewLineSrtPos - 1] == '\\'; + } + + // if (NewLineSrtPos != std::string::npos && !IsNewLineEsc) // is not escaped + //{ + // // + // // here we could get the comment but for now we just skip + // // + // std::string comment(input.substr(i, NewLineSrtPos - i)); + + // // + // // append comments to be passed to script engine + // // + // if (IdxBracket) + // { + // current += comment; + // } + + // // + // // forward the buffer + // // + // i = i + (NewLineSrtPos - i) + 1; // +1 for "\n". the "continue;" will also go past another time. + + // continue; + //} + // else if (NewLineChrPos != std::string::npos) + //{ + // // + // // here we could get the comment but for now we just skip + // // + // std::string comment(input.substr(i, NewLineChrPos - i)); + + // // + // // append comments to be passed to script engine + // // + // if (IdxBracket) + // { + // current += comment; + // } + + // // + // // forward the buffer + // // + // i = i + (NewLineChrPos - i); + + // continue; // go past '\n' + //} + // else + //{ + // + // no "\\n" nor '\n' found so we just mark the chars as comment till end of string + // + std::string comment(input.substr(i, input.size())); + + // fix the escaped newline + if (IsNewLineEsc) + { + SIZE_T start_pos = 0; + while ((start_pos = comment.find("\\\\n", start_pos)) != std::string::npos) + { + comment.replace(start_pos, 3, "\\n"); + start_pos += 2; // Handles case where 'to' is a substring of 'from' + } + + IsNewLineEsc = FALSE; + } + + // + // append comments to be passed to script engine + // + if (IdxBracket) + { + current += comment; + } + + // + // forward the buffer + // + i = i + (input.size() - i); + + continue; + } + //} + } + else if (c2 == '*') + { + SIZE_T EndPose = input.find("*/", i + 2); // +2 for cases like /*/ + + if (EndPose != std::string::npos) + { + // + // here we could get the comment but for now we just skip + // + std::string comment(input.substr(i, EndPose - i + 2)); // */ is two bytes long + + // + // append comments to be passed to script engine + // + if (IdxBracket) + { + current += comment; + } + + // + // forward the buffer + // + i = (i + (EndPose - i)) + 1; // +1 for / + + continue; + } + else + { + // error: comment not closed + } + } + } + } + + if (InQuotes) + { + if (c == '"') + { + if (input[i - 1] != '\\') + { + InQuotes = FALSE; + + // + // if the quoted text is not within brackets, regard it as a StringLiteral token + // + if (!IdxBracket) + { + AddStringToken(tokens, current, TRUE); // TRUE for StringLiteral type + current.clear(); + continue; // dont add " char + } + else + { + current += c; + continue; // dont add " char + } + // + // if we are indeed within brackets, we continue to add the '"' char to the current buffer + // + } + else + { + input.erase(i - 1, 1); + i--; // compensate for the removed char + + // + // remove last read "\\" if we are not within a {} + // + if (!IdxBracket) + { + current.pop_back(); + } + current += c; + continue; + } + } + } + + if (c == '}') + { + if (input[i - 1] != '\\') + { + if (IdxBracket) + { + if (!InQuotes) // not closing " + { + IdxBracket--; + } + + if (!IdxBracket) // is closing } + { + AddBracketStringToken(tokens, current); + current.clear(); + + continue; + } + } + } + else if (!InQuotes) + { + input.erase(i - 1, 1); + i--; // compensate for the removed char + current.pop_back(); // remove last read \\ + + } + } + + if (((c == ' ' && !InQuotes) || c == ' ') && !InQuotes && !IdxBracket) // finding separator space char // Tab separator added too + { + if (!current.empty() && current != " ") + { + AddToken(tokens, current); + current.clear(); + + continue; + } + continue; // avoid adding extra space char + } + else if (c == '"') // string literal is adjacent to previous command + { + if (i) // check if this " is the first char to avoid out of range check + { + if (input[i - 1] != ' ' && !IdxBracket && !current.empty() && !InQuotes) // is prev cmd adjacent to " + { + AddStringToken(tokens, current); + current.clear(); + } + + if (input[i - 1] != '\\') + { + InQuotes = TRUE; + if (!IdxBracket) + { + continue; // don't include '"' in string + } + } + } + else + { + InQuotes = TRUE; + if (!IdxBracket) + { + continue; // don't include '"' in string + } + } + } + else if (c == '{' && !InQuotes) + { + if (i) // check if this { is the first char to avoid out of range check + { + if (input[i - 1] != '\\') + { + if (input[i - 1] != ' ' && !IdxBracket) // in case '{' is adjacent to previous command like "command{", on first { + { + AddToken(tokens, current); + current.clear(); + } + + IdxBracket++; + if (IdxBracket == 1) // first { + continue; // don't include '{' in string + } + else + { + input.erase(i - 1, 1); + i--; // compensate for the removed char + current.pop_back(); // remove last read \\ + + } + } + else + { + IdxBracket++; + if (IdxBracket == 1) // first { + continue; // don't include '{' in string + } + } + + // + // ignore astray \n + // + if (c == '\\' && !InQuotes) + { + if (current.empty() && input[i + 1] == 'n') + { + i++; + continue; + } + } + + current += c; + } + + if (!current.empty() && current != " ") + { + AddToken(tokens, current); + } + + if (IdxBracket) + { + // error: script bracket not closed + } + + if (InQuotes) + { + // error: Quote not closed + } + + return tokens; + } + + /** + * @brief Function to convert CommandParsingTokenType to a string + * @param Type + * + * @return std::string + */ + std::string TokenTypeToString(CommandParsingTokenType Type) + { + switch (Type) + { + case CommandParsingTokenType::Num: + return "Num"; + + case CommandParsingTokenType::String: + return "String"; + + case CommandParsingTokenType::StringLiteral: + return "StringLiteral"; + + case CommandParsingTokenType::BracketString: + return "BracketString"; + + default: + return "Unknown"; + } + } + + /** + * @brief Function to print the elements of a vector of Tokens + * @param Tokens + * + * @return VOID + */ + VOID PrintTokens(const std::vector & Tokens) + { + // + // get len of longest string + // + const INT sz = 200; // size + INT g_s1Len = 0, g_s2Len = 0, g_s3Len = 0; + INT s1 = 0, s2 = 0, s3 = 0; + CHAR LineToPrint1[sz], LineToPrint2[sz], LineToPrint3[sz]; + + for (const auto & Token : Tokens) + { + s1 = snprintf(LineToPrint1, sz, "CommandParsingTokenType: %s ", TokenTypeToString(std::get<0>(Token)).c_str()); + s2 = snprintf(LineToPrint2, sz, ", Value 1: '%s'", std::get<1>(Token).c_str()); + s3 = snprintf(LineToPrint3, sz, ", Value 2 (lower): '%s'", std::get<2>(Token).c_str()); + + if (s1 > g_s1Len) + g_s1Len = s1; + + if (s2 > g_s2Len) + g_s2Len = s2; + + if (s3 > g_s3Len) + g_s3Len = s3; + } + + for (const auto & Token : Tokens) + { + auto CaseSensitiveText = std::get<1>(Token); + auto LowerCaseText = std::get<2>(Token); + + if (std::get<0>(Token) == CommandParsingTokenType::BracketString || + std::get<0>(Token) == CommandParsingTokenType::String || + std::get<0>(Token) == CommandParsingTokenType::StringLiteral) + { + // + // Replace \n with \\n + // + + // + // Search for \n and replace with \\n + // + std::string::size_type pos = 0; + while ((pos = CaseSensitiveText.find("\n", pos)) != std::string::npos) + { + CaseSensitiveText.replace(pos, 1, "\\n"); + pos += 2; // Move past the newly added characters + } + + // + // Do the same for lower case text + // + pos = 0; + while ((pos = LowerCaseText.find("\n", pos)) != std::string::npos) + { + LowerCaseText.replace(pos, 1, "\\n"); + pos += 2; // Move past the newly added characters + } + } + + snprintf(LineToPrint1, sz, "CommandParsingTokenType: %s ", TokenTypeToString(std::get<0>(Token)).c_str()); + snprintf(LineToPrint2, sz, ", Value 1: '%s'", CaseSensitiveText.c_str()); + snprintf(LineToPrint3, sz, ", Value 2 (lower): '%s'", LowerCaseText.c_str()); + + ShowMessages("%-*s %-*s %-*s\n", // - for left align + g_s1Len, + LineToPrint1, + g_s2Len, + LineToPrint2, + g_s3Len, + LineToPrint3); + + /*ShowMessages("CommandParsingTokenType: %s , Value 1: '%s', Value 2 (lower): '%s'\n", + TokenTypeToString(std::get<0>(Token)).c_str(), + CaseSensitiveText.c_str(), + LowerCaseText.c_str());*/ + } + } + +private: + /** + * @brief Convert a string to lowercase + * @param str + * + * @return std::string + */ + std::string ToLower(const std::string & str) const + { + std::string result = str; + std::transform(result.begin(), result.end(), result.begin(), ::tolower); + + return result; + } + + /** + * @brief Add Token + * @param tokens + * @param str + * + * @return VOID + */ + VOID AddToken(std::vector & tokens, std::string & str) + { + auto tmp = str; + UINT64 tmpNum = 0; + + // + // Trim the string + // + Trim(tmp); + + if (ConvertStringToUInt64(tmp, &tmpNum)) // tmp will be modified to actual number + { + tokens.emplace_back(CommandParsingTokenType::Num, tmp, ToLower(tmp)); + } + else + { + AddStringToken(tokens, str); + } + } + + /** + * @brief Add String Token + * @param tokens + * @param str + * + * @return VOID + */ + VOID AddStringToken(std::vector & tokens, std::string & str, BOOL isLiteral = FALSE) + { + auto tmp = str; + + // + // Trim the string + // + if (!isLiteral) + Trim(tmp); + + // + // If the string is empty, we don't need to add it + // + if (tmp.empty()) + return; + if (isLiteral) + { + tokens.emplace_back(CommandParsingTokenType::StringLiteral, tmp, ToLower(tmp)); + } + else + { + tokens.emplace_back(CommandParsingTokenType::String, tmp, ToLower(tmp)); + } + } + + /** + * @brief Add Bracket String Token + * @param tokens + * @param str + * + * @return VOID + */ + VOID AddBracketStringToken(std::vector & tokens, const std::string & str) + { + tokens.emplace_back(CommandParsingTokenType::BracketString, str, ToLower(str)); + } +}; + +/** + * @brief Find the position of the first difference between two strings + * @param prsTok The first string + * @param fileTok The second string + * + * @return The position of the first difference, or -1 if the strings are equal + */ +INT +FindDifferencePosition(const CHAR * prsTok, const CHAR * fileTok) +{ + INT i = 0; + + // + // Loop until a difference is found or until the end of any string is reached + // + while (prsTok[i] != '\0' && fileTok[i] != '\0') + { + if (prsTok[i] != fileTok[i]) + { + return i; // Return the position of the first mismatch + } + i++; + } + + // + // If one string ends before the other + // + if (prsTok[i] != fileTok[i]) + { + return i; + } + + // + // If no difference is found, return -1 + // + return -1; +} + +/** + * @brief Parse the command (used for testing purposes) + * + * @param Command The text of command + * @param NumberOfTokens The number of tokens + * @param TokensList The tokens list + * @param FailedTokenNum The failed token number (if any) + * @param FailedTokenPosition The failed token position (if any) + * + * @return BOOLEAN returns TRUE if the command was parsed successfully and FALSE if there was an error + */ +BOOLEAN +HyperDbgTestCommandParser(CHAR * Command, + UINT32 NumberOfTokens, + CHAR ** TokensList, + UINT32 * FailedTokenNum, + UINT32 * FailedTokenPosition) +{ + CommandParser Parser; + + // + // Convert to string + // + string CommandString(Command); + + // + // Tokenize the command string + // + std::vector Tokens = Parser.Parse(CommandString); + + // + // Check if the number of tokens is correct + // + if (Tokens.size() != NumberOfTokens) + { + ShowMessages("err, the number of tokens is not correct\n"); + return FALSE; + } + + // + // Check if the tokens are correct + // + for (UINT32 i = 0; i < Tokens.size(); i++) + { + auto Token = Tokens.at(i); + + auto CaseSensitiveText = std::get<1>(Token); + + if (strcmp(CaseSensitiveText.c_str(), TokensList[i]) != 0) + { + // + // Set the failed token number + // + *FailedTokenNum = i; + *FailedTokenPosition = FindDifferencePosition(CaseSensitiveText.c_str(), TokensList[i]); + + ShowMessages("err, the token is not correct\n"); + return FALSE; + } + } + + // + // Everything is correct + // + return TRUE; +} + +/** + * @brief Parse the command and show tokens (used for testing purposes) + * + * @param Command The text of command + * + * @return VOID + */ +VOID +HyperDbgTestCommandParserShowTokens(CHAR * Command) +{ + CommandParser Parser; + + // + // Convert to string + // + string CommandString(Command); + + // + // Tokenize the command string + // + std::vector Tokens = Parser.Parse(CommandString); + + Parser.PrintTokens(Tokens); +} + +/** + * @brief Interpret commands + * + * @param Command The text of command + * @return INT returns return zero if it was successful or non-zero if there was + * error + */ +INT +HyperDbgInterpreter(CHAR * Command) +{ + BOOLEAN HelpCommand = FALSE; + UINT64 CommandAttributes = NULL; + CommandType::iterator Iterator; + CommandParser Parser; + + // + // Check if it's the first command and whether the mapping of command is + // initialized or not + // + if (!g_IsCommandListInitialized) + { + // + // Initialize the debugger + // + InitializeDebugger(); + + g_IsCommandListInitialized = TRUE; + } + + // + // Save the command into log open file + // + if (g_LogOpened && !g_ExecutingScript) + { + LogopenSaveToFile(Command); + LogopenSaveToFile("\n"); + } + + // + // Convert to string + // + string CommandString(Command); + + // + // Tokenize the command string + // + auto Tokens = Parser.Parse(CommandString); + + // + // Print the tokens + // + // Parser.PrintTokens(Tokens); + + // + // Check if user entered an empty input + // + if (Tokens.empty()) + { + ShowMessages("\n"); + return 0; + } + + // + // Get the first command (lower case) + // + string FirstCommand = GetLowerStringFromCommandToken(Tokens.front()); + + // + // Read the command's attributes + // + CommandAttributes = GetCommandAttributes(FirstCommand); + + // + // Check if the command needs to be continued by pressing enter + // + if (CommandAttributes & DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER) + { + g_ShouldPreviousCommandBeContinued = TRUE; + } + else + { + g_ShouldPreviousCommandBeContinued = FALSE; + } + + // + // Check and send remote command and also we check whether this + // is a command that should be handled in this command or we can + // send it to the remote computer, it is because in a remote connection + // still some of the commands should be handled in the local HyperDbg + // + if (g_IsConnectedToRemoteDebuggee && + !(CommandAttributes & DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_REMOTE_CONNECTION)) + { + // + // Check it here because generally, we use this variable in host + // for showing the correct signature but we won't try to block + // other commands, the only thing is events which is blocked + // by the remote computer itself + // + if (g_BreakPrintingOutput) + { + g_BreakPrintingOutput = FALSE; + } + + // + // It's a connection over network (VMI-Mode) + // + RemoteConnectionSendCommand(Command, (UINT32)strlen(Command) + 1); + + ShowMessages("\n"); + + // + // Indicate that we sent the command to the target system + // + return 2; + } + else if (g_IsSerialConnectedToRemoteDebuggee && + !(CommandAttributes & + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE)) + { + // + // It's a connection over serial (Debugger-Mode) + // + + if (CommandAttributes & DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN) + { + KdSendUserInputPacketToDebuggee(Command, (UINT32)strlen(Command) + 1, TRUE); + + // + // Set the debuggee to show that it's running + // + KdSetStatusAndWaitForPause(); + } + else + { + // + // Disable the breakpoints and events while executing the command in the remote computer + // + KdSendTestQueryPacketToDebuggee(TEST_BREAKPOINT_TURN_OFF_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER); + KdSendUserInputPacketToDebuggee(Command, (UINT32)strlen(Command) + 1, FALSE); + KdSendTestQueryPacketToDebuggee(TEST_BREAKPOINT_TURN_ON_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER); + } + + // + // Indicate that we sent the command to the target system + // + return 2; + } + + // + // Detect whether it's a .help command or not + // + if (!FirstCommand.compare(".help") || !FirstCommand.compare("help") || + !FirstCommand.compare(".hh") || !FirstCommand.compare("!help")) + { + if (Tokens.size() == 2) + { + // + // Show that it's a help command + // + HelpCommand = TRUE; + FirstCommand = GetLowerStringFromCommandToken(Tokens.at(1)); + } + else + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(Tokens.at(0)).c_str()); + CommandHelpHelp(); + return 0; + } + } + + // + // Start parsing commands + // + string CaseSensitiveCommandString(Command); + Iterator = g_CommandsList.find(FirstCommand); + + if (Iterator == g_CommandsList.end()) + { + // + // Command doesn't exist + // + if (!HelpCommand) + { + ShowMessages("err, couldn't resolve command at '%s'\n", + GetCaseSensitiveStringFromCommandToken(Tokens.front()).c_str()); + } + else + { + ShowMessages("err, couldn't find the help for the command at '%s'\n", + GetCaseSensitiveStringFromCommandToken(Tokens.at(1)).c_str()); + } + } + else + { + if (HelpCommand) + { + Iterator->second.CommandHelpFunction(); + } + else + { + // + // Call the parser with tokens + // + Iterator->second.CommandFunctionNewParser(Tokens, CaseSensitiveCommandString); + } + } + + // + // Save the command into log open file + // + if (g_LogOpened && !g_ExecutingScript) + { + LogopenSaveToFile("\n"); + } + + return 0; +} + +/** + * @brief Remove batch comments + * @param CommandText + * @details deprecated, not used anymore + * + * @return VOID + */ +VOID +InterpreterRemoveComments(CHAR * CommandText) +{ + BOOLEAN IsComment = FALSE; + BOOLEAN IsOnBracketString = FALSE; + BOOLEAN IsOnString = FALSE; + UINT32 LengthOfCommand = (UINT32)strlen(CommandText); + + for (SIZE_T i = 0; i < LengthOfCommand; i++) + { + if (IsComment) + { + if (CommandText[i] == '\n') + { + IsComment = FALSE; + } + else + { + if (CommandText[i] != '\0') + { + memmove((PVOID)&CommandText[i], (const PVOID)&CommandText[i + 1], strlen(CommandText) - i); + i--; + } + } + } + else if (CommandText[i] == '#' && !IsOnString) + { + // + // Comment detected + // + IsComment = TRUE; + i--; + } + else if (CommandText[i] == '#' && !IsOnString) + { + // + // Comment detected + // + IsComment = TRUE; + i--; + } + else if (CommandText[i] == '"') + { + if (i != 0 && CommandText[i - 1] == '\\') + { + // + // It's an escape character for : \" + // + } + else if (IsOnString) + { + IsOnString = FALSE; + } + else + { + IsOnString = TRUE; + } + } + } +} + +/** + * @brief Show signature of HyperDbg + * + * @return VOID + */ +VOID +HyperDbgShowSignature() +{ + if (g_IsConnectedToRemoteDebuggee) + { + // + // Remote debugging over tcp (vmi-mode) + // + ShowMessages("[%s:%s] HyperDbg> ", g_ServerIp.c_str(), g_ServerPort.c_str()); + } + else if (g_ActiveProcessDebuggingState.IsActive) + { + // + // Debugging a special process + // + ShowMessages("%x:%x %s u%sHyperDbg> ", + g_ActiveProcessDebuggingState.ProcessId, + g_ActiveProcessDebuggingState.ThreadId, + g_ActiveProcessDebuggingState.IsPaused ? "(paused)" : "(running)", + g_ActiveProcessDebuggingState.Is32Bit ? "86" : "64"); + } + else if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Remote debugging over serial (debugger-mode) + // + ShowMessages("%x: kHyperDbg> ", g_CurrentRemoteCore); + } + else + { + // + // Anything other than above scenarios including local debugging + // in vmi-mode + // + ShowMessages("HyperDbg> "); + } +} + +/** + * @brief check for multi-line commands + * + * @param CurrentCommand + * @param Reset + * @return BOOLEAN return TRUE if the command needs extra input, otherwise + * return FALSE + */ +BOOLEAN +CheckMultilineCommand(CHAR * CurrentCommand, BOOLEAN Reset) +{ + UINT32 CurrentCommandLen = 0; + std::string CurrentCommandStr(CurrentCommand); + + if (Reset) + { + g_IsInterpreterOnString = FALSE; + g_IsInterpreterPreviousCharacterABackSlash = FALSE; + g_InterpreterCountOfOpenCurlyBrackets = 0; + } + + CurrentCommandLen = (UINT32)CurrentCommandStr.length(); + + for (SIZE_T i = 0; i < CurrentCommandLen; i++) + { + switch (CurrentCommandStr.at(i)) + { + case '"': + + if (g_IsInterpreterPreviousCharacterABackSlash) + { + g_IsInterpreterPreviousCharacterABackSlash = FALSE; + break; // it's an escaped \" double-quote + } + + if (g_IsInterpreterOnString) + g_IsInterpreterOnString = FALSE; + else + g_IsInterpreterOnString = TRUE; + + break; + + case '{': + + if (g_IsInterpreterPreviousCharacterABackSlash) + g_IsInterpreterPreviousCharacterABackSlash = FALSE; + + if (!g_IsInterpreterOnString) + g_InterpreterCountOfOpenCurlyBrackets++; + + break; + + case '}': + + if (g_IsInterpreterPreviousCharacterABackSlash) + g_IsInterpreterPreviousCharacterABackSlash = FALSE; + + if (!g_IsInterpreterOnString && g_InterpreterCountOfOpenCurlyBrackets > 0) + g_InterpreterCountOfOpenCurlyBrackets--; + + break; + + case '\\': + + if (g_IsInterpreterPreviousCharacterABackSlash) + g_IsInterpreterPreviousCharacterABackSlash = FALSE; // it's not a escape character (two backslashes \\ ) + else + g_IsInterpreterPreviousCharacterABackSlash = TRUE; + + break; + + default: + + if (g_IsInterpreterPreviousCharacterABackSlash) + g_IsInterpreterPreviousCharacterABackSlash = FALSE; + + break; + } + } + + if (g_IsInterpreterOnString == FALSE && g_InterpreterCountOfOpenCurlyBrackets == 0) + { + // + // either the command is finished or it's a single + // line command + // + return FALSE; + } + else + { + // + // There still other lines, this command is incomplete + // + return TRUE; + } +} + +/** + * @brief Some of commands like stepping commands (i, p, t) and etc. + * need to be repeated when the user press enter, this function shows + * whether we should continue the previous command or not + * + * @return TRUE means the command should be continued, FALSE means command + * should be ignored + */ +BOOLEAN +ContinuePreviousCommand() +{ + BOOLEAN Result = g_ShouldPreviousCommandBeContinued; + + // + // We should keep it FALSE for the next command + // + g_ShouldPreviousCommandBeContinued = FALSE; + + if (Result) + { + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief Get Command Attributes + * + * @param FirstCommand just the first word of command (without other parameters) + * @return BOOLEAN Mask of the command's attributes + */ +UINT64 +GetCommandAttributes(const string & FirstCommand) +{ + CommandType::iterator Iterator; + + // + // Some commands should not be passed to the remote system + // and instead should be handled in the current debugger + // + + Iterator = g_CommandsList.find(FirstCommand); + + if (Iterator == g_CommandsList.end()) + { + // + // Command doesn't exist, if it's not exists then it's better to handle + // it locally, instead of sending it to the remote computer + // + return DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL; + } + else + { + return Iterator->second.CommandAttrib; + } + + return NULL; +} + +/** + * @brief Initialize the debugger and adjust commands for the first run + * + * @return VOID + */ +VOID +InitializeDebugger() +{ + // + // Initialize the mapping of functions + // + InitializeCommandsDictionary(); + + // + // Set the callback for symbol message handler + // + // + // ShowMessages is passed as PVOID (the callback API stores it in a PVOID and + // casts to the concrete fn-ptr type at the invocation site); g++ requires the + // explicit function-pointer -> void* cast that MSVC performs implicitly. + // + ScriptEngineSetTextMessageCallbackWrapper((PVOID)ShowMessages); + + // + // Register the CTRL+C and CTRL+BREAK Signals handler + // + if (!PlatformInstallCtrlHandler(BreakController)) + { + ShowMessages("err, when registering CTRL+C and CTRL+BREAK Signals " + "handler\n"); + // + // prefer to continue + // + } + + // + // *** Check for feature indicators *** + // + + // + // Get x86 processor width for virtual address + // + g_VirtualAddressWidth = Getx86VirtualAddressWidth(); + + // + // Check if processor supports TSX (RTM) + // + g_RtmSupport = CheckCpuSupportRtm(); + + // + // Load default settings + // + CommandSettingsLoadDefaultValuesFromConfigFile(); +} + +/** + * @brief Initialize commands and attributes + * + * @return VOID + */ +VOID +InitializeCommandsDictionary() +{ + g_CommandsList[".help"] = {NULL, &CommandHelpHelp, DEBUGGER_COMMAND_HELP_ATTRIBUTES}; + g_CommandsList[".hh"] = {NULL, &CommandHelpHelp, DEBUGGER_COMMAND_HELP_ATTRIBUTES}; + g_CommandsList["help"] = {NULL, &CommandHelpHelp, DEBUGGER_COMMAND_HELP_ATTRIBUTES}; + g_CommandsList["!help"] = {NULL, &CommandHelpHelp, DEBUGGER_COMMAND_HELP_ATTRIBUTES}; + + g_CommandsList["clear"] = {&CommandCls, &CommandClsHelp, DEBUGGER_COMMAND_CLEAR_ATTRIBUTES}; + g_CommandsList[".cls"] = {&CommandCls, &CommandClsHelp, DEBUGGER_COMMAND_CLEAR_ATTRIBUTES}; + g_CommandsList["cls"] = {&CommandCls, &CommandClsHelp, DEBUGGER_COMMAND_CLEAR_ATTRIBUTES}; + + g_CommandsList[".connect"] = {&CommandConnect, &CommandConnectHelp, DEBUGGER_COMMAND_CONNECT_ATTRIBUTES}; + g_CommandsList["connect"] = {&CommandConnect, &CommandConnectHelp, DEBUGGER_COMMAND_CONNECT_ATTRIBUTES}; + + g_CommandsList[".listen"] = {&CommandListen, &CommandListenHelp, DEBUGGER_COMMAND_LISTEN_ATTRIBUTES}; + g_CommandsList["listen"] = {&CommandListen, &CommandListenHelp, DEBUGGER_COMMAND_LISTEN_ATTRIBUTES}; + + g_CommandsList["g"] = {&CommandG, &CommandGHelp, DEBUGGER_COMMAND_G_ATTRIBUTES}; + g_CommandsList["go"] = {&CommandG, &CommandGHelp, DEBUGGER_COMMAND_G_ATTRIBUTES}; + + g_CommandsList["cont"] = {&CommandContinue, &CommandContinueHelp, DEBUGGER_COMMAND_CONTINUE_ATTRIBUTES}; + g_CommandsList["continue"] = {&CommandContinue, &CommandContinueHelp, DEBUGGER_COMMAND_CONTINUE_ATTRIBUTES}; + + g_CommandsList["gg"] = {&CommandGg, &CommandGgHelp, DEBUGGER_COMMAND_GG_ATTRIBUTES}; + + g_CommandsList[".attach"] = {&CommandAttach, &CommandAttachHelp, DEBUGGER_COMMAND_ATTACH_ATTRIBUTES}; + g_CommandsList["attach"] = {&CommandAttach, &CommandAttachHelp, DEBUGGER_COMMAND_ATTACH_ATTRIBUTES}; + + g_CommandsList[".detach"] = {&CommandDetach, &CommandDetachHelp, DEBUGGER_COMMAND_DETACH_ATTRIBUTES}; + g_CommandsList["detach"] = {&CommandDetach, &CommandDetachHelp, DEBUGGER_COMMAND_DETACH_ATTRIBUTES}; + + g_CommandsList[".start"] = {&CommandStart, &CommandStartHelp, DEBUGGER_COMMAND_START_ATTRIBUTES}; + g_CommandsList["start"] = {&CommandStart, &CommandStartHelp, DEBUGGER_COMMAND_START_ATTRIBUTES}; + + g_CommandsList[".restart"] = {&CommandRestart, &CommandRestartHelp, DEBUGGER_COMMAND_RESTART_ATTRIBUTES}; + g_CommandsList["restart"] = {&CommandRestart, &CommandRestartHelp, DEBUGGER_COMMAND_RESTART_ATTRIBUTES}; + + g_CommandsList[".switch"] = {&CommandSwitch, &CommandSwitchHelp, DEBUGGER_COMMAND_SWITCH_ATTRIBUTES}; + g_CommandsList["switch"] = {&CommandSwitch, &CommandSwitchHelp, DEBUGGER_COMMAND_SWITCH_ATTRIBUTES}; + + g_CommandsList[".kill"] = {&CommandKill, &CommandKillHelp, DEBUGGER_COMMAND_KILL_ATTRIBUTES}; + g_CommandsList["kill"] = {&CommandKill, &CommandKillHelp, DEBUGGER_COMMAND_KILL_ATTRIBUTES}; + + g_CommandsList[".process"] = {&CommandProcess, &CommandProcessHelp, DEBUGGER_COMMAND_PROCESS_ATTRIBUTES}; + g_CommandsList[".process2"] = {&CommandProcess, &CommandProcessHelp, DEBUGGER_COMMAND_PROCESS_ATTRIBUTES}; + g_CommandsList["process"] = {&CommandProcess, &CommandProcessHelp, DEBUGGER_COMMAND_PROCESS_ATTRIBUTES}; + g_CommandsList["process2"] = {&CommandProcess, &CommandProcessHelp, DEBUGGER_COMMAND_PROCESS_ATTRIBUTES}; + + g_CommandsList[".thread"] = {&CommandThread, &CommandThreadHelp, DEBUGGER_COMMAND_THREAD_ATTRIBUTES}; + g_CommandsList[".thread2"] = {&CommandThread, &CommandThreadHelp, DEBUGGER_COMMAND_THREAD_ATTRIBUTES}; + g_CommandsList["thread"] = {&CommandThread, &CommandThreadHelp, DEBUGGER_COMMAND_THREAD_ATTRIBUTES}; + g_CommandsList["thread2"] = {&CommandThread, &CommandThreadHelp, DEBUGGER_COMMAND_THREAD_ATTRIBUTES}; + + g_CommandsList["sleep"] = {&CommandSleep, &CommandSleepHelp, DEBUGGER_COMMAND_SLEEP_ATTRIBUTES}; + + g_CommandsList["event"] = {&CommandEvents, &CommandEventsHelp, DEBUGGER_COMMAND_EVENTS_ATTRIBUTES}; + g_CommandsList["events"] = {&CommandEvents, &CommandEventsHelp, DEBUGGER_COMMAND_EVENTS_ATTRIBUTES}; + + g_CommandsList["setting"] = {&CommandSettings, &CommandSettingsHelp, DEBUGGER_COMMAND_SETTINGS_ATTRIBUTES}; + g_CommandsList["settings"] = {&CommandSettings, &CommandSettingsHelp, DEBUGGER_COMMAND_SETTINGS_ATTRIBUTES}; + g_CommandsList[".setting"] = {&CommandSettings, &CommandSettingsHelp, DEBUGGER_COMMAND_SETTINGS_ATTRIBUTES}; + g_CommandsList[".settings"] = {&CommandSettings, &CommandSettingsHelp, DEBUGGER_COMMAND_SETTINGS_ATTRIBUTES}; + + g_CommandsList[".disconnect"] = {&CommandDisconnect, &CommandDisconnectHelp, DEBUGGER_COMMAND_DISCONNECT_ATTRIBUTES}; + g_CommandsList["disconnect"] = {&CommandDisconnect, &CommandDisconnectHelp, DEBUGGER_COMMAND_DISCONNECT_ATTRIBUTES}; + + g_CommandsList[".debug"] = {&CommandDebug, &CommandDebugHelp, DEBUGGER_COMMAND_DEBUG_ATTRIBUTES}; + g_CommandsList["debug"] = {&CommandDebug, &CommandDebugHelp, DEBUGGER_COMMAND_DEBUG_ATTRIBUTES}; + + g_CommandsList[".status"] = {&CommandStatus, &CommandStatusHelp, DEBUGGER_COMMAND_DOT_STATUS_ATTRIBUTES}; + g_CommandsList["status"] = {&CommandStatus, &CommandStatusHelp, DEBUGGER_COMMAND_STATUS_ATTRIBUTES}; + + g_CommandsList["load"] = {&CommandLoad, &CommandLoadHelp, DEBUGGER_COMMAND_LOAD_ATTRIBUTES}; + g_CommandsList[".load"] = {&CommandLoad, &CommandLoadHelp, DEBUGGER_COMMAND_LOAD_ATTRIBUTES}; + + g_CommandsList["exit"] = {&CommandExit, &CommandExitHelp, DEBUGGER_COMMAND_EXIT_ATTRIBUTES}; + g_CommandsList[".exit"] = {&CommandExit, &CommandExitHelp, DEBUGGER_COMMAND_EXIT_ATTRIBUTES}; + + g_CommandsList["flush"] = {&CommandFlush, &CommandFlushHelp, DEBUGGER_COMMAND_FLUSH_ATTRIBUTES}; + + g_CommandsList["pause"] = {&CommandPause, &CommandPauseHelp, DEBUGGER_COMMAND_PAUSE_ATTRIBUTES}; + g_CommandsList[".pause"] = {&CommandPause, &CommandPauseHelp, DEBUGGER_COMMAND_PAUSE_ATTRIBUTES}; + + g_CommandsList["unload"] = {&CommandUnload, &CommandUnloadHelp, DEBUGGER_COMMAND_UNLOAD_ATTRIBUTES}; + + g_CommandsList[".script"] = {&CommandScript, &CommandScriptHelp, DEBUGGER_COMMAND_SCRIPT_ATTRIBUTES}; + g_CommandsList["script"] = {&CommandScript, &CommandScriptHelp, DEBUGGER_COMMAND_SCRIPT_ATTRIBUTES}; + + g_CommandsList["output"] = {&CommandOutput, &CommandOutputHelp, DEBUGGER_COMMAND_OUTPUT_ATTRIBUTES}; + + g_CommandsList["print"] = {&CommandPrint, &CommandPrintHelp, DEBUGGER_COMMAND_PRINT_ATTRIBUTES}; + + g_CommandsList["?"] = {&CommandEval, &CommandEvalHelp, DEBUGGER_COMMAND_EVAL_ATTRIBUTES}; + g_CommandsList["eval"] = {&CommandEval, &CommandEvalHelp, DEBUGGER_COMMAND_EVAL_ATTRIBUTES}; + g_CommandsList["evaluate"] = {&CommandEval, &CommandEvalHelp, DEBUGGER_COMMAND_EVAL_ATTRIBUTES}; + + g_CommandsList[".logopen"] = {&CommandLogopen, &CommandLogopenHelp, DEBUGGER_COMMAND_LOGOPEN_ATTRIBUTES}; + + g_CommandsList[".logclose"] = {&CommandLogclose, &CommandLogcloseHelp, DEBUGGER_COMMAND_LOGCLOSE_ATTRIBUTES}; + + g_CommandsList[".pagein"] = {&CommandPagein, &CommandPageinHelp, DEBUGGER_COMMAND_PAGEIN_ATTRIBUTES}; + g_CommandsList["pagein"] = {&CommandPagein, &CommandPageinHelp, DEBUGGER_COMMAND_PAGEIN_ATTRIBUTES}; + + g_CommandsList["test"] = {&CommandTest, &CommandTestHelp, DEBUGGER_COMMAND_TEST_ATTRIBUTES}; + g_CommandsList[".test"] = {&CommandTest, &CommandTestHelp, DEBUGGER_COMMAND_TEST_ATTRIBUTES}; + + g_CommandsList["cpu"] = {&CommandCpu, &CommandCpuHelp, DEBUGGER_COMMAND_CPU_ATTRIBUTES}; + + g_CommandsList["wrmsr"] = {&CommandWrmsr, &CommandWrmsrHelp, DEBUGGER_COMMAND_WRMSR_ATTRIBUTES}; + + g_CommandsList["rdmsr"] = {&CommandRdmsr, &CommandRdmsrHelp, DEBUGGER_COMMAND_RDMSR_ATTRIBUTES}; + + g_CommandsList["!va2pa"] = {&CommandVa2pa, &CommandVa2paHelp, DEBUGGER_COMMAND_VA2PA_ATTRIBUTES}; + + g_CommandsList["!pa2va"] = {&CommandPa2va, &CommandPa2vaHelp, DEBUGGER_COMMAND_PA2VA_ATTRIBUTES}; + + g_CommandsList[".formats"] = {&CommandFormats, &CommandFormatsHelp, DEBUGGER_COMMAND_FORMATS_ATTRIBUTES}; + g_CommandsList[".format"] = {&CommandFormats, &CommandFormatsHelp, DEBUGGER_COMMAND_FORMATS_ATTRIBUTES}; + + g_CommandsList["!pte"] = {&CommandPte, &CommandPteHelp, DEBUGGER_COMMAND_PTE_ATTRIBUTES}; + + g_CommandsList["~"] = {&CommandCore, &CommandCoreHelp, DEBUGGER_COMMAND_CORE_ATTRIBUTES}; + g_CommandsList["core"] = {&CommandCore, &CommandCoreHelp, DEBUGGER_COMMAND_CORE_ATTRIBUTES}; + + g_CommandsList["!apic"] = {&CommandApic, &CommandApicHelp, DEBUGGER_COMMAND_APIC_ATTRIBUTES}; + g_CommandsList["!lapic"] = {&CommandApic, &CommandApicHelp, DEBUGGER_COMMAND_APIC_ATTRIBUTES}; + g_CommandsList["!localapic"] = {&CommandApic, &CommandApicHelp, DEBUGGER_COMMAND_APIC_ATTRIBUTES}; + + g_CommandsList["!ioapic"] = {&CommandIoapic, &CommandIoapicHelp, DEBUGGER_COMMAND_IOAPIC_ATTRIBUTES}; + + g_CommandsList["!monitor"] = {&CommandMonitor, &CommandMonitorHelp, DEBUGGER_COMMAND_MONITOR_ATTRIBUTES}; + + g_CommandsList["!vmcall"] = {&CommandVmcall, &CommandVmcallHelp, DEBUGGER_COMMAND_VMCALL_ATTRIBUTES}; + + g_CommandsList["!epthook"] = {&CommandEptHook, &CommandEptHookHelp, DEBUGGER_COMMAND_EPTHOOK_ATTRIBUTES}; + + g_CommandsList["bp"] = {&CommandBp, &CommandBpHelp, DEBUGGER_COMMAND_BP_ATTRIBUTES}; + + g_CommandsList["bl"] = {&CommandBl, &CommandBlHelp, DEBUGGER_COMMAND_BD_ATTRIBUTES}; + + g_CommandsList["be"] = {&CommandBe, &CommandBeHelp, DEBUGGER_COMMAND_BD_ATTRIBUTES}; + + g_CommandsList["bd"] = {&CommandBd, &CommandBdHelp, DEBUGGER_COMMAND_BD_ATTRIBUTES}; + + g_CommandsList["bc"] = {&CommandBc, &CommandBcHelp, DEBUGGER_COMMAND_BD_ATTRIBUTES}; + + g_CommandsList["!epthook2"] = {&CommandEptHook2, &CommandEptHook2Help, DEBUGGER_COMMAND_EPTHOOK2_ATTRIBUTES}; + + g_CommandsList["!cpuid"] = {&CommandCpuid, &CommandCpuidHelp, DEBUGGER_COMMAND_CPUID_ATTRIBUTES}; + + g_CommandsList["!msrread"] = {&CommandMsrread, &CommandMsrreadHelp, DEBUGGER_COMMAND_MSRREAD_ATTRIBUTES}; + g_CommandsList["!msread"] = {&CommandMsrread, &CommandMsrreadHelp, DEBUGGER_COMMAND_MSRREAD_ATTRIBUTES}; + + g_CommandsList["!msrwrite"] = {&CommandMsrwrite, &CommandMsrwriteHelp, DEBUGGER_COMMAND_MSRWRITE_ATTRIBUTES}; + + g_CommandsList["!tsc"] = {&CommandTsc, &CommandTscHelp, DEBUGGER_COMMAND_TSC_ATTRIBUTES}; + + g_CommandsList["!pmc"] = {&CommandPmc, &CommandPmcHelp, DEBUGGER_COMMAND_PMC_ATTRIBUTES}; + + g_CommandsList["!crwrite"] = {&CommandCrwrite, &CommandCrwriteHelp, DEBUGGER_COMMAND_CRWRITE_ATTRIBUTES}; + + g_CommandsList["!dr"] = {&CommandDr, &CommandDrHelp, DEBUGGER_COMMAND_DR_ATTRIBUTES}; + + g_CommandsList["!ioin"] = {&CommandIoin, &CommandIoinHelp, DEBUGGER_COMMAND_IOIN_ATTRIBUTES}; + + g_CommandsList["!ioout"] = {&CommandIoout, &CommandIooutHelp, DEBUGGER_COMMAND_IOOUT_ATTRIBUTES}; + g_CommandsList["!iout"] = {&CommandIoout, &CommandIooutHelp, DEBUGGER_COMMAND_IOOUT_ATTRIBUTES}; + + g_CommandsList["!exception"] = {&CommandException, &CommandExceptionHelp, DEBUGGER_COMMAND_EXCEPTION_ATTRIBUTES}; + + g_CommandsList["!interrupt"] = {&CommandInterrupt, &CommandInterruptHelp, DEBUGGER_COMMAND_INTERRUPT_ATTRIBUTES}; + + g_CommandsList["!syscall"] = {&CommandSyscallAndSysret, &CommandSyscallHelp, DEBUGGER_COMMAND_SYSCALL_ATTRIBUTES}; + g_CommandsList["!syscall2"] = {&CommandSyscallAndSysret, &CommandSyscallHelp, DEBUGGER_COMMAND_SYSCALL_ATTRIBUTES}; + + g_CommandsList["!sysret"] = {&CommandSyscallAndSysret, &CommandSysretHelp, DEBUGGER_COMMAND_SYSRET_ATTRIBUTES}; + g_CommandsList["!sysret2"] = {&CommandSyscallAndSysret, &CommandSysretHelp, DEBUGGER_COMMAND_SYSRET_ATTRIBUTES}; + + g_CommandsList["!mode"] = {&CommandMode, &CommandModeHelp, DEBUGGER_COMMAND_MODE_ATTRIBUTES}; + + g_CommandsList["!trace"] = {&CommandTrace, &CommandTraceHelp, DEBUGGER_COMMAND_TRACE_ATTRIBUTES}; + + g_CommandsList["!hide"] = {&CommandHide, &CommandHideHelp, DEBUGGER_COMMAND_HIDE_ATTRIBUTES}; + + g_CommandsList["!unhide"] = {&CommandUnhide, &CommandUnhideHelp, DEBUGGER_COMMAND_UNHIDE_ATTRIBUTES}; + + g_CommandsList["!measure"] = {&CommandMeasure, &CommandMeasureHelp, DEBUGGER_COMMAND_MEASURE_ATTRIBUTES}; + + g_CommandsList["lm"] = {&CommandLm, &CommandLmHelp, DEBUGGER_COMMAND_LM_ATTRIBUTES}; + + g_CommandsList["p"] = {&CommandP, &CommandPHelp, DEBUGGER_COMMAND_P_ATTRIBUTES}; + g_CommandsList["pr"] = {&CommandP, &CommandPHelp, DEBUGGER_COMMAND_P_ATTRIBUTES}; + + g_CommandsList["t"] = {&CommandT, &CommandTHelp, DEBUGGER_COMMAND_T_ATTRIBUTES}; + g_CommandsList["tr"] = {&CommandT, &CommandTHelp, DEBUGGER_COMMAND_T_ATTRIBUTES}; + + g_CommandsList["i"] = {&CommandI, &CommandIHelp, DEBUGGER_COMMAND_I_ATTRIBUTES}; + g_CommandsList["ir"] = {&CommandI, &CommandIHelp, DEBUGGER_COMMAND_I_ATTRIBUTES}; + + g_CommandsList["gu"] = {&CommandGu, &CommandGuHelp, DEBUGGER_COMMAND_GU_ATTRIBUTES}; + + g_CommandsList["db"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["dc"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["dd"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["dq"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["!db"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["!dc"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["!dd"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["!dq"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["!u"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["u"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["!u64"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["u64"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["!u2"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["u2"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["!u32"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + g_CommandsList["u32"] = {&CommandReadMemoryAndDisassembler, &CommandReadMemoryAndDisassemblerHelp, DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES}; + + g_CommandsList["eb"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; + g_CommandsList["ed"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; + g_CommandsList["eq"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; + g_CommandsList["!eb"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; + g_CommandsList["!ed"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; + g_CommandsList["!eq"] = {&CommandEditMemory, &CommandEditMemoryHelp, DEBUGGER_COMMAND_E_ATTRIBUTES}; + + g_CommandsList["sb"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; + g_CommandsList["sd"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; + g_CommandsList["sq"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; + g_CommandsList["!sb"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; + g_CommandsList["!sd"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; + g_CommandsList["!sq"] = {&CommandSearchMemory, &CommandSearchMemoryHelp, DEBUGGER_COMMAND_S_ATTRIBUTES}; + + g_CommandsList["r"] = {&CommandR, &CommandRHelp, DEBUGGER_COMMAND_R_ATTRIBUTES}; + + g_CommandsList[".sympath"] = {&CommandSympath, &CommandSympathHelp, DEBUGGER_COMMAND_SYMPATH_ATTRIBUTES}; + g_CommandsList["sympath"] = {&CommandSympath, &CommandSympathHelp, DEBUGGER_COMMAND_SYMPATH_ATTRIBUTES}; + + g_CommandsList[".sym"] = {&CommandSym, &CommandSymHelp, DEBUGGER_COMMAND_SYM_ATTRIBUTES}; + g_CommandsList["sym"] = {&CommandSym, &CommandSymHelp, DEBUGGER_COMMAND_SYM_ATTRIBUTES}; + + g_CommandsList["x"] = {&CommandX, &CommandXHelp, DEBUGGER_COMMAND_X_ATTRIBUTES}; + + g_CommandsList["prealloc"] = {&CommandPrealloc, &CommandPreallocHelp, DEBUGGER_COMMAND_PREALLOC_ATTRIBUTES}; + g_CommandsList["preallocate"] = {&CommandPrealloc, &CommandPreallocHelp, DEBUGGER_COMMAND_PREALLOC_ATTRIBUTES}; + g_CommandsList["preallocation"] = {&CommandPrealloc, &CommandPreallocHelp, DEBUGGER_COMMAND_PREALLOC_ATTRIBUTES}; + + g_CommandsList["preactivate"] = {&CommandPreactivate, &CommandPreactivateHelp, DEBUGGER_COMMAND_PREACTIVATE_ATTRIBUTES}; + g_CommandsList["preactive"] = {&CommandPreactivate, &CommandPreactivateHelp, DEBUGGER_COMMAND_PREACTIVATE_ATTRIBUTES}; + g_CommandsList["preactivation"] = {&CommandPreactivate, &CommandPreactivateHelp, DEBUGGER_COMMAND_PREACTIVATE_ATTRIBUTES}; + + g_CommandsList["k"] = {&CommandK, &CommandKHelp, DEBUGGER_COMMAND_K_ATTRIBUTES}; + g_CommandsList["kd"] = {&CommandK, &CommandKHelp, DEBUGGER_COMMAND_K_ATTRIBUTES}; + g_CommandsList["kq"] = {&CommandK, &CommandKHelp, DEBUGGER_COMMAND_K_ATTRIBUTES}; + + g_CommandsList["dt"] = {&CommandDtAndStruct, &CommandDtHelp, DEBUGGER_COMMAND_DT_ATTRIBUTES}; + g_CommandsList["!dt"] = {&CommandDtAndStruct, &CommandDtHelp, DEBUGGER_COMMAND_DT_ATTRIBUTES}; + + g_CommandsList["struct"] = {&CommandDtAndStruct, &CommandStructHelp, DEBUGGER_COMMAND_STRUCT_ATTRIBUTES}; + g_CommandsList["structure"] = {&CommandDtAndStruct, &CommandStructHelp, DEBUGGER_COMMAND_STRUCT_ATTRIBUTES}; + + g_CommandsList[".pe"] = {&CommandPe, &CommandPeHelp, DEBUGGER_COMMAND_PE_ATTRIBUTES}; + + g_CommandsList["!rev"] = {&CommandRev, &CommandRevHelp, DEBUGGER_COMMAND_REV_ATTRIBUTES}; + g_CommandsList["rev"] = {&CommandRev, &CommandRevHelp, DEBUGGER_COMMAND_REV_ATTRIBUTES}; + + g_CommandsList["!track"] = {&CommandTrack, &CommandTrackHelp, DEBUGGER_COMMAND_TRACK_ATTRIBUTES}; + g_CommandsList["track"] = {&CommandTrack, &CommandTrackHelp, DEBUGGER_COMMAND_TRACK_ATTRIBUTES}; + + g_CommandsList[".dump"] = {&CommandDump, &CommandDumpHelp, DEBUGGER_COMMAND_DUMP_ATTRIBUTES}; + g_CommandsList["dump"] = {&CommandDump, &CommandDumpHelp, DEBUGGER_COMMAND_DUMP_ATTRIBUTES}; + g_CommandsList["!dump"] = {&CommandDump, &CommandDumpHelp, DEBUGGER_COMMAND_DUMP_ATTRIBUTES}; + + g_CommandsList["a"] = {&CommandAssemble, &CommandAssembleHelp, DEBUGGER_COMMAND_A_ATTRIBUTES}; + g_CommandsList["asm"] = {&CommandAssemble, &CommandAssembleHelp, DEBUGGER_COMMAND_A_ATTRIBUTES}; + g_CommandsList["assemble"] = {&CommandAssemble, &CommandAssembleHelp, DEBUGGER_COMMAND_A_ATTRIBUTES}; + g_CommandsList["assembly"] = {&CommandAssemble, &CommandAssembleHelp, DEBUGGER_COMMAND_A_ATTRIBUTES}; + g_CommandsList["!a"] = {&CommandAssemble, &CommandAssembleHelp, DEBUGGER_COMMAND_A_ATTRIBUTES}; + g_CommandsList["!asm"] = {&CommandAssemble, &CommandAssembleHelp, DEBUGGER_COMMAND_A_ATTRIBUTES}; + g_CommandsList["!assemble"] = {&CommandAssemble, &CommandAssembleHelp, DEBUGGER_COMMAND_A_ATTRIBUTES}; + g_CommandsList["!assembly"] = {&CommandAssemble, &CommandAssembleHelp, DEBUGGER_COMMAND_A_ATTRIBUTES}; + + g_CommandsList["!pcitree"] = {&CommandPcitree, &CommandPcitreeHelp, DEBUGGER_COMMAND_PCITREE_ATTRIBUTES}; + g_CommandsList["!pcietree"] = {&CommandPcitree, &CommandPcitreeHelp, DEBUGGER_COMMAND_PCITREE_ATTRIBUTES}; + + g_CommandsList["!pcicam"] = {&CommandPcicam, &CommandPcicamHelp, DEBUGGER_COMMAND_PCICAM_ATTRIBUTES}; + + g_CommandsList["!idt"] = {&CommandIdt, &CommandIdtHelp, DEBUGGER_COMMAND_IDT_ATTRIBUTES}; + + g_CommandsList["!smi"] = {&CommandSmi, &CommandSmiHelp, DEBUGGER_COMMAND_SMI_ATTRIBUTES}; + + g_CommandsList["!lbr"] = {&CommandLbr, &CommandLbrHelp, DEBUGGER_COMMAND_LBR_ATTRIBUTES}; + + g_CommandsList["!lbrdump"] = {&CommandLbrdump, &CommandLbrdumpHelp, DEBUGGER_COMMAND_LBRDUMP_ATTRIBUTES}; + g_CommandsList["!lbrdmp"] = {&CommandLbrdump, &CommandLbrdumpHelp, DEBUGGER_COMMAND_LBRDUMP_ATTRIBUTES}; + g_CommandsList["!lbrprint"] = {&CommandLbrdump, &CommandLbrdumpHelp, DEBUGGER_COMMAND_LBRDUMP_ATTRIBUTES}; + + g_CommandsList["!pt"] = {&CommandPt, &CommandPtHelp, DEBUGGER_COMMAND_PT_ATTRIBUTES}; + + // + // hwdbg commands + // + g_CommandsList["!hw_clk"] = {&CommandHwClk, &CommandHwClkHelp, DEBUGGER_COMMAND_HWDBG_HW_CLK_ATTRIBUTES}; + g_CommandsList["!hw_clock"] = {&CommandHwClk, &CommandHwClkHelp, DEBUGGER_COMMAND_HWDBG_HW_CLK_ATTRIBUTES}; + g_CommandsList["!hwdbg_clock"] = {&CommandHwClk, &CommandHwClkHelp, DEBUGGER_COMMAND_HWDBG_HW_CLK_ATTRIBUTES}; + g_CommandsList["!hwdbg_clock"] = {&CommandHwClk, &CommandHwClkHelp, DEBUGGER_COMMAND_HWDBG_HW_CLK_ATTRIBUTES}; + + g_CommandsList["!hw"] = {&CommandHw, &CommandHwHelp, DEBUGGER_COMMAND_HWDBG_HW_ATTRIBUTES}; + + g_CommandsList["!xsetbv"] = {&CommandXsetbv, &CommandXsetbvHelp, DEBUGGER_COMMAND_XSETBV_ATTRIBUTES}; +} diff --git a/hyperdbg/libhyperdbg/code/debugger/core/steppings.cpp b/hyperdbg/libhyperdbg/code/debugger/core/steppings.cpp new file mode 100644 index 00000000..b48aa019 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/core/steppings.cpp @@ -0,0 +1,194 @@ +/** + * @file steppings.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Functions for stepping instructions + * @details + * @version 0.11 + * @date 2024-09-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; + +/** + * @brief Perform Instrumentation Step-in + * + * @return BOOLEAN + */ +BOOLEAN +SteppingInstrumentationStepIn() +{ + DEBUGGER_REMOTE_STEPPING_REQUEST RequestFormat; + + // + // Check if we're in VMI mode + // + if (g_ActiveProcessDebuggingState.IsActive) + { + ShowMessages("the instrumentation step-in is only supported in Debugger Mode\n"); + return FALSE; + } + + // + // Set type of step + // + RequestFormat = DEBUGGER_REMOTE_STEPPING_REQUEST_INSTRUMENTATION_STEP_IN; + + return KdSendStepPacketToDebuggee(RequestFormat); +} + +/** + * @brief Perform Instrumentation Step-in for Tracking + * + * @return BOOLEAN + */ +BOOLEAN +SteppingInstrumentationStepInForTracking() +{ + DEBUGGER_REMOTE_STEPPING_REQUEST RequestFormat; + + // + // Check if we're in VMI mode + // + if (g_ActiveProcessDebuggingState.IsActive) + { + ShowMessages("the instrumentation step-in is only supported in Debugger Mode\n"); + return FALSE; + } + + // + // Set type of step + // + RequestFormat = DEBUGGER_REMOTE_STEPPING_REQUEST_INSTRUMENTATION_STEP_IN_FOR_TRACKING; + + return KdSendStepPacketToDebuggee(RequestFormat); +} + +/** + * @brief Perform Regular Step-in + * + * @return BOOLEAN + */ +BOOLEAN +SteppingRegularStepIn() +{ + DEBUGGER_REMOTE_STEPPING_REQUEST RequestFormat; + + // + // Set type of step + // + RequestFormat = DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_IN; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // It's stepping over serial connection in kernel debugger + // + return KdSendStepPacketToDebuggee(RequestFormat); + } + else if (g_ActiveProcessDebuggingState.IsActive && g_ActiveProcessDebuggingState.IsPaused) + { + // + // It's stepping over user debugger + // + return UdSendStepPacketToDebuggee(g_ActiveProcessDebuggingState.ProcessDebuggingToken, + g_ActiveProcessDebuggingState.ThreadId, + RequestFormat); + } + else + { + return FALSE; + } +} + +/** + * @brief Perform Step-over + * + * @return BOOLEAN + */ +BOOLEAN +SteppingStepOver() +{ + DEBUGGER_REMOTE_STEPPING_REQUEST RequestFormat; + + // + // Set type of step + // + RequestFormat = DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // It's stepping over serial connection in kernel debugger + // + return KdSendStepPacketToDebuggee(RequestFormat); + } + else if (g_ActiveProcessDebuggingState.IsActive && g_ActiveProcessDebuggingState.IsPaused) + { + // + // It's stepping over user debugger + // + return UdSendStepPacketToDebuggee(g_ActiveProcessDebuggingState.ProcessDebuggingToken, + g_ActiveProcessDebuggingState.ThreadId, + RequestFormat); + } + else + { + return FALSE; + } +} + +/** + * @brief Perform Step-over for GU + * @param LastInstruction + * + * @return BOOLEAN + */ +BOOLEAN +SteppingStepOverForGu(BOOLEAN LastInstruction) +{ + DEBUGGER_REMOTE_STEPPING_REQUEST RequestFormat; + + // + // Set type of step + // + if (!LastInstruction) + { + RequestFormat = DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER_FOR_GU; + } + else + { + RequestFormat = DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER_FOR_GU_LAST_INSTRUCTION; + } + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // It's stepping over serial connection in kernel debugger + // + return KdSendStepPacketToDebuggee(RequestFormat); + } + else if (g_ActiveProcessDebuggingState.IsActive && g_ActiveProcessDebuggingState.IsPaused) + { + // + // It's stepping over user debugger + // + return UdSendStepPacketToDebuggee(g_ActiveProcessDebuggingState.ProcessDebuggingToken, + g_ActiveProcessDebuggingState.ThreadId, + RequestFormat); + } + else + { + // + // The target is not paused, or not a valid context + // + return FALSE; + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/driver-loader/install.cpp b/hyperdbg/libhyperdbg/code/debugger/driver-loader/install.cpp similarity index 72% rename from hyperdbg/hprdbgctrl/code/debugger/driver-loader/install.cpp rename to hyperdbg/libhyperdbg/code/debugger/driver-loader/install.cpp index 9dac2e9b..0c6e0326 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/driver-loader/install.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/driver-loader/install.cpp @@ -11,18 +11,6 @@ */ #include "pch.h" -BOOLEAN -InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe); - -BOOLEAN -RemoveDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName); - -BOOLEAN -StartDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName); - -BOOLEAN -StopDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName); - /** * @brief Install driver * @@ -70,9 +58,50 @@ InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe) if (LastError == ERROR_SERVICE_EXISTS) { // - // Ignore this error + // The service is already been created + // means that, the driver is previously installed // - return TRUE; + ShowMessages("the service (driver) already exists\n"); + + // + // We need to remove the old instance of the driver first + // Because the version of the driver might be different from the + // user-mode application + // + ShowMessages("trying to remove the old instance of the driver first\n"); + + // + // Stop the driver + // + ManageDriver(DriverName, NULL, DRIVER_FUNC_STOP); + + // + // Remove the driver + // + if (ManageDriver(DriverName, NULL, DRIVER_FUNC_REMOVE)) + { + ShowMessages("the old instance of the driver is removed successfully\n"); + } + else + { + ShowMessages("err, failed to remove the old instance of the driver\n"); + return FALSE; + } + + // + // Try to install the driver again + // + ShowMessages("installing the driver again\n"); + + if (InstallDriver(SchSCManager, DriverName, ServiceExe)) + { + return TRUE; + } + else + { + ShowMessages("err, failed to install the driver after removing the old instance\n"); + return FALSE; + } } else if (LastError == ERROR_SERVICE_MARKED_FOR_DELETE) { @@ -120,13 +149,13 @@ InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe) BOOLEAN ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, UINT16 Function) { - SC_HANDLE schSCManager; + SC_HANDLE SchSCManager; BOOLEAN Res = TRUE; // // Insure (somewhat) that the driver and service names are valid // - if (!DriverName || !ServiceName) + if (!DriverName || (Function == DRIVER_FUNC_INSTALL && !ServiceName)) { ShowMessages("invalid Driver or Service provided to ManageDriver() \n"); @@ -136,12 +165,12 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, UINT16 Function) // // Connect to the Service Control Manager and open the Services database // - schSCManager = OpenSCManager(NULL, // local machine + SchSCManager = OpenSCManager(NULL, // local machine NULL, // local database SC_MANAGER_ALL_ACCESS // access required ); - if (!schSCManager) + if (!SchSCManager) { ShowMessages("err, OpenSCManager failed (%x)\n", GetLastError()); @@ -159,12 +188,12 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, UINT16 Function) // Install the driver service // - if (InstallDriver(schSCManager, DriverName, ServiceName)) + if (InstallDriver(SchSCManager, DriverName, ServiceName)) { // // Start the driver service (i.e. start the driver) // - Res = StartDriver(schSCManager, DriverName); + Res = StartDriver(SchSCManager, DriverName); } else { @@ -181,7 +210,7 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, UINT16 Function) // // Stop the driver // - Res = StopDriver(schSCManager, DriverName); + Res = StopDriver(SchSCManager, DriverName); break; @@ -190,7 +219,7 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, UINT16 Function) // // Remove the driver service // - Res = RemoveDriver(schSCManager, DriverName); + Res = RemoveDriver(SchSCManager, DriverName); break; @@ -206,9 +235,9 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, UINT16 Function) // // Close handle to service control manager // - if (schSCManager) + if (SchSCManager) { - CloseServiceHandle(schSCManager); + CloseServiceHandle(SchSCManager); } return Res; @@ -325,7 +354,8 @@ StartDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) // ShowMessages("err, path to the driver not found, or the access to the driver file is limited\n"); - ShowMessages("most of the time, it's because anti-virus software is not finished scanning the drivers, so, if you try to load the driver again (re-enter the previous command), the problem will be solved\n"); + ShowMessages("most of the time, it's because anti-virus software is not finished scanning the drivers, " + "so, if you try to load the driver again (re-enter the previous command), the problem will be solved\n"); // // Indicate failure @@ -407,7 +437,9 @@ StopDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) } else { - ShowMessages("err, ControlService failed (%x)\n", GetLastError()); + ShowMessages("warning, failed to stop the driver. Possible reasons include the driver not currently running or an unsuccessful unload from a previous run. " + "This is not an error, HyperDbg tries to remove the previous driver and load it again (%x)\n", + GetLastError()); // // Indicate failure. Fall through to properly close the service handle @@ -427,23 +459,25 @@ StopDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) } /** - * @brief Setup driver name + * @brief Setup file name * - * @param DriverName - * @param DriverLocation + * @param FileName + * @param FileLocation * @param BufferLength + * @param CheckFileExists * * @return BOOLEAN */ BOOLEAN -SetupDriverName(const CHAR * DriverName, - _Inout_updates_bytes_all_(BufferLength) PCHAR DriverLocation, - ULONG BufferLength) +SetupPathForFileName(const CHAR * FileName, + _Inout_updates_bytes_all_(BufferLength) PCHAR FileLocation, + ULONG BufferLength, + BOOLEAN CheckFileExists) { HANDLE FileHandle; - DWORD DriverLocLen = 0; - HMODULE ProcHandle = GetModuleHandle(NULL); - char * Pos; + DWORD FileLocLen = 0; + HMODULE ProcHandle = GetModuleHandle(NULL); + CHAR * Pos; // // Get the current directory. @@ -454,9 +488,9 @@ SetupDriverName(const CHAR * DriverName, // We use the location of running exe instead of // finding driver based on current directory // - DriverLocLen = GetCurrentDirectory(BufferLength, DriverLocation); + FileLocLen = GetCurrentDirectory(BufferLength, DriverLocation); - if (DriverLocLen == 0) { + if (FileLocLen == 0) { ShowMessages("err, GetCurrentDirectory failed (%x)\n", GetLastError()); @@ -464,9 +498,9 @@ SetupDriverName(const CHAR * DriverName, } */ - GetModuleFileName(ProcHandle, DriverLocation, BufferLength); + GetModuleFileName(ProcHandle, FileLocation, BufferLength); - Pos = strrchr(DriverLocation, '\\'); + Pos = strrchr(FileLocation, '\\'); if (Pos != NULL) { // @@ -480,40 +514,38 @@ SetupDriverName(const CHAR * DriverName, // Setup path name to driver file // if (FAILED( - StringCbCat(DriverLocation, BufferLength, "\\"))) + StringCbCat(FileLocation, BufferLength, "\\"))) { return FALSE; } if (FAILED( - StringCbCat(DriverLocation, BufferLength, DriverName))) - { - return FALSE; - } - if (FAILED( - StringCbCat(DriverLocation, BufferLength, ".sys"))) + StringCbCat(FileLocation, BufferLength, FileName))) { return FALSE; } - // - // Insure driver file is in the specified directory - // - if ((FileHandle = CreateFile(DriverLocation, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) + if (CheckFileExists) { - ShowMessages("%s.sys is not loaded.\n", KERNEL_DEBUGGER_DRIVER_NAME); + // + // ensure file is in the specified directory + // + if ((FileHandle = CreateFile(FileLocation, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) + { + ShowMessages("err, target file is not loaded\n"); + + // + // Indicate failure + // + return FALSE; + } // - // Indicate failure + // Close open file handle // - return FALSE; - } - - // - // Close open file handle - // - if (FileHandle) - { - CloseHandle(FileHandle); + if (FileHandle) + { + CloseHandle(FileHandle); + } } // diff --git a/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kd.cpp b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp similarity index 86% rename from hyperdbg/hprdbgctrl/code/debugger/kernel-level/kd.cpp rename to hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp index c9820ecb..4020c620 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kd.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp @@ -14,19 +14,18 @@ // // Global Variables // -extern PMODULE_SYMBOL_DETAIL g_SymbolTable; -extern UINT32 g_SymbolTableSize; -extern UINT32 g_SymbolTableCurrentIndex; -extern HANDLE g_SerialListeningThreadHandle; -extern HANDLE g_SerialRemoteComPortHandle; -extern HANDLE g_DebuggeeStopCommandEventHandle; +extern HANDLE g_SerialListeningThreadHandle; +extern HANDLE g_SerialRemoteComPortHandle; +extern HANDLE g_DebuggeeStopCommandEventHandle; extern DEBUGGER_SYNCRONIZATION_EVENTS_STATE g_KernelSyncronizationObjectsHandleTable[DEBUGGER_MAXIMUM_SYNCRONIZATION_KERNEL_DEBUGGER_OBJECTS]; extern BYTE g_CurrentRunningInstruction[MAXIMUM_INSTR_SIZE]; extern BOOLEAN g_IsConnectedToHyperDbgLocally; +#ifdef _WIN32 extern OVERLAPPED g_OverlappedIoStructureForReadDebugger; extern OVERLAPPED g_OverlappedIoStructureForWriteDebugger; extern OVERLAPPED g_OverlappedIoStructureForReadDebuggee; +#endif // _WIN32 extern DEBUGGER_EVENT_AND_ACTION_RESULT g_DebuggeeResultOfRegisteringEvent; extern DEBUGGER_EVENT_AND_ACTION_RESULT g_DebuggeeResultOfAddingActionsToEvent; @@ -34,13 +33,15 @@ extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; extern BOOLEAN g_IsDebuggerConntectedToNamedPipe; extern BOOLEAN g_IsDebuggeeRunning; -extern BOOLEAN g_IsDebuggerModulesLoaded; +extern BOOLEAN g_IsKdModuleLoaded; +extern BOOLEAN g_IsVmmModuleLoaded; extern BOOLEAN g_SerialConnectionAlreadyClosed; extern BOOLEAN g_IgnoreNewLoggingMessages; extern BOOLEAN g_SharedEventStatus; extern BOOLEAN g_IsRunningInstruction32Bit; extern BOOLEAN g_IgnorePauseRequests; extern BOOLEAN g_IsDebuggeeInHandshakingPhase; +extern BOOLEAN g_ShouldPreviousCommandBeContinued; extern BYTE g_EndOfBufferCheckSerial[4]; extern ULONG g_CurrentRemoteCore; @@ -99,7 +100,7 @@ KdCheckForTheEndOfTheBuffer(PUINT32 CurrentLoopIndex, BYTE * Buffer) BOOLEAN KdCompareBufferWithString(CHAR * Buffer, const CHAR * CompareBuffer) { - int Result; + INT Result; Result = strcmp(Buffer, CompareBuffer); @@ -516,21 +517,29 @@ KdSendSymbolReloadPacketToDebuggee(UINT32 ProcessId) } /** - * @brief Send a Read register packet to the debuggee + * @brief Send a read register packet to the debuggee + * @param RegDes + * @param RegBuffSize * * @return BOOLEAN */ BOOLEAN -KdSendReadRegisterPacketToDebuggee(PDEBUGGEE_REGISTER_READ_DESCRIPTION RegDes) +KdSendReadRegisterPacketToDebuggee(PDEBUGGEE_REGISTER_READ_DESCRIPTION RegDes, UINT32 RegBuffSize) { // - // Send r command as read register packet + // Set the request data + // + DbgWaitSetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_READ_REGISTERS, RegDes, RegBuffSize); + + // + // Send the 'r' command as read register packet // if (!KdCommandPacketAndBufferToDebuggee( DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_READ_REGISTERS, (CHAR *)RegDes, - sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION))) + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) // only the header is enough, no need to send the entire buffer + )) { return FALSE; } @@ -544,28 +553,53 @@ KdSendReadRegisterPacketToDebuggee(PDEBUGGEE_REGISTER_READ_DESCRIPTION RegDes) } /** - * @brief Send a Read memory packet to the debuggee - * @param ReadMem + * @brief Send a write register packet to the debuggee + * @param RegDes * * @return BOOLEAN */ BOOLEAN -KdSendReadMemoryPacketToDebuggee(PDEBUGGER_READ_MEMORY ReadMem) +KdSendWriteRegisterPacketToDebuggee(PDEBUGGEE_REGISTER_WRITE_DESCRIPTION RegDes) { - PDEBUGGER_READ_MEMORY ActualBufferToSend = NULL; - UINT Size = 0; + // + // Set the request data + // + DbgWaitSetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_WRITE_REGISTER, RegDes, sizeof(DEBUGGEE_REGISTER_WRITE_DESCRIPTION)); - Size = ReadMem->Size * sizeof(CHAR) + sizeof(DEBUGGER_READ_MEMORY); - ActualBufferToSend = (PDEBUGGER_READ_MEMORY)malloc(Size); - - if (ActualBufferToSend == NULL) + // + // Send write register packet + // + if (!KdCommandPacketAndBufferToDebuggee( + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_WRITE_REGISTER, + (CHAR *)RegDes, + sizeof(DEBUGGEE_REGISTER_WRITE_DESCRIPTION))) { return FALSE; } - RtlZeroMemory(ActualBufferToSend, Size); + // + // Wait until the result of write register received + // + DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_WRITE_REGISTER); - memcpy(ActualBufferToSend, ReadMem, sizeof(DEBUGGER_READ_MEMORY)); + return TRUE; +} + +/** + * @brief Send a Read memory packet to the debuggee + * @param ReadMem + * @param Size + * + * @return BOOLEAN + */ +BOOLEAN +KdSendReadMemoryPacketToDebuggee(PDEBUGGER_READ_MEMORY ReadMem, UINT32 RequestSize) +{ + // + // Set the request data + // + DbgWaitSetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_READ_MEMORY, ReadMem, RequestSize); // // Send u-d command as read memory packet @@ -573,10 +607,10 @@ KdSendReadMemoryPacketToDebuggee(PDEBUGGER_READ_MEMORY ReadMem) if (!KdCommandPacketAndBufferToDebuggee( DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_READ_MEMORY, - (CHAR *)ActualBufferToSend, - Size)) + (CHAR *)ReadMem, + sizeof(DEBUGGER_READ_MEMORY) // only the header is enough, no need to send the entire buffer + )) { - free(ActualBufferToSend); return FALSE; } @@ -585,7 +619,6 @@ KdSendReadMemoryPacketToDebuggee(PDEBUGGER_READ_MEMORY ReadMem) // DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_READ_MEMORY); - free(ActualBufferToSend); return TRUE; } @@ -599,6 +632,11 @@ KdSendReadMemoryPacketToDebuggee(PDEBUGGER_READ_MEMORY ReadMem) BOOLEAN KdSendEditMemoryPacketToDebuggee(PDEBUGGER_EDIT_MEMORY EditMem, UINT32 Size) { + // + // Set the request data + // + DbgWaitSetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_EDIT_MEMORY, EditMem, sizeof(DEBUGGER_EDIT_MEMORY)); + // // Send d command as read memory packet // @@ -946,6 +984,181 @@ KdSendVa2paAndPa2vaPacketToDebuggee(PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS Va2paAndP return TRUE; } +/** + * @brief Send requests for APIC packet to the debuggee + * @param ApicPage + * @param ExpectedRequestSize + * + * @return BOOLEAN + */ +BOOLEAN +KdSendApicActionPacketsToDebuggee(PDEBUGGER_APIC_REQUEST ApicRequest, UINT32 ExpectedRequestSize) +{ + // + // Set the request data + // + DbgWaitSetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS, ApicRequest, ExpectedRequestSize); + + // + // Send the APIC request packets + // + if (!KdCommandPacketAndBufferToDebuggee( + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_ACTIONS_ON_APIC, + (CHAR *)ApicRequest, + sizeof(DEBUGGER_APIC_REQUEST) // only sending the request header + )) + { + return FALSE; + } + + // + // Wait until the result of actions to APIC is received + // + DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS); + + return TRUE; +} + +/** + * @brief Send requests for SMI operation packet to the debuggee + * + * @param SmiOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +KdSendSmiPacketsToDebuggee(PSMI_OPERATION_PACKETS SmiOperationRequest, UINT32 ExpectedRequestSize) +{ + // + // Set the request data + // + DbgWaitSetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_SMI_OPERATION_RESULT, SmiOperationRequest, ExpectedRequestSize); + + // + // Send the SMI request packets + // + if (!KdCommandPacketAndBufferToDebuggee( + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_SMI_OPERATION, + (CHAR *)SmiOperationRequest, + SIZEOF_SMI_OPERATION_PACKETS)) + { + return FALSE; + } + + // + // Wait until the result of actions to SMI is received + // + DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_SMI_OPERATION_RESULT); + + return TRUE; +} + +/** + * @brief Send requests for HyperTrace LBR dump packet to the debuggee + * + * @param HyperTraceLbrdumpRequest + * + * @return BOOLEAN + */ +BOOLEAN +KdSendHyperTraceLbrdumpPacketsToDebuggee(PHYPERTRACE_LBR_DUMP_PACKETS HyperTraceLbrdumpRequest, UINT32 ExpectedRequestSize) +{ + // + // Set the request data + // + DbgWaitSetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_LBR_DUMP_RESULT, HyperTraceLbrdumpRequest, ExpectedRequestSize); + + // + // Send the LBR request packets + // + if (!KdCommandPacketAndBufferToDebuggee( + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_HYPERTRACE_LBR_DUMP, + (CHAR *)HyperTraceLbrdumpRequest, + SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS)) + { + return FALSE; + } + + // + // Wait until the result of actions to HyperTrace LBR is received + // + DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_LBR_DUMP_RESULT); + + return TRUE; +} + +/** + * @brief Send requests for HyperTrace PT operation packet to the debuggee + * + * @param HyperTracePtOperationRequest + * + * @return BOOLEAN + */ +BOOLEAN +KdSendHyperTracePtPacketsToDebuggee(PHYPERTRACE_PT_OPERATION_PACKETS HyperTracePtOperationRequest, UINT32 ExpectedRequestSize) +{ + // + // Set the request data + // + DbgWaitSetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_PT_OPERATION_RESULT, HyperTracePtOperationRequest, ExpectedRequestSize); + + // + // Send the PT request packets + // + if (!KdCommandPacketAndBufferToDebuggee( + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_HYPERTRACE_PT_OPERATION, + (CHAR *)HyperTracePtOperationRequest, + SIZEOF_HYPERTRACE_PT_OPERATION_PACKETS)) + { + return FALSE; + } + + // + // Wait until the result of actions to HyperTrace PT is received + // + DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_PT_OPERATION_RESULT); + + return TRUE; +} + +/** + * @brief Send requests for IDT packet to the debuggee + * @param IdtRequest + * + * @return BOOLEAN + */ +BOOLEAN +KdSendQueryIdtPacketsToDebuggee(PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtRequest) +{ + // + // Set the request data + // + DbgWaitSetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_IDT_ENTRIES, + IdtRequest, + sizeof(INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS)); + + // + // Send the IDT request packets + // + if (!KdCommandPacketToDebuggee( + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_READ_IDT_ENTRIES)) + { + return FALSE; + } + + // + // Wait until the result of actions to IDT is received + // + DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_IDT_ENTRIES); + + return TRUE; +} + /** * @brief Sends a breakpoint set or 'bp' command packet to the debuggee * @param BpPacket @@ -1079,7 +1292,7 @@ KdSendScriptPacketToDebuggee(UINT64 BufferAddress, UINT32 BufferLength, UINT32 P * @return BOOLEAN */ BOOLEAN -KdSendUserInputPacketToDebuggee(const char * Sendbuf, int Len, BOOLEAN IgnoreBreakingAgain) +KdSendUserInputPacketToDebuggee(const CHAR * Sendbuf, INT Len, BOOLEAN IgnoreBreakingAgain) { PDEBUGGEE_USER_INPUT_PACKET UserInputPacket; UINT32 SizeOfStruct = 0; @@ -1204,6 +1417,22 @@ KdSendStepPacketToDebuggee(DEBUGGER_REMOTE_STEPPING_REQUEST StepRequestType) } } + // + // Set the debuggee is running after this command + // + if (StepRequestType == DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER || + StepRequestType == DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER_FOR_GU || + StepRequestType == DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_IN) + { + // + // The debuggee is also running after this type of command + // This is because this way the debuggee is running after the step-over or step-in + // so, if the program either terminates or couldn't run the next instruction, the + // user could pause the debuggee again + // + g_IsDebuggeeRunning = TRUE; + } + // // Send step packet to the serial // @@ -1329,7 +1558,7 @@ BOOLEAN KdReceivePacketFromDebuggee(CHAR * BufferToSave, UINT32 * LengthReceived) { - char ReadData = NULL; /* temperory Character */ + CHAR ReadData = NULL; /* temperory Character */ DWORD NoBytesRead = 0; /* Bytes read by ReadFile() */ UINT32 Loop = 0; @@ -1338,6 +1567,7 @@ KdReceivePacketFromDebuggee(CHAR * BufferToSave, // do { +#ifdef _WIN32 // // It's in the debugger // @@ -1373,6 +1603,18 @@ KdReceivePacketFromDebuggee(CHAR * BufferToSave, // Reset event for next try // ResetEvent(g_OverlappedIoStructureForReadDebugger.hEvent); +#else + // + // Linux: read one byte through the cross-platform serial transport + // + if (!PlatformSerialReadByte(g_SerialRemoteComPortHandle, + &ReadData, + &NoBytesRead, + PLATFORM_SERIAL_IO_DEBUGGER)) + { + return FALSE; + } +#endif // // We already now that the maximum packet size is MaxSerialPacketSize @@ -1419,10 +1661,11 @@ BOOLEAN KdReceivePacketFromDebugger(CHAR * BufferToSave, UINT32 * LengthReceived) { - char ReadData = NULL; /* temperory Character */ + CHAR ReadData = NULL; /* temperory Character */ DWORD NoBytesRead = 0; /* Bytes read by ReadFile() */ UINT32 Loop = 0; +#ifdef _WIN32 // // Set the timeout in milliseconds (e.g., 5000 ms = 5 seconds) // @@ -1439,12 +1682,14 @@ KdReceivePacketFromDebugger(CHAR * BufferToSave, Timeouts.WriteTotalTimeoutConstant = 0; Timeouts.WriteTotalTimeoutMultiplier = 0; SetCommTimeouts(g_SerialRemoteComPortHandle, &Timeouts); +#endif // // Read data and store in a buffer // do { +#ifdef _WIN32 // // It's in the debuggee // @@ -1480,6 +1725,19 @@ KdReceivePacketFromDebugger(CHAR * BufferToSave, // Reset event for next try // ResetEvent(g_OverlappedIoStructureForReadDebuggee.hEvent); +#else + // + // Linux: read one byte through the cross-platform serial transport + // (the 5s read timeout is applied inside the platform layer) + // + if (!PlatformSerialReadByte(g_SerialRemoteComPortHandle, + &ReadData, + &NoBytesRead, + PLATFORM_SERIAL_IO_DEBUGGEE)) + { + return FALSE; + } +#endif // // We already now that the maximum packet size is MaxSerialPacketSize @@ -1539,7 +1797,7 @@ KdSendPacketToDebuggee(const CHAR * Buffer, UINT32 Length, BOOLEAN SendEndOfBuff if (Length + SERIAL_END_OF_BUFFER_CHARS_COUNT > MaxSerialPacketSize) { ShowMessages("err, buffer is above the maximum buffer size that can be sent to debuggee (%d > %d), " - "for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/increase-communication-buffer-size\n", + "for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/increase-communication-buffer-size\n", Length + SERIAL_END_OF_BUFFER_CHARS_COUNT, MaxSerialPacketSize); return FALSE; @@ -1554,6 +1812,7 @@ KdSendPacketToDebuggee(const CHAR * Buffer, UINT32 Length, BOOLEAN SendEndOfBuff return FALSE; } +#ifdef _WIN32 if (g_IsSerialConnectedToRemoteDebugger || g_IsDebuggeeInHandshakingPhase) { // @@ -1619,6 +1878,20 @@ KdSendPacketToDebuggee(const CHAR * Buffer, UINT32 Length, BOOLEAN SendEndOfBuff // ResetEvent(g_OverlappedIoStructureForWriteDebugger.hEvent); } +#else + // + // Linux: write through the cross-platform serial transport. The debuggee / + // handshaking path is synchronous; the debugger path is overlapped (handled + // inside the platform layer). + // + { + BOOLEAN Synchronous = (g_IsSerialConnectedToRemoteDebugger || g_IsDebuggeeInHandshakingPhase); + if (!PlatformSerialWrite(g_SerialRemoteComPortHandle, Buffer, Length, Synchronous)) + { + return FALSE; + } + } +#endif Out: if (SendEndOfBuffer) @@ -1709,7 +1982,7 @@ KdCommandPacketAndBufferToDebuggee( MaxSerialPacketSize) { ShowMessages("err, buffer is above the maximum buffer size that can be sent to debuggee (%d > %d), " - "for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/increase-communication-buffer-size", + "for more information, please visit https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/increase-communication-buffer-size", sizeof(DEBUGGER_REMOTE_PACKET) + BufferLength + SERIAL_END_OF_BUFFER_CHARS_COUNT, MaxSerialPacketSize); @@ -1759,15 +2032,16 @@ KdCommandPacketAndBufferToDebuggee( /** * @brief check if the debuggee needs to be paused + * @param SignalRunningFlag * * @return VOID */ VOID -KdBreakControlCheckAndPauseDebugger() +KdBreakControlCheckAndPauseDebugger(BOOLEAN SignalRunningFlag) { // // Check if debuggee is running, otherwise the user - // pressed ctrl+c multiple times + // pressed CTRL+C multiple times // if (g_IsDebuggeeRunning) { @@ -1782,7 +2056,10 @@ KdBreakControlCheckAndPauseDebugger() // // Signal the event // - DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_IS_DEBUGGER_RUNNING); + if (SignalRunningFlag) + { + DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_IS_DEBUGGER_RUNNING); + } } } @@ -1889,11 +2166,15 @@ KdTheRemoteSystemIsRunning() * @details wait to connect to debuggee (this is debugger) * * @param SerialHandle + * @param IsNamedPipe + * @param PauseAfterConnection + * * @return BOOLEAN */ BOOLEAN KdPrepareSerialConnectionToRemoteSystem(HANDLE SerialHandle, - BOOLEAN IsNamedPipe) + BOOLEAN IsNamedPipe, + BOOLEAN PauseAfterConnection) { BOOL Status; /* Status */ DWORD EventMask = 0; /* Event mask to trigger */ @@ -1936,7 +2217,7 @@ KdPrepareSerialConnectionToRemoteSystem(HANDLE SerialHandle, // // Initialize the handle table // - for (size_t i = 0; i < DEBUGGER_MAXIMUM_SYNCRONIZATION_KERNEL_DEBUGGER_OBJECTS; i++) + for (SIZE_T i = 0; i < DEBUGGER_MAXIMUM_SYNCRONIZATION_KERNEL_DEBUGGER_OBJECTS; i++) { g_KernelSyncronizationObjectsHandleTable[i].IsOnWaitingState = FALSE; g_KernelSyncronizationObjectsHandleTable[i].EventHandle = @@ -2000,20 +2281,33 @@ KdPrepareSerialConnectionToRemoteSystem(HANDLE SerialHandle, // g_IsDebuggerConntectedToNamedPipe = IsNamedPipe; - // - // Now, the user can press ctrl+c to pause the debuggee - // - ShowMessages("press CTRL+C to pause the debuggee\n"); - // // Process CTRL+C breaks again // g_IgnorePauseRequests = FALSE; // - // Wait for event on this thread + // Now, the user can press ctrl+c to pause the debuggee // - KdTheRemoteSystemIsRunning(); + ShowMessages("press CTRL+C to pause the debuggee\n"); + + // + // If the user wants to pause after connection + // + if (PauseAfterConnection) + { + // + // Pause the target debuggee after connection + // + KdBreakControlCheckAndPauseDebugger(FALSE); + } + else + { + // + // Wait for event on this thread + // + KdTheRemoteSystemIsRunning(); + } } return TRUE; @@ -2123,7 +2417,7 @@ StartAgain: // ShowMessages("the answer to the PING request is received: %s\n", ReceivedPingBuildVersionBuffer); - if (strcmp((const char *)BuildSignature, ReceivedPingBuildVersionBuffer) == 0) + if (strcmp((const CHAR *)BuildSignature, ReceivedPingBuildVersionBuffer) == 0) { // // Build version matched @@ -2166,16 +2460,23 @@ StartAgain: * @param Port * @param IsPreparing * @param IsNamedPipe + * @param PauseAfterConnection + * * @return BOOLEAN */ BOOLEAN -KdPrepareAndConnectDebugPort(const char * PortName, DWORD Baudrate, UINT32 Port, BOOLEAN IsPreparing, BOOLEAN IsNamedPipe) +KdPrepareAndConnectDebugPort(const CHAR * PortName, + DWORD Baudrate, + UINT32 Port, + BOOLEAN IsPreparing, + BOOLEAN IsNamedPipe, + BOOLEAN PauseAfterConnection) { HANDLE Comm; /* Handle to the Serial port */ BOOL Status; /* Status */ DCB SerialParams = {0}; /* Initializing DCB structure */ COMMTIMEOUTS Timeouts = {0}; /* Initializing timeouts structure */ - char PortNo[20] = {0}; /* contain friendly name */ + CHAR PortNo[20] = {0}; /* contain friendly name */ BOOLEAN StatusIoctl; ULONG ReturnedLength; PDEBUGGER_PREPARE_DEBUGGEE DebuggeeRequest; @@ -2378,7 +2679,7 @@ KdPrepareAndConnectDebugPort(const char * PortName, DWORD Baudrate, UINT32 Port, // // Load the VMM // - if (!CommandLoadVmmModule()) + if (HyperDbgInstallKdDriver() == 1 || HyperDbgLoadVmmModule() == 1) { CloseHandle(Comm); g_SerialRemoteComPortHandle = NULL; @@ -2398,7 +2699,7 @@ KdPrepareAndConnectDebugPort(const char * PortName, DWORD Baudrate, UINT32 Port, g_SerialRemoteComPortHandle = NULL; g_IsConnectedToHyperDbgLocally = FALSE; - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); } // @@ -2428,7 +2729,7 @@ KdPrepareAndConnectDebugPort(const char * PortName, DWORD Baudrate, UINT32 Port, // // Get base address of ntoskrnl // - DebuggeeRequest->NtoskrnlBaseAddress = DebuggerGetNtoskrnlBase(); + DebuggeeRequest->KernelBaseAddress = DebuggerGetNtoskrnlBase(); // // Set the debuggee name, version, and build number @@ -2588,7 +2889,7 @@ KdPrepareAndConnectDebugPort(const char * PortName, DWORD Baudrate, UINT32 Port, // If we are here, then it's a debugger (not debuggee) // let's prepare the debuggee // - KdPrepareSerialConnectionToRemoteSystem(Comm, IsNamedPipe); + KdPrepareSerialConnectionToRemoteSystem(Comm, IsNamedPipe, PauseAfterConnection); } // @@ -2771,7 +3072,7 @@ KdCloseConnection() // if (g_IsSerialConnectedToRemoteDebugger) { - if (g_IsConnectedToHyperDbgLocally && g_IsDebuggerModulesLoaded) + if (g_IsConnectedToHyperDbgLocally && g_IsKdModuleLoaded) { // // The messages (and outputs) should no longer be passed @@ -2847,7 +3148,7 @@ KdRegisterEventInDebuggee(PDEBUGGER_GENERAL_EVENT_DETAIL EventRegBuffer, ULONG ReturnedLength; DEBUGGER_EVENT_AND_ACTION_RESULT ReturnedBuffer = {0}; - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Send IOCTL @@ -2901,7 +3202,7 @@ KdAddActionToEventInDebuggee(PDEBUGGER_GENERAL_ACTION ActionAddingBuffer, ULONG ReturnedLength; DEBUGGER_EVENT_AND_ACTION_RESULT ReturnedBuffer = {0}; - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); Status = DeviceIoControl(g_DeviceHandle, // Handle to device @@ -2958,7 +3259,7 @@ KdSendModifyEventInDebuggee(PDEBUGGER_MODIFY_EVENTS ModifyEvent, BOOLEAN SendThe // // Check if debugger is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Send the request to the kernel @@ -3212,7 +3513,7 @@ KdUninitializeConnection() // // Close synchronization objects // - for (size_t i = 0; i < DEBUGGER_MAXIMUM_SYNCRONIZATION_KERNEL_DEBUGGER_OBJECTS; i++) + for (SIZE_T i = 0; i < DEBUGGER_MAXIMUM_SYNCRONIZATION_KERNEL_DEBUGGER_OBJECTS; i++) { if (g_KernelSyncronizationObjectsHandleTable[i].EventHandle != NULL) { @@ -3256,6 +3557,11 @@ KdUninitializeConnection() // g_IsDebuggeeRunning = FALSE; + // + // Not repeating the last command + // + g_ShouldPreviousCommandBeContinued = FALSE; + // // Clear the handler // @@ -3275,3 +3581,61 @@ KdUninitializeConnection() // g_IsDebuggerConntectedToNamedPipe = FALSE; } + +/** + * @brief Sends '!pcitree' command, including buffer, to the debuggee + * @param PcitreePacket + * + * @return BOOLEAN + */ +BOOLEAN +KdSendPcitreePacketToDebuggee(PDEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET PcitreePacket) +{ + // + // Send '!pcitree' packet + // + if (!KdCommandPacketAndBufferToDebuggee( + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_QUERY_PCITREE, + (CHAR *)PcitreePacket, + sizeof(DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET))) + { + return FALSE; + } + + // + // Wait until the result of Pcitree packet is received + // + DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_PCITREE_RESULT); + + return TRUE; +} + +/** + * @brief Request PCI device info (CAM). Current consumers include '!pcicam'. + * @param PciepinfoPacket + * + * @return BOOLEAN + */ +BOOLEAN +KdSendPcidevinfoPacketToDebuggee(PDEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET PciepinfoPacket) +{ + // + // Send Pciepinfo packet + // + if (!KdCommandPacketAndBufferToDebuggee( + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_QUERY_PCIDEVINFO, + (CHAR *)PciepinfoPacket, + sizeof(DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET))) + { + return FALSE; + } + + // + // Wait until the result of Pcitree packet is received + // + DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_PCIDEVINFO_RESULT); + + return TRUE; +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kernel-listening.cpp b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp similarity index 59% rename from hyperdbg/hprdbgctrl/code/debugger/kernel-level/kernel-listening.cpp rename to hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp index d3f3e8f6..3619e430 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kernel-listening.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp @@ -15,11 +15,7 @@ // // Global Variables // -extern DEBUGGER_SYNCRONIZATION_EVENTS_STATE - g_KernelSyncronizationObjectsHandleTable[DEBUGGER_MAXIMUM_SYNCRONIZATION_KERNEL_DEBUGGER_OBJECTS]; extern BYTE g_CurrentRunningInstruction[MAXIMUM_INSTR_SIZE]; -extern OVERLAPPED g_OverlappedIoStructureForReadDebugger; -extern OVERLAPPED g_OverlappedIoStructureForWriteDebugger; extern HANDLE g_SerialRemoteComPortHandle; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; extern BOOLEAN g_IsDebuggeeRunning; @@ -32,6 +28,9 @@ extern DEBUGGER_EVENT_AND_ACTION_RESULT g_DebuggeeResultOfRegisteringEvent; extern DEBUGGER_EVENT_AND_ACTION_RESULT g_DebuggeeResultOfAddingActionsToEvent; extern UINT64 g_ResultOfEvaluatedExpression; extern UINT32 g_ErrorStateOfResultOfEvaluatedExpression; +extern UINT64 g_KernelBaseAddress; +extern DEBUGGER_SYNCRONIZATION_EVENTS_STATE + g_KernelSyncronizationObjectsHandleTable[DEBUGGER_MAXIMUM_SYNCRONIZATION_KERNEL_DEBUGGER_OBJECTS]; /** * @brief Check if the remote debuggee needs to pause the system @@ -42,37 +41,44 @@ extern UINT32 g_ErrorStateOfResultOfEvaluatedExpressio BOOLEAN ListeningSerialPortInDebugger() { - PDEBUGGER_PREPARE_DEBUGGEE InitPacket; - PDEBUGGER_REMOTE_PACKET TheActualPacket; - PDEBUGGEE_KD_PAUSED_PACKET PausePacket; - PDEBUGGEE_MESSAGE_PACKET MessagePacket; - PDEBUGGEE_CHANGE_CORE_PACKET ChangeCorePacket; - PDEBUGGEE_SCRIPT_PACKET ScriptPacket; - PDEBUGGEE_FORMATS_PACKET FormatsPacket; - PDEBUGGER_EVENT_AND_ACTION_RESULT EventAndActionPacket; - PDEBUGGER_UPDATE_SYMBOL_TABLE SymbolUpdatePacket; - PDEBUGGER_MODIFY_EVENTS EventModifyAndQueryPacket; - PDEBUGGEE_SYMBOL_UPDATE_RESULT SymbolReloadFinishedPacket; - PDEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET ChangeProcessPacket; - PDEBUGGEE_RESULT_OF_SEARCH_PACKET SearchResultsPacket; - PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET ChangeThreadPacket; - PDEBUGGER_FLUSH_LOGGING_BUFFERS FlushPacket; - PDEBUGGER_CALLSTACK_REQUEST CallstackPacket; - PDEBUGGER_SINGLE_CALLSTACK_FRAME CallstackFramePacket; - PDEBUGGER_DEBUGGER_TEST_QUERY_BUFFER TestQueryPacket; - PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterPacket; - PDEBUGGER_READ_MEMORY ReadMemoryPacket; - PDEBUGGER_EDIT_MEMORY EditMemoryPacket; - PDEBUGGEE_BP_PACKET BpPacket; - PDEBUGGER_SHORT_CIRCUITING_EVENT ShortCircuitingPacket; - PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PtePacket; - PDEBUGGER_PAGE_IN_REQUEST PageinPacket; - PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS Va2paPa2vaPacket; - PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET ListOrModifyBreakpointPacket; - PGUEST_REGS Regs; - PGUEST_EXTRA_REGISTERS ExtraRegs; - unsigned char * MemoryBuffer; - BOOLEAN ShowSignatureWhenDisconnected = FALSE; + PDEBUGGER_PREPARE_DEBUGGEE InitPacket; + PDEBUGGER_REMOTE_PACKET TheActualPacket; + PDEBUGGEE_KD_PAUSED_PACKET PausePacket; + PDEBUGGEE_MESSAGE_PACKET MessagePacket; + PDEBUGGEE_CHANGE_CORE_PACKET ChangeCorePacket; + PDEBUGGEE_SCRIPT_PACKET ScriptPacket; + PDEBUGGEE_FORMATS_PACKET FormatsPacket; + PDEBUGGER_EVENT_AND_ACTION_RESULT EventAndActionPacket; + PDEBUGGER_UPDATE_SYMBOL_TABLE SymbolUpdatePacket; + PDEBUGGER_MODIFY_EVENTS EventModifyAndQueryPacket; + PDEBUGGEE_SYMBOL_UPDATE_RESULT SymbolReloadFinishedPacket; + PDEBUGGEE_DETAILS_AND_SWITCH_PROCESS_PACKET ChangeProcessPacket; + PDEBUGGEE_RESULT_OF_SEARCH_PACKET SearchResultsPacket; + PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET ChangeThreadPacket; + PDEBUGGER_FLUSH_LOGGING_BUFFERS FlushPacket; + PDEBUGGER_CALLSTACK_REQUEST CallstackPacket; + PDEBUGGER_SINGLE_CALLSTACK_FRAME CallstackFramePacket; + PDEBUGGER_DEBUGGER_TEST_QUERY_BUFFER TestQueryPacket; + PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterPacket; + PDEBUGGEE_REGISTER_WRITE_DESCRIPTION WriteRegisterPacket; + PDEBUGGER_APIC_REQUEST ApicRequestPacket; + PDEBUGGER_READ_MEMORY ReadMemoryPacket; + PDEBUGGER_EDIT_MEMORY EditMemoryPacket; + PDEBUGGEE_BP_PACKET BpPacket; + PDEBUGGER_SHORT_CIRCUITING_EVENT ShortCircuitingPacket; + PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PtePacket; + PSMI_OPERATION_PACKETS SmiOperationPacket; + PHYPERTRACE_LBR_DUMP_PACKETS HyperTraceLbrdumpPacket; + PHYPERTRACE_PT_OPERATION_PACKETS HyperTracePtOperationPacket; + PDEBUGGER_PAGE_IN_REQUEST PageinPacket; + PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS Va2paPa2vaPacket; + PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET ListOrModifyBreakpointPacket; + BOOLEAN ShowSignatureWhenDisconnected = FALSE; + PVOID CallerAddress = NULL; + UINT32 CallerSize = NULL_ZERO; + PDEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET PcitreePacket; + PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtEntryRequestPacket; + PDEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET PcidevinfoPacket; StartAgain: @@ -174,6 +180,11 @@ StartAgain: InitPacket = (DEBUGGER_PREPARE_DEBUGGEE *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + // + // Set the kernel base address + // + g_KernelBaseAddress = InitPacket->KernelBaseAddress; + ShowMessages("connected to debuggee %s\n", InitPacket->OsName); // @@ -787,74 +798,15 @@ StartAgain: ReadRegisterPacket = (DEBUGGEE_REGISTER_READ_DESCRIPTION *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); - if (ReadRegisterPacket->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) - { - // - // Show the result of reading registers like rax=0000000000018b01 - // - if (ReadRegisterPacket->RegisterID == DEBUGGEE_SHOW_ALL_REGISTERS) - { - Regs = (GUEST_REGS *)(((CHAR *)ReadRegisterPacket) + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION)); - ExtraRegs = (GUEST_EXTRA_REGISTERS *)(((CHAR *)ReadRegisterPacket) + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) + sizeof(GUEST_REGS)); + // + // Get the address and size of the caller + // + DbgWaitGetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_READ_REGISTERS, &CallerAddress, &CallerSize); - RFLAGS Rflags = {0}; - Rflags.AsUInt = ExtraRegs->RFLAGS; - - ShowMessages( - "RAX=%016llx RBX=%016llx RCX=%016llx\n" - "RDX=%016llx RSI=% 016llx RDI=%016llx\n" - "RIP=%016llx RSP=%016llx RBP=%016llx\n" - "R8 =%016llx R9 =%016llx R10=%016llx\n" - "R11=%016llx R12=%016llx R13=%016llx\n" - "R14=%016llx R15=%016llx IOPL=%02x\n" - "%s %s %s %s\n%s %s %s %s\n" - "CS %04x SS %04x DS %04x ES %04x FS %04x GS %04x\n" - "RFLAGS=%016llx\n", - Regs->rax, - Regs->rbx, - Regs->rcx, - Regs->rdx, - Regs->rsi, - Regs->rdi, - ExtraRegs->RIP, - Regs->rsp, - Regs->rbp, - Regs->r8, - Regs->r9, - Regs->r10, - Regs->r11, - Regs->r12, - Regs->r13, - Regs->r14, - Regs->r15, - Rflags.IoPrivilegeLevel, - Rflags.OverflowFlag ? "OF 1" : "OF 0", - Rflags.DirectionFlag ? "DF 1" : "DF 0", - Rflags.InterruptEnableFlag ? "IF 1" : "IF 0", - Rflags.SignFlag ? "SF 1" : "SF 0", - Rflags.ZeroFlag ? "ZF 1" : "ZF 0", - Rflags.ParityFlag ? "PF 1" : "PF 0", - Rflags.CarryFlag ? "CF 1" : "CF 0", - Rflags.AuxiliaryCarryFlag ? "AXF 1" : "AXF 0", - ExtraRegs->CS, - ExtraRegs->SS, - ExtraRegs->DS, - ExtraRegs->ES, - ExtraRegs->FS, - ExtraRegs->GS, - ExtraRegs->RFLAGS); - } - else - { - ShowMessages("%s=%016llx\n", - RegistersNames[ReadRegisterPacket->RegisterID], - ReadRegisterPacket->Value); - } - } - else - { - ShowErrorMessage(ReadRegisterPacket->KernelStatus); - } + // + // Copy the memory buffer for the caller + // + memcpy(CallerAddress, ReadRegisterPacket, CallerSize); // // Signal the event relating to receiving result of reading registers @@ -862,139 +814,86 @@ StartAgain: DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_READ_REGISTERS); break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_WRITE_REGISTER: + + WriteRegisterPacket = (DEBUGGEE_REGISTER_WRITE_DESCRIPTION *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Get the address and size of the caller + // + DbgWaitGetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_WRITE_REGISTER, &CallerAddress, &CallerSize); + + // + // Copy the memory buffer for the caller + // + memcpy(CallerAddress, WriteRegisterPacket, CallerSize); + + // + // Signal the event relating to receiving result of writing register + // + DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_WRITE_REGISTER); + + break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_APIC_REQUESTS: + + ApicRequestPacket = (DEBUGGER_APIC_REQUEST *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Get the address and size of the caller + // + DbgWaitGetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS, &CallerAddress, &CallerSize); + + // + // Copy the memory buffer for the caller + // + memcpy(CallerAddress, ApicRequestPacket, CallerSize); + + // + // Signal the event relating to receiving result of performing actions into APIC + // + DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS); + + break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_QUERY_IDT_ENTRIES_REQUESTS: + + IdtEntryRequestPacket = (INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Get the address and size of the caller + // + DbgWaitGetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_IDT_ENTRIES, &CallerAddress, &CallerSize); + + // + // Copy the memory buffer for the caller + // + memcpy(CallerAddress, IdtEntryRequestPacket, CallerSize); + + // + // Signal the event relating to receiving result of querying IDT entries + // + DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_IDT_ENTRIES); + + break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_READING_MEMORY: ReadMemoryPacket = (DEBUGGER_READ_MEMORY *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); - if (ReadMemoryPacket->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) - { - // - // Show the result of reading memory like mem=0000000000018b01 - // - MemoryBuffer = (unsigned char *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET) + sizeof(DEBUGGER_READ_MEMORY)); - - switch (ReadMemoryPacket->Style) - { - case DEBUGGER_SHOW_COMMAND_DISASSEMBLE64: - - // - // Check if assembly mismatch occurred with the target address - // - if (ReadMemoryPacket->Is32BitAddress == TRUE && - ReadMemoryPacket->MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS) - { - ShowMessages("the target address seems to be located in a 32-bit program, if so, " - "please consider using the 'u32' instead to utilize the 32-bit disassembler\n"); - } - - // - // Show diassembles - // - HyperDbgDisassembler64(MemoryBuffer, ReadMemoryPacket->Address, ReadMemoryPacket->ReturnLength, 0, FALSE, NULL); - - break; - - case DEBUGGER_SHOW_COMMAND_DISASSEMBLE32: - - // - // Check if assembly mismatch occurred with the target address - // - if (ReadMemoryPacket->Is32BitAddress == FALSE && - ReadMemoryPacket->MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS) - { - ShowMessages("the target address seems to be located in a 64-bit program, if so, " - "please consider using the 'u' instead to utilize the 64-bit disassembler\n"); - } - - // - // Show diassembles - // - HyperDbgDisassembler32(MemoryBuffer, ReadMemoryPacket->Address, ReadMemoryPacket->ReturnLength, 0, FALSE, NULL); - - break; - - case DEBUGGER_SHOW_COMMAND_DB: - - ShowMemoryCommandDB( - MemoryBuffer, - ReadMemoryPacket->Size, - ReadMemoryPacket->Address, - ReadMemoryPacket->MemoryType, - ReadMemoryPacket->ReturnLength); - - break; - - case DEBUGGER_SHOW_COMMAND_DC: - - ShowMemoryCommandDC( - MemoryBuffer, - ReadMemoryPacket->Size, - ReadMemoryPacket->Address, - ReadMemoryPacket->MemoryType, - ReadMemoryPacket->ReturnLength); - - break; - - case DEBUGGER_SHOW_COMMAND_DD: - - ShowMemoryCommandDD( - MemoryBuffer, - ReadMemoryPacket->Size, - ReadMemoryPacket->Address, - ReadMemoryPacket->MemoryType, - ReadMemoryPacket->ReturnLength); - - break; - - case DEBUGGER_SHOW_COMMAND_DQ: - - ShowMemoryCommandDQ( - MemoryBuffer, - ReadMemoryPacket->Size, - ReadMemoryPacket->Address, - ReadMemoryPacket->MemoryType, - ReadMemoryPacket->ReturnLength); - - break; - - case DEBUGGER_SHOW_COMMAND_DUMP: - - CommandDumpSaveIntoFile(MemoryBuffer, ReadMemoryPacket->Size); - - break; - - case DEBUGGER_SHOW_COMMAND_DT: - - // - // Show the 'dt' command view - // - ScriptEngineShowDataBasedOnSymbolTypesWrapper(ReadMemoryPacket->DtDetails->TypeName, - ReadMemoryPacket->Address, - FALSE, - MemoryBuffer, - ReadMemoryPacket->DtDetails->AdditionalParameters); - - break; - } - } - else - { - ShowErrorMessage(ReadMemoryPacket->KernelStatus); - - if (ReadMemoryPacket->Style == DEBUGGER_SHOW_COMMAND_DUMP && - ReadMemoryPacket->KernelStatus == DEBUGGER_ERROR_INVALID_ADDRESS) - { - ShowMessages("HyperDbg attempted to access an invalid target address: 0x%llx\n" - "if you are confident that the address is valid, it may be paged out " - "or not yet available in the current CR3 page table\n" - "you can use the '.pagein' command to load this page table into memory and " - "trigger a page fault (#PF), please refer to the documentation for further details\n\n", - ReadMemoryPacket->Address); - } - } + // + // Get the address and size of the caller + // + DbgWaitGetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_READ_MEMORY, &CallerAddress, &CallerSize); // - // Signal the event relating to receiving result of reading registers + // Copy the memory buffer for the caller + // + memcpy(CallerAddress, ReadMemoryPacket, CallerSize); + + // + // Signal the event relating to receiving result of reading memory // DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_READ_MEMORY); @@ -1004,19 +903,18 @@ StartAgain: EditMemoryPacket = (DEBUGGER_EDIT_MEMORY *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); - if (EditMemoryPacket->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) - { - // - // Show the result of reading memory like mem=0000000000018b01 - // - } - else - { - ShowErrorMessage(EditMemoryPacket->KernelStatus); - } + // + // Get the address and size of the caller + // + DbgWaitGetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_EDIT_MEMORY, &CallerAddress, &CallerSize); // - // Signal the event relating to receiving result of reading registers + // Copy the memory buffer for the caller + // + memcpy(CallerAddress, EditMemoryPacket, CallerSize); + + // + // Signal the event relating to receiving result of editing memory // DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_EDIT_MEMORY); @@ -1087,6 +985,69 @@ StartAgain: break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_SMI_OPERATION_REQUESTS: + + SmiOperationPacket = (SMI_OPERATION_PACKETS *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Get the address and size of the caller + // + DbgWaitGetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_SMI_OPERATION_RESULT, &CallerAddress, &CallerSize); + + // + // Copy the memory buffer for the caller + // + memcpy(CallerAddress, SmiOperationPacket, CallerSize); + + // + // Signal the event relating to receiving result of SMI operation + // + DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_SMI_OPERATION_RESULT); + + break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_HYPERTRACE_LBR_DUMP_REQUESTS: + + HyperTraceLbrdumpPacket = (HYPERTRACE_LBR_DUMP_PACKETS *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Get the address and size of the caller + // + DbgWaitGetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_LBR_DUMP_RESULT, &CallerAddress, &CallerSize); + + // + // Copy the memory buffer for the caller + // + memcpy(CallerAddress, HyperTraceLbrdumpPacket, CallerSize); + + // + // Signal the event relating to receiving result of HyperTrace LBR dump + // + DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_LBR_DUMP_RESULT); + + break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_HYPERTRACE_PT_OPERATION_REQUESTS: + + HyperTracePtOperationPacket = (HYPERTRACE_PT_OPERATION_PACKETS *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Get the address and size of the caller + // + DbgWaitGetKernelRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_PT_OPERATION_RESULT, &CallerAddress, &CallerSize); + + // + // Copy the memory buffer for the caller + // + memcpy(CallerAddress, HyperTracePtOperationPacket, CallerSize); + + // + // Signal the event relating to receiving result of HyperTrace PT operation + // + DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_PT_OPERATION_RESULT); + + break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_BRINGING_PAGES_IN: PageinPacket = (DEBUGGER_PAGE_IN_REQUEST *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); @@ -1171,6 +1132,279 @@ StartAgain: break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_PCITREE: + + PcitreePacket = (DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + if (PcitreePacket->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // + // Print PCI device tree + // + ShowMessages("%-12s | %-9s | %-17s | %s \n%s\n", "DBDF", "VID:DID", "Vendor Name", "Device Name", "----------------------------------------------------------------------"); + for (UINT8 i = 0; i < (PcitreePacket->DeviceInfoListNum < DEV_MAX_NUM ? PcitreePacket->DeviceInfoListNum : DEV_MAX_NUM); i++) + { + Vendor * CurrentVendor = GetVendorById(PcitreePacket->DeviceInfoList[i].ConfigSpace.VendorId); + char * CurrentVendorName = (char *)"N/A"; + char * CurrentDeviceName = (char *)"N/A"; + + if (CurrentVendor != NULL) + { + CurrentVendorName = CurrentVendor->VendorName; + Device * CurrentDevice = GetDeviceFromVendor(CurrentVendor, PcitreePacket->DeviceInfoList[i].ConfigSpace.DeviceId); + + if (CurrentDevice != NULL) + { + CurrentDeviceName = CurrentDevice->DeviceName; + } + } + + ShowMessages("%04x:%02x:%02x:%x | %04x:%04x | %-17.*s | %.*s\n", + 0, // TODO: Add support for domains beyond 0000 + PcitreePacket->DeviceInfoList[i].Bus, + PcitreePacket->DeviceInfoList[i].Device, + PcitreePacket->DeviceInfoList[i].Function, + PcitreePacket->DeviceInfoList[i].ConfigSpace.VendorId, + PcitreePacket->DeviceInfoList[i].ConfigSpace.DeviceId, + strnlen_s(CurrentVendorName, PCI_NAME_STR_LENGTH), + CurrentVendorName, + strnlen_s(CurrentDeviceName, PCI_NAME_STR_LENGTH), + CurrentDeviceName + + ); + + FreeVendor(CurrentVendor); + } + FreePciIdDatabase(); + } + else + { + ShowErrorMessage(PcitreePacket->KernelStatus); + } + + // + // Signal the event relating to receiving result of pcitree query + // + DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_PCITREE_RESULT); + + break; + + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_PCIDEVINFO: + + PcidevinfoPacket = (DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + if (PcidevinfoPacket->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // For some reason, MSVC refuses to initialize these at top of case + const CHAR * PciHeaderTypeAsString[] = {"Endpoint", "PCI-to-PCI Bridge", "PCI-to-CardBus Bridge"}; + const CHAR * PciMmioBarTypeAsString[] = {"32-bit Wide", + "Reserved", + "64-bit Wide", + "Reserved"}; + UINT8 BarNumOffset = 0; + + ShowMessages("PCI configuration space (CAM) for device %04x:%02x:%02x:%x\n", + 0, // TODO: Add support for domains beyond 0000 + PcidevinfoPacket->DeviceInfo.Bus, + PcidevinfoPacket->DeviceInfo.Device, + PcidevinfoPacket->DeviceInfo.Function); + + if (!PcidevinfoPacket->PrintRaw) + { + Vendor * CurrentVendor = GetVendorById(PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.VendorId); + CHAR * CurrentVendorName = (CHAR *)"N/A"; + CHAR * CurrentDeviceName = (CHAR *)"N/A"; + + if (CurrentVendor != NULL) + { + CurrentVendorName = CurrentVendor->VendorName; + Device * CurrentDevice = GetDeviceFromVendor(CurrentVendor, PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.DeviceId); + + if (CurrentDevice != NULL) + { + CurrentDeviceName = CurrentDevice->DeviceName; + } + } + + ShowMessages("\nCommon Header:\nVID:DID: %04x:%04x\nVendor Name: %-17.*s\nDevice Name: %.*s\nCommand: %04x\n", + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.VendorId, + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.DeviceId, + strnlen_s(CurrentVendorName, PCI_NAME_STR_LENGTH), + CurrentVendorName, + strnlen_s(CurrentDeviceName, PCI_NAME_STR_LENGTH), + CurrentDeviceName, + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.Command); + + if ((PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01) << 7 == 0) // Only applicable to endpoints + { + ShowMessages(" Memory Space: %u\n I/O Space: %u\n", + (PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1, + (PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.Command & 0x1)); + } + + ShowMessages("Status: %04x\nRevision ID: %02x\nClass Code: %06x\nCacheLineSize: %02x\nPrimaryLatencyTimer: %02x\nHeaderType: %s (%02x)\n Multi-function Device: %s\nBist: %02x\n", + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.Status, + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.RevisionId, + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.ClassCode, + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.CacheLineSize, + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.PrimaryLatencyTimer, + (PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) < 2 ? PciHeaderTypeAsString[(PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x1)] : "Unknown", + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType, + (PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x1) ? "True" : "False", + PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.Bist); + FreeVendor(CurrentVendor); + FreePciIdDatabase(); + + ShowMessages("\nDevice Header:\n"); + + if ((PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01) << 7 == 0) // Endpoint + { + for (UINT8 i = 0; i < 5; i++) + { + // Memory I/O + if ((PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x1) == 0) + { + // 64-bit BAR + if (((PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1) == 2) + { + UINT64 BarMsb = PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i + 1]; + UINT64 BarLsb = PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i]; + UINT64 ActualBar = ((BarMsb & 0xFFFFFFFF) << 32) + (BarLsb & 0xFFFFFFF0); + + ShowMessages("BAR%u %s\n BAR Type: MMIO\n MMIO BAR Type: %s (%02x)\n BAR MSB: %08x\n BAR LSB: %08x\n BAR (actual): %016llx\n Prefetchable: %s\n", + i - BarNumOffset, + ((PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1 == 0) || !PcidevinfoPacket->DeviceInfo.MmioBarInfo[i].IsEnabled ? "[disabled]" : "", + PciMmioBarTypeAsString[(PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1], + (PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1, + BarMsb, + BarLsb, + ActualBar, + (PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x8 >> 3) ? "True" : "False"); + i++; + BarNumOffset++; + } + // 32-bit BAR + else + { + UINT32 ActualBar = (PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0xFFFFFFF0); + + ShowMessages("BAR%u %s\n BAR Type: MMIO\n BAR: %08x\n BAR (actual): %08x\n Prefetchable: %s\n", + i - BarNumOffset, + ((PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1 == 0) || !PcidevinfoPacket->DeviceInfo.MmioBarInfo[i].IsEnabled ? "[disabled]" : "", + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i], + ActualBar, + (PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x8 >> 3) ? "True" : "False"); + } + } + // Port I/O + else + { + // 32-bit BAR is the only flavor we have here + UINT32 ActualBar32 = PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0xFFFFFFFC; + + ShowMessages("BAR%u %s\n BAR Type: Port IO\n BAR: %08x\n BAR (actual): %08x\n Reserved: %u\n", + i - BarNumOffset, + ((PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.Command & 0x1) == 0) ? "[disabled]" : "", + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i], + ActualBar32, + (PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x2) >> 1); + } + } + + ShowMessages("Cardbus CIS Pointer: %08x\nSubsystem Vendor ID: %04x\nSubsystem ID: %04x\nROM BAR: %08x\nCapabilities Pointer: %02x\nReserved (0xD): %06x\nReserved (0xE): %08x\nInterrupt Line: %02x\nInterrupt Pin: %02x\nMin Grant: %02x\nMax latency: %02x\n", + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.CardBusCISPtr, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.SubVendorId, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.SubSystemId, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.ROMBar, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.CapabilitiesPtr, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Reserved, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Reserved1, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.InterruptLine, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.InterruptPin, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.MinGnt, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.MaxLat); + } + else if ((PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) == 1) // PCI-to-PCI Bridge + { + ShowMessages("BAR0: %08x\nBAR1: %08x\n", PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Bar[0], PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Bar[1]); + + ShowMessages("Primary Bus Number: %02x\nSecondary Bus Number: %02x\nSubordinate Bus Number: %02x\nSecondary Latency Timer: %02x\nI/O Base: %02x\nI/O Limit: %02x\nSecondary Status: %04x\nMemory Base: %04x\nMemory Limit: %04x\nPrefetchable Memory Base: %04x\nPrefetchable Memory Limit: %04x\nPrefetchable Base Upper 32 Bits: %08x\nPrefetchable Limit Upper 32 Bits: %08x\nI/O Base Upper 16 Bits: %04x\nI/O Limit Upper 16 Bits: %04x\nCapability Pointer: %02x\nReserved: %06x\nROM BAR: %08x\nInterrupt Line: %02x\nInterrupt Pin: %02x\nBridge Control: %04x\n", + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrimaryBusNumber, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SecondaryBusNumber, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SubordinateBusNumber, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SecondaryLatencyTimer, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoBase, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoLimit, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SecondaryStatus, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.MemoryBase, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.MemoryLimit, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableMemoryBase, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableMemoryLimit, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableBaseUpper32b, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableLimitUpper32b, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoLimitUpper16b, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoBaseUpper16b, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.CapabilityPtr, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Reserved, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.ROMBar, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.InterruptLine, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.InterruptPin, + PcidevinfoPacket->DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.BridgeControl); + } + else if ((PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) == 2) // PCI-to-CardBus Bridge + { + ShowMessages("Parsing header type %s (%02x) currently unsupported\n", PciHeaderTypeAsString[PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01], PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01); + } + else + { + ShowMessages("\nDevice Header:\nUnknown header type %02x\n", (PcidevinfoPacket->DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f)); + } + } + else + { + UINT32 * cs = (UINT32 *)&PcidevinfoPacket->DeviceInfo.ConfigSpace; // Overflows into .ConfigSpaceAdditional - no padding due to pack(0) + + ShowMessages(" 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"); + + for (UINT16 i = 0; i < CAM_CONFIG_SPACE_LENGTH; i += 16) + { + ShowMessages("%02x: ", i); + for (UINT8 j = 0; j < 16; j++) + { + ShowMessages("%02x ", *(((BYTE *)cs) + j)); + } + + // Print ASCII representation + // Replace non-printable characters with "." + for (UINT8 j = 0; j < 16; j++) + { + CHAR c = (CHAR) * (cs + j); + if (c >= 32 && c <= 126) + { + ShowMessages("%c", c); + } + else + { + ShowMessages("."); + } + } + ShowMessages("\n"); + cs += 4; + } + } + } + else + { + ShowErrorMessage(PcidevinfoPacket->KernelStatus); + } + + // + // Signal the event relating to receiving result of pcitree query + // + DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_PCIDEVINFO_RESULT); + + break; + default: ShowMessages("err, unknown packet action received from the debugger\n"); break; @@ -1205,7 +1439,7 @@ ListeningSerialPortInDebuggee() StartAgain: BOOL Status; /* Status */ - char SerialBuffer[MaxSerialPacketSize] = { + CHAR SerialBuffer[MaxSerialPacketSize] = { 0}; /* Buffer to send and receive data */ DWORD EventMask = 0; /* Event mask to trigger */ char ReadData = NULL; /* temperory Character */ diff --git a/hyperdbg/libhyperdbg/code/debugger/misc/assembler.cpp b/hyperdbg/libhyperdbg/code/debugger/misc/assembler.cpp new file mode 100644 index 00000000..8c8990ee --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/misc/assembler.cpp @@ -0,0 +1,264 @@ +/** + * @file assembler.cpp + * @author Abbas Masoumi Gorji (AbbasMG@hyperdbg.org) + * @brief Turns assembly codes into bytes + * @details + * @version 0.10 + * @date 2024-07-16 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief tries to solve the symbol issue with Keystone, which apparently originates from LLVM-MC. + * + * @return VOID + */ +VOID +AssembleData::ParseAssemblyData() +{ + std::string RawAsm = AsmRaw; + + // + // remove all "\n" instances + // + RawAsm.erase(std::remove(RawAsm.begin(), RawAsm.end(), '\n'), RawAsm.end()); + + // + // remove multiple spaces + // + std::regex MultipleSpaces(" +"); + RawAsm = std::regex_replace(RawAsm, MultipleSpaces, " "); + + // + // split assembly line by ';' + // + std::vector AssemblyInstructions; + SIZE_T Pos = 0; + std::string Delimiter = ";"; + while ((Pos = RawAsm.find(Delimiter)) != std::string::npos) + { + std::string Token = RawAsm.substr(0, Pos); + if (!Token.empty()) + { + AssemblyInstructions.push_back(Token); + } + RawAsm.erase(0, Pos + Delimiter.length()); + } + if (!RawAsm.empty()) + { + AssemblyInstructions.push_back(RawAsm); + } + + // + // process each assembly instruction + // + for (auto & InstructionLine : AssemblyInstructions) + { + std::string Expr {}; + UINT64 ExprAddr {}; + SIZE_T Start {}; + + while ((Start = InstructionLine.find('<', Start)) != std::string::npos) + { + SIZE_T End = InstructionLine.find('>', Start); + if (End != std::string::npos) + { + std::string Expr = InstructionLine.substr(Start + 1, End - Start - 1); + if (!SymbolConvertNameOrExprToAddress(Expr, &ExprAddr) && ExprAddr == 0) + { + ShowMessages("err, failed to resolve the symbol [ %s ].\n", Expr.c_str()); + Start += Expr.size() + 2; + continue; + } + + std::ostringstream Oss; + Oss << std::hex << std::showbase << ExprAddr; + InstructionLine.replace(Start, End - Start + 1, Oss.str()); + } + else + { + // + // No matching '>' found, break the loop + // + break; + } + Start += Expr.size() + 2; + } + } + + // + // Append ";" between two std::strings + // + auto ApndSemCln = [](std::string a, std::string b) { + return std::move(a) + ';' + std::move(b); + }; + + // + // Concatenate each assembly line + // + AsmFixed = std::accumulate(std::next(AssemblyInstructions.begin()), AssemblyInstructions.end(), AssemblyInstructions.at(0), ApndSemCln); + + if (!AsmFixed.empty() && AsmFixed.back() == ';') + { + // + // remove the last ";" for it will be counted as a statement by Keystone and a wrong number would be printed + // + AsmFixed.pop_back(); + } + + while (!AsmFixed.empty() && AsmFixed.back() == ';') + { + AsmFixed.pop_back(); + } +} + +INT +AssembleData::Assemble(UINT64 StartAddr, ks_arch Arch, INT Mode, INT Syntax) +{ + ks_engine * Ks; + + KsErr = ks_open(Arch, Mode, &Ks); + if (KsErr != KS_ERR_OK) + { + ShowMessages("err, failed on ks_open()"); + return -1; + } + + if (Syntax) + { + KsErr = ks_option(Ks, KS_OPT_SYNTAX, Syntax); + if (KsErr != KS_ERR_OK) + { + ShowMessages("err, failed on ks_option() with error code = %u\n", KsErr); + } + } + + // + // as long as symbols are parsed before passing asm code, SymResolver is not needed, for now. + // + KsErr = ks_option(Ks, KS_OPT_SYM_RESOLVER, 0); // null SymResolver + if (KsErr != KS_ERR_OK) + { + ShowMessages("err, failed on ks_option() with error code = %u\n", KsErr); + } + + if (ks_asm(Ks, AsmFixed.c_str(), StartAddr, &EncodedBytes, &BytesCount, &StatementCount)) + { + KsErr = ks_errno(Ks); + ShowMessages("err, failed on ks_asm() with count = %lu, error code = %u\n", (int)StatementCount, KsErr); + } + else + { + if (BytesCount == 0) + { + ShowMessages("err, the assemble operation returned no bytes, most likely due to incorrect formatting of assembly snippet\n"); + } + else + { + ShowMessages("generated assembly: %lu (decimal) bytes, %lu (decimal) statements ==>> ", (int)BytesCount, (int)StatementCount); + + SIZE_T i; + ShowMessages("%s = ", AsmFixed.c_str()); + for (i = 0; i < BytesCount; i++) + { + ShowMessages("%02x ", EncodedBytes[i]); + EncBytesIntVec.push_back(static_cast(EncodedBytes[i])); + } + ShowMessages("\n"); + + ks_close(Ks); + return 0; + } + } + ks_close(Ks); + return -1; +} + +AssembleData * +create_AssembleData() +{ + return new AssembleData; +} + +/** + * @brief Assembler function + * + * @param AssemblyCode The assembly code + * @param StartAddress The start address of the assembly code + * @param Length The length of the assembly code in bytes (to be returned) + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +HyperDbgAssembleGetLength(const CHAR * AssemblyCode, UINT64 StartAddress, UINT32 * Length) +{ + AssembleData AssembleData; + + // + // Convert assembly code to string + // + std::string AsmCode = AssemblyCode; + + AssembleData.AsmRaw = AsmCode; + AssembleData.ParseAssemblyData(); + + if (AssembleData.Assemble(StartAddress)) + { + return FALSE; + } + else + { + // + // Get the BytesCount + // + *Length = (UINT32)AssembleData.BytesCount; + + return TRUE; + } +} + +/** + * @brief Assembler function + * + * @param AssemblyCode The assembly code + * @param StartAddress The start address of the assembly code + * @param BufferToStoreAssembledData The buffer to store the assembled data + * @param BufferSize The size of the buffer + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +HyperDbgAssemble(const CHAR * AssemblyCode, UINT64 StartAddress, PVOID BufferToStoreAssembledData, UINT32 BufferSize) +{ + AssembleData AssembleData; + + // + // Convert assembly code to string + // + std::string AsmCode = AssemblyCode; + + AssembleData.AsmRaw = AsmCode; + AssembleData.ParseAssemblyData(); + + if (AssembleData.Assemble(StartAddress)) + { + return FALSE; + } + else + { + if (AssembleData.BytesCount > BufferSize) + { + return FALSE; + } + + // + // Copy the assembled data to the buffer + // + memcpy(BufferToStoreAssembledData, AssembleData.EncodedBytes, AssembleData.BytesCount); + + return TRUE; + } +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/misc/callstack.cpp b/hyperdbg/libhyperdbg/code/debugger/misc/callstack.cpp similarity index 97% rename from hyperdbg/hprdbgctrl/code/debugger/misc/callstack.cpp rename to hyperdbg/libhyperdbg/code/debugger/misc/callstack.cpp index cd14ddeb..729c592f 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/misc/callstack.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/misc/callstack.cpp @@ -98,7 +98,7 @@ CallstackReturnAddressToCallingAddress(UCHAR * ReturnAddress, PUINT32 IndexOfCal // The mask of F8 is used because we want to mask out the bottom // three bits (which are most often used for register selection) // - const unsigned char RmMask = 0xF8; + const UCHAR RmMask = 0xF8; // // 7-byte format: @@ -223,7 +223,7 @@ CallstackShowFrames(PDEBUGGER_SINGLE_CALLSTACK_FRAME CallstackFrames, // // Print callstack frames // - for (size_t i = 0; i < FrameCount; i++) + for (SIZE_T i = 0; i < FrameCount; i++) { IsCall = FALSE; @@ -233,7 +233,7 @@ CallstackShowFrames(PDEBUGGER_SINGLE_CALLSTACK_FRAME CallstackFrames, // Check if it's call or just a simple code address // if (CallstackFrames[i].IsExecutable && CallstackReturnAddressToCallingAddress( - (unsigned char *)&CallstackFrames[i].InstructionBytesOnRip[MAXIMUM_CALL_INSTR_SIZE], + (UCHAR *)&CallstackFrames[i].InstructionBytesOnRip[MAXIMUM_CALL_INSTR_SIZE], &CallLength)) { // diff --git a/hyperdbg/hprdbgctrl/code/debugger/misc/disassembler.cpp b/hyperdbg/libhyperdbg/code/debugger/misc/disassembler.cpp similarity index 86% rename from hyperdbg/hprdbgctrl/code/debugger/misc/disassembler.cpp rename to hyperdbg/libhyperdbg/code/debugger/misc/disassembler.cpp index 2d157d32..edd85b69 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/misc/disassembler.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/misc/disassembler.cpp @@ -55,7 +55,7 @@ typedef struct ZydisSymbol_ /** * @brief The symbol name. */ - const char * name; + const CHAR * name; } ZydisSymbol; ZydisFormatterFunc default_print_address_absolute; @@ -120,13 +120,13 @@ DisassembleBuffer(ZydisDecoder * decoder, ZyanU64 runtime_address, ZyanU8 * data, ZyanUSize length, - uint32_t maximum_instr, + UINT32 maximum_instr, BOOLEAN is_x86_64, BOOLEAN show_of_branch_is_taken, PRFLAGS rflags) { ZydisFormatter formatter; - int instr_decoded = 0; + INT InstrDecoded = 0; UINT64 UsedBaseAddress = NULL; if (g_DisassemblerSyntax == 1) @@ -160,7 +160,7 @@ DisassembleBuffer(ZydisDecoder * decoder, ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; ZydisDecodedInstruction instruction; - char buffer[256]; + CHAR buffer[256]; while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(decoder, data, length, &instruction, operands))) { @@ -192,7 +192,7 @@ DisassembleBuffer(ZydisDecoder * decoder, // // Show the memory for this instruction // - for (size_t i = 0; i < instruction.length; i++) + for (SIZE_T i = 0; i < instruction.length; i++) { ZyanU8 MemoryContent = data[i]; ShowMessages(" %02X", MemoryContent); @@ -203,7 +203,7 @@ DisassembleBuffer(ZydisDecoder * decoder, #define PaddingLength 12 if (instruction.length < PaddingLength) { - for (size_t i = 0; i < PaddingLength - instruction.length; i++) + for (SIZE_T i = 0; i < PaddingLength - instruction.length; i++) { ShowMessages(" "); } @@ -253,9 +253,9 @@ DisassembleBuffer(ZydisDecoder * decoder, data += instruction.length; length -= instruction.length; runtime_address += instruction.length; - instr_decoded++; + InstrDecoded++; - if (instr_decoded == maximum_instr) + if (InstrDecoded == maximum_instr) { return; } @@ -265,9 +265,9 @@ DisassembleBuffer(ZydisDecoder * decoder, /** * @brief Zydis test * - * @return int + * @return INT */ -int +INT ZydisTest() { if (ZydisGetVersion() != ZYDIS_VERSION) @@ -327,15 +327,15 @@ ZydisTest() * @param Rflags in the case ShowBranchIsTakenOrNot is true, we use this * variable to show the result of jump * - * @return int + * @return INT */ -int -HyperDbgDisassembler64(unsigned char * BufferToDisassemble, - UINT64 BaseAddress, - UINT64 Size, - UINT32 MaximumInstrDecoded, - BOOLEAN ShowBranchIsTakenOrNot, - PRFLAGS Rflags) +INT +HyperDbgDisassembler64(UCHAR * BufferToDisassemble, + UINT64 BaseAddress, + UINT64 Size, + UINT32 MaximumInstrDecoded, + BOOLEAN ShowBranchIsTakenOrNot, + PRFLAGS Rflags) { if (ZydisGetVersion() != ZYDIS_VERSION) { @@ -367,15 +367,15 @@ HyperDbgDisassembler64(unsigned char * BufferToDisassemble, * @param Rflags in the case ShowBranchIsTakenOrNot is true, we use this * variable to show the result of jump * - * @return int + * @return INT */ -int -HyperDbgDisassembler32(unsigned char * BufferToDisassemble, - UINT64 BaseAddress, - UINT64 Size, - UINT32 MaximumInstrDecoded, - BOOLEAN ShowBranchIsTakenOrNot, - PRFLAGS Rflags) +INT +HyperDbgDisassembler32(UCHAR * BufferToDisassemble, + UINT64 BaseAddress, + UINT64 Size, + UINT32 MaximumInstrDecoded, + BOOLEAN ShowBranchIsTakenOrNot, + PRFLAGS Rflags) { if (ZydisGetVersion() != ZYDIS_VERSION) { @@ -407,16 +407,16 @@ HyperDbgDisassembler32(unsigned char * BufferToDisassemble, * @return DEBUGGER_NEXT_INSTRUCTION_FINDER_STATUS */ DEBUGGER_CONDITIONAL_JUMP_STATUS -HyperDbgIsConditionalJumpTaken(unsigned char * BufferToDisassemble, - UINT64 BuffLength, - RFLAGS Rflags, - BOOLEAN Isx86_64) +HyperDbgIsConditionalJumpTaken(UCHAR * BufferToDisassemble, + UINT64 BuffLength, + RFLAGS Rflags, + BOOLEAN Isx86_64) { ZydisDecoder decoder; ZydisFormatter formatter; ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; - UINT64 CurrentRip = 0; - int instr_decoded = 0; + UINT64 CurrentRip = 0; + INT InstrDecoded = 0; ZydisDecodedInstruction instruction; UINT32 MaximumInstrDecoded = 1; @@ -753,18 +753,18 @@ HyperDbgIsConditionalJumpTaken(unsigned char * BufferToDisassemble, */ BOOLEAN HyperDbgCheckWhetherTheCurrentInstructionIsCall( - unsigned char * BufferToDisassemble, - UINT64 BuffLength, - BOOLEAN Isx86_64, - PUINT32 CallLength) + UCHAR * BufferToDisassemble, + UINT64 BuffLength, + BOOLEAN Isx86_64, + PUINT32 CallLength) { ZydisDecoder decoder; ZydisFormatter formatter; ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; - UINT64 CurrentRip = 0; - int instr_decoded = 0; + UINT64 CurrentRip = 0; + INT InstrDecoded = 0; ZydisDecodedInstruction instruction; - char buffer[256]; + CHAR buffer[256]; UINT32 MaximumInstrDecoded = 1; // @@ -854,15 +854,15 @@ HyperDbgCheckWhetherTheCurrentInstructionIsCall( */ UINT32 HyperDbgLengthDisassemblerEngine( - unsigned char * BufferToDisassemble, - UINT64 BuffLength, - BOOLEAN Isx86_64) + UCHAR * BufferToDisassemble, + UINT64 BuffLength, + BOOLEAN Isx86_64) { ZydisDecoder decoder; ZydisFormatter formatter; ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; - UINT64 CurrentRip = 0; - int instr_decoded = 0; + UINT64 CurrentRip = 0; + INT InstrDecoded = 0; ZydisDecodedInstruction instruction; UINT32 MaximumInstrDecoded = 1; @@ -981,18 +981,18 @@ ZydisFormatterPrintAddressAbsoluteForTrackingInstructions(const ZydisFormatter * */ BOOLEAN HyperDbgCheckWhetherTheCurrentInstructionIsCallOrRet( - unsigned char * BufferToDisassemble, - UINT64 CurrentRip, - UINT32 BuffLength, - BOOLEAN Isx86_64, - PBOOLEAN IsRet) + UCHAR * BufferToDisassemble, + UINT64 CurrentRip, + UINT32 BuffLength, + BOOLEAN Isx86_64, + PBOOLEAN IsRet) { ZydisDecoder decoder; ZydisFormatter formatter; ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; - int instr_decoded = 0; + INT InstrDecoded = 0; ZydisDecodedInstruction instruction; - char buffer[256]; + CHAR buffer[256]; UINT32 MaximumInstrDecoded = 1; if (ZydisGetVersion() != ZYDIS_VERSION) @@ -1088,23 +1088,22 @@ HyperDbgCheckWhetherTheCurrentInstructionIsCallOrRet( * @param BufferToDisassemble Current Bytes of assembly * @param BuffLength Length of buffer * @param Isx86_64 Whether it's an x86 or x64 - * @param RetLength Length of ret (if return value is TRUE) * * @return BOOLEAN */ BOOLEAN HyperDbgCheckWhetherTheCurrentInstructionIsRet( - unsigned char * BufferToDisassemble, - UINT64 BuffLength, - BOOLEAN Isx86_64) + UCHAR * BufferToDisassemble, + UINT64 BuffLength, + BOOLEAN Isx86_64) { ZydisDecoder decoder; ZydisFormatter formatter; ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; - UINT64 CurrentRip = 0; - int instr_decoded = 0; + UINT64 CurrentRip = 0; + INT InstrDecoded = 0; ZydisDecodedInstruction instruction; - char buffer[256]; + CHAR buffer[256]; UINT32 MaximumInstrDecoded = 1; if (ZydisGetVersion() != ZYDIS_VERSION) @@ -1171,3 +1170,95 @@ HyperDbgCheckWhetherTheCurrentInstructionIsRet( // return FALSE; } + +/** + * @brief Get immediate value on EAX register + * + * @param BufferToDisassemble Current Bytes of assembly + * @param BuffLength Length of buffer + * @param Isx86_64 Whether it's an x86 or x64 + * + * @return UINT32 + */ +UINT32 +HyperDbgGetImmediateValueOnEaxForSyscallNumber( + UCHAR * BufferToDisassemble, + UINT64 BuffLength, + BOOLEAN Isx86_64) +{ + ZydisDecoder decoder; + ZydisFormatter formatter; + ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; + UINT64 CurrentRip = 0; + INT InstrDecoded = 0; + ZydisDecodedInstruction instruction; + CHAR buffer[256]; + UINT32 MaximumInstrDecoded = 1; + + if (ZydisGetVersion() != ZYDIS_VERSION) + { + ShowMessages("invalid zydis version\n"); + return DEBUGGER_CONDITIONAL_JUMP_STATUS_ERROR; + } + + if (Isx86_64) + { + ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64); + } + else + { + ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_STACK_WIDTH_32); + } + + ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); + + ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, ZYAN_TRUE); + ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE); + + // + // Replace the `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function that + // formats the absolute addresses + // + default_print_address_absolute = + (ZydisFormatterFunc)&ZydisFormatterPrintAddressAbsolute; + ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, (const void **)&default_print_address_absolute); + + while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(&decoder, BufferToDisassemble, BuffLength, &instruction, operands))) + { + // + // We have to pass a `runtime_address` different to + // `ZYDIS_RUNTIME_ADDRESS_NONE` to enable printing of absolute addresses + // + + ZydisFormatterFormatInstruction(&formatter, &instruction, operands, instruction.operand_count_visible, &buffer[0], sizeof(buffer), (ZyanU64)CurrentRip, ZYAN_NULL); + + if (instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_SYSCALL) + { + // + // It's a SYSCALL instruction, we couldn't find the syscall number + // + return NULL; + } + + if (instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_MOV && + instruction.operand_count == 2 && + (operands[0].reg.value == ZYDIS_REGISTER_RAX || operands[0].reg.value == ZYDIS_REGISTER_EAX)) + { + // + // It's a MOV + // Log syscall number + // + // ShowMessages("Syscall number : 0x%x\n", operands[1].imm.value.u); + + return (UINT32)operands[1].imm.value.u; + } + + BufferToDisassemble += instruction.length; + BuffLength -= instruction.length; + } + + // + // Reaching here means that we didn't find any MOV instruction + // + return NULL; +} diff --git a/hyperdbg/libhyperdbg/code/debugger/misc/pci-id.cpp b/hyperdbg/libhyperdbg/code/debugger/misc/pci-id.cpp new file mode 100644 index 00000000..d6fef971 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/misc/pci-id.cpp @@ -0,0 +1,386 @@ +/** + * @file pci-id.cpp + * @author Bj�rn Ruytenberg (bjorn@bjornweb.nl) + * @brief Provides runtime access to PCI ID database + * @details + * @version 0.12 + * @date 2024-12-04 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +static CHAR * PciIdDatabaseBuffer = NULL; + +/** + * @brief Trims whitespaces in passed string + * + * @param Str + * @param MaxLen + * @return CHAR* + */ +CHAR * +TrimWhitespace(CHAR * Str, UINT8 MaxLen) +{ + CHAR * End; + while (*Str == ' ') + Str++; // Trim leading space + if (*Str == '\0') + return Str; + End = Str + strnlen_s(Str, MaxLen) - 1; + while (End > Str && (*End == ' ' || *End == '\n' || *End == '\r')) + End--; + *(End + 1) = '\0'; + return Str; +} + +/** + * @brief Converts passed string to lowercase + * + * @param Str + * @return CHAR* + */ +CHAR * +ToLower(CHAR * Str) +{ + UINT8 StrLength = (UINT8)strnlen_s(Str, PCI_ID_AS_STR_LENGTH); + CHAR * CurrentChar = Str; + + while (CurrentChar < Str + StrLength) + { + *CurrentChar = tolower(*CurrentChar); + CurrentChar++; + } + return Str; +} + +/** + * @brief Read line from string. Treats SrcBuffer as a stream (similar to fgets and friends), i.e. updates SrcBuffer by number of characters read. + * + * @param DestBuffer + * @param CharLimit + * @param SrcBuffer + * @return CHAR* + */ +CHAR * +ReadLine(CHAR * DestBuffer, UINT64 CharLimit, CHAR ** SrcBuffer) +{ + CHAR * Line = strchr(*SrcBuffer, '\n'); + if (!Line) + { + return NULL; + } + else + { + strncpy_s(DestBuffer, CharLimit, *SrcBuffer, (Line - *SrcBuffer)); + *SrcBuffer += (Line - *SrcBuffer + 1); + return *SrcBuffer; + } +} + +/** + * @brief Get Vendor by PCI ID, encoded in ASCII. Do not call directly - use GetVendorById() instead. + * + * @param Filename + * @param VendorId + * @return Vendor * + */ +Vendor * +GetVendorByIdStr(const CHAR * Filename, const CHAR * VendorId) +{ + Vendor * MatchedVendor = NULL; + BOOLEAN FoundVendorId = FALSE; + Device * LastDevice = NULL; + SubDevice * LastSubDevice = NULL; + CHAR * PciIdDbBufPtr = NULL; + CHAR Line[1024] = {'\0'}; + + if (!PciIdDatabaseBuffer) + { + FILE * f = fopen(Filename, "rb"); + SIZE_T Length = 0; + + if (f == NULL) + { + ShowMessages("Error: Cannot open file '%s': error %d\n", Filename, errno); + return NULL; + } + + fseek(f, 0, SEEK_END); + Length = ftell(f); + + PciIdDatabaseBuffer = (CHAR *)malloc(Length); + if (!PciIdDatabaseBuffer) + { + return NULL; + } + + fseek(f, 0, SEEK_SET); + fread(PciIdDatabaseBuffer, 1, Length, f); + fclose(f); + } + + PciIdDbBufPtr = PciIdDatabaseBuffer; + + while (ReadLine(Line, sizeof(Line), &PciIdDbBufPtr) != NULL) + { + CHAR FormatStr[24]; + + // Skip comments and empty lines + if (Line[0] == '#' || Line[0] == '\0') + { + continue; + } + + // Find vendor + // We assume PCI ID database comprises unique entries only, i.e. we return the first matching entry + if (Line[0] != '\t' && FoundVendorId == FALSE) + { + CHAR VendorBuf[PCI_ID_AS_STR_LENGTH + 1], VendorNameBuf[PCI_NAME_STR_LENGTH + 1]; + + snprintf(FormatStr, sizeof(FormatStr), "%%4s %%%d[^\n]", PCI_NAME_STR_LENGTH); // FormatStr = "%4s %PCI_NAME_STR_LENGTH[^\n]" + if (sscanf(Line, FormatStr, VendorBuf, VendorNameBuf) == 2) + { + if (strncmp(VendorBuf, VendorId, sizeof(VendorId)) == 0) + { + MatchedVendor = (Vendor *)malloc(sizeof(Vendor)); + if (!MatchedVendor) + { + return NULL; + } + + INT Result = sscanf(VendorBuf, "%hx", &(MatchedVendor->VendorId)); + if (Result != 1) + { + return NULL; + } + strncpy_s(MatchedVendor->VendorName, sizeof(MatchedVendor->VendorName), TrimWhitespace(VendorNameBuf, PCI_NAME_STR_LENGTH), _TRUNCATE); + FoundVendorId = TRUE; + } + } + } + // Get all devices for vendor + else if (Line[0] == '\t' && Line[1] != '\t' && FoundVendorId == TRUE) + { + CHAR DeviceBuf[PCI_ID_AS_STR_LENGTH + 1], DeviceNameBuf[PCI_NAME_STR_LENGTH + 1]; + + snprintf(FormatStr, sizeof(FormatStr), "%%4s %%%d[^\n]", PCI_NAME_STR_LENGTH); // FormatStr = "%4s %PCI_NAME_STR_LENGTH[^\n]" + if (sscanf(Line + 1, FormatStr, DeviceBuf, DeviceNameBuf) == 2) + { + Device * NewDevice = (Device *)malloc(sizeof(Device)); + if (!NewDevice) + { + FreeVendor(MatchedVendor); + return NULL; + } + + int Result = sscanf(DeviceBuf, "%hx", &(NewDevice->DeviceId)); + if (Result != 1) + { + FreeVendor(MatchedVendor); + return NULL; + } + + strncpy_s(NewDevice->DeviceName, sizeof(NewDevice->DeviceName), TrimWhitespace(DeviceNameBuf, PCI_NAME_STR_LENGTH), _TRUNCATE); + NewDevice->SubDevices = NULL; + NewDevice->Next = NULL; + + if (LastDevice) + { + LastDevice->Next = NewDevice; + } + else + { + MatchedVendor->Devices = NewDevice; // First device + } + LastDevice = NewDevice; + LastSubDevice = NULL; + } + } + // Get all subdevices for device + else if (Line[0] == '\t' && Line[1] == '\t' && FoundVendorId == TRUE && LastDevice) + { + CHAR SubVendorBuf[PCI_ID_AS_STR_LENGTH + 1], SubDeviceBuf[PCI_ID_AS_STR_LENGTH + 1], SubsystemNameBuf[PCI_NAME_STR_LENGTH + 1]; + + snprintf(FormatStr, sizeof(FormatStr), "%%4s %%4s %%%d[^\n]", PCI_NAME_STR_LENGTH); // FormatStr = "%4s %4s %PCI_NAME_STR_LENGTH[^\n]" + if (sscanf(Line + 2, FormatStr, SubVendorBuf, SubDeviceBuf, SubsystemNameBuf) == 3) + { + SubDevice * NewSubDevice = (SubDevice *)malloc(sizeof(SubDevice)); + if (!NewSubDevice) + { + FreeVendor(MatchedVendor); + return NULL; + } + + int Result = sscanf(SubVendorBuf, "%hx", &NewSubDevice->SubVendorId); + if (Result != 1) + { + FreeVendor(MatchedVendor); + return NULL; + } + + Result = sscanf(SubDeviceBuf, "%hx", &NewSubDevice->SubDeviceId); + if (Result != 1) + { + FreeVendor(MatchedVendor); + return NULL; + } + + strncpy_s(NewSubDevice->SubSystemName, sizeof(NewSubDevice->SubSystemName), TrimWhitespace(SubsystemNameBuf, PCI_NAME_STR_LENGTH), _TRUNCATE); + NewSubDevice->Next = NULL; + + if (LastSubDevice) + { + LastSubDevice->Next = NewSubDevice; + } + else + { + LastDevice->SubDevices = NewSubDevice; // First subdevice + } + LastSubDevice = NewSubDevice; + } + } + else if (Line[0] != '\t' && FoundVendorId == TRUE) // We hit the next vendor entry, so we're done parsing + { + break; + } + } + + return MatchedVendor; +} + +/** + * @brief Frees Vendor and all of its members + * + * @param VendorToFree + * @return VOID + */ +VOID +FreeVendor(Vendor * VendorToFree) +{ + if (VendorToFree == NULL) + return; + + Device * CurrentDevice = VendorToFree->Devices; + while (CurrentDevice) + { + SubDevice * CurrentSubDevice = CurrentDevice->SubDevices; + + while (CurrentSubDevice) + { + SubDevice * NextSubDevice = CurrentSubDevice->Next; + free(CurrentSubDevice); + CurrentSubDevice = NextSubDevice; + } + + Device * NextDevice = CurrentDevice->Next; + free(CurrentDevice); + CurrentDevice = NextDevice; + } +} + +/** + * @brief Frees PciIdDatabaseBuffer + * @return VOID + */ +VOID +FreePciIdDatabase() +{ + if (PciIdDatabaseBuffer != NULL) + { + free(PciIdDatabaseBuffer); + PciIdDatabaseBuffer = NULL; + } +} + +/** + * @brief Returns Vendor entry, including corresponding devices and subdevices + * @details Use FreeVendor() on returned Vendor pointer after usage. First call will initialize database - call FreeDatabase() once done querying. + * + * @param VendorId + * @return Vendor + */ +Vendor * +GetVendorById(UINT16 VendorId) +{ + CHAR VendorIdAsStr[5]; + CHAR ExecutablePath[MAX_PATH]; + HMODULE hModule = GetModuleHandle(NULL); + + snprintf(VendorIdAsStr, sizeof(VendorIdAsStr), "%04X", VendorId); + GetModuleFileName(hModule, ExecutablePath, sizeof(ExecutablePath)); + + // Extract executable name + CHAR * ExecutableName = strrchr(ExecutablePath, '\\'); + if (ExecutableName != NULL) + { + ExecutableName++; + } + else + { + ExecutableName = ExecutablePath; + } + + // Swap executable name for PCI_ID_DATABASE_PATH + strncpy(ExecutableName, PCI_ID_DATABASE_PATH, sizeof(PCI_ID_DATABASE_PATH)); + + return GetVendorByIdStr(ExecutablePath, ToLower(VendorIdAsStr)); +} + +/** + * @brief Returns Device entry corresponding to DeviceId + * + * @param VendorToUse + * @param DeviceId + * @return Device + */ +Device * +GetDeviceFromVendor(Vendor * VendorToUse, UINT16 DeviceId) +{ + Device * CurrentDevice = NULL; + if (!VendorToUse) + { + return NULL; + } + + CurrentDevice = VendorToUse->Devices; + while (CurrentDevice != NULL) + { + if (CurrentDevice->DeviceId == DeviceId) + { + return CurrentDevice; + } + CurrentDevice = CurrentDevice->Next; + } + return NULL; +} + +/** + * @brief Returns SubDevice entry corresponding to SubVendorId and DeviceId + * + * @param DeviceToUse + * @param SubVendorId + * @param SubDeviceId + * @return SubDevice + */ +SubDevice * +GetSubDeviceFromDevice(Device * DeviceToUse, UINT16 SubVendorId, UINT16 SubDeviceId) +{ + SubDevice * CurrentSubDevice = NULL; + if (!DeviceToUse) + { + return NULL; + } + + CurrentSubDevice = DeviceToUse->SubDevices; + while (CurrentSubDevice != NULL) + { + if (CurrentSubDevice->SubVendorId == SubVendorId && CurrentSubDevice->SubDeviceId == SubDeviceId) + { + return CurrentSubDevice; + } + CurrentSubDevice = CurrentSubDevice->Next; + } + return NULL; +} diff --git a/hyperdbg/libhyperdbg/code/debugger/misc/pt-helper.cpp b/hyperdbg/libhyperdbg/code/debugger/misc/pt-helper.cpp new file mode 100644 index 00000000..6f80b752 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/misc/pt-helper.cpp @@ -0,0 +1,432 @@ +/** + * @file pt-help.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief PT helper functions + * @details + * @version 0.21 + * @date 2026-07-03 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Read the process image for PT decoding + * + * @param Buffer + * @param Size + * @param Asid + * @param Ip + * @param Context + * + * @return int + */ +int +PtHelperReadImage(UINT8 * Buffer, SIZE_T Size, const struct pt_asid * Asid, UINT64 Ip, VOID * Context) +{ + (VOID) Asid; + + IMAGE_SYMBOL_CONTEXT * Ctx = (IMAGE_SYMBOL_CONTEXT *)Context; + + if (Ctx == NULL || Ctx->Code == NULL || Ip < Ctx->CodeBase || Ip >= Ctx->CodeBase + Ctx->CodeSize) + return -pte_nomap; + + UINT64 Available = Ctx->CodeBase + Ctx->CodeSize - Ip; + SIZE_T Count = (Size < Available) ? Size : (SIZE_T)Available; + + memcpy(Buffer, Ctx->Code + (Ip - Ctx->CodeBase), Count); + return (int)Count; +} + +/** + * @brief Capture the .text section of a process image + * + * @param Process + * @param TextStart + * @param TextEnd + * @param Ctx + * + * @return BOOLEAN + */ +BOOLEAN +PtHelperCaptureImage(HANDLE Process, UINT64 * TextStart, UINT64 * TextEnd, IMAGE_SYMBOL_CONTEXT * Ctx) +{ + HMODULE Ntdll = GetModuleHandleA("ntdll.dll"); + PFN_NT_QIP NtQip = Ntdll ? (PFN_NT_QIP)GetProcAddress(Ntdll, "NtQueryInformationProcess") : NULL; + PROC_BASIC_INFO Pbi = {0}; + ULONG Ret = 0; + SIZE_T Got = 0; + UINT64 Base = 0; + IMAGE_DOS_HEADER Dos; + IMAGE_NT_HEADERS64 Nt; + UINT64 SectionBase; + + if (NtQip == NULL || NtQip(Process, 0, &Pbi, sizeof(Pbi), &Ret) < 0 || Pbi.PebBaseAddress == NULL) + return FALSE; + + if (!ReadProcessMemory(Process, (PBYTE)Pbi.PebBaseAddress + 0x10, &Base, sizeof(Base), &Got) || Base == 0) + return FALSE; + + if (!ReadProcessMemory(Process, (PVOID)Base, &Dos, sizeof(Dos), &Got) || Dos.e_magic != IMAGE_DOS_SIGNATURE) + return FALSE; + + if (!ReadProcessMemory(Process, (PBYTE)Base + Dos.e_lfanew, &Nt, sizeof(Nt), &Got) || Nt.Signature != IMAGE_NT_SIGNATURE) + return FALSE; + + Ctx->ImageBase = Base; + SectionBase = Base + Dos.e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS64, OptionalHeader) + Nt.FileHeader.SizeOfOptionalHeader; + + for (WORD i = 0; i < Nt.FileHeader.NumberOfSections; i++) + { + IMAGE_SECTION_HEADER Section; + + if (!ReadProcessMemory(Process, (PBYTE)SectionBase + (UINT64)i * sizeof(Section), &Section, sizeof(Section), &Got)) + return FALSE; + + if (memcmp(Section.Name, ".text", 6) != 0) + continue; + + UINT64 Start = Base + Section.VirtualAddress; + UINT64 Size = Section.Misc.VirtualSize ? Section.Misc.VirtualSize : Section.SizeOfRawData; + + if (Size == 0) + return FALSE; + + Ctx->Code = (UINT8 *)malloc((SIZE_T)Size); + if (Ctx->Code == NULL) + return FALSE; + + if (!ReadProcessMemory(Process, (PVOID)Start, Ctx->Code, (SIZE_T)Size, &Got) || Got != Size) + { + free(Ctx->Code); + Ctx->Code = NULL; + return FALSE; + } + + Ctx->CodeBase = Start; + Ctx->CodeSize = Size; + *TextStart = Start; + *TextEnd = Start + Size - 1; + return TRUE; + } + + return FALSE; +} + +/** + * @brief Resolve function address using symbol information + * + * @param Process + * @param Path + * @param Name + * @param ImageBase + * @param Start + * @param End + * + * @return BOOLEAN + */ +BOOLEAN +PtHelperResolveFunction(HANDLE Process, const CHAR * Path, const CHAR * Name, UINT64 ImageBase, UINT64 * Start, UINT64 * End) +{ + union + { + SYMBOL_INFO Info; + BYTE Buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; + } Symbol = {0}; + BOOLEAN Ok = FALSE; + + SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); + if (!SymInitialize(Process, NULL, FALSE)) + return FALSE; + + if (SymLoadModuleEx(Process, NULL, Path, NULL, (DWORD64)ImageBase, 0, NULL, 0) != 0) + { + Symbol.Info.SizeOfStruct = sizeof(SYMBOL_INFO); + Symbol.Info.MaxNameLen = MAX_SYM_NAME; + + if (SymFromName(Process, Name, &Symbol.Info) && Symbol.Info.Address != 0) + { + *Start = Symbol.Info.Address; + *End = Symbol.Info.Address + (Symbol.Info.Size ? Symbol.Info.Size : 0x200) - 1; + Ok = TRUE; + } + } + + SymCleanup(Process); + return Ok; +} + +/** + * @brief Get PT packet name + * + * @param Type + * + * @return const CHAR * + */ +const CHAR * +PtHelperPacketName(enum pt_packet_type Type) +{ + switch (Type) + { + case ppt_psb: + return "PSB"; + case ppt_psbend: + return "PSBEND"; + case ppt_pad: + return "PAD"; + case ppt_fup: + return "FUP"; + case ppt_tip: + return "TIP"; + case ppt_tip_pge: + return "TIP.PGE"; + case ppt_tip_pgd: + return "TIP.PGD"; + case ppt_tnt_8: + return "TNT8"; + case ppt_tnt_64: + return "TNT64"; + case ppt_mode: + return "MODE"; + case ppt_pip: + return "PIP"; + case ppt_vmcs: + return "VMCS"; + case ppt_cbr: + return "CBR"; + case ppt_tsc: + return "TSC"; + case ppt_tma: + return "TMA"; + case ppt_mtc: + return "MTC"; + case ppt_cyc: + return "CYC"; + case ppt_ovf: + return "OVF"; + case ppt_stop: + return "STOP"; + case ppt_exstop: + return "EXSTOP"; + case ppt_mnt: + return "MNT"; + case ppt_ptw: + return "PTW"; + default: + return "?"; + } +} + +/** + * @brief Reconstruct IP from PT packet + * + * @param Packet + * @param LastIp + * + * @return UINT64 + */ +UINT64 +PtHelperReconstructIp(const struct pt_packet_ip * Packet, UINT64 * LastIp) +{ + UINT64 Value = *LastIp; + + switch (Packet->ipc) + { + case pt_ipc_update_16: + Value = (Value & ~0xffffull) | (Packet->ip & 0xffffull); + break; + case pt_ipc_update_32: + Value = (Value & ~0xffffffffull) | (Packet->ip & 0xffffffffull); + break; + case pt_ipc_update_48: + Value = (Value & ~0xffffffffffffull) | (Packet->ip & 0xffffffffffffull); + break; + case pt_ipc_sext_48: + Value = Packet->ip & 0xffffffffffffull; + if (Value & 0x800000000000ull) + Value |= 0xffff000000000000ull; + break; + default: + Value = Packet->ip; + break; + } + + *LastIp = Value; + return Value; +} + +/** + * @brief Decode PT packets + * + * @param Cpu + * @param Buffer + * @param Size + * @param ImageBase + * + * @return UINT64 + */ +UINT64 +PtHelperDecodeCorePackets(UINT32 Cpu, const UINT8 * Buffer, UINT64 Size, UINT64 ImageBase) +{ + struct pt_config Config; + struct pt_packet_decoder * Decoder; + UINT64 Count = 0; + UINT64 LastIp = 0; + int Status; + + pt_config_init(&Config); + Config.begin = (UINT8 *)Buffer; + Config.end = (UINT8 *)Buffer + Size; + + Decoder = pt_pkt_alloc_decoder(&Config); + if (Decoder == NULL) + { + ShowMessages("[-] core %u: cannot allocate packet decoder\n", Cpu); + return 0; + } + + for (;;) + { + Status = pt_pkt_sync_forward(Decoder); + if (Status < 0) + break; + + for (;;) + { + struct pt_packet Packet; + + Status = pt_pkt_next(Decoder, &Packet, sizeof(Packet)); + if (Status < 0) + break; + + Count++; + + switch (Packet.type) + { + case ppt_tnt_8: + case ppt_tnt_64: + ShowMessages(" %-8s %2u ", PtHelperPacketName(Packet.type), Packet.payload.tnt.bit_size); + for (UINT8 Bit = 0; Bit < Packet.payload.tnt.bit_size && Bit < 64; Bit++) + putchar(((Packet.payload.tnt.payload >> (Packet.payload.tnt.bit_size - 1 - Bit)) & 1) ? 'T' : 'N'); + putchar('\n'); + break; + + case ppt_tip: + case ppt_fup: + case ppt_tip_pge: + case ppt_tip_pgd: + if (Packet.payload.ip.ipc == pt_ipc_suppressed) + ShowMessages(" %-8s (ip suppressed)\n", PtHelperPacketName(Packet.type)); + else + { + UINT64 Ip = PtHelperReconstructIp(&Packet.payload.ip, &LastIp); + ShowMessages(" %-8s 0x%016llx exe+0x%llx\n", + PtHelperPacketName(Packet.type), + (UINT64)Ip, + (UINT64)(Ip - ImageBase)); + } + break; + + case ppt_pip: + ShowMessages(" %-8s cr3=0x%llx\n", PtHelperPacketName(Packet.type), (UINT64)Packet.payload.pip.cr3); + break; + + case ppt_cbr: + // ShowMessages(" %-8s ratio=%u\n", PtHelperPacketName(Packet.type), Packet.payload.cbr.ratio); + break; + + case ppt_tsc: + ShowMessages(" %-8s tsc=0x%llx\n", PtHelperPacketName(Packet.type), (UINT64)Packet.payload.tsc.tsc); + break; + + default: + // ShowMessages(" %-8s\n", PtHelperPacketName(Packet.type)); + break; + } + } + } + + pt_pkt_free_decoder(Decoder); + return Count; +} + +/** + * @brief Decode PT instructions + * + * @param Cpu + * @param Buffer + * @param Size + * @param Ctx + * + * @return UINT64 + */ +UINT64 +PtHelperDecodeCore(UINT32 Cpu, const UINT8 * Buffer, UINT64 Size, IMAGE_SYMBOL_CONTEXT * Ctx) +{ + struct pt_config Config; + struct pt_insn_decoder * Decoder; + struct pt_image * Image; + UINT64 Count = 0; + int Status; + + pt_config_init(&Config); + Config.begin = (UINT8 *)Buffer; + Config.end = (UINT8 *)Buffer + Size; + + Decoder = pt_insn_alloc_decoder(&Config); + if (Decoder == NULL) + { + ShowMessages("[-] core %u: cannot allocate instruction decoder\n", Cpu); + return 0; + } + + Image = pt_insn_get_image(Decoder); + pt_image_set_callback(Image, PtHelperReadImage, Ctx); + + for (;;) + { + Status = pt_insn_sync_forward(Decoder); + if (Status < 0) + break; + + for (;;) + { + struct pt_insn Insn; + + while (Status & pts_event_pending) + { + struct pt_event Event; + Status = pt_insn_event(Decoder, &Event, sizeof(Event)); + if (Status < 0) + break; + } + + if (Status < 0 || (Status & pts_eos)) + break; + + Status = pt_insn_next(Decoder, &Insn, sizeof(Insn)); + if (Status < 0) + break; + + ZydisDisassembledInstruction Disasm; + ZydisMachineMode Mode = (Insn.mode == ptem_32bit) ? ZYDIS_MACHINE_MODE_LEGACY_32 : ZYDIS_MACHINE_MODE_LONG_64; + + if (ZYAN_SUCCESS(ZydisDisassembleIntel(Mode, Insn.ip, Insn.raw, Insn.size, &Disasm))) + ShowMessages(" 0x%016llx exe+0x%-6llx %s\n", + (UINT64)Insn.ip, + (UINT64)(Insn.ip - Ctx->ImageBase), + Disasm.text); + else + ShowMessages(" 0x%016llx (undecodable)\n", (UINT64)Insn.ip); + + Count++; + } + + if (Status >= 0 && (Status & pts_eos)) + break; + } + + pt_insn_free_decoder(Decoder); + return Count; +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/misc/readmem.cpp b/hyperdbg/libhyperdbg/code/debugger/misc/readmem.cpp similarity index 50% rename from hyperdbg/hprdbgctrl/code/debugger/misc/readmem.cpp rename to hyperdbg/libhyperdbg/code/debugger/misc/readmem.cpp index de387945..4cfcf555 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/misc/readmem.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/misc/readmem.cpp @@ -15,11 +15,170 @@ // // Global Variables // +extern BOOLEAN g_IsKdModuleLoaded; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; /** * @brief Read memory and disassembler * + * @param TargetAddress location of where to read the memory + * @param MemoryType type of memory (phyical or virtual) + * @param ReadingType read from kernel or vmx-root + * @param Pid The target process id + * @param Size size of memory to read + * @param GetAddressMode check for address mode + * @param AddressMode Address mode (32 or 64) + * @param TargetBufferToStore The buffer to store the read memory + * @param ReturnLength The length of the read memory + * + * @return BOOLEAN TRUE if the operation was successful, otherwise FALSE + */ +BOOLEAN +HyperDbgReadMemory(UINT64 TargetAddress, + DEBUGGER_READ_MEMORY_TYPE MemoryType, + DEBUGGER_READ_READING_TYPE ReadingType, + UINT32 Pid, + UINT32 Size, + BOOLEAN GetAddressMode, + DEBUGGER_READ_MEMORY_ADDRESS_MODE * AddressMode, + BYTE * TargetBufferToStore, + UINT32 * ReturnLength) +{ + BOOL Status; + ULONG ReturnedLength; + DEBUGGER_READ_MEMORY ReadMem = {0}; + UINT32 SizeOfTargetBuffer; + + // + // Check if driver is loaded if it's in local debugging mode + // + if (!g_IsSerialConnectedToRemoteDebuggee) + { + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + } + + // + // Fill the read memory structure + // + ReadMem.Address = TargetAddress; + ReadMem.Pid = Pid; + ReadMem.Size = Size; + ReadMem.MemoryType = MemoryType; + ReadMem.ReadingType = ReadingType; + ReadMem.GetAddressMode = GetAddressMode; + + // + // allocate buffer for transferring messages + // + SizeOfTargetBuffer = sizeof(DEBUGGER_READ_MEMORY) + (Size * sizeof(CHAR)); + DEBUGGER_READ_MEMORY * MemReadRequest = (DEBUGGER_READ_MEMORY *)malloc(SizeOfTargetBuffer); + + // + // Check if the buffer is allocated successfully + // + if (MemReadRequest == NULL) + { + return FALSE; + } + + ZeroMemory(MemReadRequest, SizeOfTargetBuffer); + + // + // Copy the buffer to send + // + memcpy(MemReadRequest, &ReadMem, sizeof(DEBUGGER_READ_MEMORY)); + + // + // Check if this is used for Debugger Mode or VMI mode + // + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // It's on Debugger mode + // + if (!KdSendReadMemoryPacketToDebuggee(MemReadRequest, SizeOfTargetBuffer)) + { + std::free(MemReadRequest); + return FALSE; + } + } + else + { + // + // It's on local debugging mode + // + Status = DeviceIoControl(g_DeviceHandle, // Handle to device + IOCTL_DEBUGGER_READ_MEMORY, // IO Control Code (IOCTL) + MemReadRequest, // Input Buffer to driver. + SIZEOF_DEBUGGER_READ_MEMORY, // Input buffer length + MemReadRequest, // Output Buffer from driver. + SizeOfTargetBuffer, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + std::free(MemReadRequest); + return FALSE; + } + } + + // + // Check if reading memory was successful or not + // + if (MemReadRequest->KernelStatus != DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + ShowErrorMessage(MemReadRequest->KernelStatus); + std::free(MemReadRequest); + return FALSE; + } + else + { + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Change the ReturnedLength as it contains the headers + // + *ReturnLength = MemReadRequest->ReturnLength; + } + else + { + // + // Change the ReturnedLength as it contains the headers + // + ReturnedLength -= SIZEOF_DEBUGGER_READ_MEMORY; + *ReturnLength = ReturnedLength; + } + + // + // Set address mode (if requested) + // + if (GetAddressMode) + { + *AddressMode = MemReadRequest->AddressMode; + } + + // + // Copy the buffer + // + memcpy(TargetBufferToStore, + ((UCHAR *)MemReadRequest) + sizeof(DEBUGGER_READ_MEMORY), + *ReturnLength); + + // + // free the buffer + // + std::free(MemReadRequest); + + return TRUE; + } +} + +/** + * @brief Show memory or disassembler + * * @param Style style of show memory (as byte, dwrod, qword) * @param Address location of where to read the memory * @param MemoryType type of memory (phyical or virtual) @@ -31,26 +190,19 @@ extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; * @return VOID */ VOID -HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, - UINT64 Address, - DEBUGGER_READ_MEMORY_TYPE MemoryType, - DEBUGGER_READ_READING_TYPE ReadingType, - UINT32 Pid, - UINT32 Size, - PDEBUGGER_DT_COMMAND_OPTIONS DtDetails) +HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, + UINT64 Address, + DEBUGGER_READ_MEMORY_TYPE MemoryType, + DEBUGGER_READ_READING_TYPE ReadingType, + UINT32 Pid, + UINT32 Size, + PDEBUGGER_DT_COMMAND_OPTIONS DtDetails) { - BOOL Status; - ULONG ReturnedLength; - DEBUGGER_READ_MEMORY ReadMem = {0}; - UINT32 SizeOfTargetBuffer; - - ReadMem.Address = Address; - ReadMem.Pid = Pid; - ReadMem.Size = Size; - ReadMem.MemoryType = MemoryType; - ReadMem.ReadingType = ReadingType; - ReadMem.Style = Style; - ReadMem.DtDetails = DtDetails; + UINT32 ReturnedLength; + UCHAR * Buffer; + DEBUGGER_READ_MEMORY_ADDRESS_MODE AddressMode; + BOOLEAN CheckForAddressMode = FALSE; + BOOLEAN Status = FALSE; // // Check if this is used for disassembler or not @@ -58,68 +210,55 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, if (Style == DEBUGGER_SHOW_COMMAND_DISASSEMBLE64 || Style == DEBUGGER_SHOW_COMMAND_DISASSEMBLE32) { - ReadMem.IsForDisasm = TRUE; + CheckForAddressMode = TRUE; } else { - ReadMem.IsForDisasm = FALSE; + CheckForAddressMode = FALSE; } // - // send the request + // Allocate buffer for output // - if (g_IsSerialConnectedToRemoteDebuggee) - { - KdSendReadMemoryPacketToDebuggee(&ReadMem); - return; - } + Buffer = (UCHAR *)malloc(Size); // - // It's on VMI mode + // Perform reading memory // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); - - // - // allocate buffer for transferring messages - // - SizeOfTargetBuffer = (Size * sizeof(CHAR)) + sizeof(DEBUGGER_READ_MEMORY); - unsigned char * OutputBuffer = (unsigned char *)malloc(SizeOfTargetBuffer); - - ZeroMemory(OutputBuffer, SizeOfTargetBuffer); - - Status = DeviceIoControl(g_DeviceHandle, // Handle to device - IOCTL_DEBUGGER_READ_MEMORY, // IO Control Code (IOCTL) - &ReadMem, // Input Buffer to driver. - SIZEOF_DEBUGGER_READ_MEMORY, // Input buffer length - OutputBuffer, // Output Buffer from driver. - SizeOfTargetBuffer, // Length of output buffer in bytes. - &ReturnedLength, // Bytes placed in buffer. - NULL // synchronous call - ); - - if (!Status) - { - ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); - std::free(OutputBuffer); - return; - } + Status = HyperDbgReadMemory(Address, + MemoryType, + ReadingType, + Pid, + Size, + CheckForAddressMode, + &AddressMode, + (BYTE *)Buffer, + &ReturnedLength); // // Check if reading memory was successful or not // - if (((PDEBUGGER_READ_MEMORY)OutputBuffer)->KernelStatus != DEBUGGER_OPERATION_WAS_SUCCESSFUL) + if (!Status) { - std::free(OutputBuffer); - ShowErrorMessage(((PDEBUGGER_READ_MEMORY)OutputBuffer)->KernelStatus); + // + // Check for extra message for the dump command + // + if (Style == DEBUGGER_SHOW_COMMAND_DUMP) + { + ShowMessages("HyperDbg attempted to access an invalid target address: 0x%llx\n" + "if you are confident that the address is valid, it may be paged out " + "or not yet available in the current CR3 page table\n" + "you can use the '.pagein' command to load this page table into memory and " + "trigger a page fault (#PF), please refer to the documentation for further details\n\n", + Address); + } + + // + // free the buffer + // + std::free(Buffer); return; } - else - { - // - // Change the ReturnedLength as it contains the headers - // - ReturnedLength -= SIZEOF_DEBUGGER_READ_MEMORY; - } switch (Style) { @@ -133,7 +272,7 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, ScriptEngineShowDataBasedOnSymbolTypesWrapper(DtDetails->TypeName, Address, FALSE, - ((unsigned char *)OutputBuffer) + sizeof(DEBUGGER_READ_MEMORY), + Buffer, DtDetails->AdditionalParameters); } else if (ReturnedLength == 0) @@ -150,7 +289,7 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, case DEBUGGER_SHOW_COMMAND_DB: ShowMemoryCommandDB( - ((unsigned char *)OutputBuffer) + sizeof(DEBUGGER_READ_MEMORY), + Buffer, Size, Address, MemoryType, @@ -161,7 +300,7 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, case DEBUGGER_SHOW_COMMAND_DC: ShowMemoryCommandDC( - ((unsigned char *)OutputBuffer) + sizeof(DEBUGGER_READ_MEMORY), + Buffer, Size, Address, MemoryType, @@ -172,7 +311,7 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, case DEBUGGER_SHOW_COMMAND_DD: ShowMemoryCommandDD( - ((unsigned char *)OutputBuffer) + sizeof(DEBUGGER_READ_MEMORY), + Buffer, Size, Address, MemoryType, @@ -183,7 +322,7 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, case DEBUGGER_SHOW_COMMAND_DQ: ShowMemoryCommandDQ( - ((unsigned char *)OutputBuffer) + sizeof(DEBUGGER_READ_MEMORY), + Buffer, Size, Address, MemoryType, @@ -193,7 +332,7 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, case DEBUGGER_SHOW_COMMAND_DUMP: - CommandDumpSaveIntoFile(((unsigned char *)OutputBuffer) + sizeof(DEBUGGER_READ_MEMORY), Size); + CommandDumpSaveIntoFile(Buffer, Size); break; @@ -202,8 +341,7 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, // // Check if assembly mismatch occurred with the target address // - if (((PDEBUGGER_READ_MEMORY)OutputBuffer)->Is32BitAddress == TRUE && - MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS) + if (AddressMode == DEBUGGER_READ_ADDRESS_MODE_32_BIT && MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS) { ShowMessages("the target address seems to be located in a 32-bit program, if so, " "please consider using the 'u32' instead to utilize the 32-bit disassembler\n"); @@ -212,13 +350,20 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, // // Show diassembles // - HyperDbgDisassembler64( - ((unsigned char *)OutputBuffer) + sizeof(DEBUGGER_READ_MEMORY), - Address, - ReturnedLength, - 0, - FALSE, - NULL); + if (ReturnedLength != 0) + { + HyperDbgDisassembler64( + Buffer, + Address, + ReturnedLength, + 0, + FALSE, + NULL); + } + else + { + ShowMessages("err, invalid address\n"); + } break; @@ -227,8 +372,7 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, // // Check if assembly mismatch occurred with the target address // - if (((PDEBUGGER_READ_MEMORY)OutputBuffer)->Is32BitAddress == FALSE && - MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS) + if (AddressMode == DEBUGGER_READ_ADDRESS_MODE_64_BIT && MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS) { ShowMessages("the target address seems to be located in a 64-bit program, if so, " "please consider using the 'u' instead to utilize the 64-bit disassembler\n"); @@ -237,13 +381,20 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, // // Show diassembles // - HyperDbgDisassembler32( - ((unsigned char *)OutputBuffer) + sizeof(DEBUGGER_READ_MEMORY), - Address, - ReturnedLength, - 0, - FALSE, - NULL); + if (ReturnedLength != 0) + { + HyperDbgDisassembler32( + Buffer, + Address, + ReturnedLength, + 0, + FALSE, + NULL); + } + else + { + ShowMessages("err, invalid address\n"); + } break; } @@ -251,9 +402,7 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, // // free the buffer // - std::free(OutputBuffer); - - ShowMessages("\n"); + std::free(Buffer); } /** @@ -264,11 +413,13 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, * @param Address location of where to read the memory * @param MemoryType type of memory (phyical or virtual) * @param Length Length of memory to show + * + * @return VOID */ -void -ShowMemoryCommandDB(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length) +VOID +ShowMemoryCommandDB(UCHAR * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length) { - unsigned int Character; + UINT32 Character; for (UINT32 i = 0; i < Size; i += 16) { @@ -285,7 +436,7 @@ ShowMemoryCommandDB(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, D // // Print the hex code // - for (size_t j = 0; j < 16; j++) + for (SIZE_T j = 0; j < 16; j++) { // // check to see if the address is valid or not @@ -304,7 +455,7 @@ ShowMemoryCommandDB(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, D // Print the character // ShowMessages(" "); - for (size_t j = 0; j < 16; j++) + for (SIZE_T j = 0; j < 16; j++) { Character = (OutputBuffer[i + j]); if (isprint(Character)) @@ -332,11 +483,13 @@ ShowMemoryCommandDB(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, D * @param Address location of where to read the memory * @param MemoryType type of memory (phyical or virtual) * @param Length Length of memory to show + * + * @return VOID */ -void -ShowMemoryCommandDC(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length) +VOID +ShowMemoryCommandDC(UCHAR * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length) { - unsigned int Character; + UINT32 Character; for (UINT32 i = 0; i < Size; i += 16) { if (MemoryType == DEBUGGER_READ_PHYSICAL_ADDRESS) @@ -352,7 +505,7 @@ ShowMemoryCommandDC(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, D // // Print the hex code // - for (size_t j = 0; j < 16; j += 4) + for (SIZE_T j = 0; j < 16; j += 4) { // // check to see if the address is valid or not @@ -373,7 +526,7 @@ ShowMemoryCommandDC(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, D // ShowMessages(" "); - for (size_t j = 0; j < 16; j++) + for (SIZE_T j = 0; j < 16; j++) { Character = (OutputBuffer[i + j]); if (isprint(Character)) @@ -401,9 +554,11 @@ ShowMemoryCommandDC(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, D * @param Address location of where to read the memory * @param MemoryType type of memory (phyical or virtual) * @param Length Length of memory to show + * + * @return VOID */ -void -ShowMemoryCommandDD(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length) +VOID +ShowMemoryCommandDD(UCHAR * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length) { for (UINT32 i = 0; i < Size; i += 16) { @@ -420,7 +575,7 @@ ShowMemoryCommandDD(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, D // // Print the hex code // - for (size_t j = 0; j < 16; j += 4) + for (SIZE_T j = 0; j < 16; j += 4) { // // check to see if the address is valid or not @@ -450,9 +605,11 @@ ShowMemoryCommandDD(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, D * @param Address location of where to read the memory * @param MemoryType type of memory (phyical or virtual) * @param Length Length of memory to show + * + * @return VOID */ -void -ShowMemoryCommandDQ(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length) +VOID +ShowMemoryCommandDQ(UCHAR * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length) { for (UINT32 i = 0; i < Size; i += 16) { @@ -469,7 +626,7 @@ ShowMemoryCommandDQ(unsigned char * OutputBuffer, UINT32 Size, UINT64 Address, D // // Print the hex code // - for (size_t j = 0; j < 16; j += 8) + for (SIZE_T j = 0; j < 16; j += 8) { // // check to see if the address is valid or not diff --git a/hyperdbg/hprdbgctrl/code/debugger/script-engine/script-engine-wrapper.cpp b/hyperdbg/libhyperdbg/code/debugger/script-engine/script-engine-wrapper.cpp similarity index 73% rename from hyperdbg/hprdbgctrl/code/debugger/script-engine/script-engine-wrapper.cpp rename to hyperdbg/libhyperdbg/code/debugger/script-engine/script-engine-wrapper.cpp index 7fe6739e..cf32100a 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/script-engine/script-engine-wrapper.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/script-engine/script-engine-wrapper.cpp @@ -12,14 +12,17 @@ */ #include "pch.h" +// #define _SCRIPT_ENGINE_IR_PRINT_EN +// #define _SCRIPT_ENGINE_CODEEXEC_DBG_EN + // // Global Variables // extern UINT64 * g_ScriptGlobalVariables; -extern UINT64 * g_ScriptLocalVariables; -extern UINT64 * g_ScriptTempVariables; +extern UINT64 * g_ScriptStackBuffer; extern UINT64 g_CurrentExprEvalResult; extern BOOLEAN g_CurrentExprEvalResultHasError; +extern UINT64 * g_HwdbgPinsStatus; // // Temporary structures used only for testing @@ -48,7 +51,7 @@ typedef struct _ALLOCATED_MEMORY_FOR_SCRIPT_ENGINE_CASTING * @return UINT64 */ UINT64 -ScriptEngineConvertNameToAddressWrapper(const char * FunctionOrVariableName, PBOOLEAN WasFound) +ScriptEngineConvertNameToAddressWrapper(const CHAR * FunctionOrVariableName, PBOOLEAN WasFound) { return ScriptEngineConvertNameToAddress(FunctionOrVariableName, WasFound); } @@ -62,7 +65,7 @@ ScriptEngineConvertNameToAddressWrapper(const char * FunctionOrVariableName, PBO * @return UINT32 */ UINT32 -ScriptEngineLoadFileSymbolWrapper(UINT64 BaseAddress, const char * PdbFileName, const char * CustomModuleName) +ScriptEngineLoadFileSymbolWrapper(UINT64 BaseAddress, const CHAR * PdbFileName, const CHAR * CustomModuleName) { return ScriptEngineLoadFileSymbol(BaseAddress, PdbFileName, CustomModuleName); } @@ -98,7 +101,7 @@ ScriptEngineUnloadAllSymbolsWrapper() * @return UINT32 */ UINT32 -ScriptEngineUnloadModuleSymbolWrapper(char * ModuleName) +ScriptEngineUnloadModuleSymbolWrapper(CHAR * ModuleName) { return ScriptEngineUnloadModuleSymbol(ModuleName); } @@ -111,7 +114,7 @@ ScriptEngineUnloadModuleSymbolWrapper(char * ModuleName) * @return UINT32 */ UINT32 -ScriptEngineSearchSymbolForMaskWrapper(const char * SearchMask) +ScriptEngineSearchSymbolForMaskWrapper(const CHAR * SearchMask) { return ScriptEngineSearchSymbolForMask(SearchMask); } @@ -154,7 +157,7 @@ ScriptEngineGetDataTypeSizeWrapper(CHAR * TypeName, UINT64 * TypeSize) * @return BOOLEAN */ BOOLEAN -ScriptEngineCreateSymbolTableForDisassemblerWrapper(void * CallbackFunction) +ScriptEngineCreateSymbolTableForDisassemblerWrapper(PVOID CallbackFunction) { return ScriptEngineCreateSymbolTableForDisassembler(CallbackFunction); } @@ -168,10 +171,10 @@ ScriptEngineCreateSymbolTableForDisassemblerWrapper(void * CallbackFunction) * @return BOOLEAN */ BOOLEAN -ScriptEngineConvertFileToPdbPathWrapper(const char * LocalFilePath, char * ResultPath) +ScriptEngineConvertFileToPdbPathWrapper(const CHAR * LocalFilePath, CHAR * ResultPath, SIZE_T ResultPathSize) { - return ScriptEngineConvertFileToPdbPath(LocalFilePath, ResultPath); + return ScriptEngineConvertFileToPdbPath(LocalFilePath, ResultPath, ResultPathSize); } /** @@ -189,7 +192,7 @@ BOOLEAN ScriptEngineSymbolInitLoadWrapper(PMODULE_SYMBOL_DETAIL BufferToStoreDetails, UINT32 StoredLength, BOOLEAN DownloadIfAvailable, - const char * SymbolPath, + const CHAR * SymbolPath, BOOLEAN IsSilentLoad) { return ScriptEngineSymbolInitLoad(BufferToStoreDetails, StoredLength, DownloadIfAvailable, SymbolPath, IsSilentLoad); @@ -208,11 +211,11 @@ ScriptEngineSymbolInitLoadWrapper(PMODULE_SYMBOL_DETAIL BufferToStoreDetails, */ BOOLEAN ScriptEngineShowDataBasedOnSymbolTypesWrapper( - const char * TypeName, + const CHAR * TypeName, UINT64 Address, BOOLEAN IsStruct, PVOID BufferAddress, - const char * AdditionalParameters) + const CHAR * AdditionalParameters) { return ScriptEngineShowDataBasedOnSymbolTypes(TypeName, Address, IsStruct, BufferAddress, AdditionalParameters); } @@ -240,15 +243,45 @@ ScriptEngineSymbolAbortLoadingWrapper() * @return BOOLEAN */ BOOLEAN -ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetailsWrapper(const char * LocalFilePath, - char * PdbFilePath, - char * GuidAndAgeDetails, +ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetailsWrapper(const CHAR * LocalFilePath, + CHAR * PdbFilePath, + CHAR * GuidAndAgeDetails, BOOLEAN Is32BitModule) { return ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetails(LocalFilePath, PdbFilePath, GuidAndAgeDetails, Is32BitModule); } +/** + * @brief ScriptEngineConvertLoadedModuleToPdbFileAndGuidAndAgeDetails wrapper + * + * @param LoadedImageBytes + * @param LoadedImageSize + * @param LocalFilePath + * @param PdbFilePath + * @param GuidAndAgeDetails + * @param Is32BitModule + * + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineConvertLoadedModuleToPdbFileAndGuidAndAgeDetailsWrapper(const BYTE * LoadedImageBytes, + SIZE_T LoadedImageSize, + const CHAR * LocalFilePath, + CHAR * PdbFilePath, + CHAR * GuidAndAgeDetails, + BOOLEAN Is32BitModule) + +{ + return ScriptEngineConvertLoadedModuleToPdbFileAndGuidAndAgeDetails( + LoadedImageBytes, + LoadedImageSize, + LocalFilePath, + PdbFilePath, + GuidAndAgeDetails, + Is32BitModule); +} + // // *********************** Function links (wrapper) *********************** // @@ -262,10 +295,10 @@ ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetailsWrapper(const char * LocalFi * @return PVOID */ PVOID -ScriptEngineParseWrapper(char * Expr, BOOLEAN ShowErrorMessageIfAny) +ScriptEngineParseWrapper(CHAR * Expr, BOOLEAN ShowErrorMessageIfAny) { PSYMBOL_BUFFER SymbolBuffer; - SymbolBuffer = ScriptEngineParse(Expr); + SymbolBuffer = (PSYMBOL_BUFFER)ScriptEngineParse(Expr); // // Check if there is an error or not @@ -298,11 +331,11 @@ ScriptEngineParseWrapper(char * Expr, BOOLEAN ShowErrorMessageIfAny) VOID PrintSymbolBufferWrapper(PVOID SymbolBuffer) { - PrintSymbolBuffer((PSYMBOL_BUFFER)SymbolBuffer); + PrintSymbolBuffer(SymbolBuffer); } /** - * @brief test function + * @brief Script engine evaluation wrapper * @param GuestRegs * @param Expr * @@ -312,7 +345,7 @@ VOID ScriptEngineEvalWrapper(PGUEST_REGS GuestRegs, string Expr) { - SCRIPT_ENGINE_VARIABLES_LIST VariablesList = {0}; + SCRIPT_ENGINE_GENERAL_REGISTERS ScriptGeneralRegisters = {0}; // // Allocate global variables holder @@ -332,72 +365,52 @@ ScriptEngineEvalWrapper(PGUEST_REGS GuestRegs, } // - // Allocate local variables holder, actually in reality each core should - // have its own set of local variables but as we never run multi-core scripts - // in user-mode, thus, it's okay to just have one buffer for local variables + // Allocate stack buffer holder, actually in reality each core should + // have its own set of stack buffer but as we never run multi-core scripts + // in user-mode, thus, it's okay to just have one buffer for stack buffer // - if (!g_ScriptLocalVariables) + if (!g_ScriptStackBuffer) { - g_ScriptLocalVariables = (UINT64 *)malloc(MAX_VAR_COUNT * sizeof(UINT64)); + g_ScriptStackBuffer = (UINT64 *)malloc(MAX_STACK_BUFFER_COUNT * sizeof(UINT64)); - if (g_ScriptLocalVariables == NULL) + if (g_ScriptStackBuffer == NULL) { free(g_ScriptGlobalVariables); - ShowMessages("err, could not allocate memory for user-mode local variables"); + ShowMessages("err, could not allocate memory for user-mode stack buffer"); return; } - - RtlZeroMemory(g_ScriptLocalVariables, MAX_VAR_COUNT * sizeof(UINT64)); - } - - // - // Allocate temp variables holder, actually in reality each core should - // have its own set of temp variables but as we never run multi-core scripts - // in user-mode, thus, it's okay to just have one buffer for temp variables - // - if (!g_ScriptTempVariables) - { - g_ScriptTempVariables = (UINT64 *)malloc(MAX_TEMP_COUNT * sizeof(UINT64)); - - if (g_ScriptTempVariables == NULL) - { - free(g_ScriptGlobalVariables); - free(g_ScriptLocalVariables); - - ShowMessages("err, could not allocate memory for user-mode temp variables"); - - return; - } - - RtlZeroMemory(g_ScriptTempVariables, MAX_TEMP_COUNT * sizeof(UINT64)); } // // Run Parser // - PSYMBOL_BUFFER CodeBuffer = ScriptEngineParse((char *)Expr.c_str()); + PSYMBOL_BUFFER CodeBuffer = (PSYMBOL_BUFFER)ScriptEngineParse((char *)Expr.c_str()); +#ifdef _SCRIPT_ENGINE_IR_PRINT_EN // // Print symbol buffer // - // PrintSymbolBuffer(CodeBuffer); + PrintSymbolBuffer((PVOID)CodeBuffer); +#endif ACTION_BUFFER ActionBuffer = {0}; SYMBOL ErrorSymbol = {0}; - // - // - // - PSYMBOL_BUFFER StackBuffer = GetStackBuffer(); - int StackIndx = 0; - int StackBaseIndx = 0; - int StackTempBaseIndx = 0; + UINT64 EXECUTENUMBER = 0; + + ScriptGeneralRegisters.StackBuffer = g_ScriptStackBuffer; + ScriptGeneralRegisters.GlobalVariablesList = g_ScriptGlobalVariables; + RtlZeroMemory(g_ScriptStackBuffer, MAX_STACK_BUFFER_COUNT * sizeof(UINT64)); if (CodeBuffer->Message == NULL) { - for (UINT64 i = 0; i < CodeBuffer->Pointer;) +#ifdef _SCRIPT_ENGINE_CODEEXEC_DBG_EN + printf("\nScriptEngineExecute:\n"); +#endif + UINT64 i = 0; + for (; i < CodeBuffer->Pointer;) { // // Fill the action buffer but as we're in user-mode here @@ -408,36 +421,57 @@ ScriptEngineEvalWrapper(PGUEST_REGS GuestRegs, ActionBuffer.ImmediatelySendTheResults = FALSE; ActionBuffer.Tag = NULL; - // - // Fill the variables list for this run - // - VariablesList.TempList = g_ScriptTempVariables; - VariablesList.GlobalVariablesList = g_ScriptGlobalVariables; - VariablesList.LocalVariablesList = g_ScriptLocalVariables; +#ifdef _SCRIPT_ENGINE_CODEEXEC_DBG_EN + printf("Address = %lld, StackIndx = %lld, StackBaseIndx = %lld\n", i, ScriptGeneralRegisters.StackIndx, ScriptGeneralRegisters.StackBaseIndx); + PSYMBOL Operator = (PSYMBOL)((UINT64)CodeBuffer->Head + + (UINT64)(i * sizeof(SYMBOL))); + printf("Function = %s\n", FunctionNames[Operator->Value]); + printf("Stack Buffer:\n"); + for (UINT64 j = 0; j < ScriptGeneralRegisters.StackIndx; j++) + { + printf("StackIndx = %lld, Value = %lld", j, ScriptGeneralRegisters.StackBuffer[j]); + + if (j == ScriptGeneralRegisters.StackBaseIndx) + { + printf(" <===== StackBaseIndx"); + } + printf("\n"); + } + printf("\n"); +#endif // // If has error, show error message and abort // if (ScriptEngineExecute(GuestRegs, &ActionBuffer, - &VariablesList, + &ScriptGeneralRegisters, CodeBuffer, &i, - StackBuffer, - &StackIndx, - &StackBaseIndx, - &StackTempBaseIndx, &ErrorSymbol) == TRUE) { - CHAR NameOfOperator[MAX_FUNCTION_NAME_LENGTH] = {0}; - - ScriptEngineGetOperatorName(&ErrorSymbol, NameOfOperator); - ShowMessages("invalid returning address for operator: %s", - NameOfOperator); + ShowMessages("err, ScriptEngineExecute, function = %s\n", + FunctionNames[ErrorSymbol.Value]); g_CurrentExprEvalResultHasError = TRUE; g_CurrentExprEvalResult = NULL; break; } + else if (ScriptGeneralRegisters.StackIndx >= MAX_STACK_BUFFER_COUNT) + { + ShowMessages("err, stack buffer overflow (more information: https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/change-script-engine-limitations)\n"); + g_CurrentExprEvalResultHasError = TRUE; + g_CurrentExprEvalResult = NULL; + break; + } + else if (EXECUTENUMBER >= MAX_EXECUTION_COUNT) + { + ShowMessages("err, exceeding the max execution count (more information: https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/change-script-engine-limitations)\n"); + g_CurrentExprEvalResultHasError = TRUE; + g_CurrentExprEvalResult = NULL; + break; + } + + EXECUTENUMBER++; } } else @@ -663,12 +697,12 @@ ScriptEngineWrapperTestParser(const string & Expr) GUEST_REGS GuestRegs = {0}; - char test[] = "Hello world !"; - wchar_t testw[] = + CHAR test[] = "Hello world !"; + WCHAR testw[] = L"A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 " L"9 a b c d e f g h i j k l m n o p q r s t u v w x y z"; - char * RspReg = (char *)malloc(0x100); + CHAR * RspReg = (CHAR *)malloc(0x100); if (RspReg == NULL) { @@ -708,6 +742,32 @@ ScriptEngineWrapperTestParser(const string & Expr) free(AllocationsForCastings.Buff6); } +/** + * @brief test parser for hwdbg + * @param Expr + * + * @return VOID + */ +VOID +ScriptEngineWrapperTestParserForHwdbg(const string & Expr) +{ + if (!g_HwdbgPinsStatus) + { + g_HwdbgPinsStatus = (UINT64 *)malloc(MAX_HWDBG_TESTING_PIN_COUNT * sizeof(UINT64)); + + if (g_HwdbgPinsStatus == NULL) + { + ShowMessages("err, could not allocate memory for hwdbg pins status"); + + return; + } + + RtlZeroMemory(g_HwdbgPinsStatus, MAX_HWDBG_TESTING_PIN_COUNT * sizeof(UINT64)); + } + + ScriptEngineEvalWrapper((PGUEST_REGS)g_HwdbgPinsStatus, Expr); +} + /** * @brief In the local debugging (VMI mode) environment, this function computes the expressions * @details for example, if the user u ExAllocatePoolWithTag+0x10 this will evaluate the expr diff --git a/hyperdbg/libhyperdbg/code/debugger/script-engine/script-engine.cpp b/hyperdbg/libhyperdbg/code/debugger/script-engine/script-engine.cpp new file mode 100644 index 00000000..73b07f71 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/script-engine/script-engine.cpp @@ -0,0 +1,198 @@ +/** + * @file script-engine.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Interpret script engine affairs + * @details + * @version 0.1 + * @date 2021-09-23 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern UINT64 g_ResultOfEvaluatedExpression; +extern UINT32 g_ErrorStateOfResultOfEvaluatedExpression; +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; + +/** + * @brief Get the value from the evaluation of single expression + * from local debuggee and remote debuggee + * + * @param Expr + * @param HasError + * @return UINT64 + */ +UINT64 +ScriptEngineEvalSingleExpression(string Expr, PBOOLEAN HasError) +{ + UINT64 Result = NULL; + + // + // Prepend and append 'formats(' and ')' + // + Expr.insert(0, "formats("); + Expr.append(");"); + + if (g_IsSerialConnectedToRemoteDebuggee || g_ActiveProcessDebuggingState.IsActive) + { + // + // Send data to the target user debugger or kernel debugger + // + if (!ScriptEngineExecuteSingleExpression((CHAR *)Expr.c_str(), TRUE, TRUE)) + { + *HasError = TRUE; + return NULL; + } + + // + // Check whether there was an error in evaluation or not + // + if (g_ErrorStateOfResultOfEvaluatedExpression == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // + // Everything was fine, return the result of the evaluated + // expression and null the global holders + // + Result = g_ResultOfEvaluatedExpression; + g_ErrorStateOfResultOfEvaluatedExpression = NULL; + g_ResultOfEvaluatedExpression = NULL; + *HasError = FALSE; + } + else + { + // + // There was an error evaluating the expression from the kernel (debuggee) + // + g_ErrorStateOfResultOfEvaluatedExpression = NULL; + g_ResultOfEvaluatedExpression = NULL; + + *HasError = TRUE; + Result = NULL; + } + } + else + { + // + // It's in vmi-mode, + // execute it locally with regs set to ZERO + // + Result = ScriptEngineEvalUInt64StyleExpressionWrapper(Expr, HasError); + } + + return Result; +} + +/** + * @brief Execute single expression for the kernel debugger and the user-mode debugger + * + * @param Expr + * @param ShowErrorMessageIfAny + * @param IsFormat If it's a format expression + * + * @return BOOLEAN Returns TRUE if it was successful + */ +BOOLEAN +ScriptEngineExecuteSingleExpression(CHAR * Expr, BOOLEAN ShowErrorMessageIfAny, BOOLEAN IsFormat) +{ + PVOID CodeBuffer; + UINT64 BufferAddress; + UINT32 BufferLength; + UINT32 Pointer; + BOOLEAN Result = FALSE; + + // + // Check whether a kernel debugger is connected or a user-mode debugger is active + // + if (!g_IsSerialConnectedToRemoteDebuggee && !g_ActiveProcessDebuggingState.IsActive) + { + if (ShowErrorMessageIfAny) + { + ShowMessages("err, you're not connected to any debuggee (neither user debugger nor kernel debugger)\n"); + } + return FALSE; + } + + // + // Check if the user-mode debuggee is paused + // + if (g_ActiveProcessDebuggingState.IsActive && !g_ActiveProcessDebuggingState.IsPaused) + { + if (ShowErrorMessageIfAny) + { + ShowMessages("err, the target process is NOT paused, you should run 'pause' to pause it\n"); + } + return FALSE; + } + + // + // Run script engine handler + // + CodeBuffer = ScriptEngineParseWrapper(Expr, ShowErrorMessageIfAny); + + if (CodeBuffer == NULL) + { + // + // return to show that this item contains an error + // + return FALSE; + } + + // + // Print symbols (test) + // + // PrintSymbolBufferWrapper(CodeBuffer); + + // + // Set the buffer and length + // + BufferAddress = ScriptEngineWrapperGetHead(CodeBuffer); + BufferLength = ScriptEngineWrapperGetSize(CodeBuffer); + Pointer = ScriptEngineWrapperGetPointer(CodeBuffer); + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Send it to the remote debuggee (kernel debugger) + // + Result = KdSendScriptPacketToDebuggee(BufferAddress, + BufferLength, + Pointer, + IsFormat); + } + else if (g_ActiveProcessDebuggingState.IsActive) + { + // + // Send it to the user debugger + // + Result = UdSendScriptBufferToProcess( + g_ActiveProcessDebuggingState.ProcessDebuggingToken, + g_ActiveProcessDebuggingState.ThreadId, + BufferAddress, + BufferLength, + Pointer, + IsFormat); + } + else + { + // + // Not connected to any debuggee + // + ShowMessages("err, you're not connected to any debuggee (neither user debugger nor kernel debugger)\n"); + Result = FALSE; + } + + // + // Remove the buffer of script engine interpreted code + // + ScriptEngineWrapperRemoveSymbolBuffer(CodeBuffer); + + // + // Return result + // + return Result; +} diff --git a/hyperdbg/libhyperdbg/code/debugger/script-engine/symbol-linux.cpp b/hyperdbg/libhyperdbg/code/debugger/script-engine/symbol-linux.cpp new file mode 100644 index 00000000..2f7f65a4 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/script-engine/symbol-linux.cpp @@ -0,0 +1,107 @@ +/** + * @file symbol-linux.cpp + * @author Max Raulea (max.raulea@gmail.com) + * @brief Linux stub implementations of the symbol subsystem + * @details The Windows implementation uses DbgHelp + PDB files (symbol-parser/). + * Linux uses ELF/DWARF which requires a separate implementation. + * These stubs allow the library to compile and link on Linux while + * keeping all call sites intact. + * + * TODO: implement a real ELF/DWARF symbol parser for Linux + * (libdw / libelf / libbfd) and replace these stubs. + * + * @version 0.1 + * @date 2026-06-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#ifdef __linux__ + +VOID +SymbolBuildAndShowSymbolTable() +{ + ShowMessages("err, symbol table is not supported on Linux yet\n"); +} + +BOOLEAN +SymbolShowFunctionNameBasedOnAddress(UINT64 Address, PUINT64 UsedBaseAddress) +{ + return FALSE; +} + +BOOLEAN +SymbolLoadOrDownloadSymbols(BOOLEAN IsDownload, BOOLEAN SilentLoad) +{ + if (!SilentLoad) + ShowMessages("err, symbol loading is not supported on Linux yet\n"); + return FALSE; +} + +/** + * @brief Attempt to resolve a name or expression to an address. + * + * On Linux, full symbol resolution (ELF/DWARF) is not yet implemented. + * This stub handles the common case of a plain hex/decimal literal so that + * numeric addresses still work everywhere in the debugger. + */ +BOOLEAN +SymbolConvertNameOrExprToAddress(const string & TextToConvert, PUINT64 Result) +{ + try + { + *Result = std::stoull(TextToConvert, nullptr, 0); + return TRUE; + } + catch (...) + { + return FALSE; + } +} + +BOOLEAN +SymbolDeleteSymTable() +{ + return TRUE; +} + +BOOLEAN +SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, + PUINT32 StoredLength, + UINT32 UserProcessId, + BOOLEAN SendOverSerial) +{ + return FALSE; +} + +BOOLEAN +SymbolBuildAndUpdateSymbolTable(PMODULE_SYMBOL_DETAIL SymbolDetail) +{ + return FALSE; +} + +VOID +SymbolInitialReload() +{ +} + +BOOLEAN +SymbolLocalReload(UINT32 UserProcessId) +{ + return FALSE; +} + +VOID +SymbolPrepareDebuggerWithSymbolInfo(UINT32 UserProcessId) +{ +} + +BOOLEAN +SymbolReloadSymbolTableInDebuggerMode(UINT32 ProcessId) +{ + return FALSE; +} + +#endif // __linux__ diff --git a/hyperdbg/hprdbgctrl/code/debugger/script-engine/symbol.cpp b/hyperdbg/libhyperdbg/code/debugger/script-engine/symbol.cpp similarity index 67% rename from hyperdbg/hprdbgctrl/code/debugger/script-engine/symbol.cpp rename to hyperdbg/libhyperdbg/code/debugger/script-engine/symbol.cpp index 979cf373..bfb02fbe 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/script-engine/symbol.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/script-engine/symbol.cpp @@ -19,7 +19,6 @@ extern PMODULE_SYMBOL_DETAIL g_SymbolTable; extern UINT32 g_SymbolTableSize; extern UINT32 g_SymbolTableCurrentIndex; extern BOOLEAN g_IsExecutingSymbolLoadingRoutines; -extern BOOLEAN g_IsSerialConnectedToRemoteDebugger; extern BOOLEAN g_AddressConversion; extern std::map g_DisassemblerSymbolMap; @@ -86,10 +85,10 @@ SymbolPrepareDebuggerWithSymbolInfo(UINT32 UserProcessId) * @return VOID */ VOID -SymbolCreateDisassemblerMapCallback(UINT64 Address, - char * ModuleName, - char * ObjectName, - unsigned int ObjectSize) +SymbolCreateDisassemblerMapCallback(UINT64 Address, + CHAR * ModuleName, + CHAR * ObjectName, + UINT32 ObjectSize) { // // It has a string, should not be initialized with zero @@ -273,7 +272,7 @@ SymbolBuildAndShowSymbolTable() // // show packet details // - for (size_t i = 0; i < g_SymbolTableSize / sizeof(MODULE_SYMBOL_DETAIL); i++) + for (SIZE_T i = 0; i < g_SymbolTableSize / sizeof(MODULE_SYMBOL_DETAIL); i++) { ShowMessages("is pdb details available? : %s\n", g_SymbolTable[i].IsSymbolDetailsFound ? "true" : "false"); ShowMessages("is pdb a path instead of module name? : %s\n", g_SymbolTable[i].IsLocalSymbolPath ? "true" : "false"); @@ -424,6 +423,291 @@ SymbolConvertNameOrExprToAddress(const string & TextToConvert, PUINT64 Result) return IsFound; } +/** + * @brief Read user virtual memory of the debuggee process + * + * @param BaseAddress the base address to read from + * @param UserProcessId the target process id to read its memory + * @param ReadSize the size of bytes to read + * @param Bytes the output vector to receive the read bytes + * + * @return BOOLEAN shows whether the reading was successful or not + */ +static BOOLEAN +SymbolReadUserVirtualMemoryExact(UINT64 BaseAddress, UINT32 UserProcessId, UINT32 ReadSize, std::vector & Bytes) +{ + BOOL Status = FALSE; + ULONG ReturnedLength = 0; + if (ReadSize > 0xffffffffu - SIZEOF_DEBUGGER_READ_MEMORY) + { + return FALSE; + } + + UINT32 SizeOfTargetBuffer = SIZEOF_DEBUGGER_READ_MEMORY + ReadSize; + DEBUGGER_READ_MEMORY ReadMemoryRequest = {0}; + DEBUGGER_READ_MEMORY * MemReadRequest = NULL; + + Bytes.clear(); + + if (g_DeviceHandle == NULL || BaseAddress == 0 || UserProcessId == 0 || ReadSize == 0) + { + return FALSE; + } + + MemReadRequest = (DEBUGGER_READ_MEMORY *)malloc(SizeOfTargetBuffer); + if (MemReadRequest == NULL) + { + return FALSE; + } + + ReadMemoryRequest.Address = BaseAddress; + ReadMemoryRequest.Pid = UserProcessId; + ReadMemoryRequest.Size = ReadSize; + ReadMemoryRequest.MemoryType = DEBUGGER_READ_VIRTUAL_ADDRESS; + ReadMemoryRequest.ReadingType = READ_FROM_KERNEL; + + RtlZeroMemory(MemReadRequest, SizeOfTargetBuffer); + memcpy(MemReadRequest, &ReadMemoryRequest, sizeof(DEBUGGER_READ_MEMORY)); + + Status = DeviceIoControl(g_DeviceHandle, + IOCTL_DEBUGGER_READ_MEMORY, + MemReadRequest, + SIZEOF_DEBUGGER_READ_MEMORY, + MemReadRequest, + SizeOfTargetBuffer, + &ReturnedLength, + NULL); + + if (!Status || MemReadRequest->KernelStatus != DEBUGGER_OPERATION_WAS_SUCCESSFUL || ReturnedLength != SizeOfTargetBuffer) + { + free(MemReadRequest); + return FALSE; + } + + Bytes.resize(ReadSize); + memcpy(Bytes.data(), ((UCHAR *)MemReadRequest) + SIZEOF_DEBUGGER_READ_MEMORY, ReadSize); + + free(MemReadRequest); + return TRUE; +} + +/** + * @brief Check if the provided range is valid and update the required size to read if needed + * + * @param Offset the offset of the range to check + * @param Length the length of the range to check + * @param RequiredSize a pointer to the variable containing the current required size, which will be updated if the end of the range exceeds it + * + * @return BOOLEAN TRUE if the range is valid and RequiredSize is updated if needed, FALSE if the range is invalid (e.g., due to overflow) + */ +static BOOLEAN +SymbolAddLoadedImageReadRange(UINT32 Offset, UINT32 Length, UINT32 * RequiredSize) +{ + UINT32 EndOffset = 0; + + if (RequiredSize == NULL) + { + return FALSE; + } + + if (Length == 0) + { + return TRUE; + } + + if (Offset > 0xffffffffu - Length) + { + return FALSE; + } + + EndOffset = Offset + Length; + if (EndOffset > *RequiredSize) + { + *RequiredSize = EndOffset; + } + + return TRUE; +} + +/** + * @brief Check if the provided range is within the bounds of the loaded image bytes + * + * @param LoadedImageBytes the vector containing the bytes of the loaded image + * @param Offset the offset of the range to check + * @param Length the length of the range to check + * + * @return BOOLEAN TRUE if the range is within bounds, FALSE otherwise + */ +static BOOLEAN +SymbolLoadedImageHasRange(const std::vector & LoadedImageBytes, UINT32 Offset, UINT32 Length) +{ + return Length <= LoadedImageBytes.size() && Offset <= LoadedImageBytes.size() - Length; +} + +/** + * @brief Parse the headers of a loaded PE image from the provided bytes and extract the SizeOfImage and DebugDirectory details + * + * @param LoadedImagePrefix a vector containing the initial bytes of the loaded image, which should include at least the DOS header and NT headers + * @param SizeOfImage an output pointer to receive the SizeOfImage extracted from the optional header + * @param DebugDirectory an optional output pointer to receive the IMAGE_DATA_DIRECTORY entry for the debug directory if available (can be NULL if not needed) + * + * @return BOOLEAN TRUE if the headers were successfully parsed and SizeOfImage was extracted, FALSE otherwise (e.g., if the headers are invalid or incomplete) + */ +static BOOLEAN +SymbolGetLoadedImageHeaderDetails(const std::vector & LoadedImagePrefix, UINT32 * SizeOfImage, IMAGE_DATA_DIRECTORY * DebugDirectory) +{ + if (LoadedImagePrefix.size() < sizeof(IMAGE_DOS_HEADER) || SizeOfImage == NULL) + { + return FALSE; + } + + if (DebugDirectory != NULL) + { + RtlZeroMemory(DebugDirectory, sizeof(*DebugDirectory)); + } + + const IMAGE_DOS_HEADER * DosHeader = (const IMAGE_DOS_HEADER *)LoadedImagePrefix.data(); + if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE || DosHeader->e_lfanew < 0) + { + return FALSE; + } + + SIZE_T NtHeaderOffset = (SIZE_T)DosHeader->e_lfanew; + if (NtHeaderOffset > LoadedImagePrefix.size() || sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) > LoadedImagePrefix.size() - NtHeaderOffset) + { + return FALSE; + } + + const BYTE * NtHeaders = LoadedImagePrefix.data() + NtHeaderOffset; + if (*(const DWORD *)NtHeaders != IMAGE_NT_SIGNATURE) + { + return FALSE; + } + + const IMAGE_FILE_HEADER * FileHeader = (const IMAGE_FILE_HEADER *)(NtHeaders + sizeof(DWORD)); + SIZE_T OptionalHeaderOffset = NtHeaderOffset + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER); + + if (OptionalHeaderOffset > LoadedImagePrefix.size() || FileHeader->SizeOfOptionalHeader < sizeof(WORD) || + FileHeader->SizeOfOptionalHeader > LoadedImagePrefix.size() - OptionalHeaderOffset) + { + return FALSE; + } + + const BYTE * OptionalHeader = LoadedImagePrefix.data() + OptionalHeaderOffset; + WORD Magic = *(const WORD *)OptionalHeader; + + if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC && FileHeader->SizeOfOptionalHeader >= sizeof(IMAGE_OPTIONAL_HEADER32)) + { + const IMAGE_OPTIONAL_HEADER32 * OptionalHeader32 = (const IMAGE_OPTIONAL_HEADER32 *)OptionalHeader; + + *SizeOfImage = OptionalHeader32->SizeOfImage; + if (DebugDirectory != NULL && OptionalHeader32->NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_DEBUG) + { + *DebugDirectory = OptionalHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]; + } + + return TRUE; + } + + if (Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC && FileHeader->SizeOfOptionalHeader >= sizeof(IMAGE_OPTIONAL_HEADER64)) + { + const IMAGE_OPTIONAL_HEADER64 * OptionalHeader64 = (const IMAGE_OPTIONAL_HEADER64 *)OptionalHeader; + + *SizeOfImage = OptionalHeader64->SizeOfImage; + if (DebugDirectory != NULL && OptionalHeader64->NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_DEBUG) + { + *DebugDirectory = OptionalHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]; + } + + return TRUE; + } + + return FALSE; +} + +/** + * @brief Read the necessary bytes of a loaded user-mode module to extract the debug directory and code view information for symbol loading + * + * @param BaseAddress the base address of the loaded module in the user process + * @param UserProcessId the target process id to read its memory + * @param LoadedImageBytes an output vector to receive the bytes of the loaded image that are necessary for symbol extraction (should be cleared and filled by this function) + * + * @return BOOLEAN TRUE if the necessary bytes were successfully read, FALSE otherwise (e.g., if memory reading failed or headers are invalid) + */ +static BOOLEAN +SymbolReadLoadedUserModuleForCodeView(UINT64 BaseAddress, UINT32 UserProcessId, std::vector & LoadedImageBytes) +{ + static constexpr UINT32 InitialLoadedImagePrefixSize = 4 * 1024; + static constexpr UINT32 MaximumLoadedImageCodeViewReadSize = 4 * 1024 * 1024; + + UINT32 SizeOfImage = 0; + UINT32 RequiredSize = InitialLoadedImagePrefixSize; + IMAGE_DATA_DIRECTORY DebugDirectory = {0}; + + if (!SymbolReadUserVirtualMemoryExact(BaseAddress, UserProcessId, InitialLoadedImagePrefixSize, LoadedImageBytes)) + { + return FALSE; + } + + if (!SymbolGetLoadedImageHeaderDetails(LoadedImageBytes, &SizeOfImage, &DebugDirectory) || SizeOfImage == 0) + { + return TRUE; + } + + if (DebugDirectory.VirtualAddress == 0 || DebugDirectory.Size < sizeof(IMAGE_DEBUG_DIRECTORY) || + DebugDirectory.Size % sizeof(IMAGE_DEBUG_DIRECTORY) != 0) + { + return TRUE; + } + + if (!SymbolAddLoadedImageReadRange(DebugDirectory.VirtualAddress, DebugDirectory.Size, &RequiredSize) || + RequiredSize > SizeOfImage || + RequiredSize > MaximumLoadedImageCodeViewReadSize) + { + return TRUE; + } + + if (RequiredSize > LoadedImageBytes.size() && !SymbolReadUserVirtualMemoryExact(BaseAddress, UserProcessId, RequiredSize, LoadedImageBytes)) + { + return FALSE; + } + + if (SymbolLoadedImageHasRange(LoadedImageBytes, DebugDirectory.VirtualAddress, DebugDirectory.Size)) + { + const IMAGE_DEBUG_DIRECTORY * DebugEntries = (const IMAGE_DEBUG_DIRECTORY *)(LoadedImageBytes.data() + DebugDirectory.VirtualAddress); + DWORD DebugEntryCount = DebugDirectory.Size / sizeof(IMAGE_DEBUG_DIRECTORY); + + for (DWORD Index = 0; Index < DebugEntryCount; Index++) + { + const IMAGE_DEBUG_DIRECTORY * DebugEntry = &DebugEntries[Index]; + + if (DebugEntry->Type != IMAGE_DEBUG_TYPE_CODEVIEW || + DebugEntry->SizeOfData < sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD)) + { + continue; + } + + UINT32 NextRequiredSize = RequiredSize; + if (!SymbolAddLoadedImageReadRange(DebugEntry->AddressOfRawData, DebugEntry->SizeOfData, &NextRequiredSize) || + NextRequiredSize > SizeOfImage || + NextRequiredSize > MaximumLoadedImageCodeViewReadSize) + { + continue; + } + + RequiredSize = NextRequiredSize; + } + } + + if (RequiredSize <= LoadedImageBytes.size()) + { + LoadedImageBytes.resize(RequiredSize); + return TRUE; + } + + return SymbolReadUserVirtualMemoryExact(BaseAddress, UserProcessId, RequiredSize, LoadedImageBytes); +} + /** * @brief Delete and free structures and variables related to the symbols * @@ -474,18 +758,16 @@ SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, UINT32 UserProcessId, BOOLEAN SendOverSerial) { - PRTL_PROCESS_MODULES ModuleInfo; - NTSTATUS NtStatus; BOOLEAN Status; ULONG ReturnedLength; + PRTL_PROCESS_MODULES ModuleInfo = NULL; PMODULE_SYMBOL_DETAIL ModuleSymDetailArray = NULL; - char SystemRoot[MAX_PATH] = {0}; - char ModuleSymbolPath[MAX_PATH] = {0}; - char TempPath[MAX_PATH] = {0}; - char ModuleSymbolGuidAndAge[MAXIMUM_GUID_AND_AGE_SIZE] = {0}; + CHAR SystemRoot[MAX_PATH] = {0}; + CHAR ModuleSymbolPath[MAX_PATH] = {0}; + CHAR TempPath[MAX_PATH] = {0}; + CHAR ModuleSymbolGuidAndAge[MAXIMUM_GUID_AND_AGE_SIZE] = {0}; BOOLEAN IsSymbolPdbDetailAvailable = FALSE; BOOLEAN IsFreeUsermodeModulesBuffer = FALSE; - ULONG SysModuleInfoBufferSize = 0; UINT32 ModuleDetailsSize = 0; UINT32 ModulesCount = 0; PUSERMODE_LOADED_MODULE_DETAILS ModuleDetailsRequest = NULL; @@ -516,7 +798,7 @@ SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, transform(SystemRootString.begin(), SystemRootString.end(), SystemRootString.begin(), - [](unsigned char c) { return std::tolower(c); }); + [](UCHAR c) { return std::tolower(c); }); // // Remove system32 from the root @@ -528,37 +810,9 @@ SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, // Get kernel-mode modules information // ***************************************************************** // - - // - // Get required size of "RTL_PROCESS_MODULES" buffer - // - NtStatus = NtQuerySystemInformation(SystemModuleInformation, NULL, NULL, &SysModuleInfoBufferSize); - - // - // Allocate memory for the module list - // - ModuleInfo = (PRTL_PROCESS_MODULES)VirtualAlloc( - NULL, - SysModuleInfoBufferSize, - MEM_COMMIT | MEM_RESERVE, - PAGE_READWRITE); - - if (!ModuleInfo) + if (SymbolCheckAndAllocateModuleInformation(&ModuleInfo) == FALSE) { - ShowMessages("err, unable to allocate memory for module list (%x)\n", - GetLastError()); - return FALSE; - } - - if (!NT_SUCCESS( - NtStatus = NtQuerySystemInformation(SystemModuleInformation, - ModuleInfo, - SysModuleInfoBufferSize, - NULL))) - { - ShowMessages("err, unable to query module list (%#x)\n", NtStatus); - - VirtualFree(ModuleInfo, 0, MEM_RELEASE); + ShowMessages("err, unable to get module information\n"); return FALSE; } @@ -661,7 +915,7 @@ SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, // // check the module list // - if (ModuleCountRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + if (ModuleDetailsRequest->Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL) { // // Se the modules buffer @@ -681,7 +935,7 @@ SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, } else { - ShowErrorMessage(ModuleCountRequest.Result); + ShowErrorMessage(ModuleDetailsRequest->Result); free(ModuleDetailsRequest); break; } @@ -718,6 +972,8 @@ SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, { free(ModuleDetailsRequest); } + + free(ModuleInfo); return FALSE; } @@ -753,17 +1009,31 @@ SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, RtlZeroMemory(ModuleSymbolPath, sizeof(ModuleSymbolPath)); RtlZeroMemory(TempPath, sizeof(TempPath)); RtlZeroMemory(ModuleSymbolGuidAndAge, sizeof(ModuleSymbolGuidAndAge)); + std::vector LoadedImageBytes; // // Convert symbol path from unicode to ascii // wcstombs(TempPath, Modules[i].FilePath, MAX_PATH); - if (ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetailsWrapper( - TempPath, - ModuleSymbolPath, - ModuleSymbolGuidAndAge, - ModuleDetailsRequest->Is32Bit)) + if (SendOverSerial && Modules[i].BaseAddress != 0 && + SymbolReadLoadedUserModuleForCodeView(Modules[i].BaseAddress, UserProcessId, LoadedImageBytes) && + ScriptEngineConvertLoadedModuleToPdbFileAndGuidAndAgeDetailsWrapper(LoadedImageBytes.data(), + LoadedImageBytes.size(), + TempPath, + ModuleSymbolPath, + ModuleSymbolGuidAndAge, + ModuleDetailsRequest->Is32Bit)) + { + IsSymbolPdbDetailAvailable = TRUE; + + // ShowMessages("Hash : %s , Symbol path : %s\n", ModuleSymbolGuidAndAge, ModuleSymbolPath); + } + else if (ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetailsWrapper( + TempPath, + ModuleSymbolPath, + ModuleSymbolGuidAndAge, + ModuleDetailsRequest->Is32Bit)) { IsSymbolPdbDetailAvailable = TRUE; @@ -835,7 +1105,7 @@ SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, RtlZeroMemory(ModuleSymbolPath, sizeof(ModuleSymbolPath)); RtlZeroMemory(ModuleSymbolGuidAndAge, sizeof(ModuleSymbolGuidAndAge)); - string ModuleFullPath((const char *)ModuleInfo->Modules[i].FullPathName); + string ModuleFullPath((const CHAR *)ModuleInfo->Modules[i].FullPathName); if (ModuleFullPath.rfind("\\SystemRoot\\", 0) == 0) { @@ -903,7 +1173,7 @@ SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, // if (SendOverSerial) { - KdSendSymbolDetailPacket(&ModuleSymDetailArray[IndexInSymbolBuffer], i, ModuleInfo->NumberOfModules + ModulesCount); + KdSendSymbolDetailPacket(&ModuleSymDetailArray[IndexInSymbolBuffer], IndexInSymbolBuffer, ModuleInfo->NumberOfModules + ModulesCount); } } @@ -917,7 +1187,7 @@ SymbolBuildSymbolTable(PMODULE_SYMBOL_DETAIL * BufferToStoreDetails, *BufferToStoreDetails = ModuleSymDetailArray; *StoredLength = (ModuleInfo->NumberOfModules + ModulesCount) * sizeof(MODULE_SYMBOL_DETAIL); - VirtualFree(ModuleInfo, 0, MEM_RELEASE); + free(ModuleInfo); if (IsFreeUsermodeModulesBuffer) { @@ -1021,3 +1291,60 @@ SymbolReloadSymbolTableInDebuggerMode(UINT32 ProcessId) return FALSE; } } + +/** + * @brief Check and allocate module information + * @details The caller should free the buffer + * @param Modules + * + * @return BOOLEAN + */ +BOOLEAN +SymbolCheckAndAllocateModuleInformation(PRTL_PROCESS_MODULES * Modules) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + ULONG SysModuleInfoBufferSize = 0; + + // + // Enable Debug privilege to the current token + // + if (!WindowsSetDebugPrivilege()) + { + ShowMessages("err, couldn't set debug privilege\n"); + return FALSE; + } + + // + // Get required size of "RTL_PROCESS_MODULES" buffer + // + Status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, NULL, NULL, &SysModuleInfoBufferSize); + + // + // print the size of the buffer + // + // ShowMessages("size of the buffer : %x\n", SysModuleInfoBufferSize); + + *Modules = (PRTL_PROCESS_MODULES)malloc(SysModuleInfoBufferSize); + + if (*Modules == NULL) + { + ShowMessages("err, unable to allocate memory for module list (%x)\n", + GetLastError()); + return FALSE; + } + + // + // Get the module list + // + Status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, *Modules, SysModuleInfoBufferSize, NULL); + + if (!NT_SUCCESS(Status)) + { + ShowMessages("err, unable to query module list (%x)\n", Status); + free(*Modules); + + return FALSE; + } + + return TRUE; +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/tests/tests.cpp b/hyperdbg/libhyperdbg/code/debugger/tests/tests.cpp similarity index 70% rename from hyperdbg/hprdbgctrl/code/debugger/tests/tests.cpp rename to hyperdbg/libhyperdbg/code/debugger/tests/tests.cpp index 1af60beb..2516858d 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/tests/tests.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/tests/tests.cpp @@ -29,7 +29,7 @@ SetupTestName(_Inout_updates_bytes_all_(BufferLength) PCHAR TestLocation, HANDLE fileHandle; DWORD driverLocLen = 0; HMODULE ProcHandle = GetModuleHandle(NULL); - char * Pos; + CHAR * Pos; // // Get the current directory. @@ -72,12 +72,12 @@ SetupTestName(_Inout_updates_bytes_all_(BufferLength) PCHAR TestLocation, } // - // Insure driver file is in the specified directory. + // Insure test file is in the specified directory // if ((fileHandle = CreateFile(TestLocation, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { - ShowMessages("%s.exe is not loaded.\n", TEST_PROCESS_NAME); + ShowMessages("%s.exe is not loaded\n", TEST_PROCESS_NAME); // // Indicate failure. @@ -102,29 +102,25 @@ SetupTestName(_Inout_updates_bytes_all_(BufferLength) PCHAR TestLocation, /** * @brief Create a Process And Open Pipe Connection object * - * @param KernelInformation Details from kernel to create lookup table - * @param KernelInformationSize Size of KernelInformation * @param ConnectionPipeHandle Pointer to receive Pipe Handle * @param ThreadHandle Pointer to receive Thread Handle * @param ProcessHandle Pointer to receive Process Handle * @return BOOLEAN */ BOOLEAN -CreateProcessAndOpenPipeConnection(PVOID KernelInformation, - UINT32 KernelInformationSize, - PHANDLE ConnectionPipeHandle, +CreateProcessAndOpenPipeConnection(PHANDLE ConnectionPipeHandle, PHANDLE ThreadHandle, PHANDLE ProcessHandle) { HANDLE PipeHandle; BOOLEAN SentMessageResult; UINT32 ReadBytes; - char * BufferToRead; - char * BufferToSend; - char HandshakeBuffer[] = "Hello, Dear Test Process... Yes, I'm HyperDbg Debugger :)"; + CHAR * BufferToRead; + CHAR * BufferToSend; + CHAR HandshakeBuffer[] = "Hello, Dear Test Process... Yes, I'm HyperDbg Debugger :)"; PROCESS_INFORMATION ProcessInfo; STARTUPINFO StartupInfo; - char CmdArgs[] = TEST_PROCESS_NAME " im-hyperdbg"; + CHAR CmdArgs[] = TEST_PROCESS_NAME " im-hyperdbg"; PipeHandle = NamedPipeServerCreatePipe("\\\\.\\Pipe\\HyperDbgTests", TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE, @@ -137,8 +133,26 @@ CreateProcessAndOpenPipeConnection(PVOID KernelInformation, return FALSE; } - BufferToRead = (char *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); - BufferToSend = (char *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + BufferToRead = (CHAR *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + + if (!BufferToRead) + { + // + // Enable to allocate buffer + // + return FALSE; + } + + BufferToSend = (CHAR *)malloc(TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); + + if (!BufferToSend) + { + // + // Enable to allocate buffer + // + free(BufferToSend); + return FALSE; + } RtlZeroMemory(BufferToRead, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); RtlZeroMemory(BufferToSend, TEST_CASE_MAXIMUM_BUFFERS_TO_COMMUNICATE); @@ -164,7 +178,6 @@ CreateProcessAndOpenPipeConnection(PVOID KernelInformation, // // Test process not found // - free(BufferToRead); free(BufferToSend); @@ -247,47 +260,31 @@ CreateProcessAndOpenPipeConnection(PVOID KernelInformation, return FALSE; } - if (strcmp(BufferToRead, "Wow! I miss you... Would you plz send me the " - "kernel information?") == 0) + if (strcmp(BufferToRead, "Wow! I miss you... Would you plz send test cases?") == 0) { - { - // - // Send the kernel information - // - SentMessageResult = NamedPipeServerSendMessageToClient( - PipeHandle, - (char *)KernelInformation, - KernelInformationSize); + // + // Set the output handles + // + *ConnectionPipeHandle = PipeHandle; + *ThreadHandle = ProcessInfo.hThread; + *ProcessHandle = ProcessInfo.hProcess; - if (!SentMessageResult) - { - // - // error in sending - // + free(BufferToRead); + free(BufferToSend); - free(BufferToRead); - free(BufferToSend); - - return FALSE; - } - } + return TRUE; } - // - // Set the output handles - // - *ConnectionPipeHandle = PipeHandle; - *ThreadHandle = ProcessInfo.hThread; - *ProcessHandle = ProcessInfo.hProcess; + ShowMessages("err, could not handshake with the test process\n"); free(BufferToRead); free(BufferToSend); - return TRUE; + return FALSE; } else { - ShowMessages("the process could not be started\n"); + ShowMessages("err, the process could not be started\n"); free(BufferToRead); free(BufferToSend); @@ -302,6 +299,63 @@ CreateProcessAndOpenPipeConnection(PVOID KernelInformation, return FALSE; } +/** + * @brief Opens test process + * + * @param ThreadHandle Pointer to receive Thread Handle + * @param ProcessHandle Pointer to receive Process Handle + * @param Args Arguments + * + * @return BOOLEAN + */ +BOOLEAN +OpenHyperDbgTestProcess(PHANDLE ThreadHandle, + PHANDLE ProcessHandle, + CHAR * Args) +{ + PROCESS_INFORMATION ProcessInfo = {0}; + STARTUPINFO StartupInfo = {0}; + CHAR CmdArgs[MAX_PATH] = {0}; + + // + // the only compulsory field + // + StartupInfo.cb = sizeof(StartupInfo); + + // + // Set-up path + // + if (!SetupTestName(g_TestLocation, sizeof(g_TestLocation))) + { + return FALSE; + } + + // + // Format CmdArgs to include executable and its arguments + // + sprintf_s(CmdArgs, sizeof(CmdArgs), "\"%s\" %s", g_TestLocation, Args); + + // + // Open test process + // + if (CreateProcessA(NULL, CmdArgs, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo)) + { + // + // Set the output handles + // + *ThreadHandle = ProcessInfo.hThread; + *ProcessHandle = ProcessInfo.hProcess; + + return TRUE; + } + else + { + ShowMessages("err, CreateProcess failed with error %x\n", GetLastError()); + } + + return FALSE; +} + /** * @brief Close the pipe connection and the remote process * diff --git a/hyperdbg/hprdbgctrl/code/debugger/transparency/gaussian-rng.cpp b/hyperdbg/libhyperdbg/code/debugger/transparency/gaussian-rng.cpp similarity index 96% rename from hyperdbg/hprdbgctrl/code/debugger/transparency/gaussian-rng.cpp rename to hyperdbg/libhyperdbg/code/debugger/transparency/gaussian-rng.cpp index a45cd251..dff25845 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/transparency/gaussian-rng.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/transparency/gaussian-rng.cpp @@ -21,7 +21,7 @@ double Median(vector Cases) { - size_t Size = Cases.size(); + SIZE_T Size = Cases.size(); if (Size == 0) { @@ -52,7 +52,7 @@ template T Average(const vector & vec) { - size_t Sz; + SIZE_T Sz; T Mean; Sz = vec.size(); if (Sz == 1) @@ -122,11 +122,11 @@ Randn(double mu, double sigma) { double U1, U2, W, mult; static double X1, X2; - static int call = 0; + static INT Call = 0; - if (call == 1) + if (Call == 1) { - call = !call; + Call = !Call; return (mu + sigma * (double)X2); } @@ -141,7 +141,7 @@ Randn(double mu, double sigma) X1 = U1 * mult; X2 = U2 * mult; - call = !call; + Call = !Call; return (mu + sigma * (double)X1); } @@ -158,7 +158,7 @@ VOID GuassianGenerateRandom(vector Data, UINT64 * AverageOfData, UINT64 * StandardDeviationOfData, UINT64 * MedianOfData) { vector FinalData; - int CountOfOutliers = 0; + INT CountOfOutliers = 0; double Medians; double Mad; double StandardDeviation; diff --git a/hyperdbg/hprdbgctrl/code/debugger/transparency/transparency.cpp b/hyperdbg/libhyperdbg/code/debugger/transparency/transparency.cpp similarity index 87% rename from hyperdbg/hprdbgctrl/code/debugger/transparency/transparency.cpp rename to hyperdbg/libhyperdbg/code/debugger/transparency/transparency.cpp index 48250170..9e3f6b67 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/transparency/transparency.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/transparency/transparency.cpp @@ -16,13 +16,13 @@ using namespace std; /** * @brief get the difference clock cycles between two rdtsc(s) * - * @return unsigned long long + * @return UINT64 */ -unsigned long long +UINT64 TransparentModeRdtscDiffVmexit() { - unsigned long long ret, ret2; - int cpuid_result[4] = {0}; + UINT64 Ret, Ret2; + INT CpuidResult[4] = {0}; // // GCC @@ -33,7 +33,7 @@ TransparentModeRdtscDiffVmexit() // // Win32 // - ret = __rdtsc(); + Ret = CpuReadTsc(); /* vm exit forced here. it uses: eax = 0; cpuid; */ @@ -45,7 +45,7 @@ TransparentModeRdtscDiffVmexit() // // WIN32 // - __cpuid(cpuid_result, 0); + CpuCpuId(CpuidResult, 0); // // GCC @@ -56,44 +56,32 @@ TransparentModeRdtscDiffVmexit() // // WIN32 // - ret2 = __rdtsc(); + Ret2 = CpuReadTsc(); - return ret2 - ret; + return Ret2 - Ret; } /** * @brief get the difference clock cycles between rdtsc+cpuid+rdtsc * - * @return unsigned long long + * @return UINT64 */ -unsigned long long +UINT64 TransparentModeRdtscVmexitTracing() { - unsigned long long ret, ret2; - - // - // GCC - // - // __asm__ volatile("rdtsc" : "=a" (eax), "=d" (edx)); - // ret = ((unsigned long long)eax) | (((unsigned long long)edx) << 32); + UINT64 Ret, Ret2; // // WIN32 // - ret = __rdtsc(); - - // - // GCC - // - // __asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx)); - // ret2 = ((unsigned long long)eax) | (((unsigned long long)edx) << 32); + Ret = CpuReadTsc(); // // WIN32 // - ret2 = __rdtsc(); + Ret2 = CpuReadTsc(); - return ret2 - ret; + return Ret2 - Ret; } /** @@ -103,9 +91,9 @@ TransparentModeRdtscVmexitTracing() * @param Average a pointer to save average on it * @param StandardDeviation a pointer to standard deviation average on it * @param Median a pointer to save median on it - * @return int + * @return INT */ -int +INT TransparentModeCpuidTimeStampCounter(UINT64 * Average, UINT64 * StandardDeviation, UINT64 * Median) @@ -145,9 +133,9 @@ TransparentModeCpuidTimeStampCounter(UINT64 * Average, * @param Average a pointer to save average on it * @param StandardDeviation a pointer to standard deviation average on it * @param Median a pointer to save median on it - * @return int + * @return INT */ -int +INT TransparentModeRdtscEmulationDetection(UINT64 * Average, UINT64 * StandardDeviation, UINT64 * Median) diff --git a/hyperdbg/libhyperdbg/code/debugger/user-level/pe-parser.cpp b/hyperdbg/libhyperdbg/code/debugger/user-level/pe-parser.cpp new file mode 100644 index 00000000..ce0dfc4a --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/user-level/pe-parser.cpp @@ -0,0 +1,4655 @@ +/** + * @file pe-parser.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Portable Executable parser + * @details + * @version 0.1 + * @date 2021-12-26 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Returns a human-readable name for a PE subsystem identifier + * + * Maps the Subsystem field from IMAGE_OPTIONAL_HEADER to a descriptive string. + * Unknown subsystem values return "Unknown". + * + * @param Subsystem The Subsystem value from the PE optional header + * + * @return const CHAR* A static string describing the subsystem + */ +static const CHAR * +PeGetSubsystemName(WORD Subsystem) +{ + switch (Subsystem) + { + case IMAGE_SUBSYSTEM_NATIVE: + return "Device Driver(Native windows Process)"; + case IMAGE_SUBSYSTEM_WINDOWS_GUI: + return "Windows GUI"; + case IMAGE_SUBSYSTEM_WINDOWS_CUI: + return "Windows CLI"; + case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: + return "Windows CE GUI"; + default: + return "Unknown"; + } +} + +/** + * @brief Prints the set DLL characteristics flags from a PE optional header + * + * Iterates a table of known IMAGE_DLLCHARACTERISTICS_* flag values and prints + * the name of each flag that is set in DllCharacteristics, separated by commas. + * Prints "None" when no flags are set. + * + * @param DllCharacteristics The DllCharacteristics field from the PE optional header + */ +static VOID +PeShowDllCharacteristics(WORD DllCharacteristics) +{ + BOOLEAN AnyFlag = FALSE; + + struct DLL_CHARACTERISTIC_NAME + { + WORD Flag; + const CHAR * Name; + }; + + static const DLL_CHARACTERISTIC_NAME CommonDllCharacteristics[] = { + {IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA, "High Entropy VA"}, + {IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE, "Dynamic Base"}, + {IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY, "Force Integrity"}, + {IMAGE_DLLCHARACTERISTICS_NX_COMPAT, "NX Compatible"}, + {IMAGE_DLLCHARACTERISTICS_NO_ISOLATION, "No Isolation"}, + {IMAGE_DLLCHARACTERISTICS_NO_SEH, "No SEH"}, + {IMAGE_DLLCHARACTERISTICS_NO_BIND, "No Bind"}, + {IMAGE_DLLCHARACTERISTICS_APPCONTAINER, "AppContainer"}, + {IMAGE_DLLCHARACTERISTICS_WDM_DRIVER, "WDM Driver"}, + {IMAGE_DLLCHARACTERISTICS_GUARD_CF, "Guard CF"}, + {IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, "Terminal Server Aware"}, + }; + + for (UINT32 Index = 0; Index < RTL_NUMBER_OF(CommonDllCharacteristics); Index++) + { + if ((DllCharacteristics & CommonDllCharacteristics[Index].Flag) == CommonDllCharacteristics[Index].Flag) + { + ShowMessages("%s%s", AnyFlag ? ", " : "", CommonDllCharacteristics[Index].Name); + AnyFlag = TRUE; + } + } + + if (!AnyFlag) + { + ShowMessages("None"); + } +} + +/** + * @brief Prints the raw file offset corresponding to the PE entrypoint RVA + * + * Resolves AddressOfEntryPoint through the section table to obtain a file offset + * and prints it. Prints "not mapped" when the RVA cannot be resolved. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param AddressOfEntryPoint The AddressOfEntryPoint field from the PE optional header + */ +static VOID +PeShowEntrypointFileOffset(PPE_IMAGE_READER Reader, DWORD AddressOfEntryPoint) +{ + SIZE_T FileOffset = 0; + + if (PeImageReaderRvaToFileOffset(Reader, AddressOfEntryPoint, 1, &FileOffset)) + { + ShowMessages("\n%-36s%#llx", "Entrypoint file offset :", (UINT64)FileOffset); + } + else + { + ShowMessages("\n%-36s%s", "Entrypoint file offset :", "not mapped"); + } +} + +/** + * @brief Returns the name of a PE data directory by its index + * + * Maps IMAGE_DIRECTORY_ENTRY_* index values to descriptive strings using + * the standard ordering defined in the PE specification. Returns "Unknown" + * for indices at or beyond IMAGE_NUMBEROF_DIRECTORY_ENTRIES. + * + * @param Index Zero-based data directory index (IMAGE_DIRECTORY_ENTRY_*) + * + * @return const CHAR* A static string naming the data directory + */ +static const CHAR * +PeGetDataDirectoryName(UINT32 Index) +{ + static const CHAR * DirectoryNames[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] = { + "Export Table", + "Import Table", + "Resource Table", + "Exception Table", + "Certificate Table", + "Base Relocation Table", + "Debug", + "Architecture", + "Global Ptr", + "TLS Table", + "Load Config Table", + "Bound Import", + "Import Address Table", + "Delay Import Descriptor", + "CLR Runtime Header", + "Reserved", + }; + + if (Index < RTL_NUMBER_OF(DirectoryNames)) + { + return DirectoryNames[Index]; + } + + return "Unknown"; +} + +/** + * @brief Adds two DWORD values with overflow detection + * + * Returns FALSE without modifying Result when the addition would exceed MAXDWORD; + * otherwise writes the sum to *Result and returns TRUE. + * + * @param Left First operand + * @param Right Second operand + * @param Result Output pointer that receives the sum on success; must not be NULL + * + * @return BOOLEAN TRUE if the addition succeeded, FALSE on overflow or NULL pointer + */ +static BOOLEAN +PeAddDword(DWORD Left, DWORD Right, DWORD * Result) +{ + if (Result == NULL || Right > MAXDWORD - Left) + { + return FALSE; + } + + *Result = Left + Right; + return TRUE; +} + +/** + * @brief Adds two ULONGLONG values with overflow detection + * + * Returns FALSE without modifying Result when the addition would overflow a + * 64-bit unsigned integer; otherwise writes the sum to *Result and returns TRUE. + * + * @param Left First operand + * @param Right Second operand + * @param Result Output pointer that receives the sum on success; must not be NULL + * + * @return BOOLEAN TRUE if the addition succeeded, FALSE on overflow or NULL pointer + */ +static BOOLEAN +PeAddUlonglong(ULONGLONG Left, ULONGLONG Right, ULONGLONG * Result) +{ + if (Result == NULL || Right > (~((ULONGLONG)0) - Left)) + { + return FALSE; + } + + *Result = Left + Right; + return TRUE; +} + +/** + * @brief Comparator for sorting PE_RAW_SECTION_RANGE entries by ascending start offset + * + * Intended for use with qsort(). Entries with the same Start are further ordered + * by End in ascending order. + * + * @param Left Pointer to the first PE_RAW_SECTION_RANGE to compare + * @param Right Pointer to the second PE_RAW_SECTION_RANGE to compare + * + * @return INT Negative if Left < Right, positive if Left > Right, zero if equal + */ +static INT +PeCompareRawSectionRange(const VOID * Left, const VOID * Right) +{ + const PE_RAW_SECTION_RANGE * LeftRange = (const PE_RAW_SECTION_RANGE *)Left; + const PE_RAW_SECTION_RANGE * RightRange = (const PE_RAW_SECTION_RANGE *)Right; + + if (LeftRange->Start < RightRange->Start) + { + return -1; + } + + if (LeftRange->Start > RightRange->Start) + { + return 1; + } + + if (LeftRange->End < RightRange->End) + { + return -1; + } + + if (LeftRange->End > RightRange->End) + { + return 1; + } + + return 0; +} + +/** + * @brief Checks whether an RVA range is fully contained within another RVA range + * + * Both ranges are expressed as a base RVA and a size. Returns FALSE if any + * addition overflows or if [Rva, Rva+Size) extends outside [RangeRva, RangeRva+RangeSize). + * + * @param RangeRva Base RVA of the enclosing range + * @param RangeSize Size of the enclosing range in bytes + * @param Rva Base RVA of the range to test + * @param Size Size of the range to test in bytes + * + * @return BOOLEAN TRUE if [Rva, Rva+Size) lies entirely within [RangeRva, RangeRva+RangeSize) + */ +static BOOLEAN +PeRvaContainsRange(DWORD RangeRva, DWORD RangeSize, DWORD Rva, DWORD Size) +{ + DWORD RangeEnd = 0; + DWORD RvaEnd = 0; + + if (!PeAddDword(RangeRva, RangeSize, &RangeEnd) || !PeAddDword(Rva, Size, &RvaEnd)) + { + return FALSE; + } + + return Rva >= RangeRva && RvaEnd <= RangeEnd; +} + +/** + * @brief Returns a validated pointer into the image at the location mapped by an RVA + * + * Translates Rva to a raw file offset via PeImageReaderRvaToFileOffset and then + * validates the range through PeImageReaderGetPointerAtOffset. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param Rva Relative virtual address to look up + * @param Length Number of bytes that must be accessible at the resolved offset + * @param Pointer Output pointer set to the resolved image location on success; must not be NULL + * + * @return BOOLEAN TRUE on success, FALSE if the RVA cannot be resolved or is out of bounds + */ +static BOOLEAN +PeGetPointerAtRva(PPE_IMAGE_READER Reader, DWORD Rva, DWORD Length, const BYTE ** Pointer) +{ + SIZE_T FileOffset = 0; + + if (!PeImageReaderRvaToFileOffset(Reader, Rva, Length, &FileOffset)) + { + return FALSE; + } + + return PeImageReaderGetPointerAtOffset(Reader, FileOffset, Length, Pointer); +} + +typedef enum _PE_ASCII_STRING_STATUS +{ + PeAsciiStringInvalid, + PeAsciiStringOk, + PeAsciiStringTruncated, +} PE_ASCII_STRING_STATUS; + +/** + * @brief Reads an ASCII string from the image at the given RVA + * + * Reads up to MaxLength bytes starting at Rva, stopping at the first null + * terminator. Non-printable bytes are replaced with '.'. The output buffer is + * always null-terminated. Returns PeAsciiStringInvalid if any mapped byte + * cannot be resolved, PeAsciiStringOk when the null terminator is found within + * MaxLength, and PeAsciiStringTruncated otherwise. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param Rva Starting RVA of the string + * @param MaxLength Maximum number of bytes to scan + * @param Buffer Destination buffer for the null-terminated output + * @param BufferSize Size of Buffer in bytes; must be at least 1 + * + * @return PE_ASCII_STRING_STATUS Result indicating whether the string was read successfully + */ +static PE_ASCII_STRING_STATUS +PeReadAsciiStringAtRva(PPE_IMAGE_READER Reader, DWORD Rva, DWORD MaxLength, CHAR * Buffer, SIZE_T BufferSize) +{ + if (Buffer == NULL || BufferSize == 0 || MaxLength == 0) + { + return PeAsciiStringInvalid; + } + + Buffer[0] = '\0'; + + SIZE_T OutputIndex = 0; + for (DWORD Index = 0; Index < MaxLength; Index++) + { + DWORD CharacterRva = 0; + const BYTE * Character = NULL; + + if (!PeAddDword(Rva, Index, &CharacterRva) || !PeGetPointerAtRva(Reader, CharacterRva, 1, &Character)) + { + return PeAsciiStringInvalid; + } + + if (*Character == '\0') + { + return PeAsciiStringOk; + } + + if (OutputIndex + 1 < BufferSize) + { + Buffer[OutputIndex++] = (*Character >= 0x20 && *Character <= 0x7e) ? (CHAR)*Character : '.'; + Buffer[OutputIndex] = '\0'; + } + } + + return PeAsciiStringTruncated; +} + +/** + * @brief Returns a human-readable description of a PE_ASCII_STRING_STATUS value + * + * @param Status The status value returned by PeReadAsciiStringAtRva or related functions + * + * @return const CHAR* A static string describing the status + */ +static const CHAR * +PeAsciiStatusName(PE_ASCII_STRING_STATUS Status) +{ + switch (Status) + { + case PeAsciiStringInvalid: + return "invalid mapping"; + case PeAsciiStringTruncated: + return "truncated or unterminated"; + default: + return "readable"; + } +} + +/** + * @brief Converts an absolute virtual address to a relative virtual address + * + * Subtracts ImageBase from Va and checks that the difference fits in a DWORD. + * Returns FALSE when Va < ImageBase or when the difference exceeds MAXDWORD. + * + * @param Va Absolute virtual address to convert + * @param ImageBase Base address of the image + * @param Rva Output pointer that receives the RVA on success; must not be NULL + * + * @return BOOLEAN TRUE on success, FALSE when the conversion is not representable + */ +static BOOLEAN +PeVaToRva(ULONGLONG Va, ULONGLONG ImageBase, DWORD * Rva) +{ + ULONGLONG Difference = 0; + + if (Rva == NULL || Va < ImageBase) + { + return FALSE; + } + + Difference = Va - ImageBase; + if (Difference > MAXDWORD) + { + return FALSE; + } + + *Rva = (DWORD)Difference; + return TRUE; +} + +/** + * @brief Reads a DWORD from a byte buffer at the specified byte offset + * + * Uses CopyMemory to avoid strict-aliasing and alignment issues. + * + * @param Buffer Pointer to the source byte buffer + * @param Offset Byte offset within Buffer at which to read + * + * @return DWORD The 32-bit value read from Buffer + Offset + */ +static DWORD +PeReadDwordFromBuffer(const BYTE * Buffer, SIZE_T Offset) +{ + DWORD Value = 0; + + CopyMemory(&Value, Buffer + Offset, sizeof(Value)); + return Value; +} + +/** + * @brief Reads a WORD from a byte buffer at the specified byte offset + * + * Uses CopyMemory to avoid strict-aliasing and alignment issues. + * + * @param Buffer Pointer to the source byte buffer + * @param Offset Byte offset within Buffer at which to read + * + * @return WORD The 16-bit value read from Buffer + Offset + */ +static WORD +PeReadWordFromBuffer(const BYTE * Buffer, SIZE_T Offset) +{ + WORD Value = 0; + + CopyMemory(&Value, Buffer + Offset, sizeof(Value)); + return Value; +} + +/** + * @brief Reads a BYTE from a byte buffer at the specified byte offset + * + * Uses CopyMemory to provide a consistent read interface. + * + * @param Buffer Pointer to the source byte buffer + * @param Offset Byte offset within Buffer at which to read + * + * @return BYTE The 8-bit value read from Buffer + Offset + */ +static BYTE +PeReadByteFromBuffer(const BYTE * Buffer, SIZE_T Offset) +{ + BYTE Value = 0; + + CopyMemory(&Value, Buffer + Offset, sizeof(Value)); + return Value; +} + +/** + * @brief Reads a ULONGLONG from a byte buffer at the specified byte offset + * + * Uses CopyMemory to avoid strict-aliasing and alignment issues. + * + * @param Buffer Pointer to the source byte buffer + * @param Offset Byte offset within Buffer at which to read + * + * @return ULONGLONG The 64-bit value read from Buffer + Offset + */ +static ULONGLONG +PeReadQwordFromBuffer(const BYTE * Buffer, SIZE_T Offset) +{ + ULONGLONG Value = 0; + + CopyMemory(&Value, Buffer + Offset, sizeof(Value)); + return Value; +} + +/** + * @brief Reads a pointer-sized value from a load configuration structure + * + * Reads a DWORD when Is32Bit is TRUE (PE32 pointer), or a QWORD when FALSE + * (PE32+ pointer), returning the result as a ULONGLONG in both cases. + * + * @param Buffer Pointer to the load configuration byte buffer + * @param Offset Byte offset within Buffer of the field to read + * @param Is32Bit TRUE to read a 32-bit pointer, FALSE to read a 64-bit pointer + * + * @return ULONGLONG The pointer value widened to 64 bits + */ +static ULONGLONG +PeReadLoadConfigPointer(const BYTE * Buffer, SIZE_T Offset, BOOLEAN Is32Bit) +{ + return Is32Bit ? PeReadDwordFromBuffer(Buffer, Offset) : PeReadQwordFromBuffer(Buffer, Offset); +} + +/** + * @brief Reads an ASCII string from a raw byte pointer up to MaxLength bytes + * + * Scans StringPointer[0..MaxLength-1] for a null terminator. Non-printable + * bytes are replaced with '.'. The output is always null-terminated. + * Returns PeAsciiStringOk when the terminator is found, PeAsciiStringTruncated + * when MaxLength is exhausted without a terminator, and PeAsciiStringInvalid + * on NULL arguments. + * + * @param StringPointer Pointer to the source ASCII data; must not be NULL + * @param MaxLength Maximum number of bytes to scan + * @param Buffer Destination buffer for the null-terminated output + * @param BufferSize Size of Buffer in bytes; must be at least 1 + * + * @return PE_ASCII_STRING_STATUS Result indicating whether the string was read successfully + */ +static PE_ASCII_STRING_STATUS +PeReadAsciiStringFromBuffer(const BYTE * StringPointer, DWORD MaxLength, CHAR * Buffer, SIZE_T BufferSize) +{ + if (StringPointer == NULL || Buffer == NULL || BufferSize == 0 || MaxLength == 0) + { + return PeAsciiStringInvalid; + } + + Buffer[0] = '\0'; + + SIZE_T OutputIndex = 0; + for (DWORD Index = 0; Index < MaxLength; Index++) + { + if (StringPointer[Index] == '\0') + { + return PeAsciiStringOk; + } + + if (OutputIndex + 1 < BufferSize) + { + Buffer[OutputIndex++] = (StringPointer[Index] >= 0x20 && StringPointer[Index] <= 0x7e) ? (CHAR)StringPointer[Index] : '.'; + Buffer[OutputIndex] = '\0'; + } + } + + return PeAsciiStringTruncated; +} + +/** + * @brief Reads an ASCII string located at a fixed offset within a PE data directory + * + * Computes the target RVA as Directory->VirtualAddress + Offset, clamps the + * maximum read length to the remaining bytes in the directory, and delegates + * to PeReadAsciiStringAtRva. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param Directory Pointer to the data directory entry that contains the string + * @param Offset Byte offset within the directory at which the string begins + * @param MaxLength Maximum number of bytes to scan for the null terminator + * @param Buffer Destination buffer for the null-terminated output + * @param BufferSize Size of Buffer in bytes + * + * @return PE_ASCII_STRING_STATUS Result indicating whether the string was read successfully + */ +static PE_ASCII_STRING_STATUS +PeReadAsciiStringInDirectory(PPE_IMAGE_READER Reader, + const IMAGE_DATA_DIRECTORY * Directory, + DWORD Offset, + DWORD MaxLength, + CHAR * Buffer, + SIZE_T BufferSize) +{ + DWORD StringRva = 0; + + if (Directory == NULL || Offset >= Directory->Size || !PeAddDword(Directory->VirtualAddress, Offset, &StringRva)) + { + return PeAsciiStringInvalid; + } + + DWORD Remaining = Directory->Size - Offset; + return PeReadAsciiStringAtRva(Reader, StringRva, Remaining < MaxLength ? Remaining : MaxLength, Buffer, BufferSize); +} + +/** + * @brief Computes the standard PE file checksum + * + * Implements the algorithm used by the Windows PE loader: sums all 16-bit + * words of the image (treating the checksum field itself as zero), folds the + * carry, and adds the total image size. The result matches the value stored + * in the optional header CheckSum field for well-formed images. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param ChecksumOffset Raw file offset of the 4-byte checksum field (excluded from summation) + * @param Checksum Output pointer that receives the computed checksum on success + * + * @return BOOLEAN TRUE on success, FALSE on NULL arguments or invalid checksum offset + */ +static BOOLEAN +PeComputeChecksum(PPE_IMAGE_READER Reader, SIZE_T ChecksumOffset, DWORD * Checksum) +{ + ULONGLONG Sum = 0; + + if (Reader == NULL || Checksum == NULL || ChecksumOffset > Reader->ImageSize || sizeof(DWORD) > Reader->ImageSize - ChecksumOffset) + { + return FALSE; + } + + for (SIZE_T Offset = 0; Offset < Reader->ImageSize; Offset += sizeof(WORD)) + { + WORD Value = 0; + + if (Offset >= ChecksumOffset && Offset < ChecksumOffset + sizeof(DWORD)) + { + Value = 0; + } + else if (Offset + 1 < Reader->ImageSize) + { + CopyMemory(&Value, Reader->ImageBase + Offset, sizeof(Value)); + } + else + { + Value = Reader->ImageBase[Offset]; + } + + Sum += Value; + Sum = (Sum & 0xffff) + (Sum >> 16); + } + + Sum = (Sum & 0xffff) + (Sum >> 16); + *Checksum = (DWORD)Sum + (DWORD)Reader->ImageSize; + return TRUE; +} + +/** + * @brief Prints the stored and computed PE optional header checksums + * + * Displays HeaderChecksum as read from the optional header and, when the image + * is small enough, also computes and displays the expected value via + * PeComputeChecksum. Skips computation for images larger than 64 MiB. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER (may be NULL to skip computation) + * @param HeaderChecksum Checksum value as stored in the PE optional header + * @param ChecksumOffset Raw file offset of the checksum field within the image + */ +static VOID +PeShowChecksum(PPE_IMAGE_READER Reader, DWORD HeaderChecksum, SIZE_T ChecksumOffset) +{ + const SIZE_T MaxChecksumBytes = 64 * 1024 * 1024; + DWORD ComputedChecksum = 0; + + ShowMessages("\n%-36s%#x", "Optional header checksum :", HeaderChecksum); + if (Reader != NULL && Reader->ImageSize > MaxChecksumBytes) + { + ShowMessages("\n%-36s%s", "Computed PE checksum :", "skipped, file is larger than local cap"); + return; + } + + if (PeComputeChecksum(Reader, ChecksumOffset, &ComputedChecksum)) + { + ShowMessages("\n%-36s%#x (%s)", "Computed PE checksum :", ComputedChecksum, ComputedChecksum == HeaderChecksum ? "matches" : "differs"); + } + else + { + ShowMessages("\n%-36s%s", "Computed PE checksum :", "not available"); + } +} + +/** + * @brief Prints the contents of the PE certificate (security) directory + * + * The certificate directory is stored at a raw file offset rather than an RVA. + * Iterates WIN_CERTIFICATE entries, printing the file offset, length, revision, + * and type of each. Stops when the directory is empty, invalid, or a certificate + * length or alignment error is detected. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param SecurityDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_SECURITY data directory entry + */ +static VOID +PeShowCertificateTable(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * SecurityDirectory) +{ + const DWORD MaxCertificates = 0x1000; + + ShowMessages("\n\nCertificate table\n-----------------"); + + if (SecurityDirectory->VirtualAddress == 0 || SecurityDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "Certificate table :", "empty"); + return; + } + + const BYTE * DirectoryPointer = NULL; + if (!PeImageReaderGetPointerAtOffset(Reader, SecurityDirectory->VirtualAddress, SecurityDirectory->Size, &DirectoryPointer)) + { + ShowMessages("\n%-36s%s", "Certificate table :", "invalid bounds"); + return; + } + + DWORD Offset = 0; + DWORD Count = 0; + while (Offset < SecurityDirectory->Size && Count < MaxCertificates) + { + if (SecurityDirectory->Size - Offset < 8) + { + ShowMessages("\n%-36s%#llx", "Warning, truncated certificate at :", (UINT64)SecurityDirectory->VirtualAddress + Offset); + break; + } + + const BYTE * Entry = DirectoryPointer + Offset; + DWORD Length = PeReadDwordFromBuffer(Entry, 0); + WORD Revision = PeReadWordFromBuffer(Entry, 4); + WORD Type = PeReadWordFromBuffer(Entry, 6); + + ShowMessages("\n[%u] file offset %#llx length %#x revision %#x type %#x", Count, (UINT64)SecurityDirectory->VirtualAddress + Offset, Length, Revision, Type); + + if (Length < 8) + { + ShowMessages("\n%-36s%s", "Warning :", "certificate length is smaller than header"); + break; + } + + if (Length > SecurityDirectory->Size - Offset) + { + ShowMessages("\n%-36s%s", "Warning :", "certificate entry extends past directory"); + break; + } + + DWORD AlignedLength = (Length + 7) & ~7u; + if (AlignedLength < Length || AlignedLength > SecurityDirectory->Size - Offset) + { + ShowMessages("\n%-36s%s", "Warning :", "certificate alignment extends past directory"); + break; + } + + Offset += AlignedLength; + Count++; + } + + ShowMessages("\n%-36s%u", "Certificate entry count :", Count); + if (Count == MaxCertificates) + { + ShowMessages("\n%-36s%#x", "Warning, certificate cap reached :", MaxCertificates); + } +} + +/** + * @brief Prints base relocation blocks and per-type entry counts + * + * Iterates IMAGE_BASE_RELOCATION blocks within the .reloc directory, + * printing the page RVA, block size, and entry count for each. Accumulates + * a per-type summary and emits warnings for malformed or oversized data. + * Processing stops at 0x10000 blocks or 0x100000 entries. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param RelocDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_BASERELOC data directory entry + */ +static VOID +PeShowBaseRelocations(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * RelocDirectory) +{ + const DWORD MaxBlocks = 0x10000; + const DWORD MaxEntries = 0x100000; + const DWORD MaxPrintedBlocks = 0x20; + DWORD TypeCounts[16] = {0}; + DWORD BlockCount = 0; + ULONGLONG EntryCount = 0; + BOOLEAN EntryCapped = FALSE; + + ShowMessages("\n\nBase relocations\n----------------"); + + if (RelocDirectory->VirtualAddress == 0 || RelocDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "Base relocation table :", "empty"); + return; + } + + DWORD Offset = 0; + while (Offset < RelocDirectory->Size && BlockCount < MaxBlocks && EntryCount < MaxEntries) + { + DWORD BlockRva = 0; + if (!PeAddDword(RelocDirectory->VirtualAddress, Offset, &BlockRva) || RelocDirectory->Size - Offset < sizeof(IMAGE_BASE_RELOCATION)) + { + ShowMessages("\n%-36s%s", "Warning :", "relocation block header is truncated"); + break; + } + + const BYTE * BlockPointer = NULL; + if (!PeGetPointerAtRva(Reader, BlockRva, sizeof(IMAGE_BASE_RELOCATION), &BlockPointer)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid relocation block RVA :", BlockRva); + break; + } + + DWORD PageRva = PeReadDwordFromBuffer(BlockPointer, 0); + DWORD SizeOfBlock = PeReadDwordFromBuffer(BlockPointer, 4); + + if (SizeOfBlock < sizeof(IMAGE_BASE_RELOCATION)) + { + ShowMessages("\n%-36s%s", "Warning :", "relocation block size is smaller than header"); + break; + } + + if (SizeOfBlock > RelocDirectory->Size - Offset) + { + ShowMessages("\n%-36s%s", "Warning :", "relocation block extends past directory"); + break; + } + + if (((SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) & 1) != 0) + { + ShowMessages("\n%-36s%#x", "Warning, odd relocation block size :", SizeOfBlock); + } + + DWORD EntriesInBlock = (SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); + if (BlockCount < MaxPrintedBlocks) + { + ShowMessages("\n[%u] page RVA %#x block size %#x entries %u", BlockCount, PageRva, SizeOfBlock, EntriesInBlock); + } + + DWORD EntriesRva = 0; + if (!PeAddDword(BlockRva, sizeof(IMAGE_BASE_RELOCATION), &EntriesRva)) + { + ShowMessages("\n%-36s%s", "Warning :", "relocation entries RVA overflow"); + break; + } + + const BYTE * Entries = NULL; + if (EntriesInBlock != 0 && !PeGetPointerAtRva(Reader, EntriesRva, EntriesInBlock * sizeof(WORD), &Entries)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid relocation entries RVA :", EntriesRva); + break; + } + + for (DWORD EntryIndex = 0; EntryIndex < EntriesInBlock && EntryCount < MaxEntries; EntryIndex++) + { + WORD Entry = PeReadWordFromBuffer(Entries, EntryIndex * sizeof(WORD)); + WORD Type = (Entry >> 12) & 0xf; + + TypeCounts[Type]++; + EntryCount++; + if (EntryCount == MaxEntries) + { + EntryCapped = TRUE; + break; + } + + if (Type == IMAGE_REL_BASED_HIGHADJ) + { + if (EntryIndex + 1 >= EntriesInBlock) + { + ShowMessages("\n%-36s%s", "Warning :", "HIGHADJ relocation is missing its pair entry"); + } + else + { + EntryIndex++; + EntryCount++; + } + } + } + + if (EntryCount == MaxEntries) + { + EntryCapped = TRUE; + } + + Offset += SizeOfBlock; + BlockCount++; + } + + ShowMessages("\n%-36s%u", "Relocation block count :", BlockCount); + ShowMessages("\n%-36s%llu", "Relocation entry count :", EntryCount); + for (DWORD Type = 0; Type < RTL_NUMBER_OF(TypeCounts); Type++) + { + if (TypeCounts[Type] != 0) + { + ShowMessages("\n%-36s%u = %u", "Relocation type count :", Type, TypeCounts[Type]); + } + } + + if (BlockCount == MaxBlocks) + { + ShowMessages("\n%-36s%#x", "Warning, relocation block cap reached :", MaxBlocks); + } + if (EntryCapped) + { + ShowMessages("\n%-36s%#x", "Warning, relocation entry cap reached :", MaxEntries); + } + if (BlockCount > MaxPrintedBlocks) + { + ShowMessages("\n%-36s%#x", "Info, printed relocation blocks :", MaxPrintedBlocks); + } +} + +/** + * @brief Prints bound import descriptors and their forwarder references + * + * Iterates IMAGE_BOUND_IMPORT_DESCRIPTOR entries, printing the module name, + * timestamp, and forwader reference count for each. Also expands forwader + * references inline. Processing stops after 0x1000 descriptors. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param BoundImportDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT data directory entry + */ +static VOID +PeShowBoundImports(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * BoundImportDirectory) +{ + const DWORD MaxDescriptors = 0x1000; + const DWORD MaxNameLength = 0x200; + + ShowMessages("\n\nBound imports\n-------------"); + + if (BoundImportDirectory->VirtualAddress == 0 || BoundImportDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "Bound import directory :", "empty"); + return; + } + + DWORD Offset = 0; + DWORD DescriptorCount = 0; + while (Offset < BoundImportDirectory->Size && DescriptorCount < MaxDescriptors) + { + DWORD DescriptorRva = 0; + if (!PeAddDword(BoundImportDirectory->VirtualAddress, Offset, &DescriptorRva) || BoundImportDirectory->Size - Offset < sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR)) + { + ShowMessages("\n%-36s%s", "Warning :", "bound import descriptor is truncated"); + break; + } + + const BYTE * Descriptor = NULL; + if (!PeGetPointerAtRva(Reader, DescriptorRva, sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR), &Descriptor)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid bound descriptor RVA :", DescriptorRva); + break; + } + + DWORD TimeDateStamp = PeReadDwordFromBuffer(Descriptor, 0); + WORD OffsetModuleName = PeReadWordFromBuffer(Descriptor, 4); + WORD NumberOfModuleForwarders = PeReadWordFromBuffer(Descriptor, 6); + + if (TimeDateStamp == 0 && OffsetModuleName == 0 && NumberOfModuleForwarders == 0) + { + break; + } + + CHAR ModuleName[MaxNameLength + 1] = {0}; + PE_ASCII_STRING_STATUS NameStatus = PeReadAsciiStringInDirectory(Reader, + BoundImportDirectory, + OffsetModuleName, + MaxNameLength, + ModuleName, + sizeof(ModuleName)); + + ShowMessages("\n[%u] module %s timestamp %#x forwarder refs %u", + DescriptorCount, + NameStatus == PeAsciiStringOk ? ModuleName : PeAsciiStatusName(NameStatus), + TimeDateStamp, + NumberOfModuleForwarders); + + DWORD DescriptorSpan = sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR) + (NumberOfModuleForwarders * (DWORD)sizeof(IMAGE_BOUND_FORWARDER_REF)); + if (DescriptorSpan > BoundImportDirectory->Size - Offset) + { + ShowMessages("\n%-36s%s", "Warning :", "bound import forwarder refs extend past directory"); + break; + } + + for (WORD ForwarderIndex = 0; ForwarderIndex < NumberOfModuleForwarders; ForwarderIndex++) + { + DWORD ForwarderOffset = Offset + sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR) + (ForwarderIndex * (DWORD)sizeof(IMAGE_BOUND_FORWARDER_REF)); + DWORD ForwarderRva = 0; + + if (!PeAddDword(BoundImportDirectory->VirtualAddress, ForwarderOffset, &ForwarderRva)) + { + ShowMessages("\n%-36s%s", "Warning :", "bound forwarder RVA overflow"); + break; + } + + const BYTE * Forwarder = NULL; + if (!PeGetPointerAtRva(Reader, ForwarderRva, sizeof(IMAGE_BOUND_FORWARDER_REF), &Forwarder)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid bound forwarder RVA :", ForwarderRva); + break; + } + + DWORD ForwarderTimeDateStamp = PeReadDwordFromBuffer(Forwarder, 0); + WORD ForwarderOffsetModuleName = PeReadWordFromBuffer(Forwarder, 4); + CHAR ForwarderName[MaxNameLength + 1] = {0}; + + PE_ASCII_STRING_STATUS ForwarderNameStatus = PeReadAsciiStringInDirectory(Reader, + BoundImportDirectory, + ForwarderOffsetModuleName, + MaxNameLength, + ForwarderName, + sizeof(ForwarderName)); + ShowMessages("\n [%u] forwarder %s timestamp %#x", + ForwarderIndex, + ForwarderNameStatus == PeAsciiStringOk ? ForwarderName : PeAsciiStatusName(ForwarderNameStatus), + ForwarderTimeDateStamp); + } + + Offset += DescriptorSpan; + DescriptorCount++; + } + + ShowMessages("\n%-36s%u", "Bound import descriptor count :", DescriptorCount); + if (DescriptorCount == MaxDescriptors) + { + ShowMessages("\n%-36s%#x", "Warning, bound import cap reached :", MaxDescriptors); + } +} + +/** + * @brief Computes the 64-bit FNV-1a hash of a byte buffer + * + * Uses the standard FNV-1a parameters: offset basis 14695981039346656037 + * and prime 1099511628211. Suitable for non-cryptographic fingerprinting. + * + * @param Data Pointer to the input data + * @param Size Number of bytes to hash + * + * @return ULONGLONG The 64-bit FNV-1a hash value + */ +static ULONGLONG +PeFnv1a64(const BYTE * Data, DWORD Size) +{ + ULONGLONG Hash = 14695981039346656037ull; + + for (DWORD Index = 0; Index < Size; Index++) + { + Hash ^= Data[Index]; + Hash *= 1099511628211ull; + } + + return Hash; +} + +/** + * @brief Computes the Shannon entropy of a byte buffer + * + * Calculates the frequency of each byte value (0-255) and applies the + * standard information-entropy formula. A return value near 8.0 indicates + * high entropy (e.g. compressed or encrypted data); values near 0.0 indicate + * low entropy (e.g. sparse, mostly-zero data). + * + * @param Data Pointer to the input data + * @param Size Number of bytes to analyse + * + * @return double Shannon entropy in bits per byte (0.0 to 8.0) + */ +static double +PeCalculateEntropy(const BYTE * Data, DWORD Size) +{ + DWORD Counts[256] = {0}; + double Entropy = 0.0; + + for (DWORD Index = 0; Index < Size; Index++) + { + Counts[Data[Index]]++; + } + + for (DWORD Index = 0; Index < RTL_NUMBER_OF(Counts); Index++) + { + if (Counts[Index] != 0) + { + double Probability = (double)Counts[Index] / (double)Size; + Entropy -= Probability * (log(Probability) / log(2.0)); + } + } + + return Entropy; +} + +/** + * @brief Reads a 16-bit word from the image at the location mapped by an RVA + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param Rva Relative virtual address to read from + * @param Value Output pointer that receives the WORD value on success; must not be NULL + * + * @return BOOLEAN TRUE on success, FALSE if the RVA cannot be resolved or Value is NULL + */ +static BOOLEAN +PeReadWordAtRva(PPE_IMAGE_READER Reader, DWORD Rva, WORD * Value) +{ + const BYTE * Pointer = NULL; + + if (Value == NULL || !PeGetPointerAtRva(Reader, Rva, sizeof(WORD), &Pointer)) + { + return FALSE; + } + + CopyMemory(Value, Pointer, sizeof(*Value)); + return TRUE; +} + +/** + * @brief Reads an import/export thunk value (DWORD or QWORD) from an RVA + * + * Reads sizeof(DWORD) bytes when Is32Bit is TRUE, or sizeof(ULONGLONG) bytes + * when FALSE, and widens the result to a ULONGLONG. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param Rva Relative virtual address of the thunk entry + * @param Is32Bit TRUE to read a 32-bit thunk, FALSE to read a 64-bit thunk + * @param Value Output pointer that receives the thunk value on success; must not be NULL + * + * @return BOOLEAN TRUE on success, FALSE if the RVA cannot be resolved or Value is NULL + */ +static BOOLEAN +PeReadThunkAtRva(PPE_IMAGE_READER Reader, DWORD Rva, BOOLEAN Is32Bit, ULONGLONG * Value) +{ + const BYTE * Pointer = NULL; + DWORD Size = Is32Bit ? sizeof(DWORD) : sizeof(ULONGLONG); + + if (Value == NULL || !PeGetPointerAtRva(Reader, Rva, Size, &Pointer)) + { + return FALSE; + } + + if (Is32Bit) + { + DWORD Value32 = 0; + CopyMemory(&Value32, Pointer, sizeof(Value32)); + *Value = Value32; + } + else + { + CopyMemory(Value, Pointer, sizeof(*Value)); + } + + return TRUE; +} + +/** + * @brief Prints a named resource type identifier and its occurrence count + * + * Maps well-known RT_* integer type identifiers (1-12, 14, 16, 24) to + * human-readable names. Unknown or unnamed type IDs are silently ignored. + * + * @param TypeId Numeric resource type identifier (RT_* value) + * @param Count Number of resources of this type found in the resource directory + */ +static VOID +PeShowResourceTypeCount(DWORD TypeId, DWORD Count) +{ + const CHAR * TypeName = NULL; + + switch (TypeId) + { + case 1: + TypeName = "cursor"; + break; + case 2: + TypeName = "bitmap"; + break; + case 3: + TypeName = "icon"; + break; + case 4: + TypeName = "menu"; + break; + case 5: + TypeName = "dialog"; + break; + case 6: + TypeName = "string"; + break; + case 7: + TypeName = "font directory"; + break; + case 8: + TypeName = "font"; + break; + case 9: + TypeName = "accelerator"; + break; + case 10: + TypeName = "rcdata"; + break; + case 11: + TypeName = "message table"; + break; + case 12: + TypeName = "group cursor"; + break; + case 14: + TypeName = "group icon"; + break; + case 16: + TypeName = "version"; + break; + case 24: + TypeName = "manifest"; + break; + default: + TypeName = NULL; + break; + } + + if (TypeName != NULL) + { + ShowMessages("\n%-36s%s (%u) = %u", "Resource type count :", TypeName, TypeId, Count); + } +} + +/** + * @brief Traverses and prints the PE resource directory tree + * + * Performs an iterative depth-first walk of the three-level resource directory + * (type / name or id / language), printing directory and data-entry statistics. + * Accumulates per-type counts for well-known resource types and reports total + * declared and mapped data bytes. Processing is capped at 0x4000 nodes and + * 0x10000 entries to prevent runaway on corrupt images. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param ResourceDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_RESOURCE data directory entry + */ +static VOID +PeShowResources(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * ResourceDirectory) +{ + const DWORD MaxDepth = 8; + const DWORD MaxNodes = 0x4000; + const DWORD MaxEntries = 0x10000; + const DWORD MaxVisitedOffsets = 0x4000; + + typedef struct _RESOURCE_NODE + { + DWORD Offset; + DWORD Depth; + DWORD TypeId; + } RESOURCE_NODE; + + RESOURCE_NODE * Stack = NULL; + DWORD * Visited = NULL; + DWORD StackCount = 0; + DWORD VisitedCount = 0; + DWORD TypeCounts[25] = {0}; + DWORD DirectoryCount = 0; + DWORD EntryCount = 0; + DWORD DeclaredDataEntryCount = 0; + DWORD MappedDataEntryCount = 0; + DWORD InvalidEntryCount = 0; + DWORD NamedRootTypeCount = 0; + ULONGLONG DeclaredDataBytes = 0; + ULONGLONG MappedDataBytes = 0; + BOOLEAN NodeCapReached = FALSE; + BOOLEAN EntryCapReached = FALSE; + + ShowMessages("\n\nResources\n---------"); + + if (ResourceDirectory->VirtualAddress == 0 || ResourceDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "Resource directory :", "empty"); + return; + } + + if (ResourceDirectory->Size < 16) + { + ShowMessages("\n%-36s%s", "Warning :", "resource directory is smaller than one header"); + return; + } + + Stack = new (std::nothrow) RESOURCE_NODE[MaxNodes]; + Visited = new (std::nothrow) DWORD[MaxVisitedOffsets]; + + if (Stack == NULL || Visited == NULL) + { + ShowMessages("\n%-36s%s", "Resource directory :", "memory allocation failed"); + delete[] Stack; + delete[] Visited; + return; + } + + ZeroMemory(Stack, sizeof(RESOURCE_NODE) * MaxNodes); + ZeroMemory(Visited, sizeof(DWORD) * MaxVisitedOffsets); + + Stack[StackCount].Offset = 0; + Stack[StackCount].Depth = 0; + Stack[StackCount].TypeId = 0; + StackCount++; + + while (StackCount != 0) + { + RESOURCE_NODE Node = Stack[--StackCount]; + + if (DirectoryCount >= MaxNodes) + { + NodeCapReached = TRUE; + break; + } + + if (Node.Depth > MaxDepth) + { + InvalidEntryCount++; + continue; + } + + BOOLEAN Seen = FALSE; + for (DWORD Index = 0; Index < VisitedCount; Index++) + { + if (Visited[Index] == Node.Offset) + { + Seen = TRUE; + break; + } + } + + if (Seen) + { + InvalidEntryCount++; + continue; + } + + if (VisitedCount < MaxVisitedOffsets) + { + Visited[VisitedCount++] = Node.Offset; + } + else + { + NodeCapReached = TRUE; + break; + } + + DWORD DirectoryRva = 0; + if (!PeAddDword(ResourceDirectory->VirtualAddress, Node.Offset, &DirectoryRva) || + Node.Offset > ResourceDirectory->Size || ResourceDirectory->Size - Node.Offset < 16) + { + InvalidEntryCount++; + continue; + } + + const BYTE * Directory = NULL; + if (!PeGetPointerAtRva(Reader, DirectoryRva, 16, &Directory)) + { + InvalidEntryCount++; + continue; + } + + WORD NamedEntries = PeReadWordFromBuffer(Directory, 12); + WORD IdEntries = PeReadWordFromBuffer(Directory, 14); + DWORD EntryTotal = (DWORD)NamedEntries + (DWORD)IdEntries; + DWORD EntryBytes = 0; + + if (EntryTotal > (MAXDWORD - 16) / 8 || !PeAddDword(16, EntryTotal * 8, &EntryBytes) || + EntryBytes > ResourceDirectory->Size - Node.Offset) + { + InvalidEntryCount++; + continue; + } + + DirectoryCount++; + + const BYTE * Entries = NULL; + if (EntryTotal != 0 && !PeGetPointerAtRva(Reader, DirectoryRva, EntryBytes, &Entries)) + { + InvalidEntryCount++; + continue; + } + + for (DWORD EntryIndex = 0; EntryIndex < EntryTotal; EntryIndex++) + { + if (EntryCount >= MaxEntries) + { + EntryCapReached = TRUE; + break; + } + + const BYTE * Entry = Entries + 16 + (EntryIndex * 8); + DWORD NameOrId = PeReadDwordFromBuffer(Entry, 0); + DWORD OffsetToData = PeReadDwordFromBuffer(Entry, 4); + DWORD ChildOffset = OffsetToData & 0x7fffffff; + DWORD TypeId = Node.TypeId; + + EntryCount++; + + if ((NameOrId & 0x80000000) != 0) + { + DWORD StringOffset = NameOrId & 0x7fffffff; + DWORD StringRva = 0; + + if (StringOffset > ResourceDirectory->Size || ResourceDirectory->Size - StringOffset < sizeof(WORD) || + !PeAddDword(ResourceDirectory->VirtualAddress, StringOffset, &StringRva)) + { + InvalidEntryCount++; + } + else + { + const BYTE * String = NULL; + if (!PeGetPointerAtRva(Reader, StringRva, sizeof(WORD), &String)) + { + InvalidEntryCount++; + } + else + { + WORD StringLength = PeReadWordFromBuffer(String, 0); + DWORD StringBytes = (DWORD)sizeof(WORD) + ((DWORD)StringLength * sizeof(WCHAR)); + + if (StringBytes > ResourceDirectory->Size - StringOffset || !PeGetPointerAtRva(Reader, StringRva, StringBytes, &String)) + { + InvalidEntryCount++; + } + } + } + if (Node.Depth == 0) + { + NamedRootTypeCount++; + } + } + else if (Node.Depth == 0) + { + TypeId = NameOrId & 0xffff; + if (TypeId < RTL_NUMBER_OF(TypeCounts)) + { + TypeCounts[TypeId]++; + } + } + + if ((OffsetToData & 0x80000000) != 0) + { + if (ChildOffset > ResourceDirectory->Size || ResourceDirectory->Size - ChildOffset < 16 || Node.Depth + 1 > MaxDepth) + { + InvalidEntryCount++; + continue; + } + + if (StackCount >= MaxNodes) + { + NodeCapReached = TRUE; + continue; + } + + Stack[StackCount].Offset = ChildOffset; + Stack[StackCount].Depth = Node.Depth + 1; + Stack[StackCount].TypeId = TypeId; + StackCount++; + } + else + { + DWORD DataEntryRva = 0; + if (ChildOffset > ResourceDirectory->Size || ResourceDirectory->Size - ChildOffset < 16 || + !PeAddDword(ResourceDirectory->VirtualAddress, ChildOffset, &DataEntryRva)) + { + InvalidEntryCount++; + continue; + } + + const BYTE * DataEntry = NULL; + if (!PeGetPointerAtRva(Reader, DataEntryRva, 16, &DataEntry)) + { + InvalidEntryCount++; + continue; + } + + DWORD DataRva = PeReadDwordFromBuffer(DataEntry, 0); + DWORD DataSize = PeReadDwordFromBuffer(DataEntry, 4); + + BOOLEAN PayloadMapped = TRUE; + if (DataSize != 0) + { + const BYTE * Payload = NULL; + if (!PeGetPointerAtRva(Reader, DataRva, DataSize, &Payload)) + { + InvalidEntryCount++; + PayloadMapped = FALSE; + } + } + + DeclaredDataBytes += DataSize; + DeclaredDataEntryCount++; + if (PayloadMapped) + { + MappedDataBytes += DataSize; + MappedDataEntryCount++; + } + } + } + + if (EntryCapReached) + { + break; + } + } + + ShowMessages("\n%-36s%u", "Resource directory count :", DirectoryCount); + ShowMessages("\n%-36s%u", "Resource entry count :", EntryCount); + ShowMessages("\n%-36s%u", "Resource declared data entries :", DeclaredDataEntryCount); + ShowMessages("\n%-36s%u", "Resource mapped data entries :", MappedDataEntryCount); + ShowMessages("\n%-36s%u", "Resource invalid entry count :", InvalidEntryCount); + ShowMessages("\n%-36s%u", "Resource named root types :", NamedRootTypeCount); + ShowMessages("\n%-36s%#llx", "Resource declared data bytes :", DeclaredDataBytes); + ShowMessages("\n%-36s%#llx", "Resource mapped data bytes :", MappedDataBytes); + + for (DWORD TypeId = 0; TypeId < RTL_NUMBER_OF(TypeCounts); TypeId++) + { + if (TypeCounts[TypeId] != 0) + { + PeShowResourceTypeCount(TypeId, TypeCounts[TypeId]); + } + } + + if (NodeCapReached) + { + ShowMessages("\n%-36s%#x", "Warning, resource node cap reached :", MaxNodes); + } + if (EntryCapReached) + { + ShowMessages("\n%-36s%#x", "Warning, resource entry cap reached :", MaxEntries); + } + + delete[] Stack; + delete[] Visited; +} + +/** + * @brief Prints RUNTIME_FUNCTION entries from the x64 exception directory + * + * Decodes IMAGE_RUNTIME_FUNCTION_ENTRY records for AMD64 images, printing + * the begin address, end address, unwind RVA, and key unwind info fields + * for the first 0x20 entries. For non-AMD64 machines the directory size + * is reported without per-entry decoding. Processing is capped at 0x100000 + * entries. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param ExceptionDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_EXCEPTION data directory entry + * @param Machine Machine type from the PE file header (IMAGE_FILE_MACHINE_*) + * @param Is32Bit TRUE if the PE image is 32-bit + */ +static VOID +PeShowExceptions(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * ExceptionDirectory, WORD Machine, BOOLEAN Is32Bit) +{ + const DWORD RuntimeFunctionSize = 12; + const DWORD MaxEntries = 0x100000; + const DWORD MaxPrintedEntries = 0x20; + const DWORD MaxWarnings = 8; + + ShowMessages("\n\nExceptions\n----------"); + + if (ExceptionDirectory->VirtualAddress == 0 || ExceptionDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "Exception directory :", "empty"); + return; + } + + if (Machine != IMAGE_FILE_MACHINE_AMD64 || Is32Bit) + { + ShowMessages("\n%-36s%s", "Exception directory :", "present, x64 runtime-function decoding skipped for this machine"); + ShowMessages("\n%-36s%#x", "Raw exception directory size :", ExceptionDirectory->Size); + return; + } + + if (ExceptionDirectory->Size < RuntimeFunctionSize) + { + ShowMessages("\n%-36s%s", "Warning :", "exception directory is smaller than one runtime function entry"); + return; + } + + if ((ExceptionDirectory->Size % RuntimeFunctionSize) != 0) + { + ShowMessages("\n%-36s%#x", "Warning, malformed exception size :", ExceptionDirectory->Size); + } + + DWORD EntryCount = ExceptionDirectory->Size / RuntimeFunctionSize; + BOOLEAN EntryCapped = FALSE; + DWORD RangeWarnings = 0; + DWORD UnwindWarnings = 0; + DWORD SkippedNullEntries = 0; + DWORD PrintedEntries = 0; + if (EntryCount > MaxEntries) + { + EntryCount = MaxEntries; + EntryCapped = TRUE; + } + + ShowMessages("\n%-36s%u", "Runtime function count :", EntryCount); + + for (DWORD EntryIndex = 0; EntryIndex < EntryCount; EntryIndex++) + { + DWORD EntryRva = 0; + if (!PeAddDword(ExceptionDirectory->VirtualAddress, EntryIndex * RuntimeFunctionSize, &EntryRva)) + { + ShowMessages("\n%-36s%s", "Warning :", "runtime function entry RVA overflow"); + break; + } + + const BYTE * Entry = NULL; + if (!PeGetPointerAtRva(Reader, EntryRva, RuntimeFunctionSize, &Entry)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid runtime entry RVA :", EntryRva); + break; + } + + DWORD BeginAddress = PeReadDwordFromBuffer(Entry, 0); + DWORD EndAddress = PeReadDwordFromBuffer(Entry, 4); + DWORD UnwindRva = PeReadDwordFromBuffer(Entry, 8); + + if (BeginAddress == 0 && EndAddress == 0 && UnwindRva == 0) + { + SkippedNullEntries++; + continue; + } + + if (BeginAddress >= EndAddress) + { + if (RangeWarnings < MaxWarnings && PrintedEntries < MaxPrintedEntries) + { + ShowMessages("\n%-36s%u", "Warning, invalid runtime range index :", EntryIndex); + } + RangeWarnings++; + } + + const BYTE * Unwind = NULL; + BOOLEAN UnwindMapped = UnwindRva != 0 && PeGetPointerAtRva(Reader, UnwindRva, 4, &Unwind); + if (!UnwindMapped) + { + if (UnwindWarnings < MaxWarnings && PrintedEntries < MaxPrintedEntries) + { + ShowMessages("\n%-36s%#x", "Warning, invalid unwind RVA :", UnwindRva); + } + UnwindWarnings++; + } + + if (PrintedEntries < MaxPrintedEntries) + { + if (UnwindMapped) + { + BYTE VersionAndFlags = PeReadByteFromBuffer(Unwind, 0); + BYTE Frame = PeReadByteFromBuffer(Unwind, 3); + + ShowMessages("\n[%u] begin %#x end %#x unwind %#x version %u flags %#x prolog %#x codes %u frame reg %u frame off %u", + EntryIndex, + BeginAddress, + EndAddress, + UnwindRva, + VersionAndFlags & 0x7, + VersionAndFlags >> 3, + PeReadByteFromBuffer(Unwind, 1), + PeReadByteFromBuffer(Unwind, 2), + Frame & 0xf, + Frame >> 4); + } + else + { + ShowMessages("\n[%u] begin %#x end %#x unwind %#x", EntryIndex, BeginAddress, EndAddress, UnwindRva); + } + PrintedEntries++; + } + } + + if (EntryCapped) + { + ShowMessages("\n%-36s%#x", "Warning, exception entry cap reached :", MaxEntries); + } + if (EntryCount > MaxPrintedEntries) + { + ShowMessages("\n%-36s%u", "Info, printed exception entries :", PrintedEntries); + } + if (SkippedNullEntries != 0) + { + ShowMessages("\n%-36s%u", "Info, skipped null runtime entries :", SkippedNullEntries); + } + if (RangeWarnings > MaxWarnings) + { + ShowMessages("\n%-36s%#x", "Warning, invalid range warnings shown :", MaxWarnings); + } + if (UnwindWarnings > MaxWarnings) + { + ShowMessages("\n%-36s%#x", "Warning, invalid unwind warnings shown :", MaxWarnings); + } +} + +/** + * @brief Resolves a delay-import address field to a relative virtual address + * + * Handles both the legacy VA-based format (UsesRva == FALSE) and the newer + * RVA-based format (UsesRva == TRUE). For VA-based descriptors the address is + * converted via PeVaToRva using the supplied image base. + * + * @param Address Raw address value read from the delay-import descriptor + * @param UsesRva TRUE if the descriptor uses RVAs, FALSE if it uses VAs + * @param ImageBase Image base used for VA-to-RVA conversion when UsesRva is FALSE + * @param Rva Output pointer that receives the resolved RVA on success; must not be NULL + * + * @return BOOLEAN TRUE on success, FALSE when the address cannot be converted to an RVA + */ +static BOOLEAN +PeResolveDelayImportAddress(ULONGLONG Address, BOOLEAN UsesRva, ULONGLONG ImageBase, DWORD * Rva) +{ + if (Rva == NULL) + { + return FALSE; + } + + if (UsesRva) + { + if (Address > MAXDWORD) + { + return FALSE; + } + + *Rva = (DWORD)Address; + return TRUE; + } + + return PeVaToRva(Address, ImageBase, Rva); +} + +/** + * @brief Prints delay-import descriptors and their imported function names or ordinals + * + * Iterates ImgDelayDescr records, resolving DLL names and import thunk arrays. + * Supports both legacy VA-based and RVA-based descriptor formats. Processing + * is capped at 0x1000 descriptors and 0x2000 total imported symbols. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param DelayImportDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT data directory entry + * @param Is32Bit TRUE if the PE image is 32-bit + * @param ImageBase Preferred image base used for VA-to-RVA conversion + */ +static VOID +PeShowDelayImports(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * DelayImportDirectory, BOOLEAN Is32Bit, ULONGLONG ImageBase) +{ + const DWORD MaxDescriptors = 0x1000; + const DWORD MaxTotalImports = 0x2000; + const DWORD MaxDllNameLength = 0x200; + const DWORD MaxImportNameLength = 0x200; + const DWORD DescriptorSize = 32; + + ShowMessages("\n\nDelay imports\n-------------"); + + if (DelayImportDirectory->VirtualAddress == 0 || DelayImportDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "Delay import directory :", "empty"); + return; + } + + if (DelayImportDirectory->Size < DescriptorSize) + { + ShowMessages("\n%-36s%s", "Warning :", "delay import directory is smaller than one descriptor"); + return; + } + + DWORD DescriptorCount = DelayImportDirectory->Size / DescriptorSize; + if ((DelayImportDirectory->Size % DescriptorSize) != 0) + { + ShowMessages("\n%-36s%#x", "Warning, malformed delay import size :", DelayImportDirectory->Size); + } + + BOOLEAN DescriptorCapped = FALSE; + if (DescriptorCount > MaxDescriptors) + { + DescriptorCount = MaxDescriptors; + DescriptorCapped = TRUE; + } + + DWORD TotalImports = 0; + BOOLEAN FoundTerminator = FALSE; + BOOLEAN TotalImportsCapped = FALSE; + + for (DWORD DescriptorIndex = 0; DescriptorIndex < DescriptorCount; DescriptorIndex++) + { + DWORD DescriptorRva = 0; + if (!PeAddDword(DelayImportDirectory->VirtualAddress, DescriptorIndex * DescriptorSize, &DescriptorRva)) + { + ShowMessages("\n%-36s%s", "Warning :", "delay import descriptor RVA overflow"); + break; + } + + const BYTE * Descriptor = NULL; + if (!PeGetPointerAtRva(Reader, DescriptorRva, DescriptorSize, &Descriptor)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid delay descriptor RVA :", DescriptorRva); + break; + } + + DWORD Attributes = PeReadDwordFromBuffer(Descriptor, 0); + DWORD NameValue = PeReadDwordFromBuffer(Descriptor, 4); + DWORD IatValue = PeReadDwordFromBuffer(Descriptor, 12); + DWORD IntValue = PeReadDwordFromBuffer(Descriptor, 16); + DWORD BoundIatValue = PeReadDwordFromBuffer(Descriptor, 20); + DWORD UnloadIatValue = PeReadDwordFromBuffer(Descriptor, 24); + DWORD TimeDateStamp = PeReadDwordFromBuffer(Descriptor, 28); + + if (Attributes == 0 && NameValue == 0 && PeReadDwordFromBuffer(Descriptor, 8) == 0 && IatValue == 0 && IntValue == 0 && + BoundIatValue == 0 && UnloadIatValue == 0 && TimeDateStamp == 0) + { + FoundTerminator = TRUE; + break; + } + + BOOLEAN UsesRva = (Attributes & 1) != 0; + DWORD NameRva = 0; + DWORD LookupThunkRva = 0; + DWORD IatThunkRva = 0; + + if (!UsesRva) + { + ShowMessages("\n%-36s%s", "Info :", "delay import descriptor uses VA fields"); + } + + if (!PeResolveDelayImportAddress(NameValue, UsesRva, ImageBase, &NameRva)) + { + ShowMessages("\n[%u] DLL name %s", DescriptorIndex, "invalid VA/RVA"); + ShowMessages("\n%-36s%s", "Warning :", "skipping delay imports for descriptor with unreadable DLL name"); + continue; + } + + CHAR DllName[MaxDllNameLength + 1] = {0}; + PE_ASCII_STRING_STATUS DllNameStatus = PeReadAsciiStringAtRva(Reader, + NameRva, + MaxDllNameLength, + DllName, + sizeof(DllName)); + if (DllNameStatus != PeAsciiStringOk) + { + ShowMessages("\n[%u] DLL name %s", DescriptorIndex, PeAsciiStatusName(DllNameStatus)); + ShowMessages("\n%-36s%s", "Warning :", "skipping delay imports for descriptor with unreadable DLL name"); + continue; + } + + ShowMessages("\n[%u] DLL name %s attributes %#x timestamp %#x", DescriptorIndex, DllName, Attributes, TimeDateStamp); + + if (!PeResolveDelayImportAddress(IntValue != 0 ? IntValue : IatValue, UsesRva, ImageBase, &LookupThunkRva) || + !PeResolveDelayImportAddress(IatValue, UsesRva, ImageBase, &IatThunkRva)) + { + ShowMessages("\n%-36s%s", "Warning :", "delay import thunk VA/RVA is invalid"); + continue; + } + + DWORD ThunkSize = Is32Bit ? sizeof(DWORD) : sizeof(ULONGLONG); + for (DWORD ThunkIndex = 0; TotalImports < MaxTotalImports; ThunkIndex++) + { + DWORD LookupEntryRva = 0; + DWORD IatEntryRva = 0; + if (!PeAddDword(LookupThunkRva, ThunkIndex * ThunkSize, &LookupEntryRva) || + !PeAddDword(IatThunkRva, ThunkIndex * ThunkSize, &IatEntryRva)) + { + ShowMessages("\n%-36s%s", "Warning :", "delay import thunk RVA overflow"); + break; + } + + ULONGLONG ThunkValue = 0; + if (!PeReadThunkAtRva(Reader, LookupEntryRva, Is32Bit, &ThunkValue)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid delay thunk RVA :", LookupEntryRva); + break; + } + + if (ThunkValue == 0) + { + break; + } + + ULONGLONG OrdinalFlag = Is32Bit ? IMAGE_ORDINAL_FLAG32 : IMAGE_ORDINAL_FLAG64; + if ((ThunkValue & OrdinalFlag) != 0) + { + ShowMessages("\n [%u] ordinal %u thunk RVA %#x", ThunkIndex, (UINT32)(ThunkValue & 0xffff), IatEntryRva); + TotalImports++; + continue; + } + + DWORD NameRvaFromThunk = 0; + if (!PeResolveDelayImportAddress(ThunkValue, UsesRva, ImageBase, &NameRvaFromThunk)) + { + ShowMessages("\n%-36s%#llx", "Warning, invalid delay import name VA/RVA :", (UINT64)ThunkValue); + TotalImports++; + continue; + } + + WORD Hint = 0; + if (!PeReadWordAtRva(Reader, NameRvaFromThunk, &Hint)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid delay import hint RVA :", NameRvaFromThunk); + TotalImports++; + continue; + } + + DWORD ImportNameRva = 0; + if (!PeAddDword(NameRvaFromThunk, sizeof(WORD), &ImportNameRva)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid delay import name RVA :", NameRvaFromThunk); + TotalImports++; + continue; + } + + CHAR ImportName[MaxImportNameLength + 1] = {0}; + PE_ASCII_STRING_STATUS ImportNameStatus = PeReadAsciiStringAtRva(Reader, + ImportNameRva, + MaxImportNameLength, + ImportName, + sizeof(ImportName)); + if (ImportNameStatus != PeAsciiStringOk) + { + ShowMessages("\n%-36s%#x, %s", "Warning, invalid delay import name RVA :", ImportNameRva, PeAsciiStatusName(ImportNameStatus)); + TotalImports++; + continue; + } + + ShowMessages("\n [%u] hint %#x name %s thunk RVA %#x", ThunkIndex, Hint, ImportName, IatEntryRva); + TotalImports++; + } + + if (TotalImports >= MaxTotalImports) + { + TotalImportsCapped = TRUE; + break; + } + } + + if (!FoundTerminator) + { + ShowMessages("\n%-36s%s", "Warning :", "delay import descriptor terminator not found before bounds or cap"); + } + if (DescriptorCapped) + { + ShowMessages("\n%-36s%#x", "Warning, delay descriptor cap reached :", MaxDescriptors); + } + if (TotalImportsCapped) + { + ShowMessages("\n%-36s%#x", "Warning, delay import cap reached :", MaxTotalImports); + } +} + +/** + * @brief Prints the RVA and size of an IMAGE_DATA_DIRECTORY embedded within the CLR runtime header + * + * Reads two consecutive DWORDs from the CLR header buffer at Offset to obtain + * a sub-directory RVA and size. Also reports whether the range is mapped + * within the image. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param Header Pointer to the CLR runtime header byte buffer + * @param AvailableSize Number of validated bytes available in Header + * @param Offset Byte offset within Header of the IMAGE_DATA_DIRECTORY to read + * @param Label Column label to print before the values + */ +static VOID +PeShowClrDirectoryBounds(PPE_IMAGE_READER Reader, const BYTE * Header, DWORD AvailableSize, SIZE_T Offset, const CHAR * Label) +{ + if (Offset > AvailableSize || sizeof(IMAGE_DATA_DIRECTORY) > AvailableSize - Offset) + { + return; + } + + DWORD Rva = PeReadDwordFromBuffer(Header, Offset); + DWORD Size = PeReadDwordFromBuffer(Header, Offset + sizeof(DWORD)); + + ShowMessages("\n%-36sRVA %#x size %#x", Label, Rva, Size); + if (Rva != 0 && Size != 0) + { + const BYTE * Pointer = NULL; + ShowMessages(", %s", PeGetPointerAtRva(Reader, Rva, Size, &Pointer) ? "mapped" : "not mapped"); + } +} + +/** + * @brief Prints CLR (.NET) runtime header information + * + * Reads the IMAGE_COR20_HEADER from the CLR data directory, printing the + * runtime version, flags, entry point token or RVA, and the bounds of each + * embedded sub-directory (metadata, resources, strong name, etc.). + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param ClrDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR data directory entry + */ +static VOID +PeShowClrRuntime(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * ClrDirectory) +{ + ShowMessages("\n\nCLR runtime\n-----------"); + + if (ClrDirectory->VirtualAddress == 0 || ClrDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "CLR runtime header :", "empty"); + return; + } + + if (ClrDirectory->Size < 0x48) + { + ShowMessages("\n%-36s%s", "Warning :", "CLR runtime header is smaller than required fields"); + return; + } + + const BYTE * Header = NULL; + if (!PeGetPointerAtRva(Reader, ClrDirectory->VirtualAddress, 0x48, &Header)) + { + ShowMessages("\n%-36s%s", "CLR runtime header :", "not mapped"); + return; + } + + DWORD HeaderSize = PeReadDwordFromBuffer(Header, 0); + DWORD AvailableSize = ClrDirectory->Size < HeaderSize ? ClrDirectory->Size : HeaderSize; + + ShowMessages("\n%-36s%#x", "Header size :", HeaderSize); + if (HeaderSize < 0x48 || AvailableSize < 0x48) + { + ShowMessages("\n%-36s%s", "Warning :", "CLR runtime header is truncated"); + return; + } + + if (!PeGetPointerAtRva(Reader, ClrDirectory->VirtualAddress, AvailableSize, &Header)) + { + ShowMessages("\n%-36s%s", "CLR runtime header :", "invalid bounds"); + return; + } + + WORD MajorRuntimeVersion = PeReadWordFromBuffer(Header, 4); + WORD MinorRuntimeVersion = PeReadWordFromBuffer(Header, 6); + DWORD Flags = PeReadDwordFromBuffer(Header, 16); + DWORD EntryPoint = PeReadDwordFromBuffer(Header, 20); + + ShowMessages("\n%-36s%u.%u", "Runtime version :", MajorRuntimeVersion, MinorRuntimeVersion); + PeShowClrDirectoryBounds(Reader, Header, AvailableSize, 8, "Metadata directory :"); + ShowMessages("\n%-36s%#x", "Flags :", Flags); + ShowMessages("\n%-36s%#x (%s)", "Entry point token/RVA :", EntryPoint, (Flags & 0x10) != 0 ? "native RVA" : "managed token"); + PeShowClrDirectoryBounds(Reader, Header, AvailableSize, 24, "Resources directory :"); + PeShowClrDirectoryBounds(Reader, Header, AvailableSize, 32, "Strong name directory :"); + PeShowClrDirectoryBounds(Reader, Header, AvailableSize, 40, "Code manager table :"); + PeShowClrDirectoryBounds(Reader, Header, AvailableSize, 48, "VTable fixups :"); + PeShowClrDirectoryBounds(Reader, Header, AvailableSize, 56, "Export address table jumps :"); + PeShowClrDirectoryBounds(Reader, Header, AvailableSize, 64, "Managed native header :"); +} + +/** + * @brief Prints Thread Local Storage (TLS) directory fields and TLS callback addresses + * + * Reads IMAGE_TLS_DIRECTORY32 or IMAGE_TLS_DIRECTORY64 depending on Is32Bit and + * prints all fields. Then walks the null-terminated callback VA array, converting + * each entry to an RVA and file offset. Processing stops at 0x200 callbacks. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param TlsDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_TLS data directory entry + * @param Is32Bit TRUE if the PE image is 32-bit + * @param ImageBase Preferred image base used for VA-to-RVA conversion + */ +static VOID +PeShowTls(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * TlsDirectory, BOOLEAN Is32Bit, ULONGLONG ImageBase) +{ + const DWORD MaxCallbacks = 0x200; + DWORD TlsSize = Is32Bit ? sizeof(IMAGE_TLS_DIRECTORY32) : sizeof(IMAGE_TLS_DIRECTORY64); + + ShowMessages("\n\nTLS\n---"); + + if (TlsDirectory->VirtualAddress == 0 || TlsDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "TLS directory :", "empty"); + return; + } + + if (!PeRvaContainsRange(TlsDirectory->VirtualAddress, TlsDirectory->Size, TlsDirectory->VirtualAddress, TlsSize)) + { + ShowMessages("\n%-36s%s", "TLS directory :", "invalid bounds"); + return; + } + + const BYTE * TlsPointer = NULL; + if (!PeGetPointerAtRva(Reader, TlsDirectory->VirtualAddress, TlsSize, &TlsPointer)) + { + ShowMessages("\n%-36s%s", "TLS directory :", "not mapped"); + return; + } + + ULONGLONG StartRawDataVa = Is32Bit ? PeReadDwordFromBuffer(TlsPointer, 0) : PeReadQwordFromBuffer(TlsPointer, 0); + ULONGLONG EndRawDataVa = Is32Bit ? PeReadDwordFromBuffer(TlsPointer, 4) : PeReadQwordFromBuffer(TlsPointer, 8); + ULONGLONG AddressOfIndexVa = Is32Bit ? PeReadDwordFromBuffer(TlsPointer, 8) : PeReadQwordFromBuffer(TlsPointer, 16); + ULONGLONG AddressCallbacksVa = Is32Bit ? PeReadDwordFromBuffer(TlsPointer, 12) : PeReadQwordFromBuffer(TlsPointer, 24); + DWORD SizeOfZeroFill = Is32Bit ? PeReadDwordFromBuffer(TlsPointer, 16) : PeReadDwordFromBuffer(TlsPointer, 32); + DWORD Characteristics = Is32Bit ? PeReadDwordFromBuffer(TlsPointer, 20) : PeReadDwordFromBuffer(TlsPointer, 36); + + ShowMessages("\n%-36s%#llx", "Start address of raw data VA :", StartRawDataVa); + ShowMessages("\n%-36s%#llx", "End address of raw data VA :", EndRawDataVa); + ShowMessages("\n%-36s%#llx", "Address of index VA :", AddressOfIndexVa); + ShowMessages("\n%-36s%#llx", "Address of callbacks VA :", AddressCallbacksVa); + ShowMessages("\n%-36s%#x", "Size of zero fill :", SizeOfZeroFill); + ShowMessages("\n%-36s%#x", "Characteristics :", Characteristics); + + DWORD CallbacksRva = 0; + if (AddressCallbacksVa == 0) + { + ShowMessages("\n%-36s%s", "TLS callbacks :", "empty"); + return; + } + + if (!PeVaToRva(AddressCallbacksVa, ImageBase, &CallbacksRva)) + { + ShowMessages("\n%-36s%#llx", "Warning, invalid callbacks VA :", AddressCallbacksVa); + return; + } + + DWORD EntrySize = Is32Bit ? sizeof(DWORD) : sizeof(ULONGLONG); + for (DWORD CallbackIndex = 0; CallbackIndex < MaxCallbacks; CallbackIndex++) + { + DWORD EntryRva = 0; + if (!PeAddDword(CallbacksRva, CallbackIndex * EntrySize, &EntryRva)) + { + ShowMessages("\n%-36s%s", "Warning :", "TLS callback RVA overflow"); + return; + } + + ULONGLONG CallbackVa = 0; + if (!PeReadThunkAtRva(Reader, EntryRva, Is32Bit, &CallbackVa)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid callback entry RVA :", EntryRva); + return; + } + + if (CallbackVa == 0) + { + return; + } + + DWORD CallbackRva = 0; + SIZE_T FileOffset = 0; + if (PeVaToRva(CallbackVa, ImageBase, &CallbackRva)) + { + if (PeImageReaderRvaToFileOffset(Reader, CallbackRva, 1, &FileOffset)) + { + ShowMessages("\n [%u] VA %#llx RVA %#x file offset %#llx", CallbackIndex, CallbackVa, CallbackRva, (UINT64)FileOffset); + } + else + { + ShowMessages("\n [%u] VA %#llx RVA %#x file offset %s", CallbackIndex, CallbackVa, CallbackRva, "not mapped"); + } + } + else + { + ShowMessages("\n [%u] VA %#llx RVA %s", CallbackIndex, CallbackVa, "invalid"); + } + } + + ShowMessages("\n%-36s%#x", "Warning, TLS callback cap reached :", MaxCallbacks); +} + +/** + * @brief Prints CodeView debug information embedded in a debug directory entry + * + * Handles both the RSDS (PDB 7.0) and NB10 (PDB 2.0) CodeView formats. + * For RSDS entries, prints the GUID, age, and PDB path. For NB10 entries, + * prints the offset, signature, age, and PDB path. Silently returns for + * non-CodeView entries or entries with insufficient data. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param Entry Pointer to the IMAGE_DEBUG_DIRECTORY entry to decode + */ +static VOID +PeShowDebugCodeView(PPE_IMAGE_READER Reader, const IMAGE_DEBUG_DIRECTORY * Entry) +{ + const DWORD MaxPdbPathLength = 0x400; + + if (Entry->Type != IMAGE_DEBUG_TYPE_CODEVIEW || Entry->SizeOfData < sizeof(DWORD)) + { + return; + } + + const BYTE * Payload = NULL; + if ((Entry->PointerToRawData == 0 || !PeImageReaderGetPointerAtOffset(Reader, Entry->PointerToRawData, Entry->SizeOfData, &Payload)) && + (Entry->AddressOfRawData == 0 || !PeGetPointerAtRva(Reader, Entry->AddressOfRawData, Entry->SizeOfData, &Payload))) + { + ShowMessages("\n%-36s%s", " CodeView payload :", "invalid bounds"); + return; + } + + if (memcmp(Payload, "RSDS", sizeof(DWORD)) == 0) + { + if (Entry->SizeOfData < 24) + { + ShowMessages("\n%-36s%s", " CodeView RSDS :", "truncated"); + return; + } + + DWORD Age = PeReadDwordFromBuffer(Payload, 20); + DWORD PathOffset = 24; + DWORD PathSize = Entry->SizeOfData - 24; + DWORD PathLimit = PathSize < MaxPdbPathLength ? PathSize : MaxPdbPathLength; + CHAR PdbPath[MaxPdbPathLength + 1] = {0}; + const BYTE * Guid = Payload + 4; + + PE_ASCII_STRING_STATUS PathStatus = PeReadAsciiStringFromBuffer(Payload + PathOffset, PathLimit, PdbPath, sizeof(PdbPath)); + ShowMessages("\n%-36s%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + " CodeView RSDS GUID :", + Guid[3], + Guid[2], + Guid[1], + Guid[0], + Guid[5], + Guid[4], + Guid[7], + Guid[6], + Guid[8], + Guid[9], + Guid[10], + Guid[11], + Guid[12], + Guid[13], + Guid[14], + Guid[15]); + ShowMessages("\n%-36s%u", " CodeView age :", Age); + ShowMessages("\n%-36s%s", " CodeView PDB path :", PathStatus == PeAsciiStringOk ? PdbPath : PeAsciiStatusName(PathStatus)); + } + else if (memcmp(Payload, "NB10", sizeof(DWORD)) == 0) + { + if (Entry->SizeOfData < 16) + { + ShowMessages("\n%-36s%s", " CodeView NB10 :", "truncated"); + return; + } + + DWORD Offset = PeReadDwordFromBuffer(Payload, 4); + DWORD Timestamp = PeReadDwordFromBuffer(Payload, 8); + DWORD Age = PeReadDwordFromBuffer(Payload, 12); + DWORD PathOffset = 16; + DWORD PathSize = Entry->SizeOfData - 16; + DWORD PathLimit = PathSize < MaxPdbPathLength ? PathSize : MaxPdbPathLength; + CHAR PdbPath[MaxPdbPathLength + 1] = {0}; + + PE_ASCII_STRING_STATUS PathStatus = PeReadAsciiStringFromBuffer(Payload + PathOffset, PathLimit, PdbPath, sizeof(PdbPath)); + ShowMessages("\n%-36s%#x", " CodeView NB10 offset :", Offset); + ShowMessages("\n%-36s%#x", " CodeView NB10 signature :", Timestamp); + ShowMessages("\n%-36s%u", " CodeView age :", Age); + ShowMessages("\n%-36s%s", " CodeView PDB path :", PathStatus == PeAsciiStringOk ? PdbPath : PeAsciiStatusName(PathStatus)); + } +} + +/** + * @brief Prints all IMAGE_DEBUG_DIRECTORY entries in the debug data directory + * + * Iterates the debug directory, printing characteristics, timestamp, version, + * type, size, and address fields for each entry. Also validates the raw data + * bounds and delegates to PeShowDebugCodeView for CodeView entries. + * Processing is capped at 0x1000 entries. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param DebugDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_DEBUG data directory entry + */ +static VOID +PeShowDebug(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * DebugDirectory) +{ + const DWORD MaxDebugEntries = 0x1000; + + ShowMessages("\n\nDebug\n-----"); + + if (DebugDirectory->VirtualAddress == 0 || DebugDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "Debug directory :", "empty"); + return; + } + + DWORD EntryCount = DebugDirectory->Size / sizeof(IMAGE_DEBUG_DIRECTORY); + if (EntryCount == 0) + { + ShowMessages("\n%-36s%s", "Warning :", "debug directory is smaller than one descriptor"); + return; + } + + if ((DebugDirectory->Size % sizeof(IMAGE_DEBUG_DIRECTORY)) != 0) + { + ShowMessages("\n%-36s%#x", "Warning, malformed debug size :", DebugDirectory->Size); + } + + BOOLEAN EntryCapped = FALSE; + if (EntryCount > MaxDebugEntries) + { + EntryCount = MaxDebugEntries; + EntryCapped = TRUE; + } + + for (DWORD EntryIndex = 0; EntryIndex < EntryCount; EntryIndex++) + { + DWORD EntryRva = 0; + if (!PeAddDword(DebugDirectory->VirtualAddress, EntryIndex * (DWORD)sizeof(IMAGE_DEBUG_DIRECTORY), &EntryRva)) + { + ShowMessages("\n%-36s%s", "Warning :", "debug directory RVA overflow"); + break; + } + + const IMAGE_DEBUG_DIRECTORY * Entry = NULL; + if (!PeGetPointerAtRva(Reader, EntryRva, sizeof(IMAGE_DEBUG_DIRECTORY), (const BYTE **)&Entry)) + { + ShowMessages("\n%-36s%s", "Warning :", "debug directory entry is not mapped"); + break; + } + + ShowMessages("\n[%u] characteristics %#x time date stamp %#x major %u minor %u type %u size %#x address %#x raw %#x", + EntryIndex, + Entry->Characteristics, + Entry->TimeDateStamp, + Entry->MajorVersion, + Entry->MinorVersion, + Entry->Type, + Entry->SizeOfData, + Entry->AddressOfRawData, + Entry->PointerToRawData); + + if (Entry->SizeOfData != 0 && Entry->PointerToRawData != 0) + { + const BYTE * Payload = NULL; + ShowMessages("\n%-36s%s", " Payload bounds :", PeImageReaderGetPointerAtOffset(Reader, Entry->PointerToRawData, Entry->SizeOfData, &Payload) ? "valid" : "invalid"); + } + + PeShowDebugCodeView(Reader, Entry); + } + + if (EntryCapped) + { + ShowMessages("\n%-36s%#x", "Warning, debug entry cap reached :", MaxDebugEntries); + } +} + +/** + * @brief Checks whether a load configuration structure contains a specific field + * + * Returns TRUE when the range [Offset, Offset + FieldSize) lies entirely within + * the first AvailableSize bytes of the load config buffer. + * + * @param AvailableSize Number of bytes available in the load config buffer + * @param Offset Byte offset of the field within the load config structure + * @param FieldSize Size of the field in bytes + * + * @return BOOLEAN TRUE if the field is present, FALSE if it is beyond AvailableSize + */ +static BOOLEAN +PeLoadConfigHasField(DWORD AvailableSize, SIZE_T Offset, SIZE_T FieldSize) +{ + return Offset <= AvailableSize && FieldSize <= AvailableSize - Offset; +} + +/** + * @brief Prints a DWORD field from the load config structure if it is present + * + * Uses PeLoadConfigHasField to verify the field is within AvailableSize before + * reading and printing the value with the supplied label. + * + * @param Config Pointer to the load configuration byte buffer + * @param AvailableSize Number of validated bytes in Config + * @param Offset Byte offset of the DWORD field within Config + * @param Label Column label to print before the value + */ +static VOID +PeShowLoadConfigDword(const BYTE * Config, DWORD AvailableSize, SIZE_T Offset, const CHAR * Label) +{ + if (PeLoadConfigHasField(AvailableSize, Offset, sizeof(DWORD))) + { + ShowMessages("\n%-36s%#x", Label, PeReadDwordFromBuffer(Config, Offset)); + } +} + +/** + * @brief Prints a pointer-sized field from the load config structure if it is present + * + * Reads sizeof(DWORD) or sizeof(ULONGLONG) depending on Is32Bit, verifies + * presence with PeLoadConfigHasField, and prints the value as a hex address. + * + * @param Config Pointer to the load configuration byte buffer + * @param AvailableSize Number of validated bytes in Config + * @param Offset Byte offset of the pointer field within Config + * @param Label Column label to print before the value + * @param Is32Bit TRUE to read a 32-bit pointer, FALSE for a 64-bit pointer + */ +static VOID +PeShowLoadConfigPointer(const BYTE * Config, DWORD AvailableSize, SIZE_T Offset, const CHAR * Label, BOOLEAN Is32Bit) +{ + SIZE_T FieldSize = Is32Bit ? sizeof(DWORD) : sizeof(ULONGLONG); + + if (PeLoadConfigHasField(AvailableSize, Offset, FieldSize)) + { + ShowMessages("\n%-36s%#llx", Label, PeReadLoadConfigPointer(Config, Offset, Is32Bit)); + } +} + +/** + * @brief Prints a count field (pointer-sized) from the load config structure if present + * + * Behaves identically to PeShowLoadConfigPointer but formats the value as a + * decimal count rather than a hex address. + * + * @param Config Pointer to the load configuration byte buffer + * @param AvailableSize Number of validated bytes in Config + * @param Offset Byte offset of the count field within Config + * @param Label Column label to print before the value + * @param Is32Bit TRUE to read a 32-bit count, FALSE for a 64-bit count + */ +static VOID +PeShowLoadConfigCount(const BYTE * Config, DWORD AvailableSize, SIZE_T Offset, const CHAR * Label, BOOLEAN Is32Bit) +{ + SIZE_T FieldSize = Is32Bit ? sizeof(DWORD) : sizeof(ULONGLONG); + + if (PeLoadConfigHasField(AvailableSize, Offset, FieldSize)) + { + ShowMessages("\n%-36s%llu", Label, PeReadLoadConfigPointer(Config, Offset, Is32Bit)); + } +} + +/** + * @brief Prints the names of set guard control-flow flags from a load config guard flags field + * + * Iterates a table of known guard flag bitmasks and prints the name of each + * set bit. Reports "None" when no known flags are set, and appends the + * unknown bitmask when unrecognised bits are present. + * + * @param GuardFlags The GuardFlags field value from the load configuration structure + */ +static VOID +PeShowLoadConfigGuardFlags(DWORD GuardFlags) +{ + BOOLEAN AnyFlag = FALSE; + DWORD KnownMask = 0; + + struct GUARD_FLAG_NAME + { + DWORD Flag; + const CHAR * Name; + }; + + static const GUARD_FLAG_NAME GuardFlagNames[] = { + {0x00000100, "CF instrumented"}, + {0x00000200, "CFW instrumented"}, + {0x00000400, "CF function table present"}, + {0x00000800, "Security cookie unused"}, + {0x00001000, "Protect delayed load IAT"}, + {0x00002000, "Delayed load IAT in its own section"}, + {0x00004000, "Export suppression info present"}, + {0x00008000, "Enable export suppression"}, + {0x00010000, "Long jump table present"}, + {0x00020000, "RF instrumented"}, + {0x00040000, "RF enable"}, + {0x00080000, "RF strict"}, + {0x00100000, "Retpoline present"}, + {0x00200000, "EH continuation table present"}, + {0x00400000, "XFG enabled"}, + {0x00800000, "CastGuard present"}, + {0x01000000, "Memcpy function present"}, + }; + + for (UINT32 Index = 0; Index < RTL_NUMBER_OF(GuardFlagNames); Index++) + { + KnownMask |= GuardFlagNames[Index].Flag; + if ((GuardFlags & GuardFlagNames[Index].Flag) == GuardFlagNames[Index].Flag) + { + ShowMessages("%s%s", AnyFlag ? ", " : "", GuardFlagNames[Index].Name); + AnyFlag = TRUE; + } + } + + if (!AnyFlag) + { + ShowMessages(GuardFlags == 0 ? "None" : "No known guard flags"); + } + + DWORD UnknownMask = GuardFlags & ~KnownMask; + if (UnknownMask != 0) + { + ShowMessages(", unknown mask %#x", UnknownMask); + } +} + +/** + * @brief Prints extended load config fields introduced in Windows 8.1 and later + * + * Handles guard address-taken IAT, guard long-jump tables, dynamic value + * relocation, CHPE metadata, RF (return-flow) guards, EH continuation tables, + * XFG, CastGuard, and memcpy pointer fields. Each field is printed only when + * AvailableSize covers its offset. + * + * @param Config Pointer to the load configuration byte buffer + * @param AvailableSize Number of validated bytes in Config + * @param Is32Bit TRUE for PE32 field offsets, FALSE for PE32+ field offsets + */ +static VOID +PeShowLoadConfigModernFields(const BYTE * Config, DWORD AvailableSize, BOOLEAN Is32Bit) +{ + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 104 : 160, "Guard address-taken IAT table :", Is32Bit); + PeShowLoadConfigCount(Config, AvailableSize, Is32Bit ? 108 : 168, "Guard address-taken IAT count :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 112 : 176, "Guard long jump target table :", Is32Bit); + PeShowLoadConfigCount(Config, AvailableSize, Is32Bit ? 116 : 184, "Guard long jump target count :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 120 : 192, "Dynamic value reloc table :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 124 : 200, "CHPE metadata pointer :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 128 : 208, "Guard RF failure routine :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 132 : 216, "Guard RF failure routine ptr :", Is32Bit); + PeShowLoadConfigDword(Config, AvailableSize, Is32Bit ? 136 : 224, "Dynamic value reloc offset :"); + if (PeLoadConfigHasField(AvailableSize, Is32Bit ? 140 : 228, sizeof(WORD))) + { + ShowMessages("\n%-36s%#x", "Dynamic value reloc section :", PeReadWordFromBuffer(Config, Is32Bit ? 140 : 228)); + } + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 144 : 232, "Guard RF verify stack ptr :", Is32Bit); + PeShowLoadConfigDword(Config, AvailableSize, Is32Bit ? 148 : 240, "Hot patch table offset :"); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 156 : 248, "Enclave config pointer :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 160 : 256, "Volatile metadata pointer :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 164 : 264, "Guard EH continuation table :", Is32Bit); + PeShowLoadConfigCount(Config, AvailableSize, Is32Bit ? 168 : 272, "Guard EH continuation count :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 172 : 280, "Guard XFG check pointer :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 176 : 288, "Guard XFG dispatch pointer :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 180 : 296, "Guard XFG table dispatch ptr :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 184 : 304, "CastGuard failure mode :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 188 : 312, "Guard memcpy pointer :", Is32Bit); +} + +/** + * @brief Prints the load configuration directory + * + * Reads the self-describing size field at the start of the load config + * structure, clamps to the directory bounds, and prints security cookie, + * SEH handler table, guard CF fields, guard flags, and extended modern + * fields via helper functions. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param LoadConfigDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG data directory entry + * @param Is32Bit TRUE if the PE image is 32-bit + */ +static VOID +PeShowLoadConfig(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * LoadConfigDirectory, BOOLEAN Is32Bit) +{ + ShowMessages("\n\nLoad config\n-----------"); + + if (LoadConfigDirectory->VirtualAddress == 0 || LoadConfigDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "Load config directory :", "empty"); + return; + } + + if (LoadConfigDirectory->Size < sizeof(DWORD)) + { + ShowMessages("\n%-36s%s", "Warning :", "load config size is too small"); + return; + } + + const BYTE * Config = NULL; + if (!PeGetPointerAtRva(Reader, LoadConfigDirectory->VirtualAddress, sizeof(DWORD), &Config)) + { + ShowMessages("\n%-36s%s", "Load config directory :", "not mapped"); + return; + } + + DWORD ConfigSize = PeReadDwordFromBuffer(Config, 0); + DWORD AvailableSize = LoadConfigDirectory->Size < ConfigSize ? LoadConfigDirectory->Size : ConfigSize; + + ShowMessages("\n%-36s%#x", "Size :", ConfigSize); + if (AvailableSize < sizeof(DWORD)) + { + ShowMessages("\n%-36s%s", "Warning :", "load config size is too small"); + return; + } + + if (!PeGetPointerAtRva(Reader, LoadConfigDirectory->VirtualAddress, AvailableSize, &Config)) + { + ShowMessages("\n%-36s%s", "Load config directory :", "invalid bounds"); + return; + } + + PeShowLoadConfigDword(Config, AvailableSize, 4, "Time date stamp :"); + if (PeLoadConfigHasField(AvailableSize, 8, sizeof(WORD))) + { + WORD MajorVersion = 0; + CopyMemory(&MajorVersion, Config + 8, sizeof(MajorVersion)); + ShowMessages("\n%-36s%u", "Major version :", MajorVersion); + } + if (PeLoadConfigHasField(AvailableSize, 10, sizeof(WORD))) + { + WORD MinorVersion = 0; + CopyMemory(&MinorVersion, Config + 10, sizeof(MinorVersion)); + ShowMessages("\n%-36s%u", "Minor version :", MinorVersion); + } + PeShowLoadConfigDword(Config, AvailableSize, 12, "Global flags clear :"); + PeShowLoadConfigDword(Config, AvailableSize, 16, "Global flags set :"); + PeShowLoadConfigDword(Config, AvailableSize, 20, "Critical section timeout :"); + PeShowLoadConfigDword(Config, AvailableSize, Is32Bit ? 44 : 72, "Process heap flags :"); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 60 : 88, "Security cookie :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 64 : 96, "SE handler table :", Is32Bit); + PeShowLoadConfigCount(Config, AvailableSize, Is32Bit ? 68 : 104, "SE handler count :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 72 : 112, "Guard CF check pointer :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 76 : 120, "Guard CF dispatch pointer :", Is32Bit); + PeShowLoadConfigPointer(Config, AvailableSize, Is32Bit ? 80 : 128, "Guard CF function table :", Is32Bit); + PeShowLoadConfigCount(Config, AvailableSize, Is32Bit ? 84 : 136, "Guard CF function count :", Is32Bit); + PeShowLoadConfigDword(Config, AvailableSize, Is32Bit ? 88 : 144, "Guard flags :"); + if (PeLoadConfigHasField(AvailableSize, Is32Bit ? 88 : 144, sizeof(DWORD))) + { + DWORD GuardFlags = PeReadDwordFromBuffer(Config, Is32Bit ? 88 : 144); + ShowMessages("\n%-36s", "Guard flag names :"); + PeShowLoadConfigGuardFlags(GuardFlags); + } + PeShowLoadConfigModernFields(Config, AvailableSize, Is32Bit); +} + +/** + * @brief Prints a summary of all PE data directory entries + * + * Iterates IMAGE_NUMBEROF_DIRECTORY_ENTRIES slots, printing the name, RVA + * (or file offset for the certificate entry), size, and mapping status of + * each. Entries beyond NumberOfRvaAndSizes are marked as "not declared". + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param Directories Pointer to the data directory array from the optional header + * @param NumberOfRvaAndSizes Value of NumberOfRvaAndSizes from the optional header + */ +static VOID +PeShowDataDirectories(PPE_IMAGE_READER Reader, + const IMAGE_DATA_DIRECTORY * Directories, + DWORD NumberOfRvaAndSizes) +{ + ShowMessages("\n\nData directories\n----------------"); + ShowMessages("\n%-36s%u", "Number of RVA and sizes :", NumberOfRvaAndSizes); + if (NumberOfRvaAndSizes > IMAGE_NUMBEROF_DIRECTORY_ENTRIES) + { + ShowMessages("\n%-36s%s", "Warning :", "number of RVA and sizes exceeds PE directory table"); + } + + for (UINT32 Index = 0; Index < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; Index++) + { + const CHAR * Name = PeGetDataDirectoryName(Index); + const CHAR * AddressLabel = Index == IMAGE_DIRECTORY_ENTRY_SECURITY ? "file offset" : "RVA"; + + if (Index >= NumberOfRvaAndSizes) + { + ShowMessages("\n[%2u] %-27s %s", Index, Name, "not declared"); + continue; + } + + const IMAGE_DATA_DIRECTORY * Directory = &Directories[Index]; + if (Directory->VirtualAddress == 0 || Directory->Size == 0) + { + ShowMessages("\n[%2u] %-27s %s %#x, size %#x, %s", + Index, + Name, + AddressLabel, + Directory->VirtualAddress, + Directory->Size, + "empty"); + continue; + } + + const BYTE * Pointer = NULL; + SIZE_T FileOffset = 0; + + if (Index == IMAGE_DIRECTORY_ENTRY_SECURITY) + { + BOOLEAN HasBounds = PeImageReaderGetPointerAtOffset(Reader, + Directory->VirtualAddress, + Directory->Size, + &Pointer); + + ShowMessages("\n[%2u] %-27s file offset %#x, size %#x, %s", + Index, + Name, + Directory->VirtualAddress, + Directory->Size, + HasBounds ? "valid bounds" : "invalid bounds"); + if (HasBounds) + { + ShowMessages(", mapped file offset %#llx", (UINT64)Directory->VirtualAddress); + } + + continue; + } + + if (PeImageReaderRvaToFileOffset(Reader, Directory->VirtualAddress, Directory->Size, &FileOffset)) + { + ShowMessages("\n[%2u] %-27s RVA %#x, size %#x, mapped file offset %#llx", + Index, + Name, + Directory->VirtualAddress, + Directory->Size, + (UINT64)FileOffset); + } + else + { + ShowMessages("\n[%2u] %-27s RVA %#x, size %#x, %s", + Index, + Name, + Directory->VirtualAddress, + Directory->Size, + "not mapped"); + } + } +} + +/** + * @brief Prints overlay data information and PE layout warnings + * + * Identifies data appended after all mapped sections (overlay), checks for + * section overlaps and gaps, validates SizeOfImage, and emits warnings for + * mismatched optional header magic/machine combinations, sections that extend + * beyond SizeOfImage, and inconsistent section raw data boundaries. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param Machine Machine type from the PE file header + * @param OptionalHeaderMagic Magic value from the PE optional header + * @param AddressOfEntryPoint AddressOfEntryPoint from the PE optional header + * @param SizeOfImage SizeOfImage from the PE optional header + * @param SizeOfHeaders SizeOfHeaders from the PE optional header + * @param Directories Pointer to the data directory array + * @param NumberOfRvaAndSizes Value of NumberOfRvaAndSizes from the optional header + */ +static VOID +PeShowOverlayAndWarnings(PPE_IMAGE_READER Reader, + WORD Machine, + WORD OptionalHeaderMagic, + DWORD AddressOfEntryPoint, + DWORD SizeOfImage, + DWORD SizeOfHeaders, + const IMAGE_DATA_DIRECTORY * Directories, + DWORD NumberOfRvaAndSizes) +{ + ULONGLONG OverlayOffset = SizeOfHeaders < Reader->ImageSize ? SizeOfHeaders : Reader->ImageSize; + BOOLEAN OverlayUnreliable = FALSE; + + ShowMessages("\n\nOverlay and warnings\n--------------------"); + + if ((ULONGLONG)SizeOfHeaders > (ULONGLONG)Reader->ImageSize) + { + ShowMessages("\n%-36s%s", "Warning :", "size of headers is larger than file size"); + } + + if (OptionalHeaderMagic == IMAGE_NT_OPTIONAL_HDR64_MAGIC && Machine == IMAGE_FILE_MACHINE_I386) + { + ShowMessages("\n%-36s%s", "Warning :", "PE32+ optional header with i386 machine type"); + } + else if (OptionalHeaderMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC && + (Machine == IMAGE_FILE_MACHINE_AMD64 || Machine == IMAGE_FILE_MACHINE_IA64)) + { + ShowMessages("\n%-36s%s", "Warning :", "PE32 optional header with 64-bit machine type"); + } + + for (UINT32 SectionIndex = 0; SectionIndex < Reader->FileHeader->NumberOfSections; SectionIndex++) + { + CHAR SectionName[IMAGE_SIZEOF_SHORT_NAME + 1]; + const IMAGE_SECTION_HEADER * Section = &Reader->SectionHeaders[SectionIndex]; + DWORD VirtualSpan = Section->Misc.VirtualSize > Section->SizeOfRawData ? Section->Misc.VirtualSize : Section->SizeOfRawData; + DWORD VirtualEnd = 0; + + PeImageReaderGetSectionName(Section, SectionName, sizeof(SectionName)); + + if (VirtualSpan != 0) + { + if (!PeAddDword(Section->VirtualAddress, VirtualSpan, &VirtualEnd)) + { + ShowMessages("\n%-36ssection '%s' RVA range overflows", "Warning :", SectionName); + } + else if (SizeOfImage != 0 && VirtualEnd > SizeOfImage) + { + ShowMessages("\n%-36ssection '%s' RVA range exceeds SizeOfImage", "Warning :", SectionName); + } + } + + if (Section->SizeOfRawData != 0) + { + ULONGLONG RawStart = Section->PointerToRawData; + ULONGLONG RawEnd = 0; + + if (!PeAddUlonglong(RawStart, Section->SizeOfRawData, &RawEnd)) + { + ShowMessages("\n%-36ssection '%s' raw data range overflows", "Warning :", SectionName); + OverlayUnreliable = TRUE; + } + else if (RawStart > (ULONGLONG)Reader->ImageSize || RawEnd > (ULONGLONG)Reader->ImageSize) + { + ShowMessages("\n%-36ssection '%s' raw data is outside file", "Warning :", SectionName); + OverlayUnreliable = TRUE; + } + else if (RawEnd > OverlayOffset) + { + OverlayOffset = RawEnd; + } + } + } + + if (Reader->FileHeader->NumberOfSections > 1) + { + PE_RAW_SECTION_RANGE * Ranges = (PE_RAW_SECTION_RANGE *)malloc(sizeof(PE_RAW_SECTION_RANGE) * Reader->FileHeader->NumberOfSections); + UINT32 Count = 0; + + if (Ranges == NULL) + { + ShowMessages("\n%-36s%s", "Warning :", "raw section overlap check skipped, allocation failed"); + } + else + { + for (UINT32 SectionIndex = 0; SectionIndex < Reader->FileHeader->NumberOfSections; SectionIndex++) + { + const IMAGE_SECTION_HEADER * Section = &Reader->SectionHeaders[SectionIndex]; + ULONGLONG End; + + if (Section->SizeOfRawData == 0 || + !PeAddUlonglong(Section->PointerToRawData, Section->SizeOfRawData, &End) || + Section->PointerToRawData > Reader->ImageSize || End > Reader->ImageSize) + { + continue; + } + + Ranges[Count].Start = Section->PointerToRawData; + Ranges[Count].End = End; + Ranges[Count].Section = Section; + Count++; + } + + if (Count > 1) + { + UINT32 MaxEndIndex = 0; + + qsort(Ranges, Count, sizeof(Ranges[0]), PeCompareRawSectionRange); + + for (UINT32 RangeIndex = 1; RangeIndex < Count; RangeIndex++) + { + if (Ranges[RangeIndex].Start < Ranges[MaxEndIndex].End) + { + CHAR LeftName[IMAGE_SIZEOF_SHORT_NAME + 1]; + CHAR RightName[IMAGE_SIZEOF_SHORT_NAME + 1]; + + PeImageReaderGetSectionName(Ranges[MaxEndIndex].Section, LeftName, sizeof(LeftName)); + PeImageReaderGetSectionName(Ranges[RangeIndex].Section, RightName, sizeof(RightName)); + ShowMessages("\n%-36sraw data overlap detected between '%s' and '%s'; additional overlaps may be omitted", + "Warning :", + LeftName, + RightName); + } + + if (Ranges[RangeIndex].End > Ranges[MaxEndIndex].End) + { + MaxEndIndex = RangeIndex; + } + } + } + + free(Ranges); + } + } + + if (AddressOfEntryPoint != 0) + { + BOOLEAN EntrypointFound = FALSE; + const IMAGE_SECTION_HEADER * EntrypointSection = NULL; + + for (UINT32 SectionIndex = 0; SectionIndex < Reader->FileHeader->NumberOfSections; SectionIndex++) + { + const IMAGE_SECTION_HEADER * Section = &Reader->SectionHeaders[SectionIndex]; + DWORD VirtualSpan = Section->Misc.VirtualSize > Section->SizeOfRawData ? Section->Misc.VirtualSize : Section->SizeOfRawData; + DWORD VirtualEnd = 0; + + if (VirtualSpan == 0 || !PeAddDword(Section->VirtualAddress, VirtualSpan, &VirtualEnd)) + { + continue; + } + + if (AddressOfEntryPoint >= Section->VirtualAddress && AddressOfEntryPoint < VirtualEnd) + { + EntrypointFound = TRUE; + EntrypointSection = Section; + break; + } + } + + if (!EntrypointFound) + { + ShowMessages("\n%-36s%s", "Warning :", "entrypoint is outside all sections"); + } + else if ((EntrypointSection->Characteristics & IMAGE_SCN_MEM_EXECUTE) == 0) + { + CHAR SectionName[IMAGE_SIZEOF_SHORT_NAME + 1]; + + PeImageReaderGetSectionName(EntrypointSection, SectionName, sizeof(SectionName)); + ShowMessages("\n%-36sentrypoint section '%s' is not executable", "Warning :", SectionName); + } + } + + if (OverlayUnreliable) + { + ShowMessages("\n%-36s%s", "Overlay :", "not computed because section raw data is invalid"); + } + else if ((ULONGLONG)Reader->ImageSize > OverlayOffset) + { + ULONGLONG OverlaySize = (ULONGLONG)Reader->ImageSize - OverlayOffset; + + ShowMessages("\n%-36s%#llx", "Overlay offset :", OverlayOffset); + ShowMessages("\n%-36s%#llx", "Overlay size :", OverlaySize); + + if (Directories != NULL && NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_SECURITY) + { + const IMAGE_DATA_DIRECTORY * SecurityDirectory = &Directories[IMAGE_DIRECTORY_ENTRY_SECURITY]; + + if (SecurityDirectory->VirtualAddress != 0 && SecurityDirectory->Size != 0 && + (ULONGLONG)SecurityDirectory->VirtualAddress >= OverlayOffset) + { + ShowMessages("\n%-36s%s", "Info :", "overlay includes certificate data; not necessarily suspicious"); + } + } + } + else + { + ShowMessages("\n%-36s%s", "Overlay :", "none"); + } +} + +/** + * @brief Prints all import descriptors and their imported function names or ordinals + * + * Iterates IMAGE_IMPORT_DESCRIPTOR records, resolving DLL names and walking + * the original-first-thunk (or first-thunk) arrays to print each imported + * symbol with its hint and IAT RVA. Warns when the null terminator descriptor + * is not found within the declared directory size. Processing is capped at + * 0x1000 descriptors and 0x2000 total imports. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param ImportDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_IMPORT data directory entry + * @param Is32Bit TRUE if the PE image is 32-bit + */ +static VOID +PeShowImports(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * ImportDirectory, BOOLEAN Is32Bit) +{ + const DWORD MaxImportDescriptors = 0x1000; + const DWORD MaxTotalImports = 0x2000; + const DWORD MaxDllNameLength = 0x200; + const DWORD MaxImportNameLength = 0x200; + + ShowMessages("\n\nImports\n-------"); + + if (ImportDirectory->VirtualAddress == 0 || ImportDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "Import directory :", "empty"); + return; + } + + const BYTE * DirectoryPointer = NULL; + if (!PeGetPointerAtRva(Reader, ImportDirectory->VirtualAddress, sizeof(IMAGE_IMPORT_DESCRIPTOR), &DirectoryPointer)) + { + ShowMessages("\n%-36s%s", "Import directory :", "not mapped"); + return; + } + + DWORD DescriptorCount = ImportDirectory->Size / sizeof(IMAGE_IMPORT_DESCRIPTOR); + if (DescriptorCount == 0) + { + ShowMessages("\n%-36s%s", "Warning :", "import directory is smaller than one descriptor"); + return; + } + + BOOLEAN DescriptorCapped = FALSE; + if (DescriptorCount > MaxImportDescriptors) + { + DescriptorCount = MaxImportDescriptors; + DescriptorCapped = TRUE; + } + + DWORD TotalImports = 0; + BOOLEAN FoundTerminator = FALSE; + BOOLEAN TotalImportsCapped = FALSE; + + for (DWORD DescriptorIndex = 0; DescriptorIndex < DescriptorCount; DescriptorIndex++) + { + DWORD DescriptorRva = 0; + + if (!PeAddDword(ImportDirectory->VirtualAddress, + DescriptorIndex * (DWORD)sizeof(IMAGE_IMPORT_DESCRIPTOR), + &DescriptorRva)) + { + break; + } + + const IMAGE_IMPORT_DESCRIPTOR * Descriptor = NULL; + if (!PeGetPointerAtRva(Reader, + DescriptorRva, + sizeof(IMAGE_IMPORT_DESCRIPTOR), + (const BYTE **)&Descriptor)) + { + ShowMessages("\n%-36s%s", "Warning :", "import descriptor is not mapped"); + break; + } + + if (Descriptor->OriginalFirstThunk == 0 && Descriptor->TimeDateStamp == 0 && Descriptor->ForwarderChain == 0 && + Descriptor->Name == 0 && Descriptor->FirstThunk == 0) + { + FoundTerminator = TRUE; + break; + } + + CHAR DllName[MaxDllNameLength + 1] = {0}; + PE_ASCII_STRING_STATUS DllNameStatus = PeReadAsciiStringAtRva(Reader, + Descriptor->Name, + MaxDllNameLength, + DllName, + sizeof(DllName)); + if (DllNameStatus != PeAsciiStringOk) + { + ShowMessages("\n[%u] DLL name %s", DescriptorIndex, PeAsciiStatusName(DllNameStatus)); + ShowMessages("\n%-36s%s", "Warning :", "skipping imports for descriptor with unreadable DLL name"); + continue; + } + + ShowMessages("\n[%u] DLL name %s", DescriptorIndex, DllName); + + DWORD LookupThunkRva = Descriptor->OriginalFirstThunk != 0 ? Descriptor->OriginalFirstThunk : Descriptor->FirstThunk; + if (LookupThunkRva == 0 || Descriptor->FirstThunk == 0) + { + ShowMessages("\n%-36s%s", "Warning :", "import thunk array is empty"); + continue; + } + + DWORD ThunkSize = Is32Bit ? sizeof(DWORD) : sizeof(ULONGLONG); + for (DWORD ThunkIndex = 0; TotalImports < MaxTotalImports; ThunkIndex++) + { + DWORD LookupEntryRva = 0; + DWORD IatEntryRva = 0; + if (!PeAddDword(LookupThunkRva, ThunkIndex * ThunkSize, &LookupEntryRva) || + !PeAddDword(Descriptor->FirstThunk, ThunkIndex * ThunkSize, &IatEntryRva)) + { + ShowMessages("\n%-36s%s", "Warning :", "import thunk RVA overflow"); + break; + } + + ULONGLONG ThunkValue = 0; + if (!PeReadThunkAtRva(Reader, LookupEntryRva, Is32Bit, &ThunkValue)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid thunk RVA :", LookupEntryRva); + break; + } + + if (ThunkValue == 0) + { + break; + } + + ULONGLONG OrdinalFlag = Is32Bit ? IMAGE_ORDINAL_FLAG32 : IMAGE_ORDINAL_FLAG64; + if ((ThunkValue & OrdinalFlag) != 0) + { + ShowMessages("\n [%u] ordinal %u thunk RVA %#x", ThunkIndex, (UINT32)(ThunkValue & 0xffff), IatEntryRva); + TotalImports++; + continue; + } + + if (ThunkValue > MAXDWORD) + { + ShowMessages("\n%-36s%#llx", "Warning, invalid import name RVA :", (UINT64)ThunkValue); + TotalImports++; + continue; + } + + DWORD NameRva = (DWORD)ThunkValue; + WORD Hint = 0; + if (!PeReadWordAtRva(Reader, NameRva, &Hint)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid import hint RVA :", NameRva); + TotalImports++; + continue; + } + + DWORD ImportNameRva = 0; + if (!PeAddDword(NameRva, sizeof(WORD), &ImportNameRva)) + { + ShowMessages("\n%-36s%#x", "Warning, invalid import name RVA :", NameRva); + TotalImports++; + continue; + } + + CHAR ImportName[MaxImportNameLength + 1] = {0}; + PE_ASCII_STRING_STATUS ImportNameStatus = PeReadAsciiStringAtRva(Reader, + ImportNameRva, + MaxImportNameLength, + ImportName, + sizeof(ImportName)); + if (ImportNameStatus != PeAsciiStringOk) + { + ShowMessages("\n%-36s%#x, %s", "Warning, invalid import name RVA :", ImportNameRva, PeAsciiStatusName(ImportNameStatus)); + TotalImports++; + continue; + } + + ShowMessages("\n [%u] hint %#x name %s thunk RVA %#x", ThunkIndex, Hint, ImportName, IatEntryRva); + TotalImports++; + } + + if (TotalImports >= MaxTotalImports) + { + TotalImportsCapped = TRUE; + break; + } + } + + if (!FoundTerminator) + { + ShowMessages("\n%-36s%s", "Warning :", "import descriptor terminator not found before bounds or cap"); + } + + if (DescriptorCapped) + { + ShowMessages("\n%-36s%#x", "Warning, descriptor cap reached :", MaxImportDescriptors); + } + + if (TotalImportsCapped) + { + ShowMessages("\n%-36s%#x", "Warning, import cap reached :", MaxTotalImports); + } +} + +/** + * @brief Validates and retrieves a pointer to a PE export table array + * + * Computes the total byte size of the table as Count * EntrySize, verifies + * that the multiplication does not overflow, and then resolves the table RVA + * via PeGetPointerAtRva. When Count is zero *Pointer is set to NULL and TRUE + * is returned without any range check. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param TableRva RVA of the export table array + * @param Count Number of entries in the table + * @param EntrySize Size of each entry in bytes + * @param Pointer Output pointer set to the validated table location on success + * + * @return BOOLEAN TRUE on success, FALSE on overflow or if the RVA is not mapped + */ +static BOOLEAN +PeValidateExportTable(PPE_IMAGE_READER Reader, DWORD TableRva, DWORD Count, DWORD EntrySize, const BYTE ** Pointer) +{ + DWORD TableSize = 0; + + if (Count == 0) + { + *Pointer = NULL; + return TRUE; + } + + if (EntrySize != 0 && Count > MAXDWORD / EntrySize) + { + return FALSE; + } + + TableSize = Count * EntrySize; + return PeGetPointerAtRva(Reader, TableRva, TableSize, Pointer); +} + +/** + * @brief Prints one export entry including its ordinal, name, and function RVA or forwarder + * + * If FunctionRva falls within the export directory's RVA range the entry is + * treated as a forwarder string and that string is read and displayed. + * Otherwise the raw function RVA is printed. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param ExportDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_EXPORT data directory entry + * @param Index Zero-based display index of this export entry + * @param Ordinal Export ordinal (base-adjusted) + * @param Name Export name string, or an error description if not available + * @param FunctionRva RVA of the exported function or forwarder string + */ +static VOID +PeShowExportEntry(PPE_IMAGE_READER Reader, + const IMAGE_DATA_DIRECTORY * ExportDirectory, + DWORD Index, + DWORD Ordinal, + const CHAR * Name, + DWORD FunctionRva) +{ + const DWORD MaxForwarderLength = 0x1000; + + if (PeRvaContainsRange(ExportDirectory->VirtualAddress, ExportDirectory->Size, FunctionRva, 1)) + { + DWORD ForwarderRemaining = ExportDirectory->Size - (FunctionRva - ExportDirectory->VirtualAddress); + DWORD ForwarderMaxLength = ForwarderRemaining < MaxForwarderLength ? ForwarderRemaining : MaxForwarderLength; + + CHAR Forwarder[MaxForwarderLength + 1] = {0}; + PE_ASCII_STRING_STATUS ForwarderStatus = PeReadAsciiStringAtRva(Reader, + FunctionRva, + ForwarderMaxLength, + Forwarder, + sizeof(Forwarder)); + if (ForwarderStatus == PeAsciiStringOk) + { + ShowMessages("\n[%u] ordinal %u name %s forwarder %s", Index, Ordinal, Name, Forwarder); + } + else + { + ShowMessages("\n[%u] ordinal %u name %s forwarder %s", Index, Ordinal, Name, PeAsciiStatusName(ForwarderStatus)); + } + + return; + } + + ShowMessages("\n[%u] ordinal %u name %s RVA %#x", Index, Ordinal, Name, FunctionRva); +} + +/** + * @brief Prints the export directory including the export address, name, and ordinal tables + * + * Reads the IMAGE_EXPORT_DIRECTORY header, validates the three export tables + * (AddressOfFunctions, AddressOfNames, AddressOfNameOrdinals), and iterates + * all exported functions. Named exports are matched via the name-ordinal table; + * unnamed exports are printed with their ordinal. Forwarder strings are handled + * via PeShowExportEntry. Processing is capped at 0x2000 total exports. + * + * @param Reader Pointer to an initialized PE_IMAGE_READER + * @param ExportDirectory Pointer to the IMAGE_DIRECTORY_ENTRY_EXPORT data directory entry + */ +static VOID +PeShowExports(PPE_IMAGE_READER Reader, const IMAGE_DATA_DIRECTORY * ExportDirectory) +{ + const DWORD MaxExports = 0x2000; + const DWORD MaxDllNameLength = 0x200; + const DWORD MaxExportNameLength = 0x200; + + ShowMessages("\n\nExports\n-------"); + + if (ExportDirectory->VirtualAddress == 0 || ExportDirectory->Size == 0) + { + ShowMessages("\n%-36s%s", "Export directory :", "empty"); + return; + } + + if (!PeRvaContainsRange(ExportDirectory->VirtualAddress, + ExportDirectory->Size, + ExportDirectory->VirtualAddress, + sizeof(IMAGE_EXPORT_DIRECTORY))) + { + ShowMessages("\n%-36s%s", "Export directory :", "invalid bounds"); + return; + } + + const IMAGE_EXPORT_DIRECTORY * Directory = NULL; + if (!PeGetPointerAtRva(Reader, + ExportDirectory->VirtualAddress, + sizeof(IMAGE_EXPORT_DIRECTORY), + (const BYTE **)&Directory)) + { + ShowMessages("\n%-36s%s", "Export directory :", "not mapped"); + return; + } + + CHAR DllName[MaxDllNameLength + 1] = {0}; + PE_ASCII_STRING_STATUS DllNameStatus = PeReadAsciiStringAtRva(Reader, + Directory->Name, + MaxDllNameLength, + DllName, + sizeof(DllName)); + ShowMessages("\n%-36s%s", "DLL name :", DllNameStatus == PeAsciiStringOk ? DllName : PeAsciiStatusName(DllNameStatus)); + ShowMessages("\n%-36s%u", "Ordinal base :", Directory->Base); + ShowMessages("\n%-36s%u", "Address table count :", Directory->NumberOfFunctions); + ShowMessages("\n%-36s%u", "Name pointer count :", Directory->NumberOfNames); + + const BYTE * AddressTablePointer = NULL; + const BYTE * NamePointerTablePointer = NULL; + const BYTE * OrdinalTablePointer = NULL; + + BOOLEAN AddressTableValid = PeValidateExportTable(Reader, + Directory->AddressOfFunctions, + Directory->NumberOfFunctions, + sizeof(DWORD), + &AddressTablePointer); + BOOLEAN NamePointerTableValid = PeValidateExportTable(Reader, + Directory->AddressOfNames, + Directory->NumberOfNames, + sizeof(DWORD), + &NamePointerTablePointer); + BOOLEAN OrdinalTableValid = PeValidateExportTable(Reader, + Directory->AddressOfNameOrdinals, + Directory->NumberOfNames, + sizeof(WORD), + &OrdinalTablePointer); + + if (!AddressTableValid) + { + ShowMessages("\n%-36s%s", "Warning :", "export address table is not mapped"); + return; + } + + if (!NamePointerTableValid) + { + ShowMessages("\n%-36s%s", "Warning :", "export name pointer table is not mapped"); + } + + if (!OrdinalTableValid) + { + ShowMessages("\n%-36s%s", "Warning :", "export ordinal table is not mapped"); + } + + DWORD NamedCount = Directory->NumberOfNames; + BOOLEAN NamedCapped = FALSE; + if (NamedCount > MaxExports) + { + NamedCount = MaxExports; + NamedCapped = TRUE; + } + + DWORD FunctionCount = Directory->NumberOfFunctions; + BOOLEAN FunctionCapped = FALSE; + if (FunctionCount > MaxExports) + { + FunctionCount = MaxExports; + FunctionCapped = TRUE; + } + + BYTE NamedAddressIndexes[MaxExports] = {0}; + + if (NamePointerTableValid && OrdinalTableValid) + { + for (DWORD NameIndex = 0; NameIndex < NamedCount; NameIndex++) + { + DWORD NameRva = 0; + WORD AddressIndex = 0; + + CopyMemory(&NameRva, NamePointerTablePointer + (NameIndex * sizeof(DWORD)), sizeof(NameRva)); + CopyMemory(&AddressIndex, OrdinalTablePointer + (NameIndex * sizeof(WORD)), sizeof(AddressIndex)); + + if (AddressIndex >= Directory->NumberOfFunctions) + { + ShowMessages("\n%-36s%u", "Warning, invalid export ordinal index :", AddressIndex); + continue; + } + + DWORD FunctionRva = 0; + CopyMemory(&FunctionRva, AddressTablePointer + (AddressIndex * sizeof(DWORD)), sizeof(FunctionRva)); + + CHAR ExportName[MaxExportNameLength + 1] = {0}; + PE_ASCII_STRING_STATUS ExportNameStatus = PeReadAsciiStringAtRva(Reader, + NameRva, + MaxExportNameLength, + ExportName, + sizeof(ExportName)); + if (ExportNameStatus != PeAsciiStringOk) + { + ShowMessages("\n%-36s%#x, %s", "Warning, invalid export name RVA :", NameRva, PeAsciiStatusName(ExportNameStatus)); + continue; + } + + DWORD DisplayOrdinal = 0; + if (!PeAddDword(Directory->Base, AddressIndex, &DisplayOrdinal)) + { + ShowMessages("\n%-36s%u", "Warning, invalid export ordinal index :", AddressIndex); + continue; + } + + if (AddressIndex < FunctionCount) + { + NamedAddressIndexes[AddressIndex] = TRUE; + } + + PeShowExportEntry(Reader, + ExportDirectory, + NameIndex, + DisplayOrdinal, + ExportName, + FunctionRva); + } + } + + for (DWORD AddressIndex = 0; AddressIndex < FunctionCount; AddressIndex++) + { + if (NamedAddressIndexes[AddressIndex]) + { + continue; + } + + DWORD FunctionRva = 0; + CopyMemory(&FunctionRva, AddressTablePointer + (AddressIndex * sizeof(DWORD)), sizeof(FunctionRva)); + + DWORD DisplayOrdinal = 0; + if (!PeAddDword(Directory->Base, AddressIndex, &DisplayOrdinal)) + { + ShowMessages("\n%-36s%u", "Warning, invalid export ordinal index :", AddressIndex); + continue; + } + + PeShowExportEntry(Reader, + ExportDirectory, + AddressIndex, + DisplayOrdinal, + "", + FunctionRva); + } + + if (NamedCapped) + { + ShowMessages("\n%-36s%#x", "Warning, named export cap reached :", MaxExports); + } + + if (FunctionCapped) + { + ShowMessages("\n%-36s%#x", "Warning, export cap reached :", MaxExports); + } +} + +/** + * @brief Locates the Rich header signature in a PE file + * + * The Rich header is an undocumented Microsoft structure embedded in PE files + * that contains information about the tools and compilers used during the build process. + * This function searches for the "Rich" signature string within the DOS stub area. + * + * @param DosHeader Pointer to the DOS header structure of the PE file + * @param SearchSize Capped number of bytes to search + * @param StartOffset Offset to start searching from + * @param Key Output buffer to store the 4-byte XOR key found after "Rich" signature + * + * @note The Rich header is located between the DOS header and PE header + * @note The XOR key is used to decode the actual Rich header entries + **/ +static INT +FindRichHeader(PIMAGE_DOS_HEADER DosHeader, DWORD SearchSize, DWORD StartOffset, CHAR Key[]) +{ + if (DosHeader == NULL || Key == NULL) + { + return -1; + } + + // + // Get PE header offset - this defines our search boundary + // + LONG Offset = DosHeader->e_lfanew; + + if (SearchSize < sizeof(IMAGE_DOS_HEADER) || + DosHeader->e_magic != IMAGE_DOS_SIGNATURE || + Offset < (LONG)sizeof(IMAGE_DOS_HEADER) || + Offset < 8) + { + return -1; + } + + CHAR * BaseAddr = (CHAR *)DosHeader; + DWORD SearchLimit = (DWORD)Offset; + if (SearchLimit > SearchSize) + { + SearchLimit = SearchSize; + } + + if (StartOffset + 8 < StartOffset || StartOffset + 8 > SearchLimit) + { + return -1; + } + + // + // Search for "Rich" signature + // We need 4 bytes for "Rich" and 4 bytes for the key before the PE header. + // + for (DWORD Offset = StartOffset; Offset + 8 <= SearchLimit; ++Offset) + { + // + // Check for "Rich" signature (4 ASCII bytes) + // + if (BaseAddr[Offset] == 'R' && + BaseAddr[Offset + 1] == 'i' && + BaseAddr[Offset + 2] == 'c' && + BaseAddr[Offset + 3] == 'h') + { + // + // Extract the 4-byte XOR key that immediately follows "Rich" + // + memcpy(Key, BaseAddr + Offset + 4, 4); + + // + // Return the offset where "Rich" signature was found + // + return Offset; + } + } + + // + // Rich header signature not found + // + return -1; +} + +/** + * @brief Decrypts Rich header data using XOR decryption and initializes header info + * + * The Rich header is encrypted using a simple XOR cipher with a 4-byte key. + * This function decrypts the entire header in-place and populates the + * PEFILE_RICH_HEADER_INFO structure with metadata about the decrypted data. + * + * @param RichHeaderPtr Pointer to the raw Rich header data to be decrypted + * @param RichHeaderSize Size of the Rich header data in bytes + * @param Key 4-byte XOR key used for decryption + * @param PeFileRichHeaderInfo structure containing Rich header metadata and buffer information + * + * @note The Rich header uses a repeating 4-byte XOR key for encryption + * @note After decryption, the header contains 16 bytes of metadata followed by 8-byte entries + * @note Each entry represents one compilation tool (compiler, linker, assembler, etc.) + * + */ +static BOOLEAN +FindRichEntries(CHAR * RichHeaderPtr, + INT RichHeaderSize, + CHAR Key[], + PRICH_HEADER_INFO PeFileRichHeaderInfo) +{ + if (RichHeaderPtr == NULL || Key == NULL || PeFileRichHeaderInfo == NULL || + RichHeaderSize < 16 || ((RichHeaderSize - 16) % 8) != 0) + { + return FALSE; + } + + INT EntryCount = (RichHeaderSize - 16) / 8; + + if (EntryCount <= 0) + { + return FALSE; + } + + // + // Decrypt the entire Rich header using XOR with the 4-byte key + // + for (int i = 0; i < RichHeaderSize; i += 4) + { + // + // Apply XOR decryption to each 4-byte block + // + for (int x = 0; x < 4; x++) + { + RichHeaderPtr[i + x] ^= Key[x]; + } + } + + if (RichHeaderPtr[0] != 'D' || RichHeaderPtr[1] != 'a' || + RichHeaderPtr[2] != 'n' || RichHeaderPtr[3] != 'S') + { + return FALSE; + } + + for (int i = 4; i < 16; i++) + { + if (RichHeaderPtr[i] != 0) + { + return FALSE; + } + } + + // + // Initialize the Rich header info structure + // + PeFileRichHeaderInfo->Size = RichHeaderSize; + PeFileRichHeaderInfo->PtrToBuffer = RichHeaderPtr; + + // + // Calculate number of entries: subtract 16-byte header, divide by 8 bytes per entry + // + PeFileRichHeaderInfo->Entries = EntryCount; + + return TRUE; +} + +/** + * @brief Parses decrypted Rich header data into structured entries + * + * After decryption, the Rich header contains a series of 8-byte entries, each describing + * a compilation tool used during the build process. This function extracts and converts + * the little-endian binary data into structured RICH_ENTRY objects. + * + * Rich header format after decryption: + * - Bytes 0-15: Header metadata (DanS signature + padding) + * - Bytes 16+: 8-byte entries (prodID:2, buildID:2, useCount:4) + * + * @param RichHeaderSize Size of the entire Rich header in bytes + * @param RichHeaderPtr Pointer to the decrypted Rich header data + * @param PeFileRichHeader structure containing the parsed Rich header entries + * + * @warning Assumes the Rich header has been properly decrypted first + */ +static BOOLEAN +SetRichEntries(INT RichHeaderSize, CHAR * RichHeaderPtr, PRICH_HEADER PeFileRichHeader) +{ + if (RichHeaderPtr == NULL || PeFileRichHeader == NULL || PeFileRichHeader->Entries == NULL || + RichHeaderSize < 16 || ((RichHeaderSize - 16) % 8) != 0) + { + return FALSE; + } + + INT EntryCount = (RichHeaderSize - 16) / 8; + + if (EntryCount <= 0) + { + return FALSE; + } + + // + // Start at offset 16 to skip the header metadata, process 8-byte entries + // + for (int i = 16, EntryIndex = 0; i + 8 <= RichHeaderSize; i += 8, EntryIndex++) + { + // + // Extract Product ID (bytes 2-3 of entry, little-endian) + // + WORD ProdID = ((UCHAR)RichHeaderPtr[i + 3] << 8) | (UCHAR)RichHeaderPtr[i + 2]; + + // + // Extract Build ID (bytes 0-1 of entry, little-endian) + // + WORD BuildID = ((UCHAR)RichHeaderPtr[i + 1] << 8) | (UCHAR)RichHeaderPtr[i]; + + // + // Extract Use Count (bytes 4-7 of entry, little-endian 32-bit) + // + DWORD UseCount = PeReadDwordFromBuffer((const BYTE *)RichHeaderPtr, i + 4); + + // + // Store the parsed entry (adjust index: i/8 gives entry number, -2 for header offset) + // + PeFileRichHeader->Entries[EntryIndex] = {ProdID, BuildID, UseCount}; + } + + PeFileRichHeader->Entries[EntryCount] = {0x0000, 0x0000, 0x00000000}; + + return TRUE; +} + +/** + * @brief Determines the size of the Rich header by finding the DanS signature + * + * The Rich header begins with the "DanS" signature (after decryption) and ends + * with the "Rich" signature. This function works backwards from the "Rich" signature + * to find the beginning and calculate the total size. + * + * Rich header structure: + * [DanS signature] [Padding] [Tool Entries] [Rich signature] [XOR Key] + * + * @param Key 4-byte XOR key for decryption (extracted from after "Rich" signature) + * @param Index Offset where "Rich" signature was found + * @param DataPtr Pointer to the beginning of the PE file data + * + * @return INT Size of the Rich header in bytes, or 0 if DanS signature not found + * + */ +static INT +DecryptRichHeader(CHAR Key[], INT Index, CHAR * DataPtr, INT DataSize) +{ + if (Key == NULL || DataPtr == NULL || DataSize < 16 || Index < 16 || Index + 4 > DataSize) + { + return 0; + } + + // + // Start searching backwards from just before the "Rich" signature + // + INT IndexPointer = Index - 4; + INT RichHeaderSize = 0; + + // + // Search backwards for the DanS signature that marks the beginning + // + while (IndexPointer >= 0) + { + CHAR TmpChar[4]; + + // + // Read 4 bytes and decrypt them with the XOR key + // + memcpy(TmpChar, DataPtr + IndexPointer, 4); + + for (int i = 0; i < 4; i++) + { + TmpChar[i] ^= Key[i]; + } + + // + // Move backwards and increment size counter + // + IndexPointer -= 4; + RichHeaderSize += 4; + + // + // Check for DanS signature after decryption. + // + if (TmpChar[0] == 'D' && TmpChar[1] == 'a' && TmpChar[2] == 'n' && TmpChar[3] == 'S') + { + return RichHeaderSize; + } + } + + return 0; +} + +/** + * @brief Show hex dump of sections of PE + * @param Ptr + * @param Size + * @param SecAddress + * + * @return VOID + */ + +static VOID +PeHexDump(CHAR * Ptr, SIZE_T Size, ULONGLONG SecAddress) +{ + SIZE_T i = 1; + INT Temp = 0; + + if (Ptr == NULL || Size == 0) + { + return; + } + + // + // Buffer to store the character dump displayed at the + // right side + // + CHAR Buf[18]; + ShowMessages("\n\n%llx: |", SecAddress); + + Buf[Temp] = ' '; // initial space + Buf[Temp + 16] = ' '; // final space + Buf[Temp + 17] = 0; // End of Buf + Temp++; // Temp = 1; + + for (; i <= Size; i++, Ptr++, Temp++) + { + Buf[Temp] = !iscntrl((*Ptr) & 0xff) ? (*Ptr) & 0xff : '.'; + ShowMessages("%-3.2x", (*Ptr) & 0xff); + + if (i % 16 == 0) + { + // + // print the character dump to the right + // + ShowMessages("%s\n", Buf); + if (i + 1 <= Size) + ShowMessages("%llx: ", SecAddress += 16); + Temp = 0; + } + if (i % 4 == 0) + ShowMessages("| "); + } + if (i % 16 != 0) + { + Buf[Temp] = 0; + for (; i % 16 != 0; i++) + ShowMessages("%-3.2c", ' '); + ShowMessages("%s\n", Buf); + } +} + +/** + * @brief Show information about different sections of PE and the dump of sections + * @param AddressOfFile + * @param SectionToShow + * @param Is32Bit + * + * @return BOOLEAN + */ +BOOLEAN +PeShowSectionInformationAndDump(const WCHAR * AddressOfFile, + const CHAR * SectionToShow, + BOOLEAN Is32Bit) +{ + RICH_HEADER_INFO PeFileRichHeaderInfo {0}; + RICH_HEADER PeFileRichHeader {0}; + BOOLEAN Result = FALSE, RichFound = FALSE, SectionFound = FALSE; + const DWORD MaxRichReadSize = 1024 * 1024; + const INT MaxRichHeaderSize = 256 * 1024; + const INT MaxRichHeaderEntries = 0x4000; + const DWORD MaxSectionScanBytes = 16 * 1024 * 1024; + const ULONGLONG MaxTotalSectionScanBytes = 64 * 1024 * 1024; + const SIZE_T MaxSectionDumpBytes = 1024 * 1024; + const ULONGLONG MaxTotalSectionDumpBytes = 4 * 1024 * 1024; + HANDLE FileHandle = INVALID_HANDLE_VALUE; // Open file handle (kept for the raw Rich-header read) + SIZE_T MappedSize = 0; // Size of the mapped file in bytes + UINT32 NumberOfSections; // Number of sections + LPVOID BaseAddr = NULL; // Pointer to the base memory of mapped file + PIMAGE_DOS_HEADER DosHeader; // Pointer to DOS Header + PIMAGE_NT_HEADERS32 NtHeader32 = NULL; // Pointer to NT Header 32 bit + PIMAGE_NT_HEADERS64 NtHeader64 = NULL; // Pointer to NT Header 64 bit + IMAGE_FILE_HEADER Header; // Pointer to image file header of NT Header + IMAGE_OPTIONAL_HEADER32 OpHeader32; // Optional Header of PE files present in NT Header structure + IMAGE_OPTIONAL_HEADER64 OpHeader64; // Optional Header of PE files present in NT Header structure + const IMAGE_SECTION_HEADER * SecHeader; // Section Header or Section Table Header + PE_IMAGE_READER Reader; + IMAGE_DATA_DIRECTORY EmptyDirectory = {0}; + LARGE_INTEGER FileSize; + CHAR Key[4]; + INT RichHeaderOffset = -1; + const CHAR * RichHeaderStatus = "not found"; + BOOLEAN RichSearchCapped = FALSE; + ULONGLONG RemainingSectionScanBytes = MaxTotalSectionScanBytes; + ULONGLONG RemainingSectionDumpBytes = MaxTotalSectionDumpBytes; + time_t TimeDateStamp; + + // + // Open and map the EXE file read-only. The wrapper also hands back the open + // file handle so the raw Rich-header read below can still seek/read it. + // + BaseAddr = PlatformMapFileReadOnly(AddressOfFile, &MappedSize, &FileHandle); + + if (BaseAddr == NULL) + { + ShowMessages("err, could not open the file specified\n"); + return FALSE; + } + + FileSize.QuadPart = (LONGLONG)MappedSize; + + if (FileSize.QuadPart < (LONGLONG)sizeof(IMAGE_DOS_HEADER)) + { + PlatformUnmapFile(BaseAddr, MappedSize, FileHandle); + return FALSE; + } + + // + // Get the DOS Header Base + // + DosHeader = (PIMAGE_DOS_HEADER)BaseAddr; // 0x04000000 + + if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE || + DosHeader->e_lfanew < sizeof(IMAGE_DOS_HEADER) || + (LONGLONG)DosHeader->e_lfanew > FileSize.QuadPart || + (LONGLONG)DosHeader->e_lfanew + (LONGLONG)(Is32Bit ? sizeof(IMAGE_NT_HEADERS32) : sizeof(IMAGE_NT_HEADERS64)) > FileSize.QuadPart) + { + ShowMessages("\nGiven File is not a valid PE file\n"); + Result = FALSE; + goto Finished; + } + + if (!PeImageReaderInitialize((const BYTE *)BaseAddr, (SIZE_T)FileSize.QuadPart, &Reader)) + { + ShowMessages("\nGiven File is not a valid PE file\n"); + Result = FALSE; + goto Finished; + } + + if (DosHeader->e_lfanew > 0 && (ULONGLONG)DosHeader->e_lfanew <= (ULONGLONG)MAXDWORD) + { + CHAR * DataPtr = NULL; + DWORD BytesRead = 0; + DWORD RichReadSize = (DWORD)DosHeader->e_lfanew; + DWORD SearchOffset = 0; + BOOLEAN HadCandidate = FALSE; + LARGE_INTEGER FileStart = {0}; + + if (RichReadSize > MaxRichReadSize) + { + RichReadSize = MaxRichReadSize; + RichHeaderStatus = "not found in first 1 MiB"; + RichSearchCapped = TRUE; + } + + if (RichReadSize >= 8) + { + DataPtr = new (std::nothrow) CHAR[RichReadSize]; + if (DataPtr == NULL) + { + RichHeaderStatus = "allocation failed"; + goto SkipRichHeader; + } + + if (!PlatformReadFileAtOffset(FileHandle, 0, DataPtr, RichReadSize, &BytesRead) || BytesRead != RichReadSize) + { + RichHeaderStatus = "read failed"; + delete[] DataPtr; + goto SkipRichHeader; + } + + for (;;) + { + CHAR * RichHeaderPtr = NULL; + + RichHeaderOffset = FindRichHeader(DosHeader, RichReadSize, SearchOffset, Key); + if (RichHeaderOffset < 0) + { + break; + } + + HadCandidate = TRUE; + RichHeaderStatus = RichSearchCapped ? "malformed candidate in first 1 MiB" : "malformed"; + + INT RichHeaderSize = DecryptRichHeader(Key, RichHeaderOffset, DataPtr, (INT)RichReadSize); + INT IndexPointer = RichHeaderOffset - RichHeaderSize; + + if (RichHeaderSize < 16 || RichHeaderSize > MaxRichHeaderSize || ((RichHeaderSize - 16) % 8) != 0 || + (RichHeaderSize - 16) / 8 == 0 || (RichHeaderSize - 16) / 8 > MaxRichHeaderEntries || + IndexPointer < 0 || RichHeaderSize > (INT)RichReadSize || IndexPointer > (INT)RichReadSize - RichHeaderSize) + { + SearchOffset = (DWORD)RichHeaderOffset + 1; + continue; + } + + RichHeaderPtr = new (std::nothrow) CHAR[RichHeaderSize]; + if (RichHeaderPtr == NULL) + { + RichHeaderStatus = "allocation failed"; + break; + } + + memcpy(RichHeaderPtr, DataPtr + IndexPointer, RichHeaderSize); + + if (!FindRichEntries(RichHeaderPtr, RichHeaderSize, Key, &PeFileRichHeaderInfo)) + { + delete[] RichHeaderPtr; + SearchOffset = (DWORD)RichHeaderOffset + 1; + continue; + } + + RichHeaderPtr = NULL; + + if (PeFileRichHeaderInfo.Entries > MaxRichHeaderEntries || PeFileRichHeaderInfo.Entries >= INT_MAX / (INT)sizeof(RICH_HEADER_ENTRY) - 1) + { + delete[] PeFileRichHeaderInfo.PtrToBuffer; + PeFileRichHeaderInfo = {0}; + SearchOffset = (DWORD)RichHeaderOffset + 1; + continue; + } + + PeFileRichHeader.Entries = new (std::nothrow) RICH_HEADER_ENTRY[PeFileRichHeaderInfo.Entries + 1]; + if (PeFileRichHeader.Entries == NULL) + { + RichHeaderStatus = "allocation failed"; + delete[] PeFileRichHeaderInfo.PtrToBuffer; + PeFileRichHeaderInfo = {0}; + break; + } + + if (!SetRichEntries(RichHeaderSize, PeFileRichHeaderInfo.PtrToBuffer, &PeFileRichHeader)) + { + delete[] PeFileRichHeaderInfo.PtrToBuffer; + PeFileRichHeaderInfo = {0}; + delete[] PeFileRichHeader.Entries; + PeFileRichHeader.Entries = NULL; + SearchOffset = (DWORD)RichHeaderOffset + 1; + continue; + } + + RichFound = TRUE; + break; + } + + if (!RichFound && !HadCandidate && (DWORD)DosHeader->e_lfanew <= MaxRichReadSize) + { + RichHeaderStatus = "not found"; + } + + delete[] DataPtr; + } + } + +SkipRichHeader: + + // + // Check for Valid DOS file + // + if (DosHeader->e_magic == IMAGE_DOS_SIGNATURE) + { + // + // Dump the Dos Header info + // + ShowMessages("\nValid Dos Exe File\n------------------\n"); + ShowMessages("\nDumping DOS Header Info....\n---------------------------"); + ShowMessages("\n%-36s%s ", + "Magic number : ", + DosHeader->e_magic == 0x5a4d ? "MZ" : "-"); + ShowMessages("\n%-36s%#x", "Bytes on last page of file :", DosHeader->e_cblp); + ShowMessages("\n%-36s%#x", "Pages in file : ", DosHeader->e_cp); + ShowMessages("\n%-36s%#x", "Relocation : ", DosHeader->e_crlc); + ShowMessages("\n%-36s%#x", + "Size of header in paragraphs : ", + DosHeader->e_cparhdr); + ShowMessages("\n%-36s%#x", + "Minimum extra paragraphs needed : ", + DosHeader->e_minalloc); + ShowMessages("\n%-36s%#x", + "Maximum extra paragraphs needed : ", + DosHeader->e_maxalloc); + ShowMessages("\n%-36s%#x", "Initial (relative) SS value : ", DosHeader->e_ss); + ShowMessages("\n%-36s%#x", "Initial SP value : ", DosHeader->e_sp); + ShowMessages("\n%-36s%#x", "Checksum : ", DosHeader->e_csum); + ShowMessages("\n%-36s%#x", "Initial IP value : ", DosHeader->e_ip); + ShowMessages("\n%-36s%#x", "Initial (relative) CS value : ", DosHeader->e_cs); + ShowMessages("\n%-36s%#x", + "File address of relocation table : ", + DosHeader->e_lfarlc); + ShowMessages("\n%-36s%#x", "Overlay number : ", DosHeader->e_ovno); + ShowMessages("\n%-36s%#x", "OEM identifier : ", DosHeader->e_oemid); + ShowMessages("\n%-36s%#x", + "OEM information(e_oemid specific) :", + DosHeader->e_oeminfo); + ShowMessages("\n%-36s%#x", "RVA address of PE header : ", DosHeader->e_lfanew); + ShowMessages("\n===============================================================" + "================\n"); + } + else + { + ShowMessages("\nGiven File is not a valid DOS file\n"); + Result = FALSE; + goto Finished; + } + + if (RichFound) + { + ShowMessages("\n===============================================================================\n"); + ShowMessages(" RICH HEADER \n"); + ShowMessages("===============================================================================\n"); + ShowMessages("Entries: %d\n\n", PeFileRichHeaderInfo.Entries); + ShowMessages("%-10s %-10s %-10s\n", "Build ID", "Prod ID", "Use Count"); + ShowMessages("---------------------------------------\n"); + + for (int i = 0; i < PeFileRichHeaderInfo.Entries; i++) + { + ShowMessages("0x%08X 0x%08X %10u\n", + PeFileRichHeader.Entries[i].BuildID, + PeFileRichHeader.Entries[i].ProdID, + PeFileRichHeader.Entries[i].UseCount); + } + + ShowMessages("==============Rich Header End ==================\n"); + } + else + { + ShowMessages("=========== Rich Header Not Shown (%s) ===========\n", RichHeaderStatus); + } + + // + // Offset of NT Header is found at 0x3c location in DOS header specified by + // e_lfanew + // Get the Base of NT Header(PE Header) = DosHeader + RVA address of PE + // header + // + if (Is32Bit) + { + NtHeader32 = (PIMAGE_NT_HEADERS32)((UINT64)(DosHeader) + (DosHeader->e_lfanew)); + } + else + { + NtHeader64 = (PIMAGE_NT_HEADERS64)((UINT64)(DosHeader) + (DosHeader->e_lfanew)); + } + + // + // Identify for valid PE file + // + if (Is32Bit && NtHeader32->Signature == IMAGE_NT_SIGNATURE) + { + ShowMessages("\nValid PE32 file \n-------------\n"); + } + else if (!Is32Bit && NtHeader64->Signature == IMAGE_NT_SIGNATURE) + { + ShowMessages("\nValid PE64 file \n-------------\n"); + } + else + { + ShowMessages("err, the specified file is not a valid PE file"); + Result = FALSE; + goto Finished; + } + + // + // Dump NT Header Info.... + // + ShowMessages("\nDumping COFF/PE Header " + "Info....\n--------------------------------"); + ShowMessages("\n%-36s%s", "Signature :", "PE"); + + // + // Get the IMAGE FILE HEADER Structure + // + if (Is32Bit) + { + Header = NtHeader32->FileHeader; + } + else + { + Header = NtHeader64->FileHeader; + } + + // + // Determine Machine Architecture + // + ShowMessages("\n%-36s", "Machine Architecture :"); + + // + // Only few are determined (for remaining refer + // to the above specification) + // + switch (Header.Machine) + { + case 0x0: + ShowMessages("All "); + break; + case 0x14d: + ShowMessages("Intel i860"); + break; + case 0x14c: + ShowMessages("Intel i386, i486, i586"); + break; + case 0x200: + ShowMessages("Intel Itanium processor"); + break; + case 0x8664: + ShowMessages("AMD x64"); + break; + case 0x162: + ShowMessages("MIPS R3000"); + break; + case 0x166: + ShowMessages("MIPS R4000"); + break; + case 0x183: + ShowMessages("DEC Alpha AXP"); + break; + default: + ShowMessages("Not Found"); + break; + } + + // + // Determine the characteristics of the given file + // + ShowMessages("\n%-36s", "Characteristics : "); + if ((Header.Characteristics & 0x0002) == 0x0002) + ShowMessages("Executable Image, "); + if ((Header.Characteristics & 0x0020) == 0x0020) + ShowMessages("Application can address > 2GB, "); + if ((Header.Characteristics & 0x1000) == 0x1000) + ShowMessages("System file (Kernel Mode Driver(I think)), "); + if ((Header.Characteristics & 0x2000) == 0x2000) + ShowMessages("Dll file, "); + if ((Header.Characteristics & 0x4000) == 0x4000) + ShowMessages("Application runs only in Uniprocessor, "); + + // + // Determine Time Stamp + // + TimeDateStamp = Header.TimeDateStamp; + ShowMessages("\n%-36s%s", + "Time Stamp :", + ctime(&TimeDateStamp)); + + // + // Determine number of sections + // + ShowMessages("%-36s%d", "No.sections(size) :", Header.NumberOfSections); + ShowMessages("\n%-36s%d", "No.entries in symbol table :", Header.NumberOfSymbols); + ShowMessages("\n%-36s%d", + "Size of optional header :", + Header.SizeOfOptionalHeader); + ShowMessages("\n%-36s%#x", "Raw machine value :", Header.Machine); + ShowMessages("\n%-36s%#x", "Pointer to symbol table :", Header.PointerToSymbolTable); + ShowMessages("\n%-36s%#x", "Raw characteristics value :", Header.Characteristics); + + ShowMessages("\n\nDumping PE Optional Header " + "Info....\n-----------------------------------"); + + if (Is32Bit) + { + // + // Info about Optional Header + // + OpHeader32 = NtHeader32->OptionalHeader; + ShowMessages("\n\nInfo of optional Header\n-----------------------"); + ShowMessages("\n%-36s%#x", + "Address of Entry Point : ", + OpHeader32.AddressOfEntryPoint); + ShowMessages("\n%-36s%#x", "Raw optional header magic :", OpHeader32.Magic); + PeShowEntrypointFileOffset(&Reader, OpHeader32.AddressOfEntryPoint); + ShowMessages("\n%-36s%#llx", "Base Address of the Image : ", OpHeader32.ImageBase); + ShowMessages("\n%-36s%s", "SubSystem type : ", PeGetSubsystemName(OpHeader32.Subsystem)); + ShowMessages("\n%-36s%s", "Given file is a : ", OpHeader32.Magic == 0x20b ? "PE32+(64)" : "PE32"); + ShowMessages("\n%-36s%#x", "File Alignment :", OpHeader32.FileAlignment); + ShowMessages("\n%-36s%#x", "Size of Image :", OpHeader32.SizeOfImage); + ShowMessages("\n%-36s%#x", "Size of Headers :", OpHeader32.SizeOfHeaders); + PeShowChecksum(&Reader, + OpHeader32.CheckSum, + (SIZE_T)(Reader.NtHeaders - Reader.ImageBase) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER32, CheckSum)); + ShowMessages("\n%-36s%#x", "Raw DLL characteristics value :", OpHeader32.DllCharacteristics); + ShowMessages("\n%-36s", "DLL characteristics flags :"); + PeShowDllCharacteristics(OpHeader32.DllCharacteristics); + ShowMessages("\n%-36s%d", "Size of code segment(.text) : ", OpHeader32.SizeOfCode); + ShowMessages("\n%-36s%#x", + "Base address of code segment(RVA) :", + OpHeader32.BaseOfCode); + ShowMessages("\n%-36s%d", + "Size of Initialized data : ", + OpHeader32.SizeOfInitializedData); + + ShowMessages("\n%-36s%#x", + "Base address of data segment(RVA) :", + OpHeader32.BaseOfData); + + ShowMessages("\n%-36s%#x", "Section Alignment :", OpHeader32.SectionAlignment); + ShowMessages("\n%-36s%d", "Major Linker Version : ", OpHeader32.MajorLinkerVersion); + ShowMessages("\n%-36s%d", "Minor Linker Version : ", OpHeader32.MinorLinkerVersion); + PeShowDataDirectories(&Reader, OpHeader32.DataDirectory, OpHeader32.NumberOfRvaAndSizes); + PeShowCertificateTable(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_SECURITY ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] : &EmptyDirectory); + PeShowBaseRelocations(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BASERELOC ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC] : &EmptyDirectory); + PeShowBoundImports(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT] : &EmptyDirectory); + PeShowResources(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] : &EmptyDirectory); + PeShowExceptions(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION] : &EmptyDirectory, + Header.Machine, + TRUE); + PeShowDelayImports(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT] : &EmptyDirectory, + TRUE, + OpHeader32.ImageBase); + PeShowClrRuntime(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] : &EmptyDirectory); + PeShowTls(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_TLS ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS] : &EmptyDirectory, + TRUE, + OpHeader32.ImageBase); + PeShowDebug(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_DEBUG ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG] : &EmptyDirectory); + PeShowLoadConfig(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG] : &EmptyDirectory, + TRUE); + PeShowImports(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] : &EmptyDirectory, + TRUE); + PeShowExports(&Reader, + OpHeader32.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXPORT ? &OpHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] : &EmptyDirectory); + } + else + { + // + // Info about Optional Header + // + OpHeader64 = NtHeader64->OptionalHeader; + ShowMessages("\n\nInfo of optional Header\n-----------------------"); + ShowMessages("\n%-36s%#x", + "Address of Entry Point : ", + OpHeader64.AddressOfEntryPoint); + ShowMessages("\n%-36s%#x", "Raw optional header magic :", OpHeader64.Magic); + PeShowEntrypointFileOffset(&Reader, OpHeader64.AddressOfEntryPoint); + ShowMessages("\n%-36s%#llx", "Base Address of the Image : ", OpHeader64.ImageBase); + ShowMessages("\n%-36s%s", "SubSystem type : ", PeGetSubsystemName(OpHeader64.Subsystem)); + ShowMessages("\n%-36s%s", "Given file is a : ", OpHeader64.Magic == 0x20b ? "PE32+(64)" : "PE32"); + ShowMessages("\n%-36s%#x", "File Alignment :", OpHeader64.FileAlignment); + ShowMessages("\n%-36s%#x", "Size of Image :", OpHeader64.SizeOfImage); + ShowMessages("\n%-36s%#x", "Size of Headers :", OpHeader64.SizeOfHeaders); + PeShowChecksum(&Reader, + OpHeader64.CheckSum, + (SIZE_T)(Reader.NtHeaders - Reader.ImageBase) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER64, CheckSum)); + ShowMessages("\n%-36s%#x", "Raw DLL characteristics value :", OpHeader64.DllCharacteristics); + ShowMessages("\n%-36s", "DLL characteristics flags :"); + PeShowDllCharacteristics(OpHeader64.DllCharacteristics); + ShowMessages("\n%-36s%d", "Size of code segment(.text) : ", OpHeader64.SizeOfCode); + ShowMessages("\n%-36s%#x", + "Base address of code segment(RVA) :", + OpHeader64.BaseOfCode); + ShowMessages("\n%-36s%d", + "Size of Initialized data : ", + OpHeader64.SizeOfInitializedData); + + ShowMessages("\n%-36s%#x", "Section Alignment :", OpHeader64.SectionAlignment); + ShowMessages("\n%-36s%d", "Major Linker Version : ", OpHeader64.MajorLinkerVersion); + ShowMessages("\n%-36s%d", "Minor Linker Version : ", OpHeader64.MinorLinkerVersion); + PeShowDataDirectories(&Reader, OpHeader64.DataDirectory, OpHeader64.NumberOfRvaAndSizes); + PeShowCertificateTable(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_SECURITY ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] : &EmptyDirectory); + PeShowBaseRelocations(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BASERELOC ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC] : &EmptyDirectory); + PeShowBoundImports(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT] : &EmptyDirectory); + PeShowResources(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] : &EmptyDirectory); + PeShowExceptions(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION] : &EmptyDirectory, + Header.Machine, + FALSE); + PeShowDelayImports(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT] : &EmptyDirectory, + FALSE, + OpHeader64.ImageBase); + PeShowClrRuntime(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] : &EmptyDirectory); + PeShowTls(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_TLS ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS] : &EmptyDirectory, + FALSE, + OpHeader64.ImageBase); + PeShowDebug(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_DEBUG ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG] : &EmptyDirectory); + PeShowLoadConfig(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG] : &EmptyDirectory, + FALSE); + PeShowImports(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] : &EmptyDirectory, + FALSE); + PeShowExports(&Reader, + OpHeader64.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXPORT ? &OpHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] : &EmptyDirectory); + } + + ShowMessages("\n\nDumping Sections Header " + "Info....\n--------------------------------"); + + // + // Retrieve a pointer to First Section Header(or Section Table Entry) + // + SecHeader = Reader.SectionHeaders; + NumberOfSections = Reader.FileHeader->NumberOfSections; + + for (UINT32 i = 0; i < NumberOfSections; i++, SecHeader++) + { + CHAR SectionName[IMAGE_SIZEOF_SHORT_NAME + 1]; + const BYTE * Pointer = NULL; + const CHAR * RawDataBounds = "empty"; + + PeImageReaderGetSectionName(SecHeader, SectionName, sizeof(SectionName)); + + if (SecHeader->SizeOfRawData != 0) + { + RawDataBounds = PeImageReaderGetPointerAtOffset(&Reader, + SecHeader->PointerToRawData, + SecHeader->SizeOfRawData, + &Pointer) + ? "valid" + : "invalid"; + } + + ShowMessages("\n\nSection Info (%d of %d)", i + 1, NumberOfSections); + + ShowMessages("\n---------------------"); + ShowMessages("\n%-36s%s", "Section Header name : ", SectionName); + ShowMessages("\n%-36s%#x", + "ActualSize of code or data : ", + SecHeader->Misc.VirtualSize); + ShowMessages("\n%-36s%#x", "Virtual Address(RVA) :", SecHeader->VirtualAddress); + ShowMessages("\n%-36s%#x", + "Size of raw data (rounded to FA) : ", + SecHeader->SizeOfRawData); + ShowMessages("\n%-36s%#x", + "Pointer to Raw Data : ", + SecHeader->PointerToRawData); + ShowMessages("\n%-36s%s", "Raw data bounds :", RawDataBounds); + if (Pointer != NULL && SecHeader->SizeOfRawData != 0) + { + if (SecHeader->SizeOfRawData > MaxSectionScanBytes) + { + ShowMessages("\n%-36s%s", "Raw data entropy :", "skipped, section is larger than local cap"); + ShowMessages("\n%-36s%s", "Raw data FNV-1a64 :", "skipped, section is larger than local cap"); + } + else if ((ULONGLONG)SecHeader->SizeOfRawData > RemainingSectionScanBytes) + { + RemainingSectionScanBytes = 0; + ShowMessages("\n%-36s%s", "Raw data entropy :", "skipped, global scan budget exhausted"); + ShowMessages("\n%-36s%s", "Raw data FNV-1a64 :", "skipped, global scan budget exhausted"); + } + else + { + ShowMessages("\n%-36s%.4f", "Raw data entropy :", PeCalculateEntropy(Pointer, SecHeader->SizeOfRawData)); + ShowMessages("\n%-36s%#llx", "Raw data FNV-1a64 :", PeFnv1a64(Pointer, SecHeader->SizeOfRawData)); + RemainingSectionScanBytes -= SecHeader->SizeOfRawData; + } + } + if (SecHeader->SizeOfRawData != 0 && SecHeader->Misc.VirtualSize > SecHeader->SizeOfRawData) + { + ShowMessages("\n%-36s%s", "Warning :", "virtual size is larger than raw data"); + } + ShowMessages("\n%-36s%#x", + "Pointer to Relocations : ", + SecHeader->PointerToRelocations); + ShowMessages("\n%-36s%#x", + "Pointer to Line numbers : ", + SecHeader->PointerToLinenumbers); + ShowMessages("\n%-36s%#x", + "Number of relocations : ", + SecHeader->NumberOfRelocations); + ShowMessages("\n%-36s%#x", + "Number of line numbers : ", + SecHeader->NumberOfLinenumbers); + ShowMessages("\n%-36s%s", "Characteristics : ", "Contains "); + if ((SecHeader->Characteristics & 0x20) == 0x20) + ShowMessages("executable code, "); + if ((SecHeader->Characteristics & 0x40) == 0x40) + ShowMessages("initialized data, "); + if ((SecHeader->Characteristics & 0x80) == 0x80) + ShowMessages("uninitialized data, "); + if ((SecHeader->Characteristics & 0x200) == 0x200) + ShowMessages("comments and linker commands, "); + if ((SecHeader->Characteristics & 0x10000000) == 0x10000000) + ShowMessages("shareable data(via DLLs), "); + if ((SecHeader->Characteristics & 0x40000000) == 0x40000000) + ShowMessages("Readable, "); + if ((SecHeader->Characteristics & 0x80000000) == 0x80000000) + ShowMessages("Writable, "); + + // + // show the hex dump if the user needs it + // + if (SectionToShow != NULL) + { + if (!_strcmpi(SectionToShow, SectionName)) + { + SectionFound = TRUE; + + if (SecHeader->SizeOfRawData != 0) + { + SIZE_T DumpSize = SecHeader->SizeOfRawData; + BOOLEAN TruncatedBySectionCap = FALSE; + BOOLEAN TruncatedByGlobalCap = FALSE; + + if (Pointer == NULL) + { + ShowMessages("\nerr, invalid section raw data\n"); + continue; + } + + if (RemainingSectionDumpBytes == 0) + { + ShowMessages("\n%-36s%s", "Warning, section dump skipped :", "global dump budget exhausted"); + continue; + } + + if (DumpSize > MaxSectionDumpBytes) + { + DumpSize = MaxSectionDumpBytes; + TruncatedBySectionCap = TRUE; + } + + if ((ULONGLONG)DumpSize > RemainingSectionDumpBytes) + { + DumpSize = (SIZE_T)RemainingSectionDumpBytes; + TruncatedByGlobalCap = TRUE; + } + + if (TruncatedBySectionCap) + { + ShowMessages("\n%-36s%#llx of %#x bytes", + "Warning, section dump truncated by section cap :", + (UINT64)DumpSize, + SecHeader->SizeOfRawData); + } + if (TruncatedByGlobalCap) + { + ShowMessages("\n%-36s%#llx of %#x bytes", + "Warning, section dump truncated by global cap :", + (UINT64)DumpSize, + SecHeader->SizeOfRawData); + } + + if (Is32Bit) + { + PeHexDump((CHAR *)Pointer, + DumpSize, + (ULONGLONG)OpHeader32.ImageBase + SecHeader->VirtualAddress); + } + else + { + PeHexDump((CHAR *)Pointer, + DumpSize, + OpHeader64.ImageBase + SecHeader->VirtualAddress); + } + + RemainingSectionDumpBytes -= DumpSize; + } + } + } + } + + PeShowOverlayAndWarnings(&Reader, + Header.Machine, + Is32Bit ? OpHeader32.Magic : OpHeader64.Magic, + Is32Bit ? OpHeader32.AddressOfEntryPoint : OpHeader64.AddressOfEntryPoint, + Is32Bit ? OpHeader32.SizeOfImage : OpHeader64.SizeOfImage, + Is32Bit ? OpHeader32.SizeOfHeaders : OpHeader64.SizeOfHeaders, + Is32Bit ? OpHeader32.DataDirectory : OpHeader64.DataDirectory, + Is32Bit ? OpHeader32.NumberOfRvaAndSizes : OpHeader64.NumberOfRvaAndSizes); + + if (SectionToShow != NULL && !SectionFound) + { + ShowMessages("\nerr, section '%s' was not found\n", SectionToShow); + } + + ShowMessages("\n===============================================================" + "================\n"); + + // + // Set result to true + // + Result = TRUE; + +Finished: + // + // Unmap and close the handles + // + if (PeFileRichHeaderInfo.PtrToBuffer != NULL) + { + delete[] PeFileRichHeaderInfo.PtrToBuffer; + } + + if (PeFileRichHeader.Entries != NULL) + { + delete[] PeFileRichHeader.Entries; + } + + PlatformUnmapFile(BaseAddr, MappedSize, FileHandle); + + return Result; +} + +/** + * @brief Detect whether PE is a 32-bit PE or 64-bit PE + * @param AddressOfFile + * @param Is32Bit + * + * @return BOOLEAN + */ +BOOLEAN +PeIsPE32BitOr64Bit(const WCHAR * AddressOfFile, PBOOLEAN Is32Bit) +{ + BOOLEAN Result = FALSE; + HANDLE FileHandle = INVALID_HANDLE_VALUE; // Open file handle + SIZE_T MappedSize = 0; // Size of the mapped file in bytes + LPVOID BaseAddr; // Pointer to the base memory of mapped file + PIMAGE_DOS_HEADER DosHeader; // Pointer to DOS Header + PIMAGE_NT_HEADERS32 NtHeader32 = NULL; // Pointer to NT Header 32 bit + PE_IMAGE_READER Reader; + LARGE_INTEGER FileSize; + + // + // Open and map the EXE file read-only + // + BaseAddr = PlatformMapFileReadOnly(AddressOfFile, &MappedSize, &FileHandle); + + if (BaseAddr == NULL) + { + ShowMessages("err, unable to read or map the file (%x)\n", PlatformGetLastError()); + return FALSE; + } + + FileSize.QuadPart = (LONGLONG)MappedSize; + + if (FileSize.QuadPart < (LONGLONG)sizeof(IMAGE_DOS_HEADER)) + { + PlatformUnmapFile(BaseAddr, MappedSize, FileHandle); + return FALSE; + } + + // + // Get the DOS Header Base + // + DosHeader = (PIMAGE_DOS_HEADER)BaseAddr; // 0x04000000 + + // + // Check for Valid DOS file + // + if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) + { + Result = FALSE; + + ShowMessages("err, the selected file is not in a valid PE format\n"); + goto Finished; + } + + if (DosHeader->e_lfanew < sizeof(IMAGE_DOS_HEADER) || + (LONGLONG)DosHeader->e_lfanew + (LONGLONG)sizeof(IMAGE_NT_HEADERS32) > FileSize.QuadPart) + { + Result = FALSE; + + ShowMessages("err, invalid image NT header offset\n"); + goto Finished; + } + + // + // Offset of NT Header is found at 0x3c location in DOS header specified by + // e_lfanew + // Get the Base of NT Header(PE Header) = DosHeader + RVA address of PE + // header + // + + NtHeader32 = (PIMAGE_NT_HEADERS32)((UINT64)(DosHeader) + (DosHeader->e_lfanew)); + + // + // Identify for valid PE file + // + if (NtHeader32->Signature != IMAGE_NT_SIGNATURE) + { + Result = FALSE; + + ShowMessages("err, invalid image NT signature\n"); + goto Finished; + } + + if (!PeImageReaderInitialize((const BYTE *)BaseAddr, (SIZE_T)FileSize.QuadPart, &Reader)) + { + Result = FALSE; + + ShowMessages("err, the selected file is not in a valid PE format\n"); + goto Finished; + } + + // + // Only few are determined (for remaining refer + // to the above specification) + // + switch (Reader.FileHeader->Machine) + { + case IMAGE_FILE_MACHINE_I386: + *Is32Bit = TRUE; + Result = TRUE; + goto Finished; + break; + case IMAGE_FILE_MACHINE_AMD64: + *Is32Bit = FALSE; + Result = TRUE; + goto Finished; + break; + default: + ShowMessages("err, PE file is not i386 or AMD64; thus, it's not supported " + "in HyperDbg\n"); + Result = FALSE; + goto Finished; + break; + } + +Finished: + // + // Unmap and close the handles + // + PlatformUnmapFile(BaseAddr, MappedSize, FileHandle); + + return Result; +} + +/** + * @brief Get the syscall number of a given Nt function + * @param NtFunctionName + * + * @return UINT32 + */ +UINT32 +PeGetSyscallNumber(LPCSTR NtFunctionName) +{ + HMODULE DllHandle = NULL; + + // + // Load ntdll.dll to get the address of the Nt function + // + DllHandle = LoadLibraryA("ntdll.dll"); + + if (!DllHandle) + { + ShowMessages("err, failed to load ntdll.dll\n"); + return NULL; + } + + // + // Choose any Nt function + // + VOID * TargetFunc = GetProcAddress(DllHandle, NtFunctionName); + + if (!TargetFunc) + { + // + // If we failed to get the address of the Nt function, + // maybe it's from win32u.dll + // + DllHandle = LoadLibraryA("win32u.dll"); + + if (!DllHandle) + { + ShowMessages("err, failed to load win32u.dll\n"); + return NULL; + } + + TargetFunc = GetProcAddress(DllHandle, NtFunctionName); + + if (!TargetFunc) + { + ShowMessages("err, failed to get address of %s\n", NtFunctionName); + return NULL; + } + } + + // + // By default, we send 30 bytes to the disassembler, + // since usually the syscall handler is less than 30 bytes, + // and we want to avoid disassembling another function + // + return HyperDbgGetImmediateValueOnEaxForSyscallNumber((UCHAR *)TargetFunc, 30, TRUE); +} diff --git a/hyperdbg/hprdbgctrl/code/debugger/user-level/ud.cpp b/hyperdbg/libhyperdbg/code/debugger/user-level/ud.cpp similarity index 70% rename from hyperdbg/hprdbgctrl/code/debugger/user-level/ud.cpp rename to hyperdbg/libhyperdbg/code/debugger/user-level/ud.cpp index effeaccb..111930b4 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/user-level/ud.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/user-level/ud.cpp @@ -17,6 +17,10 @@ extern UINT32 g_ProcessIdOfLatestStartingProcess; extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; extern BOOLEAN g_IsUserDebuggerInitialized; +extern BOOLEAN g_IsVmmModuleLoaded; +extern UINT64 g_ResultOfEvaluatedExpression; +extern UINT32 g_ErrorStateOfResultOfEvaluatedExpression; +extern CommandType g_CommandsList; extern DEBUGGER_SYNCRONIZATION_EVENTS_STATE g_UserSyncronizationObjectsHandleTable[DEBUGGER_MAXIMUM_SYNCRONIZATION_USER_DEBUGGER_OBJECTS]; @@ -34,12 +38,18 @@ UdInitializeUserDebugger() // // Initialize the handle table // - for (size_t i = 0; i < DEBUGGER_MAXIMUM_SYNCRONIZATION_USER_DEBUGGER_OBJECTS; i++) + for (SIZE_T i = 0; i < DEBUGGER_MAXIMUM_SYNCRONIZATION_USER_DEBUGGER_OBJECTS; i++) { g_UserSyncronizationObjectsHandleTable[i].IsOnWaitingState = FALSE; g_UserSyncronizationObjectsHandleTable[i].EventHandle = CreateEvent(NULL, FALSE, FALSE, NULL); } + // + // To make it more convenient, we set not to continue the previous command + // after pressing enter , so the user can enter the command for the 'g' command + // + g_CommandsList["g"].CommandAttrib &= ~DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER; + // // Indicate that it's initialized // @@ -61,12 +71,12 @@ UdUninitializeUserDebugger() // // Remove the active process // - UdRemoveActiveDebuggingProcess(TRUE); + UdRemoveActiveDebuggingProcess(); // // Initialize the handle table // - for (size_t i = 0; i < DEBUGGER_MAXIMUM_SYNCRONIZATION_USER_DEBUGGER_OBJECTS; i++) + for (SIZE_T i = 0; i < DEBUGGER_MAXIMUM_SYNCRONIZATION_USER_DEBUGGER_OBJECTS; i++) { if (g_UserSyncronizationObjectsHandleTable[i].EventHandle != NULL) { @@ -90,43 +100,56 @@ UdUninitializeUserDebugger() /** * @brief set the current active debugging process (thread) * @param DebuggingId + * @param Rip * @param ProcessId * @param ThreadId * @param Is32Bit + * @param InstructionBytesOnRip * * @return VOID */ VOID UdSetActiveDebuggingProcess(UINT64 DebuggingId, + UINT64 Rip, UINT32 ProcessId, UINT32 ThreadId, BOOLEAN Is32Bit, - BOOLEAN IsPaused) + BOOLEAN IsPaused, + BYTE InstructionBytesOnRip[]) { - g_ActiveProcessDebuggingState.ProcessId = ProcessId; - g_ActiveProcessDebuggingState.ThreadId = ThreadId; - g_ActiveProcessDebuggingState.Is32Bit = Is32Bit; + // + // Activate the debugging + // + g_ActiveProcessDebuggingState.IsActive = TRUE; + + // + // Set the details + // + g_ActiveProcessDebuggingState.ProcessId = ProcessId; + g_ActiveProcessDebuggingState.ThreadId = ThreadId; + g_ActiveProcessDebuggingState.Is32Bit = Is32Bit; + g_ActiveProcessDebuggingState.Rip = Rip; + g_ActiveProcessDebuggingState.ProcessDebuggingToken = DebuggingId; + // + // Set current instruction + // + memcpy(&g_ActiveProcessDebuggingState.InstructionBytesOnRip[0], &InstructionBytesOnRip[0], MAXIMUM_INSTR_SIZE); + // // Set pausing state // g_ActiveProcessDebuggingState.IsPaused = IsPaused; - - // - // Activate the debugging - // - g_ActiveProcessDebuggingState.IsActive = TRUE; } /** * @brief Remove the current active debugging process (thread) - * @param DontSwitchToNewProcess * * @return VOID */ VOID -UdRemoveActiveDebuggingProcess(BOOLEAN DontSwitchToNewProcess) +UdRemoveActiveDebuggingProcess() { // // Activate the debugging @@ -177,9 +200,9 @@ UdPrintError() * @brief List of threads by owner process id * * @param OwnerPID - * @return BOOL if there was an error then returns false, otherwise return true + * @return BOOLEAN if there was an error then returns false, otherwise return true */ -BOOL +BOOLEAN UdListProcessThreads(DWORD OwnerPID) { HANDLE ThreadSnap = INVALID_HANDLE_VALUE; @@ -303,7 +326,7 @@ UdCheckThreadByProcessId(DWORD Pid, DWORD Tid) * @return BOOLEAN */ BOOLEAN -UdCreateSuspendedProcess(const WCHAR * FileName, WCHAR * CommandLine, PPROCESS_INFORMATION ProcessInformation) +UdCreateSuspendedProcess(const WCHAR * FileName, const WCHAR * CommandLine, PPROCESS_INFORMATION ProcessInformation) { STARTUPINFOW StartupInfo; BOOL CreateProcessResult; @@ -315,7 +338,7 @@ UdCreateSuspendedProcess(const WCHAR * FileName, WCHAR * CommandLine, PPROCESS_I // Create process suspended // CreateProcessResult = CreateProcessW(FileName, - CommandLine, + (WCHAR *)CommandLine, NULL, NULL, FALSE, @@ -348,7 +371,7 @@ UdCreateSuspendedProcess(const WCHAR * FileName, WCHAR * CommandLine, PPROCESS_I BOOLEAN UdAttachToProcess(UINT32 TargetPid, const WCHAR * TargetFileAddress, - WCHAR * CommandLine, + const WCHAR * CommandLine, BOOLEAN RunCallbackAtTheFirstInstruction) { BOOLEAN Status; @@ -362,9 +385,9 @@ UdAttachToProcess(UINT32 TargetPid, UdInitializeUserDebugger(); // - // Check if debugger is loaded or not + // Check if the VMM module is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Check whether it's starting a new process or not @@ -379,7 +402,7 @@ UdAttachToProcess(UINT32 TargetPid, } // - // Set the state of the debugger for getting the + // Set the state of the debugger for getting the callback at the first instruction // AttachRequest.CheckCallbackAtFirstInstruction = RunCallbackAtTheFirstInstruction; @@ -451,9 +474,8 @@ UdAttachToProcess(UINT32 TargetPid, // it's a .attach command, no need for further action // ShowMessages("successfully attached to the target process!\n" - "please keep interacting with the process until all the " - "threads are intercepted and halted; whenever you execute " - "the first command, the thread interception will be stopped\n"); + "please keep interacting with the process until all the threads are " + "intercepted and halted; you can run the 'g' command to continue the debuggee\n"); return TRUE; } @@ -670,9 +692,9 @@ UdKillProcess(UINT32 TargetPid) DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS KillRequest = {0}; // - // Check if debugger is loaded or not + // Check if VMM module is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Check if the process exists @@ -736,7 +758,7 @@ UdKillProcess(UINT32 TargetPid) // // Remove the current active debugging process (thread) // - UdRemoveActiveDebuggingProcess(FALSE); + UdRemoveActiveDebuggingProcess(); // // The operation of attaching was successful @@ -768,15 +790,15 @@ UdDetachProcess(UINT32 TargetPid, UINT64 ProcessDetailToken) DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS DetachRequest = {0}; // - // Check if debugger is loaded or not + // Check if the VMM module is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Send the continue command to the target process as we // want to continue the debuggee process before detaching // - UdContinueDebuggee(ProcessDetailToken); + UdContinueProcess(ProcessDetailToken); // // We wanna detach a process @@ -818,7 +840,7 @@ UdDetachProcess(UINT32 TargetPid, UINT64 ProcessDetailToken) // // Remove the current active debugging process (thread) // - UdRemoveActiveDebuggingProcess(FALSE); + UdRemoveActiveDebuggingProcess(); // // The operation of attaching was successful @@ -847,9 +869,9 @@ UdPauseProcess(UINT64 ProcessDebuggingToken) DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS PauseRequest = {0}; // - // Check if debugger is loaded or not + // Check if the VMM module is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // We wanna pause a process @@ -884,7 +906,75 @@ UdPauseProcess(UINT64 ProcessDebuggingToken) } // - // Check if killing was successful or not + // Check if pausing was successful or not + // + if (PauseRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // + // The operation of attaching was successful + // + return TRUE; + } + else + { + ShowErrorMessage((UINT32)PauseRequest.Result); + return FALSE; + } +} + +/** + * @brief Continue the target process + * + * @param ProcessDebuggingToken + * + * @return BOOLEAN + */ +BOOLEAN +UdContinueProcess(UINT64 ProcessDebuggingToken) +{ + BOOLEAN Status; + ULONG ReturnedLength; + DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS PauseRequest = {0}; + + // + // Check if the VMM module is loaded or not + // + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // We wanna continue a process + // + PauseRequest.Action = DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_CONTINUE_PROCESS; + + // + // Set the process debugging token + // + PauseRequest.Token = ProcessDebuggingToken; + + // + // Send the request to the kernel + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // IO Control + // code + &PauseRequest, // Input Buffer to driver. + SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // Input buffer length + &PauseRequest, // Output Buffer from driver. + SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // Length of output + // buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + return FALSE; + } + + // + // Check if continuing was successful or not // if (PauseRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL) { @@ -905,87 +995,243 @@ UdPauseProcess(UINT64 ProcessDebuggingToken) * @param ProcessDetailToken * @param ThreadId * @param ActionType + * @param OptionalBuffer + * @param OptionalBufferSize * @param ApplyToAllPausedThreads + * @param WaitForEventCompletion * @param OptionalParam1 * @param OptionalParam2 * @param OptionalParam3 * @param OptionalParam4 * - * @return VOID + * @return BOOLEAN */ -VOID +BOOLEAN UdSendCommand(UINT64 ProcessDetailToken, UINT32 ThreadId, DEBUGGER_UD_COMMAND_ACTION_TYPE ActionType, + PVOID OptionalBuffer, + UINT32 OptionalBufferSize, BOOLEAN ApplyToAllPausedThreads, + BOOLEAN WaitForEventCompletion, UINT64 OptionalParam1, UINT64 OptionalParam2, UINT64 OptionalParam3, UINT64 OptionalParam4) { - BOOL Status; - ULONG ReturnedLength; - DEBUGGER_UD_COMMAND_PACKET CommandPacket; + BOOL Status; + ULONG ReturnedLength; + UINT32 TargetBufferSize = 0; + DEBUGGER_UD_COMMAND_PACKET * CommandPacket; - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // Calculate the target buffer size + // + if (OptionalBufferSize == 0) + { + TargetBufferSize = sizeof(DEBUGGER_UD_COMMAND_PACKET); + } + else + { + TargetBufferSize = sizeof(DEBUGGER_UD_COMMAND_PACKET) + OptionalBufferSize; + } + + // + // Allocate the target buffer + // + CommandPacket = (DEBUGGER_UD_COMMAND_PACKET *)malloc(TargetBufferSize); + + if (CommandPacket == NULL) + { + ShowMessages("err, unable to allocate memory for command\n"); + return FALSE; + } // // Zero the packet // - RtlZeroMemory(&CommandPacket, sizeof(DEBUGGER_UD_COMMAND_PACKET)); + RtlZeroMemory(CommandPacket, TargetBufferSize); // // Set to the details // - CommandPacket.ProcessDebuggingDetailToken = ProcessDetailToken; - CommandPacket.ApplyToAllPausedThreads = ApplyToAllPausedThreads; - CommandPacket.TargetThreadId = ThreadId; - CommandPacket.UdAction.ActionType = ActionType; - CommandPacket.UdAction.OptionalParam1 = OptionalParam1; - CommandPacket.UdAction.OptionalParam2 = OptionalParam2; - CommandPacket.UdAction.OptionalParam3 = OptionalParam3; - CommandPacket.UdAction.OptionalParam4 = OptionalParam4; + CommandPacket->ProcessDebuggingDetailToken = ProcessDetailToken; + CommandPacket->ApplyToAllPausedThreads = ApplyToAllPausedThreads; + CommandPacket->TargetThreadId = ThreadId; + CommandPacket->WaitForEventCompletion = WaitForEventCompletion; + CommandPacket->UdAction.ActionType = ActionType; + CommandPacket->UdAction.OptionalParam1 = OptionalParam1; + CommandPacket->UdAction.OptionalParam2 = OptionalParam2; + CommandPacket->UdAction.OptionalParam3 = OptionalParam3; + CommandPacket->UdAction.OptionalParam4 = OptionalParam4; + + // + // Copy the optional buffer if it's present + // + if (OptionalBuffer != NULL && OptionalBufferSize != 0) + { + // + // Append the optional buffer to the command packet buffer + // + memcpy((PVOID)((UINT8 *)CommandPacket + sizeof(DEBUGGER_UD_COMMAND_PACKET)), OptionalBuffer, OptionalBufferSize); + } // // Send IOCTL // - Status = DeviceIoControl(g_DeviceHandle, // Handle to device - IOCTL_SEND_USER_DEBUGGER_COMMANDS, // IO Control Code (IOCTL) - &CommandPacket, // Input Buffer to driver. - sizeof(DEBUGGER_UD_COMMAND_PACKET), // Input buffer length - &CommandPacket, // Output Buffer from driver. - sizeof(DEBUGGER_UD_COMMAND_PACKET), // Length of output buffer in bytes. - &ReturnedLength, // Bytes placed in buffer. - NULL // synchronous call + Status = DeviceIoControl(g_DeviceHandle, // Handle to device + IOCTL_SEND_USER_DEBUGGER_COMMANDS, // IO Control Code (IOCTL) + CommandPacket, // Input Buffer to driver. + TargetBufferSize, // Input buffer length + CommandPacket, // Output Buffer from driver. + TargetBufferSize, // Length of output buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call ); if (!Status) { ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); - return; + + free(CommandPacket); + return FALSE; } + + if (CommandPacket->Result != DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + ShowErrorMessage((UINT32)CommandPacket->Result); + + free(CommandPacket); + return FALSE; + } + + // + // Copy the result of optional buffer to the caller buffer + // + if (OptionalBuffer != NULL && OptionalBufferSize != 0) + { + // + // Append the optional buffer to the command packet buffer + // + memcpy(OptionalBuffer, + (PVOID)((UINT8 *)CommandPacket + sizeof(DEBUGGER_UD_COMMAND_PACKET)), + OptionalBufferSize); + } + + // + // Free the allocated buffer + // + free(CommandPacket); + + return TRUE; } /** - * @brief Continue the target user debugger - * @param ProcessDetailToken + * @brief Send the command to the user debugger * - * @return VOID + * @param ProcessDetailToken + * @param TargetThreadId + * @param RegDes + * @param RegBuffSize + * + * @return BOOLEAN */ -VOID -UdContinueDebuggee(UINT64 ProcessDetailToken) +BOOLEAN +UdSendReadRegisterToUserDebugger(UINT64 ProcessDetailToken, + UINT32 TargetThreadId, + PDEBUGGEE_REGISTER_READ_DESCRIPTION RegDes, + UINT32 RegBuffSize) + { // - // Send the 'continue' command + // Send the read register command // - UdSendCommand(ProcessDetailToken, - NULL, - DEBUGGER_UD_COMMAND_ACTION_TYPE_CONTINUE, - TRUE, - NULL, - NULL, - NULL, - NULL); + return UdSendCommand(ProcessDetailToken, + TargetThreadId, + DEBUGGER_UD_COMMAND_ACTION_TYPE_READ_REGISTERS, + RegDes, + RegBuffSize, + FALSE, + TRUE, + RegDes->RegisterId, + NULL, + NULL, + NULL); +} + +/** + * @brief Send script buffer to the user debugger + * + * @param ProcessDetailToken + * @param TargetThreadId + * @param BufferAddress + * @param BufferLength + * @param Pointer + * + * @return BOOLEAN + */ +BOOLEAN +UdSendScriptBufferToProcess(UINT64 ProcessDetailToken, + UINT32 TargetThreadId, + UINT64 BufferAddress, + UINT32 BufferLength, + UINT32 Pointer, + BOOLEAN IsFormat) + +{ + PDEBUGGEE_SCRIPT_PACKET ScriptPacket; + UINT32 SizeOfStruct = 0; + BOOLEAN Result = FALSE; + + SizeOfStruct = sizeof(DEBUGGEE_SCRIPT_PACKET) + BufferLength; + + ScriptPacket = (DEBUGGEE_SCRIPT_PACKET *)malloc(SizeOfStruct); + + RtlZeroMemory(ScriptPacket, SizeOfStruct); + + // + // Fill the script packet buffer + // + ScriptPacket->ScriptBufferSize = BufferLength; + ScriptPacket->ScriptBufferPointer = Pointer; + ScriptPacket->IsFormat = IsFormat; + + // + // Move the buffer at the bottom of the script packet + // + memcpy((PVOID)((UINT64)ScriptPacket + sizeof(DEBUGGEE_SCRIPT_PACKET)), + (PVOID)BufferAddress, + BufferLength); + + // + // Send the script buffer command + // + Result = UdSendCommand(ProcessDetailToken, + TargetThreadId, + DEBUGGER_UD_COMMAND_ACTION_TYPE_EXECUTE_SCRIPT_BUFFER, + ScriptPacket, + SizeOfStruct, + FALSE, + TRUE, + NULL, + NULL, + NULL, + NULL); + + // + // Check if it's a format expression and if there was an error or not + // + if (IsFormat && Result) + { + g_ErrorStateOfResultOfEvaluatedExpression = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + g_ResultOfEvaluatedExpression = ScriptPacket->FormatValue; + } + + free(ScriptPacket); + + return Result; } /** @@ -994,35 +1240,66 @@ UdContinueDebuggee(UINT64 ProcessDetailToken) * @param TargetThreadId * @param StepType * - * @return VOID + * @return BOOLEAN */ -VOID -UdSendStepPacketToDebuggee(UINT64 ProcessDetailToken, UINT32 TargetThreadId, DEBUGGER_REMOTE_STEPPING_REQUEST StepType) +BOOLEAN +UdSendStepPacketToDebuggee(UINT64 ProcessDetailToken, + UINT32 TargetThreadId, + DEBUGGER_REMOTE_STEPPING_REQUEST StepType) { - // - // Wait until the result of user-input received - // - g_UserSyncronizationObjectsHandleTable - [DEBUGGER_SYNCRONIZATION_OBJECT_USER_DEBUGGER_IS_DEBUGGER_RUNNING] - .IsOnWaitingState = TRUE; + BOOLEAN IsCurrentInstructionACall = FALSE; + UINT32 CallInstructionSize = 0; // - // Send the 'continue' command + // Check for specific stepping type // - UdSendCommand(ProcessDetailToken, - TargetThreadId, - DEBUGGER_UD_COMMAND_ACTION_TYPE_REGULAR_STEP, - FALSE, - StepType, - NULL, - NULL, - NULL); + if (StepType == DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER) + { + // + // We should check whether the current instruction is a 'call' + // instruction or not, if yes we have to compute the length of call + // + if (HyperDbgCheckWhetherTheCurrentInstructionIsCall( + (UCHAR *)&g_ActiveProcessDebuggingState.InstructionBytesOnRip[0], + MAXIMUM_INSTR_SIZE, + g_ActiveProcessDebuggingState.Is32Bit ? FALSE : TRUE, // equals to !g_IsRunningInstruction32Bit + &CallInstructionSize)) + { + // + // It's a call in step-over + // + IsCurrentInstructionACall = TRUE; + CallInstructionSize = CallInstructionSize; + } + } - WaitForSingleObject( - g_UserSyncronizationObjectsHandleTable - [DEBUGGER_SYNCRONIZATION_OBJECT_USER_DEBUGGER_IS_DEBUGGER_RUNNING] - .EventHandle, - INFINITE); + // + // Send the 'step' command + // + if (UdSendCommand(ProcessDetailToken, + TargetThreadId, + DEBUGGER_UD_COMMAND_ACTION_TYPE_REGULAR_STEP, + NULL, + 0, + FALSE, + FALSE, + StepType, + IsCurrentInstructionACall, + CallInstructionSize, + NULL)) + { + // + // Wait until the result of user-input received + // + DbgWaitForUserResponse(DEBUGGER_SYNCRONIZATION_OBJECT_USER_DEBUGGER_IS_DEBUGGER_RUNNING); + + return TRUE; + } + + // + // An error happened + // + return FALSE; } /** @@ -1041,9 +1318,9 @@ UdSetActiveDebuggingThreadByPidOrTid(UINT32 TargetPidOrTid, BOOLEAN IsTid) DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS SwitchRequest = {0}; // - // Check if debugger is loaded or not + // Check if the VMM module is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // We wanna switch to a process or thread @@ -1067,8 +1344,7 @@ UdSetActiveDebuggingThreadByPidOrTid(UINT32 TargetPidOrTid, BOOLEAN IsTid) // Status = DeviceIoControl( g_DeviceHandle, // Handle to device - IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // IO Control - // code + IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // IO Control code &SwitchRequest, // Input Buffer to driver. SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // Input buffer length &SwitchRequest, // Output Buffer from driver. @@ -1093,10 +1369,12 @@ UdSetActiveDebuggingThreadByPidOrTid(UINT32 TargetPidOrTid, BOOLEAN IsTid) // Set the current active debugging process (thread) // UdSetActiveDebuggingProcess(SwitchRequest.Token, + SwitchRequest.Rip, SwitchRequest.ProcessId, SwitchRequest.ThreadId, SwitchRequest.Is32Bit, - SwitchRequest.IsPaused); + SwitchRequest.IsPaused, + SwitchRequest.InstructionBytesOnRip); // // The operation of attaching was successful @@ -1126,9 +1404,9 @@ UdShowListActiveDebuggingProcessesAndThreads() UINT32 SizeOfBufferForThreadsAndProcessDetails = NULL; // - // Check if debugger is loaded or not + // Check if the VMM module is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Check if user debugger is active or not @@ -1222,7 +1500,7 @@ UdShowListActiveDebuggingProcessesAndThreads() // // Show list of active processes and threads // - for (size_t i = 0; i < QueryCountOfActiveThreadsRequest.CountOfActiveDebuggingThreadsAndProcesses; i++) + for (SIZE_T i = 0; i < QueryCountOfActiveThreadsRequest.CountOfActiveDebuggingThreadsAndProcesses; i++) { if (AddressOfThreadsAndProcessDetails[i].IsProcess) { @@ -1245,9 +1523,10 @@ UdShowListActiveDebuggingProcessesAndThreads() { CheckCurrentProcessOrThread = TRUE; } - ShowMessages("\t%s %04x (thread)\n", + ShowMessages("\t%s %04x (thread) | # blkd exec attempts: %llx\n", CheckCurrentProcessOrThread ? "->" : " ", - AddressOfThreadsAndProcessDetails[i].ThreadId); + AddressOfThreadsAndProcessDetails[i].ThreadId, + AddressOfThreadsAndProcessDetails[i].NumberOfBlockedContextSwitches); } } } diff --git a/hyperdbg/hprdbgctrl/code/debugger/user-level/user-listening.cpp b/hyperdbg/libhyperdbg/code/debugger/user-level/user-listening.cpp similarity index 56% rename from hyperdbg/hprdbgctrl/code/debugger/user-level/user-listening.cpp rename to hyperdbg/libhyperdbg/code/debugger/user-level/user-listening.cpp index 1da00cc2..bcb78a05 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/user-level/user-listening.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/user-level/user-listening.cpp @@ -28,15 +28,6 @@ extern DEBUGGER_SYNCRONIZATION_EVENTS_STATE VOID UdHandleUserDebuggerPausing(PDEBUGGEE_UD_PAUSED_PACKET PausePacket) { - // - // Set the current active debugging process (thread) - // - UdSetActiveDebuggingProcess(PausePacket->ProcessDebuggingToken, - PausePacket->ProcessId, - PausePacket->ThreadId, - PausePacket->Is32Bit, - TRUE); - // // Perform extra tasks for pausing reasons // @@ -50,9 +41,9 @@ UdHandleUserDebuggerPausing(PDEBUGGEE_UD_PAUSED_PACKET PausePacket) break; case DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_THREAD_INTERCEPTED: - ShowMessages("\nthread: %x from process: %x intercepted\n", - PausePacket->ThreadId, - PausePacket->ProcessId); + // ShowMessages("\nthread: %x from process: %x intercepted\n", + // PausePacket->ThreadId, + // PausePacket->ProcessId); break; @@ -77,29 +68,48 @@ UdHandleUserDebuggerPausing(PDEBUGGEE_UD_PAUSED_PACKET PausePacket) } } - if (!PausePacket->Is32Bit) + // + // For the first thread that is paused, show the disassembly + // + if (g_ActiveProcessDebuggingState.IsPaused == FALSE || PausePacket->ThreadId == g_ActiveProcessDebuggingState.ThreadId) { // - // Show diassembles + // Set the current active debugging process (thread) // - HyperDbgDisassembler64(PausePacket->InstructionBytesOnRip, - PausePacket->Rip, - MAXIMUM_INSTR_SIZE, - 1, - TRUE, - (PRFLAGS)&PausePacket->Rflags); - } - else - { - // - // Show diassembles - // - HyperDbgDisassembler32(PausePacket->InstructionBytesOnRip, - PausePacket->Rip, - MAXIMUM_INSTR_SIZE, - 1, - TRUE, - (PRFLAGS)&PausePacket->Rflags); + UdSetActiveDebuggingProcess(PausePacket->ProcessDebuggingToken, + PausePacket->Rip, + PausePacket->ProcessId, + PausePacket->ThreadId, + PausePacket->Is32Bit, + TRUE, + &PausePacket->InstructionBytesOnRip[0]); + + if (!PausePacket->Is32Bit) + { + // + // Show diassembles + // + ShowMessages("\n"); + HyperDbgDisassembler64(PausePacket->InstructionBytesOnRip, + PausePacket->Rip, + MAXIMUM_INSTR_SIZE, + 1, + TRUE, + (PRFLAGS)&PausePacket->Rflags); + } + else + { + // + // Show diassembles + // + ShowMessages("\n"); + HyperDbgDisassembler32(PausePacket->InstructionBytesOnRip, + PausePacket->Rip, + MAXIMUM_INSTR_SIZE, + 1, + TRUE, + (PRFLAGS)&PausePacket->Rflags); + } } // diff --git a/hyperdbg/libhyperdbg/code/export/export.cpp b/hyperdbg/libhyperdbg/code/export/export.cpp new file mode 100644 index 00000000..f78f73a5 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/export/export.cpp @@ -0,0 +1,986 @@ +/** + * @file export.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @author jtaw5649 + * @brief Exported functions from libhyperdbg interface + * @details + * @version 0.10 + * @date 2024-06-24 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern TCHAR g_DriverLocation[MAX_PATH]; +extern TCHAR g_DriverName[MAX_PATH]; +extern BOOLEAN g_UseCustomDriverLocation; + +/** + * @brief Detects the support of VMX + * + * @return BOOLEAN Returns true if the CPU supports VMX + */ +BOOLEAN +hyperdbg_u_detect_vmx_support() +{ + return VmxSupportDetection(); +} + +/** + * @brief Read the vendor string of the CPU + * + * @param vendor_string The buffer to store the vendor string + * @return VOID + */ +VOID +hyperdbg_u_read_vendor_string(CHAR * vendor_string) +{ + CpuReadVendorString(vendor_string); +} + +/** + * @brief Load the VMM + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_load_vmm() +{ + return HyperDbgLoadVmmModule(); +} + +/** + * @brief Check if any module is loaded + * + * @return BOOLEAN Returns true if any module is loaded and false if no module is loaded + */ +BOOLEAN +hyperdbg_u_is_any_module_loaded() +{ + return HyperDbgIsAnyModuleLoaded(); +} + +/** + * @brief Unload all modules + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_unload_all_modules() +{ + return HyperDbgUnloadAllModules(); +} + +/** + * @brief Unload the VMM module + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_unload_vmm() +{ + return HyperDbgUnloadVmm(); +} + +/** + * @brief Unload the trace module + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_unload_hypertrace_module() +{ + return HyperDbgUnloadHyperTrace(); +} + +/** + * @brief Unload the KD module + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_unload_kd() +{ + return HyperDbgUnloadKd(); +} + +/** + * @brief Install the KD driver + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_install_kd_driver() +{ + return HyperDbgInstallKdDriver(); +} + +/** + * @brief Uninstall the KD (Kernel Debugger) driver + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_uninstall_kd_driver() +{ + return HyperDbgUninstallKdDriver(); +} + +/** + * @brief Start the KD driver + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_start_kd_driver() +{ + return HyperDbgStartKdDriver(); +} + +/** + * @brief Stop the KD driver + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_stop_kd_driver() +{ + return HyperDbgStopKdDriver(); +} + +/** + * @brief Get the vendor of the current processor + * + * @return GENERIC_PROCESSOR_VENDOR the vendor of the processor + */ +GENERIC_PROCESSOR_VENDOR +hyperdbg_u_get_processor_vendor() +{ + return HyperDbgGetProcessorVendor(); +} + +/** + * @brief Load the KD module + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_load_kd_module() +{ + return HyperDbgLoadKdModule(); +} + +/** + * @brief Load the hypertrace module + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_load_hypertrace_module() +{ + return HyperDbgLoadHyperTraceModule(); +} + +/** + * @brief Load all modules + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_load_all_modules() +{ + return HyperDbgLoadAllModules(); +} + +/** + * @brief Run a command + * + * @return INT Returns 0 if it was successful and 1 if it was failed + */ +INT +hyperdbg_u_run_command(CHAR * command) +{ + return HyperDbgInterpreter(command); +} + +/** + * @brief Parse the command (used for testing purposes) + * + * @param command The text of command + * @param number_of_tokens The number of tokens + * @param tokens_list The list of tokens + * + * @return BOOLEAN returns true if the command was parsed successfully and false if there was an error + */ +BOOLEAN +hyperdbg_u_test_command_parser(CHAR * command, + UINT32 number_of_tokens, + CHAR ** tokens_list, + UINT32 * failed_token_num, + UINT32 * failed_token_position) +{ + return HyperDbgTestCommandParser(command, number_of_tokens, tokens_list, failed_token_num, failed_token_position); +} + +/** + * @brief Parse and show tokens for the command (used for testing purposes) + * + * @param command The text of command + * + * @return VOID + */ +VOID +hyperdbg_u_test_command_parser_show_tokens(CHAR * command) +{ + return HyperDbgTestCommandParserShowTokens(command); +} + +/** + * @brief Show the signature of the debugger + * + * @return VOID + */ +VOID +hyperdbg_u_show_signature() +{ + HyperDbgShowSignature(); +} + +/** + * @brief Set the function callback that will be called if any message + * needs to be shown (by passing message as a parameter) + * + * @param handler Function that handles the messages + * + * @return VOID + */ +VOID +hyperdbg_u_set_text_message_callback(PVOID handler) +{ + SetTextMessageCallback(handler); +} + +/** + * @brief Set the function callback that will be called if any message + * needs to be shown (using shared buffer method) + * + * @param handler Function that handles the messages + * + * @return PVOID + */ +PVOID +hyperdbg_u_set_text_message_callback_using_shared_buffer(PVOID handler) +{ + return SetTextMessageCallbackUsingSharedBuffer(handler); +} + +/** + * @brief Unset the function callback that will be called if any message + * needs to be shown + * + * @return VOID + */ +VOID +hyperdbg_u_unset_text_message_callback() +{ + UnsetTextMessageCallback(); +} + +/** + * @brief Parsing the command line options for scripts + * @param argc + * @param argv + * + * @return INT + */ +INT +hyperdbg_u_script_read_file_and_execute_commandline(INT argc, CHAR * argv[]) +{ + return HyperDbgScriptReadFileAndExecuteCommandline(argc, argv); +} + +/** + * @brief Some of commands like stepping commands (i, p, t) and etc. + * need to be repeated when the user press enter, this function shows + * whether we should continue the previous command or not + * + * @return TRUE means the command should be continued, FALSE means command + * should be ignored + */ +BOOLEAN +hyperdbg_u_continue_previous_command() +{ + return ContinuePreviousCommand(); +} + +/** + * @brief Check if the command is a multiline command or not + * + * @param current_command The current command + * @param reset If it's true, it will reset the multiline command + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_check_multiline_command(CHAR * current_command, BOOLEAN reset) +{ + return CheckMultilineCommand(current_command, reset); +} + +/** + * @brief Connect to the local debugger + * + * @return VOID + */ +VOID +hyperdbg_u_connect_local_debugger() +{ + ConnectLocalDebugger(); +} +/** + * @brief Connect to the remote debugger + * + * @param ip The IP address of the remote debugger + * @param port The port of the remote debugger + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +hyperdbg_u_connect_remote_debugger(const CHAR * ip, const CHAR * port) +{ + return ConnectRemoteDebugger(ip, port); +} + +/** + * @brief Continue the debuggee (equal to the 'g' command) + * + * @return VOID + */ +VOID +hyperdbg_u_continue_debuggee() +{ + CommandGRequest(); +} + +/** + * @brief Pause the debuggee (equal to the 'pause' command) + * + * @return VOID + */ +VOID +hyperdbg_u_pause_debuggee() +{ + CommandPauseRequest(); +} + +/** + * @brief Set a breakpoint + * @param address The address of the breakpoint + * @param pid The process ID of the breakpoint + * @param tid The thread ID of the breakpoint + * @param core_number The core number of the breakpoint + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_set_breakpoint(UINT64 address, UINT32 pid, UINT32 tid, UINT32 core_number) +{ + return CommandBpRequest(address, pid, tid, core_number); +} + +/** + * @brief Set custom driver path + * + * @param driver_file_path The path of the driver + * @param driver_name The name of the driver + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +hyperdbg_u_set_custom_driver_path(CHAR * driver_file_path, CHAR * driver_name) +{ + if (strlen(driver_file_path) > MAX_PATH) + { + ShowMessages("The driver path is too long, the maximum length is %d\n", MAX_PATH); + return FALSE; + } + + if (strlen(driver_name) > MAX_PATH) + { + ShowMessages("The driver name is too long, the maximum length is %d\n", MAX_PATH); + return FALSE; + } + + // + // Copy the driver path + // + strcpy_s(g_DriverLocation, MAX_PATH, driver_file_path); + + // + // Copy the driver name + // + strcpy_s(g_DriverName, MAX_PATH, driver_name); + + // + // Set the flag to use the custom driver path + // + g_UseCustomDriverLocation = TRUE; + + return TRUE; +} + +/** + * @brief Use the default driver path + * + * @return VOID + */ +VOID +hyperdbg_u_use_default_driver_path() +{ + // + // Set the flag to use the default driver path + // + g_UseCustomDriverLocation = FALSE; +} + +/** + * @brief Read memory and disassembler + * + * @param target_address location of where to read the memory + * @param memory_type type of memory (phyical or virtual) + * @param reading_Type read from kernel or vmx-root + * @param pid The target process id + * @param size size of memory to read + * @param get_address_mode check for address mode + * @param address_mode Address mode (32 or 64) + * @param target_buffer_to_store The buffer to store the read memory + * @param return_length The length of the read memory + * + * @return BOOLEAN TRUE if the operation was successful, otherwise FALSE + */ +BOOLEAN +hyperdbg_u_read_memory(UINT64 target_address, + DEBUGGER_READ_MEMORY_TYPE memory_type, + DEBUGGER_READ_READING_TYPE reading_Type, + UINT32 pid, + UINT32 size, + BOOLEAN get_address_mode, + DEBUGGER_READ_MEMORY_ADDRESS_MODE * address_mode, + BYTE * target_buffer_to_store, + UINT32 * return_length) +{ + return HyperDbgReadMemory(target_address, memory_type, reading_Type, pid, size, get_address_mode, address_mode, target_buffer_to_store, return_length); +} + +/** + * @brief Show memory or disassembler + * + * @param style style of show memory (as byte, dwrod, qword) + * @param address location of where to read the memory + * @param memory_type type of memory (phyical or virtual) + * @param reading_type read from kernel or vmx-root + * @param pid The target process id + * @param size size of memory to read + * @param dt_details Options for dt structure show details + * + * @return VOID + */ +VOID +hyperdbg_u_show_memory_or_disassemble(DEBUGGER_SHOW_MEMORY_STYLE style, + UINT64 address, + DEBUGGER_READ_MEMORY_TYPE memory_type, + DEBUGGER_READ_READING_TYPE reading_type, + UINT32 pid, + UINT32 size, + PDEBUGGER_DT_COMMAND_OPTIONS dt_details) +{ + HyperDbgShowMemoryOrDisassemble(style, address, memory_type, reading_type, pid, size, dt_details); +} + +/** + * @brief Read all registers + * @param guest_registers The buffer to store the registers + * @param extra_registers The buffer to store the extra registers + * + * @return BOOLEAN TRUE if the operation was successful, otherwise FALSE + */ +BOOLEAN +hyperdbg_u_read_all_registers(GUEST_REGS * guest_registers, GUEST_EXTRA_REGISTERS * extra_registers) +{ + return HyperDbgReadAllRegisters(guest_registers, extra_registers); +} + +/** + * @brief Read target register + * @param register_id The target register + * @param target_register The buffer to store the register + * + * @return BOOLEAN TRUE if the operation was successful, otherwise FALSE + */ +BOOLEAN +hyperdbg_u_read_target_register(REGS_ENUM register_id, UINT64 * target_register) +{ + return HyperDbgReadTargetRegister(register_id, target_register); +} + +/** + * @brief Write target register + * @param register_id The target register + * @param value The value to write + * + * @return BOOLEAN TRUE if the operation was successful, otherwise FALSE + */ +BOOLEAN +hyperdbg_u_write_target_register(REGS_ENUM register_id, UINT64 value) +{ + return HyperDbgWriteTargetRegister(register_id, value); +} + +/** + * @brief Show all registers + * + * @return BOOLEAN TRUE if the operation was successful, otherwise FALSE + */ +BOOLEAN +hyperdbg_u_show_all_registers() +{ + return HyperDbgRegisterShowAll(); +} + +/** + * @brief Show target register + * @param register_id The target register + * + * @return BOOLEAN TRUE if the operation was successful, otherwise FALSE + */ +BOOLEAN +hyperdbg_u_show_target_register(REGS_ENUM register_id) +{ + return HyperDbgRegisterShowTargetRegister(register_id); +} + +/** + * @brief Write memory + * @param destination_address The destination address + * @param memory_type The type of memory (physical or virtual) + * @param process_id The target process id (if it's virtual memory) + * @param source_address The source address + * @param number_of_bytes The number of bytes to write + * + * @return BOOLEAN TRUE if the operation was successful, otherwise FALSE + */ +BOOLEAN +hyperdbg_u_write_memory(PVOID destination_address, + DEBUGGER_EDIT_MEMORY_TYPE memory_type, + UINT32 process_id, + PVOID source_address, + UINT32 number_of_bytes) +{ + return HyperDbgWriteMemory(destination_address, memory_type, process_id, source_address, number_of_bytes); +} + +/** + * @brief Get the kernel base + * + * @return UINT64 The kernel base + */ +UINT64 +hyperdbg_u_get_kernel_base() +{ + return DebuggerGetKernelBase(); +} + +/** + * @brief Connect to the remote debugger using COM port + * + * @param port_name The port name + * @param baudrate The baudrate + * @param pause_after_connection Pause after connection + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +hyperdbg_u_connect_remote_debugger_using_com_port(const CHAR * port_name, DWORD baudrate, BOOLEAN pause_after_connection) +{ + return HyperDbgDebugRemoteDeviceUsingComPort(port_name, baudrate, pause_after_connection); +} + +/** + * @brief Connect to the remote debugger using named pipe + * + * @param named_pipe The named pipe + * @param pause_after_connection Pause after connection + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +hyperdbg_u_connect_remote_debugger_using_named_pipe(const CHAR * named_pipe, BOOLEAN pause_after_connection) +{ + return HyperDbgDebugRemoteDeviceUsingNamedPipe(named_pipe, pause_after_connection); +} + +/** + * @brief Close the remote debugger + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +hyperdbg_u_debug_close_remote_debugger() +{ + return HyperDbgDebugCloseRemoteDebugger(); +} + +/** + * @brief Connect to the current debugger using COM port + * + * @param port_name The port name + * @param baudrate The baudrate + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +hyperdbg_u_connect_current_debugger_using_com_port(const CHAR * port_name, DWORD baudrate) +{ + return HyperDbgDebugCurrentDeviceUsingComPort(port_name, baudrate); +} + +/** + * @brief Start a new process + * + * @param path The path of the process + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +hyperdbg_u_start_process(const WCHAR * path) +{ + return UdAttachToProcess(NULL, + path, + NULL, + FALSE); +} + +/** + * @brief Start a new process + * + * @param path The path of the process + * @param arguments The arguments of the process + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +hyperdbg_u_start_process_with_args(const WCHAR * path, const WCHAR * arguments) +{ + return UdAttachToProcess(NULL, + path, + arguments, + FALSE); +} + +/** + * @brief Assembler function to get the length of the assembly code + * + * @param assembly_code The assembly code + * @param start_address The start address of the assembly code + * @param length The length of the assembly code + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +hyperdbg_u_assemble_get_length(const CHAR * assembly_code, UINT64 start_address, UINT32 * length) +{ + return HyperDbgAssembleGetLength(assembly_code, start_address, length); +} + +/** + * @brief Assembler function + * + * @param assembly_code The assembly code + * @param start_address The start address of the assembly code + * @param buffer_to_store_assembled_data The buffer to store the assembled data + * @param buffer_size The size of the buffer + * + * @return BOOLEAN Returns true if it was successful + */ +BOOLEAN +hyperdbg_u_assemble(const CHAR * assembly_code, UINT64 start_address, PVOID buffer_to_store_assembled_data, UINT32 buffer_size) +{ + return HyperDbgAssemble(assembly_code, start_address, buffer_to_store_assembled_data, buffer_size); +} + +/** + * @brief Setip the path for the filename + * + * @param filename The filename + * @param file_location + * @param buffer_len + * @param check_file_existence + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_setup_path_for_filename(const CHAR * filename, CHAR * file_location, UINT32 buffer_len, BOOLEAN check_file_existence) +{ + return SetupPathForFileName(filename, file_location, buffer_len, check_file_existence); +} + +/** + * @brief Perform instrumentation step-in + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_stepping_instrumentation_step_in() +{ + return SteppingInstrumentationStepIn(); +} + +/** + * @brief Perform regular step-in + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_stepping_regular_step_in() +{ + return SteppingRegularStepIn(); +} + +/** + * @brief Perform step-over + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_stepping_step_over() +{ + return SteppingStepOver(); +} + +/** + * @brief Perform instrumentation step-in for tracking + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_stepping_instrumentation_step_in_for_tracking() +{ + return SteppingInstrumentationStepInForTracking(); +} + +/** + * @brief Perform step-over for gu + * + * @param last_instruction + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_stepping_step_over_for_gu(BOOLEAN last_instruction) +{ + return SteppingStepOverForGu(last_instruction); +} + +/** + * @brief Get Local APIC + * @details The system automatically detects whether to read it + * in the xAPIC or x2APIC mode + * + * @param local_apic + * @param is_using_x2apic + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_get_local_apic(PLAPIC_PAGE local_apic, BOOLEAN * is_using_x2apic) +{ + return HyperDbgGetLocalApic(local_apic, is_using_x2apic); +} + +/** + * @brief Get I/O APIC + * + * @param io_apic + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_get_io_apic(IO_APIC_ENTRY_PACKETS * io_apic) +{ + return HyperDbgGetIoApic(io_apic); +} + +/** + * @brief Get IDT entry + * + * @param idt_packet + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_get_idt_entry(INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS * idt_packet) +{ + return HyperDbgGetIdtEntry(idt_packet); +} + +/** + * @brief Perform SMI operation + * + * @param SmiOperation The SMI operation packet + * + * @return + */ +BOOLEAN +hyperdbg_u_perform_smi_operation(SMI_OPERATION_PACKETS * SmiOperation) +{ + return HyperDbgPerformSmiOperation(SmiOperation); +} + +/** + * @brief Run hwdbg script + * + * @param script + * @param instance_filepath_to_read + * @param hardware_script_file_path_to_save + * @param initial_bram_buffer_size + * + * @return BOOLEAN + */ +BOOLEAN +hwdbg_script_run_script(const CHAR * script, + const CHAR * instance_filepath_to_read, + const CHAR * hardware_script_file_path_to_save, + UINT32 initial_bram_buffer_size) +{ + return HwdbgScriptRunScript(script, + instance_filepath_to_read, + hardware_script_file_path_to_save, + initial_bram_buffer_size); +} + +/** + * @brief Run (test evaluation) hwdbg script + * + * @param Expr + * + * @return VOID + */ +VOID +hwdbg_script_engine_wrapper_test_parser(const char * Expr) +{ + std::string StrExpr = Expr; // Convert const char* to std::string + ScriptEngineWrapperTestParserForHwdbg(StrExpr); +} + +/** + * @brief Enable transparent mode + * @param ProcessId The process ID to enable transparent mode for + * @param ProcessName The process name to enable transparent mode for + * @param IsProcessId If true, ProcessId is used, otherwise ProcessName is used + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_enable_transparent_mode(UINT32 ProcessId, CHAR * ProcessName, BOOLEAN IsProcessId) +{ + return HyperDbgEnableTransparentMode(ProcessId, ProcessName, IsProcessId); +} + +/** + * @brief Enable transparent mode with a feature mask + * @param ProcessId The process ID to enable transparent mode for + * @param ProcessName The process name to enable transparent mode for + * @param IsProcessId If true, ProcessId is used, otherwise ProcessName is used + * @param EvadeMask The transparent-mode feature mask, or zero for default behavior + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_enable_transparent_mode_ex(UINT32 ProcessId, CHAR * ProcessName, BOOLEAN IsProcessId, UINT32 EvadeMask) +{ + return HyperDbgEnableTransparentModeEx(ProcessId, ProcessName, IsProcessId, EvadeMask); +} + +/** + * @brief Disable transparent mode + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_disable_transparent_mode() +{ + return HyperDbgDisableTransparentMode(); +} + +/** + * @brief Run HyperDbg scripts in the target process (user debugger) or + * debuggee (kernel debugger) + * @param Expr The expression to run + * @param ShowErrorMessageIfAny If true, show error message if any + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_run_script(CHAR * Expr, BOOLEAN ShowErrorMessageIfAny) +{ + return ScriptEngineExecuteSingleExpression(Expr, ShowErrorMessageIfAny, FALSE); +} + +/** + * @brief Evaluate expression and return result based on the target + * process (user debugger) or debuggee (kernel debugger) context + * + * @param Expr The expression to evaluate + * @param HasError If true, there was an error in evaluation + * + * @return UINT64 The result of the evaluated expression + */ +UINT64 +hyperdbg_u_eval_expression(CHAR * Expr, PBOOLEAN HasError) +{ + return ScriptEngineEvalSingleExpression(Expr, HasError); +} + +/** + * @brief Dump LBR stack + * + * @param LbrdumpRequest The LBR dump request packet + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_lbr_dump(HYPERTRACE_LBR_DUMP_PACKETS * LbrdumpRequest) +{ + return HyperDbgLbrdumpSendRequest(LbrdumpRequest); +} + +/** + * @brief Perform an Intel PT operation (enable / disable / pause / resume / + * size / dump / flush / filter) + * + * @param PtRequest The PT operation request packet + * + * @return BOOLEAN TRUE if the operation was successful, otherwise FALSE + */ +BOOLEAN +hyperdbg_u_pt_operation(HYPERTRACE_PT_OPERATION_PACKETS * PtRequest) +{ + return HyperDbgPerformPtOperation(PtRequest); +} + +/** + * @brief Map the per-CPU Intel PT output buffers into the calling process + * + * @param MmapRequest The PT mmap request packet; filled with per-CPU + * { UserVa, Size } on success + * + * @return BOOLEAN TRUE if the operation was successful, otherwise FALSE + */ +BOOLEAN +hyperdbg_u_pt_mmap(HYPERTRACE_PT_MMAP_PACKETS * MmapRequest) +{ + return HyperDbgPtMmapSendRequest(MmapRequest); +} diff --git a/hyperdbg/libhyperdbg/code/hwdbg/hwdbg-interpreter.cpp b/hyperdbg/libhyperdbg/code/hwdbg/hwdbg-interpreter.cpp new file mode 100644 index 00000000..bc074b33 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/hwdbg/hwdbg-interpreter.cpp @@ -0,0 +1,700 @@ +/** + * @file hwdbg-interpreter.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Interpreter of hwdbg packets and requests + * @details + * @version 0.10 + * @date 2024-06-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern HWDBG_INSTANCE_INFORMATION g_HwdbgInstanceInfo; +extern BOOLEAN g_HwdbgInstanceInfoIsValid; +extern std::vector g_HwdbgPortConfiguration; + +/** + * @brief Interpret packets of hwdbg + * + * @param BufferReceived + * @param LengthReceived + * @return BOOLEAN + */ +BOOLEAN +HwdbgInterpretPacket(PVOID BufferReceived, UINT32 LengthReceived) +{ + PHWDBG_INSTANCE_INFORMATION InstanceInfoPacket; + PUINT32 InstanceInfoPorts; + DEBUGGER_REMOTE_PACKET * TheActualPacket = NULL; + BOOLEAN Result = FALSE; + + // + // Apply the initial offset + // + if (g_HwdbgInstanceInfoIsValid) + { + // + // Use the debuggee's preferred offset (area) since the instance info + // already received and interpreted + // + TheActualPacket = (DEBUGGER_REMOTE_PACKET *)(((CHAR *)BufferReceived) + g_HwdbgInstanceInfo.debuggeeAreaOffset); + } + else + { + // + // Use default initial offset as there is no information (instance info) + // from debuggee + // + TheActualPacket = (DEBUGGER_REMOTE_PACKET *)(((CHAR *)BufferReceived) + DEFAULT_INITIAL_DEBUGGEE_TO_DEBUGGER_OFFSET); + } + + if (TheActualPacket->Indicator == INDICATOR_OF_HYPERDBG_PACKET) + { + // + // Check checksum (for hwdbg, checksum is ignored) + // + // if (KdComputeDataChecksum((PVOID)&TheActualPacket->Indicator, + // LengthReceived - sizeof(BYTE)) != TheActualPacket->Checksum) + // { + // ShowMessages("err, checksum is invalid\n"); + // return FALSE; + // } + + // + // Check if the packet type is correct + // + if (TheActualPacket->TypeOfThePacket != DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER_HARDWARE_LEVEL) + { + // + // sth wrong happened, the packet is not belonging to use + // for hwdbg interpreter + // + ShowMessages("err, unknown packet received from the debuggee\n"); + return FALSE; + } + + // + // It's a HyperDbg packet (for hwdbg) + // + switch (TheActualPacket->RequestedActionOfThePacket) + { + case hwdbgResponseSuccessOrErrorMessage: + + Result = TRUE; + + // + // Todo: implement it + // + + break; + + case hwdbgResponseInstanceInfo: + + Result = TRUE; + InstanceInfoPacket = (HWDBG_INSTANCE_INFORMATION *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + InstanceInfoPorts = (UINT32 *)(((CHAR *)InstanceInfoPacket) + sizeof(HWDBG_INSTANCE_INFORMATION)); + + // + // Copy the instance info into the global hwdbg instance info + // + RtlCopyMemory(&g_HwdbgInstanceInfo, InstanceInfoPacket, sizeof(HWDBG_INSTANCE_INFORMATION)); + + // + // Reset previous port configurations (if any) + // + g_HwdbgPortConfiguration.clear(); + + // + // Instance info is valid from now + // + g_HwdbgInstanceInfoIsValid = TRUE; + + // + // Read port arrangements + // + for (SIZE_T i = 0; i < g_HwdbgInstanceInfo.numberOfPorts; i++) + { + g_HwdbgPortConfiguration.push_back(InstanceInfoPorts[i]); + } + + // + // Infom the script engine about the instance info + // + ScriptEngineSetHwdbgInstanceInfo(&g_HwdbgInstanceInfo); + + break; + + default: + + Result = FALSE; + ShowMessages("err, unknown packet request received from the debuggee\n"); + + break; + } + } + + // + // Packet handled successfully + // + return Result; +} + +/** + * @brief Function to parse a single line of the memory content + * + * @param Line + * @return VOID + */ +std::vector +HwdbgParseStringMemoryLine(const std::string & Line) +{ + std::vector Values; + std::stringstream Ss(Line); + std::string Token; + + // Skip the memory address part + std::getline(Ss, Token, ':'); + + // Read the hex value + while (std::getline(Ss, Token, ' ')) + { + if (Token.length() == 8 && std::all_of(Token.begin(), Token.end(), ::isxdigit)) + { + Values.push_back(static_cast(std::stoul(Token, nullptr, 16))); + } + } + + return Values; +} + +/** + * @brief Function to read the file and fill the memory buffer + * + * @param FileName + * @param MemoryBuffer + * @param BufferSize + * @return BOOLEAN + */ +BOOLEAN +HwdbgInterpreterFillMemoryFromFile( + const TCHAR * FileName, + UINT32 * MemoryBuffer, + SIZE_T BufferSize) +{ + std::ifstream File(FileName); + std::string Line; + BOOLEAN Result = TRUE; + SIZE_T Index = 0; + + if (!File.is_open()) + { + ShowMessages("err, unable to open file %s\n", FileName); + return FALSE; + } + + while (getline(File, Line)) + { + if (Index >= BufferSize) + { + Result = FALSE; + ShowMessages("err, buffer overflow, file contains more data than buffer can hold\n"); + break; + } + + vector Values = HwdbgParseStringMemoryLine(Line); + + for (UINT32 Value : Values) + { + if (Index < BufferSize) + { + MemoryBuffer[Index++] = Value; + } + else + { + ShowMessages("err, buffer overflow, file contains more data than buffer can hold\n"); + File.close(); + return FALSE; + } + } + } + + File.close(); + return Result; +} + +/** + * @brief Function to write the memory buffer to a file in the specified format + * + * @param InstanceInfo + * @param FileName + * @param MemoryBuffer + * @param BufferSize + * @param RequestedAction + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgInterpreterFillFileFromMemory( + HWDBG_INSTANCE_INFORMATION * InstanceInfo, + const TCHAR * FileName, + UINT32 * MemoryBuffer, + SIZE_T BufferSize, + HWDBG_ACTION_ENUMS RequestedAction) +{ + std::ofstream File(FileName); + + if (!File.is_open()) + { + printf("err, unable to open file %s\n", FileName); + return FALSE; + } + + SIZE_T Address = 0; + for (SIZE_T I = 0; I < BufferSize / sizeof(UINT32); ++I) + { + File << std::hex << std::setw(8) << std::setfill('0') << MemoryBuffer[I]; + File << " ; +0x" << std::hex << std::setw(1) << std::setfill('0') << Address; + + if (I == 0) + { + File << " | Checksum"; + } + else if (I == 1) + { + File << " | Checksum"; + } + else if (I == 2) + { + File << " | Indicator"; + } + else if (I == 3) + { + File << " | Indicator"; + } + else if (I == 4) + { + File << " | TypeOfThePacket - DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL (0x4)"; + } + else if (I == 5) + { + File << " | RequestedActionOfThePacket - Value" << " (0x" << std::hex << std::setw(1) << std::setfill('0') << RequestedAction << ")"; + } + else if (I == 6) + { + File << " | Start of Optional Data"; + } + + File << "\n"; + Address += 4; + } + + // + // Add zeros to the end of the file to fill the shared memory + // + if (g_HwdbgInstanceInfoIsValid) + { + while (Address < InstanceInfo->sharedMemorySize) + { + File << "00000000 ; +0x" << std::hex << std::setw(1) << std::setfill('0') << Address; + Address += 4; + + if (Address < InstanceInfo->sharedMemorySize) + { + File << "\n"; + } + } + } + + // + // Close the file + // + File.close(); + + return TRUE; +} + +/** + * @brief Function to compute number of flip-flops needed in the target device + * + * @param InstanceInfo + * @param NumberOfStages + * + * @return SIZE_T + */ +SIZE_T +HwdbgComputeNumberOfFlipFlopsNeeded( + HWDBG_INSTANCE_INFORMATION * InstanceInfo, + UINT32 NumberOfStages) +{ + // + // Calculate the number of flip-flops needed in the target device + // + operator symbol itself which only contains value (type is always equal to SYMBOL_SEMANTIC_RULE_TYPE) + // so, it is not counted as a flip-flop + // + SIZE_T NumberOfNeededFlipFlopsInTargetDevice = 0; + + // + // size of operator (GET and SET) + // + NumberOfNeededFlipFlopsInTargetDevice += (NumberOfStages * + (g_HwdbgInstanceInfo.maximumNumberOfSupportedGetScriptOperators + g_HwdbgInstanceInfo.maximumNumberOfSupportedSetScriptOperators) * + g_HwdbgInstanceInfo.scriptVariableLength * + sizeof(HWDBG_SHORT_SYMBOL) / sizeof(UINT64)); + + // + // size of main operator (/ 2 is because Type is not inferred) + // + NumberOfNeededFlipFlopsInTargetDevice += (NumberOfStages * g_HwdbgInstanceInfo.scriptVariableLength * (sizeof(HWDBG_SHORT_SYMBOL) / sizeof(UINT64)) / 2); + + // + // size of local (and global) variables + // + NumberOfNeededFlipFlopsInTargetDevice += (NumberOfStages * g_HwdbgInstanceInfo.numberOfSupportedLocalAndGlobalVariables * g_HwdbgInstanceInfo.scriptVariableLength); + + // + // size of temporary variables + // + NumberOfNeededFlipFlopsInTargetDevice += (NumberOfStages * g_HwdbgInstanceInfo.numberOfSupportedTemporaryVariables * g_HwdbgInstanceInfo.scriptVariableLength); + + // + // size of stage index register + targetStage (* 2) + // + NumberOfNeededFlipFlopsInTargetDevice += (NumberOfStages * Log2Ceil(g_HwdbgInstanceInfo.maximumNumberOfStages * (g_HwdbgInstanceInfo.maximumNumberOfSupportedGetScriptOperators + g_HwdbgInstanceInfo.maximumNumberOfSupportedSetScriptOperators + 1)) * 2); + + // + // stage enable flip-flop + // + NumberOfNeededFlipFlopsInTargetDevice += (NumberOfStages); + + // + // input => output flip-flop + // + NumberOfNeededFlipFlopsInTargetDevice += (NumberOfStages * g_HwdbgInstanceInfo.numberOfPins); + + // + // return the number of flip-flops needed in the target device + // + return NumberOfNeededFlipFlopsInTargetDevice; +} + +/** + * @brief Sends a HyperDbg packet + a buffer to the hwdbg + * + * @param InstanceInfo + * @param FileName + * @param PacketType + * @param RequestedAction + * @param Buffer + * @param BufferLength + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgInterpreterSendPacketAndBufferToHwdbg(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + const TCHAR * FileName, + DEBUGGER_REMOTE_PACKET_TYPE PacketType, + HWDBG_ACTION_ENUMS RequestedAction, + CHAR * Buffer, + UINT32 BufferLength) +{ + DEBUGGER_REMOTE_PACKET Packet = {0}; + SIZE_T CommandMaxSize = 0; + SIZE_T FinalBufferSize = 0; + + if (g_HwdbgInstanceInfoIsValid) + { + CommandMaxSize = InstanceInfo->debuggeeAreaOffset - InstanceInfo->debuggerAreaOffset; + } + else + { + // + // Use default limitation + // + CommandMaxSize = DEFAULT_INITIAL_DEBUGGEE_TO_DEBUGGER_OFFSET - DEFAULT_INITIAL_DEBUGGER_TO_DEBUGGEE_OFFSET; + } + + // + // If buffer is not available, then the length is zero + // + if (Buffer == NULL) + { + BufferLength = 0; + } + + // + // Compute the final buffer size + // + FinalBufferSize = sizeof(DEBUGGER_REMOTE_PACKET) + BufferLength; + + // + // Check if buffer not pass the boundary + // + if (FinalBufferSize > CommandMaxSize) + { + ShowMessages("err, buffer is above the maximum buffer size that can be sent to hwdbg (%d > %d)\n", + FinalBufferSize, + CommandMaxSize); + + return FALSE; + } + + // + // Make the packet's structure + // + Packet.Indicator = INDICATOR_OF_HYPERDBG_PACKET; + Packet.TypeOfThePacket = PacketType; + + // + // Set the requested action + // + Packet.RequestedActionOfThePacket = (DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION)RequestedAction; + + // + // calculate checksum of the packet + // + Packet.Checksum = + KdComputeDataChecksum((PVOID)((UINT64)&Packet + 1), + sizeof(DEBUGGER_REMOTE_PACKET) - sizeof(BYTE)); + + if (Buffer != NULL) + { + Packet.Checksum += KdComputeDataChecksum((PVOID)Buffer, BufferLength); + } + + // + // If there is an offset for debugger to debuggee command, we'll apply it here + // + if (g_HwdbgInstanceInfoIsValid) + { + FinalBufferSize += InstanceInfo->debuggerAreaOffset; + } + else + { + FinalBufferSize += DEFAULT_INITIAL_DEBUGGER_TO_DEBUGGEE_OFFSET; + } + + // + // Allocate a buffer for storing the header packet + buffer (if not empty) + // + CHAR * FinalBuffer = (CHAR *)malloc(FinalBufferSize); + + if (!FinalBuffer) + { + return FALSE; + } + + RtlZeroMemory(FinalBuffer, FinalBufferSize); + + // + // Leave the offset + // + SIZE_T Offset = g_HwdbgInstanceInfoIsValid ? InstanceInfo->debuggerAreaOffset : DEFAULT_INITIAL_DEBUGGER_TO_DEBUGGEE_OFFSET; + + // + // Copy the packet into the FinalBuffer + // + memcpy(FinalBuffer + Offset, &Packet, sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Copy the buffer (if available) into the FinalBuffer + // + if (Buffer != NULL) + { + memcpy(FinalBuffer + Offset + sizeof(DEBUGGER_REMOTE_PACKET), Buffer, BufferLength); + } + + // + // Here you would send FinalBuffer to the hardware debugger + // + HwdbgInterpreterFillFileFromMemory(InstanceInfo, FileName, (UINT32 *)FinalBuffer, FinalBufferSize, RequestedAction); + + // + // Free the allocated memory after use + // + free(FinalBuffer); + + return TRUE; +} + +/** + * @brief Show instance info details + * + * @param InstanceInfo + * + * @return VOID + */ +VOID +HwdbgShowIntanceInfo(HWDBG_INSTANCE_INFORMATION * InstanceInfo) +{ + UINT32 PortNum = 0; + + ShowMessages("Debuggee Version: 0x%x\n", InstanceInfo->version); + ShowMessages("Debuggee Maximum Number Of Stages: 0x%x\n", InstanceInfo->maximumNumberOfStages); + ShowMessages("Debuggee Script Variable Length: 0x%x\n", InstanceInfo->scriptVariableLength); + ShowMessages("Debuggee Number of Supported Local (and global) Variables: 0x%x\n", InstanceInfo->numberOfSupportedLocalAndGlobalVariables); + ShowMessages("Debuggee Number of Supported Temporary Variables: 0x%x\n", InstanceInfo->numberOfSupportedTemporaryVariables); + ShowMessages("Debuggee Maximum Number Of Supported GET Script Operators: 0x%x\n", InstanceInfo->maximumNumberOfSupportedGetScriptOperators); + ShowMessages("Debuggee Maximum Number Of Supported SET Script Operators: 0x%x\n", InstanceInfo->maximumNumberOfSupportedSetScriptOperators); + ShowMessages("Debuggee Shared Memory Size: 0x%x\n", InstanceInfo->sharedMemorySize); + ShowMessages("Debuggee Debugger Area Offset: 0x%x\n", InstanceInfo->debuggerAreaOffset); + ShowMessages("Debuggee Debuggee Area Offset: 0x%x\n", InstanceInfo->debuggeeAreaOffset); + ShowMessages("Debuggee Script Capabilities Mask: 0x%llx\n", InstanceInfo->scriptCapabilities); + + // + // Show script capabilities + // + HardwareScriptInterpreterShowScriptCapabilities(&g_HwdbgInstanceInfo); + + ShowMessages("Debuggee Number Of Pins: 0x%x\n", InstanceInfo->numberOfPins); + ShowMessages("Debuggee Number Of Ports: 0x%x\n", InstanceInfo->numberOfPorts); + + ShowMessages("Debuggee BRAM Address Width: 0x%x\n", InstanceInfo->bramAddrWidth); + ShowMessages("Debuggee BRAM Data Width: 0x%x (%d bit)\n", InstanceInfo->bramDataWidth, InstanceInfo->bramDataWidth); + + for (auto item : g_HwdbgPortConfiguration) + { + ShowMessages("Port number %d ($hw_port%d): 0x%x\n", PortNum, PortNum, item); + PortNum++; + } +} + +/** + * @brief Read the instance info from the file + * @param FileName + * @param MemoryBuffer + * @param BufferSize + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgReadInstanceInfoFromFile(const TCHAR * FileName, UINT32 * MemoryBuffer, SIZE_T BufferSize) +{ + TCHAR TestFilePath[MAX_PATH] = {0}; + + if (SetupPathForFileName(HWDBG_TEST_READ_INSTANCE_INFO_PATH, TestFilePath, sizeof(TestFilePath), TRUE) && + HwdbgInterpreterFillMemoryFromFile(TestFilePath, MemoryBuffer, BufferSize)) + { + // + // Print the content of MemoryBuffer for verification + // + for (SIZE_T I = 0; I < BufferSize; ++I) + { + ShowMessages("%08x ", MemoryBuffer[I]); + ShowMessages("\n"); + } + + // + // the instance info packet is read successfully + // + return TRUE; + } + + // + // the instance info packet is not read successfully + // + return FALSE; +} + +/** + * @brief Write test instance info request into a file + * + * @param InstanceInfo + * @param FileName + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgWriteTestInstanceInfoRequestIntoFile(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + const CHAR * FileName) +{ + TCHAR TestFilePath[MAX_PATH] = {0}; + + // + // Write test instance info request into a file + // + if (SetupPathForFileName(FileName, TestFilePath, sizeof(TestFilePath), FALSE) && + HwdbgInterpreterSendPacketAndBufferToHwdbg( + InstanceInfo, + TestFilePath, + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL, + hwdbgActionSendInstanceInfo, + NULL, + NULL_ZERO)) + { + ShowMessages("[*] instance info successfully written into file: %s\n", TestFilePath); + return TRUE; + } + + // + // Unable to write instance info request into a file + // + return FALSE; +} + +/** + * @brief Load the instance info + * + * @param InstanceFilePathToRead + * @param InitialBramBufferSize + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgLoadInstanceInfo(const TCHAR * InstanceFilePathToRead, UINT32 InitialBramBufferSize) +{ + UINT32 * MemoryBuffer = NULL; + + // + // Allocate memory buffer to read the instance info + // + MemoryBuffer = (UINT32 *)malloc(InitialBramBufferSize * sizeof(UINT32)); + + if (MemoryBuffer == NULL) + { + // + // Memory allocation failed + // + ShowMessages("err, unable to allocate memory for the instance info packet of the debuggee"); + return FALSE; + } + + // + // *** Read the instance info from the file *** + // + if (HwdbgReadInstanceInfoFromFile(InstanceFilePathToRead, MemoryBuffer, InitialBramBufferSize)) + { + ShowMessages("instance info read successfully\n"); + } + else + { + ShowMessages("err, unable to read instance info packet of the debuggee"); + free(MemoryBuffer); + return FALSE; + } + + // + // *** Interpret instance info packet *** + // + if (HwdbgInterpretPacket(MemoryBuffer, InitialBramBufferSize)) + { + ShowMessages("instance info interpreted successfully\n"); + HwdbgShowIntanceInfo(&g_HwdbgInstanceInfo); + } + else + { + ShowMessages("err, unable to interpret instance info packet of the debuggee"); + free(MemoryBuffer); + return FALSE; + } + + // + // The instance info is loaded successfully + // + free(MemoryBuffer); + return TRUE; +} diff --git a/hyperdbg/libhyperdbg/code/hwdbg/hwdbg-scripts.cpp b/hyperdbg/libhyperdbg/code/hwdbg/hwdbg-scripts.cpp new file mode 100644 index 00000000..f905eba3 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/hwdbg/hwdbg-scripts.cpp @@ -0,0 +1,516 @@ +/** + * @file hwdbg-scripts.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Hardware scripts for hwdbg + * @details + * @version 0.11 + * @date 2024-09-30 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern HWDBG_INSTANCE_INFORMATION g_HwdbgInstanceInfo; +extern BOOLEAN g_HwdbgInstanceInfoIsValid; + +/** + * @brief Print the actual script + * + * @param ScriptBuffer + * @param ScriptBufferSize + * + * @return VOID + */ +VOID +HwdbgScriptPrintScriptBuffer(CHAR * ScriptBuffer, UINT32 ScriptBufferSize) +{ + // + // Print the actual script + // + ShowMessages("\nHyperDbg (general) script buffer (size=%d, flip-flops (just script)=%d):\n\n", + ScriptBufferSize, + ScriptBufferSize * 8 // Converted to bits + ); + + for (SIZE_T i = 0; i < ScriptBufferSize; i++) + { + ShowMessages("%02X ", (UINT8)ScriptBuffer[i]); + } + + ShowMessages("\n"); +} + +/** + * @brief Compress the script buffer + * + * @param InstanceInfo + * @param ScriptBuffer + * @param ScriptBufferSize + * @param NumberOfStagesForScript + * @param NewScriptBuffer + * @param NewCompressedBufferSize + * @param NumberOfBytesPerChunk + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgScriptCompressScriptBuffer(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + SYMBOL * ScriptBuffer, + SIZE_T ScriptBufferSize, + UINT32 NumberOfStagesForScript, + HWDBG_SHORT_SYMBOL ** NewScriptBuffer, + SIZE_T * NewCompressedBufferSize, + SIZE_T * NumberOfBytesPerChunk) +{ + // + // Now, converting the script based on supported script variable length + // + if (!g_HwdbgInstanceInfoIsValid) + { + // + // The instance info is not valid + // + ShowMessages("err, the instance info is not valid\n"); + + return FALSE; + } + + // + // Check if the variable length is valid + // + if (!(InstanceInfo->scriptVariableLength >= sizeof(BYTE) * 8)) + { + // + // The script variable length is not valid (at least 8 bit (1 byte) + // + ShowMessages("err, the script variable length should be at least 8 bits (1 byte)\n"); + return FALSE; + } + + // + // *** The script variable length is valid (at least 8 bit (1 byte) *** + // + + // + // Compress script buffer + // + if (HardwareScriptInterpreterConvertSymbolToHwdbgShortSymbolBuffer(InstanceInfo, + ScriptBuffer, + ScriptBufferSize, + NumberOfStagesForScript, + NewScriptBuffer, + NewCompressedBufferSize) == FALSE) + { + ShowMessages("err, unable to convert the script buffer to short symbol buffer\n"); + return FALSE; + } + + // + // we put BRAM data width size here instead of script variable length (InstanceInfo.scriptVariableLength) + // since we want it to read one symbol filed at a time + // + if (!HardwareScriptInterpreterCompressBuffer((UINT64 *)*NewScriptBuffer, + *NewCompressedBufferSize, + InstanceInfo->scriptVariableLength, + InstanceInfo->bramDataWidth, + NewCompressedBufferSize, + NumberOfBytesPerChunk)) + { + // + // Unable to compress the buffer + // + return FALSE; + } + + // + // The script buffer is compressed successfully + // + return TRUE; +} + +/** + * @brief Print the hwdbg script buffer and hardware details + * + * @param InstanceInfo + * @param NewCompressedBufferSize + * @param NumberOfStagesForScript + * @param NumberOfOperandsForScript + * @param NewScriptBuffer + * @param NumberOfNeededFlipFlopsInTargetDevice + * @param NumberOfBytesPerChunk + * @param NumberOfOperandsImplemented + * + * @return VOID + */ +VOID +HwdbgScriptPrintFinalScriptBufferAndHardwareDetails(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + SIZE_T NewCompressedBufferSize, + UINT32 NumberOfStagesForScript, + UINT32 NumberOfOperandsForScript, + HWDBG_SHORT_SYMBOL * NewScriptBuffer, + SIZE_T NumberOfNeededFlipFlopsInTargetDevice, + SIZE_T NumberOfBytesPerChunk, + UINT32 NumberOfOperandsImplemented) +{ + ShowMessages("\n---------------------------------------------------------\n"); + + NumberOfNeededFlipFlopsInTargetDevice = HwdbgComputeNumberOfFlipFlopsNeeded(InstanceInfo, NumberOfStagesForScript); + + ShowMessages("hwdbg script buffer (buffer size=%d, stages=%d, operands needed: %d - operands used: %d (%.2f%%), total used flip-flops=%d, number of bytes per chunk: %d):\n\n", + NewCompressedBufferSize, + NumberOfStagesForScript, + NumberOfOperandsImplemented, + NumberOfOperandsForScript, + ((float)NumberOfOperandsForScript / (float)NumberOfOperandsImplemented) * 100, + NumberOfNeededFlipFlopsInTargetDevice, + NumberOfBytesPerChunk); + + for (SIZE_T i = 0; i < NewCompressedBufferSize; i++) + { + ShowMessages("%02X ", (UINT8)((CHAR *)NewScriptBuffer)[i]); + } +} + +/** + * @brief Write script configuration packet into a file + * + * @param InstanceInfo + * @param FileName + * @param NumberOfOperandsImplemented + * @param NumberOfStagesForScript + * @param NewScriptBuffer + * @param NewCompressedBufferSize + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgScriptWriteScriptConfigurationPacketIntoFile(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + const CHAR * FileName, + UINT32 NumberOfStagesForScript, + UINT32 NumberOfOperandsImplemented, + HWDBG_SHORT_SYMBOL * NewScriptBuffer, + SIZE_T NewCompressedBufferSize) +{ + TCHAR TestFilePath[MAX_PATH] = {0}; + + // + // *** Write script configuration packet into a file *** + // + + ShowMessages("\n\nwriting script configuration packet into the file\n"); + + if (SetupPathForFileName(FileName, TestFilePath, sizeof(TestFilePath), FALSE) && + HwdbgScriptSendScriptPacket( + InstanceInfo, + TestFilePath, + NumberOfStagesForScript + NumberOfOperandsImplemented - 1, // Number of symbols = Number of stages + Number of operands - 1 + NewScriptBuffer, + (UINT32)NewCompressedBufferSize)) + { + ShowMessages("\n[*] script buffer successfully written into file: %s\n", TestFilePath); + return TRUE; + } + else + { + ShowMessages("err, unable to write script buffer\n"); + return FALSE; + } +} + +/** + * @brief Create hwdbg script + * @param ScriptBuffer + * @param ScriptBufferSize + * @param HardwareScriptFilePathToSave + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgScriptCreateHwdbgScript(CHAR * ScriptBuffer, + UINT32 ScriptBufferSize, + const TCHAR * HardwareScriptFilePathToSave) +{ + UINT32 NumberOfStagesForScript = 0; + UINT32 NumberOfOperandsImplemented = 0; + UINT32 NumberOfOperandsForScript = 0; + SIZE_T NewCompressedBufferSize = 0; + SIZE_T NumberOfNeededFlipFlopsInTargetDevice = 0; + SIZE_T NumberOfBytesPerChunk = 0; + HWDBG_SHORT_SYMBOL * NewScriptBuffer = NULL; + + // + // *** Check the script capabilities with the generated script *** + // + if (!HardwareScriptInterpreterCheckScriptBufferWithScriptCapabilities(&g_HwdbgInstanceInfo, + ScriptBuffer, + ScriptBufferSize / sizeof(SYMBOL), + &NumberOfStagesForScript, + &NumberOfOperandsForScript, + &NumberOfOperandsImplemented)) + { + ShowMessages("\n[-] target script is NOT supported by this instance of hwdbg!\n"); + return FALSE; + } + else + { + ShowMessages("\n[+] target script is supported by this instance of hwdbg!\n"); + } + + // + // *** Compress the script buffer based on the instance info *** + // + if (!HwdbgScriptCompressScriptBuffer(&g_HwdbgInstanceInfo, + (SYMBOL *)ScriptBuffer, + ScriptBufferSize, + NumberOfStagesForScript, + &NewScriptBuffer, + &NewCompressedBufferSize, + &NumberOfBytesPerChunk)) + { + ShowMessages("err, unable to compress the script buffer\n"); + return FALSE; + } + + // + // Print the hwdbg script buffer + // + HwdbgScriptPrintFinalScriptBufferAndHardwareDetails(&g_HwdbgInstanceInfo, + NewCompressedBufferSize, + NumberOfStagesForScript, + NumberOfOperandsForScript, + NewScriptBuffer, + NumberOfNeededFlipFlopsInTargetDevice, + NumberOfBytesPerChunk, + NumberOfOperandsImplemented); + + // + // *** Write script configuration packet into a file *** + // + + // + // Write script configuration packet into a file + // + if (!HwdbgScriptWriteScriptConfigurationPacketIntoFile(&g_HwdbgInstanceInfo, + HardwareScriptFilePathToSave, + NumberOfStagesForScript, + NumberOfOperandsImplemented, + NewScriptBuffer, + NewCompressedBufferSize)) + { + ShowMessages("err, unable to write script buffer\n"); + return FALSE; + } + + // + // *** Free the allocated memory *** + // + + // + // Free the allocated memory for the short symbol buffer + // + if (NewScriptBuffer != NULL) + { + HardwareScriptInterpreterFreeHwdbgShortSymbolBuffer(NewScriptBuffer); + } + + // + // The script buffer is created successfully + // + return TRUE; +} + +/** Get script buffer from raw string + * @param ScriptBuffer + * @param CodeBuffer + * @param BufferAddress + * @param BufferLength + * @param Pointer + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgScriptGetScriptBufferFromRawString(string ScriptString, + PVOID * CodeBuffer, + UINT64 * BufferAddress, + UINT32 * BufferLength, + UINT32 * Pointer) +{ + PVOID ResultingCodeBuffer = NULL; + + // + // Run script engine handler + // + ResultingCodeBuffer = ScriptEngineParseWrapper((CHAR *)ScriptString.c_str(), TRUE); + + if (ResultingCodeBuffer == NULL) + { + // + // return to show that this item contains an script error + // + return FALSE; + } + + // + // Print symbols (test) + // + // PrintSymbolBufferWrapper(ResultingCodeBuffer); + + // + // Set the buffer and length + // + *BufferAddress = ScriptEngineWrapperGetHead(ResultingCodeBuffer); + *BufferLength = ScriptEngineWrapperGetSize(ResultingCodeBuffer); + *Pointer = ScriptEngineWrapperGetPointer(ResultingCodeBuffer); + + // + // Set the code buffer + // + *CodeBuffer = ResultingCodeBuffer; + + // + // The script buffer is copied successfully + // + return TRUE; +} + +/** + * @brief Sends a HyperDbg (hwdbg) script packet to the hwdbg + * + * @param InstanceInfo + * @param FileName + * @param Buffer + * @param BufferLength + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgScriptSendScriptPacket(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + const TCHAR * FileName, + UINT32 NumberOfSymbols, + HWDBG_SHORT_SYMBOL * Buffer, + UINT32 BufferLength) +{ + HWDBG_SCRIPT_BUFFER ScriptBuffer = {0}; + BOOLEAN Result = FALSE; + + // + // Make the packet's structure + // + ScriptBuffer.scriptNumberOfSymbols = NumberOfSymbols; + + // + // Allocate a buffer for storing the header packet + buffer (if not empty) + // + CHAR * FinalBuffer = (CHAR *)malloc(BufferLength + sizeof(HWDBG_SCRIPT_BUFFER)); + + if (!FinalBuffer) + { + return FALSE; + } + + RtlZeroMemory(FinalBuffer, BufferLength + sizeof(HWDBG_SCRIPT_BUFFER)); + + // + // Copy the packet into the FinalBuffer + // + memcpy(FinalBuffer, &ScriptBuffer, sizeof(HWDBG_SCRIPT_BUFFER)); + + // + // Copy the buffer (if available) into the FinalBuffer + // + if (Buffer != NULL) + { + memcpy(FinalBuffer + sizeof(HWDBG_SCRIPT_BUFFER), Buffer, BufferLength); + } + + // + // Here we would send FinalBuffer to the hardware debugger + // + Result = HwdbgInterpreterSendPacketAndBufferToHwdbg( + InstanceInfo, + FileName, + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL, + hwdbgActionConfigureScriptBuffer, + FinalBuffer, + BufferLength + sizeof(HWDBG_SCRIPT_BUFFER)); + + // + // Free the allocated memory after use + // + free(FinalBuffer); + + return Result; +} + +/** + * @brief Run script in hwdbg + * + * @param Script + * @param InstanceFilePathToRead + * @param HardwareScriptFilePathToSave + * @param InitialBramBufferSize + * + * @return BOOLEAN + */ +BOOLEAN +HwdbgScriptRunScript(const CHAR * Script, + const TCHAR * InstanceFilePathToRead, + const TCHAR * HardwareScriptFilePathToSave, + UINT32 InitialBramBufferSize) +{ + PVOID CodeBuffer; + UINT64 BufferAddress; + UINT32 BufferLength; + UINT32 Pointer; + + // + // Load the instance info + // + if (!HwdbgLoadInstanceInfo(InstanceFilePathToRead, InitialBramBufferSize)) + { + // + // Unable to load the instance info + // + return FALSE; + } + + // + // Get the script buffer from the raw string (script) + // + if (!HwdbgScriptGetScriptBufferFromRawString(Script, + &CodeBuffer, + &BufferAddress, + &BufferLength, + &Pointer)) + { + // + // Unable to get script buffer from script + // + return FALSE; + } + + // + // Print the actual script + // + HwdbgScriptPrintScriptBuffer((CHAR *)BufferAddress, BufferLength); + + // + // Create hwdbg script + // + if (!HwdbgScriptCreateHwdbgScript((CHAR *)BufferAddress, + BufferLength, + HardwareScriptFilePathToSave)) + { + ShowMessages("err, unable to create hwdbg script\n"); + return FALSE; + } + + // + // Return the result + // + return TRUE; +} diff --git a/hyperdbg/hprdbgctrl/code/objects/objects.cpp b/hyperdbg/libhyperdbg/code/objects/objects.cpp similarity index 97% rename from hyperdbg/hprdbgctrl/code/objects/objects.cpp rename to hyperdbg/libhyperdbg/code/objects/objects.cpp index f63707ac..a0fe54ce 100644 --- a/hyperdbg/hprdbgctrl/code/objects/objects.cpp +++ b/hyperdbg/libhyperdbg/code/objects/objects.cpp @@ -14,7 +14,7 @@ // // Global Variables // -extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; +extern BOOLEAN g_IsKdModuleLoaded; /** * @brief Get details about processes or threads @@ -149,9 +149,9 @@ ObjectShowProcessesOrThreadList(BOOLEAN IsProcess, PDEBUGGEE_THREAD_LIST_DETAILS_ENTRY ThreadEntries = NULL; // - // Check if driver is loaded + // Check if the debugger module is loaded // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // We wanna query the count of active processes or threads @@ -302,7 +302,7 @@ ObjectShowProcessesOrThreadList(BOOLEAN IsProcess, // // Show list of active processes and threads // - for (size_t i = 0; i < QueryCountOfActiveThreadsOrProcessesRequest.Count; i++) + for (SIZE_T i = 0; i < QueryCountOfActiveThreadsOrProcessesRequest.Count; i++) { // // Details of process/thread should be shown diff --git a/hyperdbg/hprdbgctrl/code/rev/rev-ctrl.cpp b/hyperdbg/libhyperdbg/code/rev/rev-ctrl.cpp similarity index 90% rename from hyperdbg/hprdbgctrl/code/rev/rev-ctrl.cpp rename to hyperdbg/libhyperdbg/code/rev/rev-ctrl.cpp index 1d965fc4..4a21a2dc 100644 --- a/hyperdbg/hprdbgctrl/code/rev/rev-ctrl.cpp +++ b/hyperdbg/libhyperdbg/code/rev/rev-ctrl.cpp @@ -12,6 +12,11 @@ */ #include "pch.h" +// +// Global Variables +// +extern BOOLEAN g_IsVmmModuleLoaded; + /** * @brief Request service from the reversing machine * @@ -28,7 +33,7 @@ RevRequestService(REVERSING_MACHINE_RECONSTRUCT_MEMORY_REQUEST * RevRequest) // // Check if debugger is loaded or not // - AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); // // Send the request to the kernel diff --git a/hyperdbg/libhyperdbg/header/app/libhyperdbg.h b/hyperdbg/libhyperdbg/header/app/libhyperdbg.h new file mode 100644 index 00000000..ca3dce77 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/app/libhyperdbg.h @@ -0,0 +1,80 @@ +/** + * @file libhyperdbg.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief headers for libhyperdbg + * @details + * @version 0.10 + * @date 2024-06-24 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +HyperDbgIsAnyModuleLoaded(); + +INT +HyperDbgUnloadAllModules(); + +INT +HyperDbgInitHyperTraceModule(); + +INT +HyperDbgUnloadVmm(); + +INT +HyperDbgUnloadHyperTrace(); + +INT +HyperDbgUnloadKd(); + +INT +HyperDbgInstallKdDriver(); + +INT +HyperDbgUninstallKdDriver(); + +INT +HyperDbgLoadKdModule(); + +INT +HyperDbgLoadVmmModule(); + +INT +HyperDbgLoadHyperTraceModule(); + +INT +HyperDbgLoadAllModules(); + +INT +HyperDbgStartKdDriver(); + +INT +HyperDbgStopKdDriver(); + +INT +HyperDbgInterpreter(CHAR * Command); + +INT +HyperDbgScriptReadFileAndExecuteCommandline(INT argc, CHAR * argv[]); + +GENERIC_PROCESSOR_VENDOR +HyperDbgGetProcessorVendor(); + +BOOLEAN +HyperDbgTestCommandParser(CHAR * Command, + UINT32 NumberOfTokens, + CHAR ** TokensList, + UINT32 * FailedTokenNum, + UINT32 * FailedTokenPosition); + +VOID +HyperDbgTestCommandParserShowTokens(CHAR * Command); + +VOID +HyperDbgShowSignature(); diff --git a/hyperdbg/libhyperdbg/header/app/messaging.h b/hyperdbg/libhyperdbg/header/app/messaging.h new file mode 100644 index 00000000..db804888 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/app/messaging.h @@ -0,0 +1,25 @@ +/** + * @file messaging.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief headers for messaging functions + * @details + * @version 0.19 + * @date 2026-05-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +SetTextMessageCallback(PVOID Handler); + +PVOID +SetTextMessageCallbackUsingSharedBuffer(PVOID Handler); + +VOID +UnsetTextMessageCallback(); diff --git a/hyperdbg/libhyperdbg/header/app/packets.h b/hyperdbg/libhyperdbg/header/app/packets.h new file mode 100644 index 00000000..98015021 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/app/packets.h @@ -0,0 +1,22 @@ +/** + * @file packets.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief headers for kernel packet functions + * @details + * @version 0.19 + * @date 2026-05-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +ReadIrpBasedBuffer(); + +DWORD WINAPI +IrpBasedBufferThread(void * data); diff --git a/hyperdbg/libhyperdbg/header/common/common.h b/hyperdbg/libhyperdbg/header/common/common.h new file mode 100644 index 00000000..bdf2a82b --- /dev/null +++ b/hyperdbg/libhyperdbg/header/common/common.h @@ -0,0 +1,326 @@ +/** + * @file common.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief header for HyperDbg's general functions for reading and converting and + * etc + * @details + * @version 0.1 + * @date 2020-05-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Definitions // +////////////////////////////////////////////////// + +#define AssertReturn return; + +#define AssertReturnFalse return FALSE; + +#define AssertReturnOne return 1; + +#define PAUSE_MESSAGE_IN_USER_DEBUGGER "\nTo pause the target process, run the 'pause' command" + +#define ASSERT_MESSAGE_DRIVER_NOT_LOADED "handle of the driver not found, probably the driver is not loaded. Did you use 'load' command?\n" + +#define ASSERT_MESSAGE_KD_NOT_LOADED "the kd (kernel debugger) module is not loaded. Did you use 'load kd' command?\n" + +#define ASSERT_MESSAGE_VMM_NOT_LOADED "the vmm (virtualization) module is not loaded. Did you use 'load vmm' command?\n" + +#define ASSERT_MESSAGE_HYPERTRACE_NOT_LOADED "the trace (hypertrace) module is not loaded. Did you use 'load trace' command?\n" + +#define ASSERT_MESSAGE_BUILD_SIGNATURE_DOESNT_MATCH "the handshaking process was successful; however, there is a mismatch between " \ + "the version/build of the debuggee and the debugger. please use the same " \ + "version/build for both the debuggee and debugger\n" + +#define ASSERT_MESSAGE_CANNOT_SPECIFY_PID "err, since HyperDbg won't context-switch to keep the system in a halted state, " \ + "you cannot specify 'pid' for this command in the debugger mode. You can switch to the target process " \ + "memory layout using the '.process' or the '.thread' command. After that, you can use " \ + "this command without specifying the process ID. Alternatively, you can modify the current " \ + "CR3 register to achieve the same functionality\n" + +#define AssertReturnStmt(expr, stmt, rc) \ + do \ + { \ + if (expr) \ + { \ + /* likely */ \ + } \ + else \ + { \ + stmt; \ + rc; \ + } \ + } while (0) + +#define AssertShowMessageReturnStmt(expr1, expr2, message1, message2, rc) \ + do \ + { \ + if (expr1 && expr2) \ + { \ + /* likely */ \ + } \ + else \ + { \ + if (!expr1) \ + ShowMessages(message1); \ + else if (!expr2) \ + ShowMessages(message2); \ + rc; \ + } \ + } while (0) + +/** + * @brief Size of each page (4096 bytes) + * + */ +#define PAGE_SIZE 0x1000 + +/** + * @brief Aligning a page + * + */ +#define PAGE_ALIGN(Va) ((PVOID)((ULONG_PTR)(Va) & ~(PAGE_SIZE - 1))) + +/** + * @brief Cpuid to get virtual address width + * + */ +#define CPUID_ADDR_WIDTH 0x80000008 + +////////////////////////////////////////////////// +// Kernel & User Synchronization // +////////////////////////////////////////////////// + +#define DbgWaitForKernelResponse(KernelSyncObjectId) \ + do \ + { \ + DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ + &g_KernelSyncronizationObjectsHandleTable[KernelSyncObjectId]; \ + \ + SyncronizationObject->IsOnWaitingState = TRUE; \ + PlatformWaitForSingleObject(SyncronizationObject->EventHandle, INFINITE); \ + \ + } while (FALSE); + +#define DbgWaitForUserResponse(UserSyncObjectId) \ + do \ + { \ + DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ + &g_UserSyncronizationObjectsHandleTable[UserSyncObjectId]; \ + \ + SyncronizationObject->IsOnWaitingState = TRUE; \ + PlatformWaitForSingleObject(SyncronizationObject->EventHandle, INFINITE); \ + \ + } while (FALSE); + +#define DbgWaitSetKernelRequestData(KernelSyncObjectId, ReqData, ReqSize) \ + do \ + { \ + DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ + &g_KernelSyncronizationObjectsHandleTable[KernelSyncObjectId]; \ + \ + SyncronizationObject->RequestData = (PVOID)ReqData; \ + SyncronizationObject->RequestSize = (UINT32)ReqSize; \ + \ + } while (FALSE); + +#define DbgWaitSetUserRequestData(UserSyncObjectId, ReqData, ReqSize) \ + do \ + { \ + DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ + &g_UserSyncronizationObjectsHandleTable[UserSyncObjectId]; \ + \ + SyncronizationObject->RequestData = (PVOID)ReqData; \ + SyncronizationObject->RequestSize = (UINT32)ReqSize; \ + \ + } while (FALSE); + +#define DbgWaitGetKernelRequestData(KernelSyncObjectId, ReqData, ReqSize) \ + do \ + { \ + DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ + &g_KernelSyncronizationObjectsHandleTable[KernelSyncObjectId]; \ + \ + *ReqData = SyncronizationObject->RequestData; \ + *ReqSize = SyncronizationObject->RequestSize; \ + SyncronizationObject->RequestData = NULL; \ + SyncronizationObject->RequestSize = NULL_ZERO; \ + \ + } while (FALSE); + +#define DbgWaitGetUserRequestData(UserSyncObjectId, ReqData, ReqSize) \ + do \ + { \ + DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ + &g_UserSyncronizationObjectsHandleTable[UserSyncObjectId]; \ + \ + *ReqData = SyncronizationObject->RequestData; \ + *ReqSize = SyncronizationObject->RequestSize; \ + SyncronizationObject->RequestData = NULL; \ + SyncronizationObject->RequestSize = NULL_ZERO; \ + \ + } while (FALSE); + +#define DbgReceivedKernelResponse(KernelSyncObjectId) \ + do \ + { \ + DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ + &g_KernelSyncronizationObjectsHandleTable[KernelSyncObjectId]; \ + \ + SyncronizationObject->IsOnWaitingState = FALSE; \ + SetEvent(SyncronizationObject->EventHandle); \ + } while (FALSE); + +#define DbgReceivedUserResponse(UserSyncObjectId) \ + do \ + { \ + DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ + &g_UserSyncronizationObjectsHandleTable[UserSyncObjectId]; \ + \ + SyncronizationObject->IsOnWaitingState = FALSE; \ + SetEvent(SyncronizationObject->EventHandle); \ + } while (FALSE); + +////////////////////////////////////////////////// +// Assembly Functions // +////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +extern BOOLEAN +AsmVmxSupportDetection(); + +#ifdef __cplusplus +} +#endif + +////////////////////////////////////////////////// +// Spinlocks // +////////////////////////////////////////////////// + +VOID +SpinlockLock(volatile LONG * Lock); + +VOID +SpinlockLockWithCustomWait(volatile LONG * Lock, UINT32 MaximumWait); + +VOID +SpinlockUnlock(volatile LONG * Lock); + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +PrintBits(const UINT32 size, const VOID * ptr); + +BOOL +Replace(std::string & str, const std::string & from, const std::string & to); + +VOID +ReplaceAll(string & str, const string & from, const string & to); + +const vector +Split(const string & s, const CHAR & c); + +BOOLEAN +IsNumber(const string & str); + +UINT32 +Log2Ceil(UINT32 n); + +BOOLEAN +IsHexNotation(const string & s); + +vector +HexToBytes(const string & hex); + +BOOLEAN +ConvertStringToUInt64(string TextToConvert, PUINT64 Result); + +BOOLEAN +ConvertStringToUInt32(string TextToConvert, PUINT32 Result); + +BOOLEAN +ConvertTokenToUInt64(CommandToken TargetToken, PUINT64 Result); + +BOOLEAN +ConvertTokenToUInt32(CommandToken TargetToken, PUINT32 Result); + +std::string +GetCaseSensitiveStringFromCommandToken(CommandToken TargetToken); + +std::string +GetLowerStringFromCommandToken(CommandToken TargetToken); + +BOOLEAN +CompareLowerCaseStrings(CommandToken TargetToken, const CHAR * StringToCompare); + +BOOLEAN +IsTokenBracketString(CommandToken TargetToken); + +BOOLEAN +HasEnding(string const & fullString, string const & ending); + +BOOLEAN +ValidateIP(const string & ip); + +BOOL +SetPrivilege(HANDLE Token, // access token handle + LPCTSTR Privilege, // name of privilege to enable/disable + BOOL EnablePrivilege // to enable or disable privilege +); + +VOID +Trim(std::string & s); + +std::string +RemoveSpaces(std::string str); + +BOOLEAN +IsFileExistA(const CHAR * FileName); + +BOOLEAN +IsFileExistW(const WCHAR * FileName); + +VOID +GetConfigFilePath(PWCHAR ConfigPath); + +VOID +StringToWString(std::wstring & ws, const std::string & s); + +SIZE_T +FindCaseInsensitive(std::string Input, std::string ToSearch, SIZE_T Pos); + +SIZE_T +FindCaseInsensitiveW(std::wstring Input, std::wstring ToSearch, SIZE_T Pos); + +CHAR * +ConvertStringVectorToCharPointerArray(const std::string & s); + +std::vector +ListDirectory(const std::string & Directory, const std::string & Extension); + +BOOLEAN +IsEmptyString(CHAR * Text); + +VOID +CommonCpuidInstruction(UINT32 Func, UINT32 SubFunc, INT * CpuInfo); + +BOOLEAN +CheckCpuSupportRtm(); + +UINT32 +Getx86VirtualAddressWidth(); + +BOOLEAN +CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size); + +BOOLEAN +VmxSupportDetection(); diff --git a/hyperdbg/hprdbgctrl/header/list.h b/hyperdbg/libhyperdbg/header/common/list.h similarity index 100% rename from hyperdbg/hprdbgctrl/header/list.h rename to hyperdbg/libhyperdbg/header/common/list.h diff --git a/hyperdbg/libhyperdbg/header/debugger/commands/commands.h b/hyperdbg/libhyperdbg/header/debugger/commands/commands.h new file mode 100644 index 00000000..9e24fec9 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/debugger/commands/commands.h @@ -0,0 +1,797 @@ +/** + * @file commands.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @author Alee Amini (alee@hyperdbg.org) + * @brief The hyperdbg command interpreter and driver connector + * @details + * @version 0.1 + * @date 2020-04-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +using namespace std; + +////////////////////////////////////////////////// +// Externs // +////////////////////////////////////////////////// + +extern HANDLE g_DeviceHandle; + +////////////////////////////////////////////////// +// Settings // +////////////////////////////////////////////////// + +VOID +CommandSettingsLoadDefaultValuesFromConfigFile(); + +VOID +CommandSettingsSetValueFromConfigFile(std::string OptionName, std::string OptionValue); + +BOOLEAN +CommandSettingsGetValueFromConfigFile(std::string OptionName, std::string & OptionValue); + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +CpuReadVendorString(CHAR * Result); + +INT +ReadCpuDetails(); + +VOID +ShowMessages(const CHAR * Fmt, ...); + +string +SeparateTo64BitValue(UINT64 Value); + +VOID +ShowMemoryCommandDB(UCHAR * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length); + +VOID +ShowMemoryCommandDD(UCHAR * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length); + +VOID +ShowMemoryCommandDC(UCHAR * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length); + +VOID +ShowMemoryCommandDQ(UCHAR * OutputBuffer, UINT32 Size, UINT64 Address, DEBUGGER_READ_MEMORY_TYPE MemoryType, UINT64 Length); + +VOID +CommandPteShowResults(UINT64 TargetVa, PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PteRead); + +DEBUGGER_CONDITIONAL_JUMP_STATUS +HyperDbgIsConditionalJumpTaken(UCHAR * BufferToDisassemble, + UINT64 BuffLength, + RFLAGS Rflags, + BOOLEAN Isx86_64); + +INT +HyperDbgDisassembler64(UCHAR * BufferToDisassemble, + UINT64 BaseAddress, + UINT64 Size, + UINT32 MaximumInstrDecoded, + BOOLEAN ShowBranchIsTakenOrNot, + PRFLAGS Rflags); + +INT +HyperDbgDisassembler32(UCHAR * BufferToDisassemble, + UINT64 BaseAddress, + UINT64 Size, + UINT32 MaximumInstrDecoded, + BOOLEAN ShowBranchIsTakenOrNot, + PRFLAGS Rflags); + +UINT32 +HyperDbgLengthDisassemblerEngine( + UCHAR * BufferToDisassemble, + UINT64 BuffLength, + BOOLEAN Isx86_64); + +BOOLEAN +HyperDbgCheckWhetherTheCurrentInstructionIsCall( + UCHAR * BufferToDisassemble, + UINT64 BuffLength, + BOOLEAN Isx86_64, + PUINT32 CallLength); + +BOOLEAN +HyperDbgCheckWhetherTheCurrentInstructionIsCallOrRet( + UCHAR * BufferToDisassemble, + UINT64 CurrentRip, + UINT32 BuffLength, + BOOLEAN Isx86_64, + PBOOLEAN IsRet); + +BOOLEAN +HyperDbgCheckWhetherTheCurrentInstructionIsRet( + UCHAR * BufferToDisassemble, + UINT64 BuffLength, + BOOLEAN Isx86_64); + +UINT32 +HyperDbgGetImmediateValueOnEaxForSyscallNumber( + UCHAR * BufferToDisassemble, + UINT64 BuffLength, + BOOLEAN Isx86_64); + +VOID +HyperDbgShowMemoryOrDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, + UINT64 Address, + DEBUGGER_READ_MEMORY_TYPE MemoryType, + DEBUGGER_READ_READING_TYPE ReadingType, + UINT32 Pid, + UINT32 Size, + PDEBUGGER_DT_COMMAND_OPTIONS DtDetails); + +BOOLEAN +HyperDbgReadMemory(UINT64 TargetAddress, + DEBUGGER_READ_MEMORY_TYPE MemoryType, + DEBUGGER_READ_READING_TYPE ReadingType, + UINT32 Pid, + UINT32 Size, + BOOLEAN GetAddressMode, + DEBUGGER_READ_MEMORY_ADDRESS_MODE * AddressMode, + BYTE * TargetBufferToStore, + UINT32 * ReturnLength); + +VOID +InitializeCommandsDictionary(); + +VOID +InitializeDebugger(); + +BOOLEAN +CheckMultilineCommand(CHAR * CurrentCommand, BOOLEAN Reset); + +BOOLEAN +ContinuePreviousCommand(); + +VOID +CommandDumpSaveIntoFile(PVOID Buffer, UINT32 Length); + +////////////////////////////////////////////////// +// Type of Commands // +////////////////////////////////////////////////// + +/** + * @brief Command's parsing type (enum) + * + */ +typedef enum +{ + Num, + String, + StringLiteral, + BracketString +} CommandParsingTokenType; + +/** + * @brief Command's parsing type + * + */ +typedef std::tuple CommandToken; + +/** + * @brief Command's function type + * + */ +typedef VOID (*CommandFuncTypeParser)(vector CommandTokens, string Command); + +/** + * @brief Command's help function type + * + */ +typedef VOID (*CommandHelpFuncType)(); + +/** + * @brief Details of each command + * + */ +typedef struct _COMMAND_DETAIL +{ + CommandFuncTypeParser CommandFunctionNewParser; + CommandHelpFuncType CommandHelpFunction; + UINT64 CommandAttrib; + +} COMMAND_DETAIL, *PCOMMAND_DETAIL; + +/** + * @brief Type saving commands and mapping to command string + * + */ +typedef std::map CommandType; + +/** + * @brief Different attributes of commands + * + */ +#define DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE 0x1 +#define DEBUGGER_COMMAND_ATTRIBUTE_EVENT 0x2 | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE +#define DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_REMOTE_CONNECTION 0x4 +#define DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER 0x8 +#define DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN 0x10 +#define DEBUGGER_COMMAND_ATTRIBUTE_HWDBG 0x20 + +/** + * @brief Absolute local commands + * + */ +#define DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_REMOTE_CONNECTION + +/** + * @brief Command's attributes + * + */ +#define DEBUGGER_COMMAND_CLEAR_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_HELP_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_CONNECT_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_LISTEN_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_G_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_GG_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_ATTACH_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN + +#define DEBUGGER_COMMAND_DETACH_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN + +#define DEBUGGER_COMMAND_SWITCH_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_CONTINUE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN + +#define DEBUGGER_COMMAND_PAUSE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN + +#define DEBUGGER_COMMAND_START_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN + +#define DEBUGGER_COMMAND_RESTART_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_WONT_STOP_DEBUGGER_AGAIN + +#define DEBUGGER_COMMAND_KILL_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_PROCESS_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_THREAD_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_SLEEP_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_EVENTS_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_SETTINGS_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_DISCONNECT_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_DEBUG_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_DOT_STATUS_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_STATUS_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_LOAD_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_EXIT_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_FLUSH_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_UNLOAD_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_SCRIPT_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_OUTPUT_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_PRINT_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_EVAL_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_LOGOPEN_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_LOGCLOSE_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_ABSOLUTE_LOCAL + +#define DEBUGGER_COMMAND_TEST_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_CPU_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_WRMSR_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_RDMSR_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_VA2PA_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_PA2VA_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_FORMATS_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_PTE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_APIC_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_IOAPIC_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_CORE_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_MONITOR_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_VMCALL_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_EPTHOOK_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_EPTHOOK2_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_CPUID_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_XSETBV_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_MSRREAD_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_MSRWRITE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_TSC_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_PMC_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_CRWRITE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_DR_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_IOIN_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_IOOUT_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_EXCEPTION_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_INTERRUPT_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_SYSCALL_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_SYSRET_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_MODE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_TRACE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_EVENT + +#define DEBUGGER_COMMAND_HIDE_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_UNHIDE_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_MEASURE_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_LM_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_P_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_T_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_I_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_D_AND_U_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_E_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_S_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_R_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_BP_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_BE_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_BD_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_BC_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_BL_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_SYMPATH_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_SYM_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_X_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_PREALLOC_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_PREACTIVATE_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_K_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_DT_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_STRUCT_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_PE_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_REV_ATTRIBUTES NULL + +#define DEBUGGER_COMMAND_TRACK_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_PAGEIN_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_DUMP_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_GU_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE | DEBUGGER_COMMAND_ATTRIBUTE_REPEAT_ON_ENTER + +#define DEBUGGER_COMMAND_HWDBG_HW_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_HWDBG + +#define DEBUGGER_COMMAND_HWDBG_HW_CLK_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_HWDBG + +#define DEBUGGER_COMMAND_A_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_PCITREE_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_PCICAM_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_IDT_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_SMI_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_LBR_ATTRIBUTES \ + NULL + +#define DEBUGGER_COMMAND_LBRDUMP_ATTRIBUTES \ + DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + +#define DEBUGGER_COMMAND_PT_ATTRIBUTES \ + NULL + +////////////////////////////////////////////////// +// Command Functions // +////////////////////////////////////////////////// + +VOID +CommandTest(vector CommandTokens, string Command); + +VOID +CommandCls(vector CommandTokens, string Command); + +VOID +CommandReadMemoryAndDisassembler(vector CommandTokens, string Command); + +VOID +CommandConnect(vector CommandTokens, string Command); + +VOID +CommandLoad(vector CommandTokens, string Command); + +VOID +CommandUnload(vector CommandTokens, string Command); + +VOID +CommandScript(vector CommandTokens, string Command); + +VOID +CommandCpu(vector CommandTokens, string Command); + +VOID +CommandExit(vector CommandTokens, string Command); + +VOID +CommandDisconnect(vector CommandTokens, string Command); + +VOID +CommandFormats(vector CommandTokens, string Command); + +VOID +CommandRdmsr(vector CommandTokens, string Command); + +VOID +CommandWrmsr(vector CommandTokens, string Command); + +VOID +CommandPte(vector CommandTokens, string Command); + +VOID +CommandMonitor(vector CommandTokens, string Command); + +VOID +CommandSyscallAndSysret(vector CommandTokens, string Command); + +VOID +CommandEptHook(vector CommandTokens, string Command); + +VOID +CommandEptHook2(vector CommandTokens, string Command); + +VOID +CommandCpuid(vector CommandTokens, string Command); + +VOID +CommandMsrread(vector CommandTokens, string Command); + +VOID +CommandMsrwrite(vector CommandTokens, string Command); + +VOID +CommandTsc(vector CommandTokens, string Command); + +VOID +CommandPmc(vector CommandTokens, string Command); + +VOID +CommandException(vector CommandTokens, string Command); + +VOID +CommandCrwrite(vector CommandTokens, string Command); + +VOID +CommandDr(vector CommandTokens, string Command); + +VOID +CommandInterrupt(vector CommandTokens, string Command); + +VOID +CommandIoin(vector CommandTokens, string Command); + +VOID +CommandIoout(vector CommandTokens, string Command); + +VOID +CommandVmcall(vector CommandTokens, string Command); + +VOID +CommandMode(vector CommandTokens, string Command); + +VOID +CommandTrace(vector CommandTokens, string Command); + +VOID +CommandHide(vector CommandTokens, string Command); + +VOID +CommandUnhide(vector CommandTokens, string Command); + +VOID +CommandLogopen(vector CommandTokens, string Command); + +VOID +CommandLogclose(vector CommandTokens, string Command); + +VOID +CommandVa2pa(vector CommandTokens, string Command); + +VOID +CommandPa2va(vector CommandTokens, string Command); + +VOID +CommandEvents(vector CommandTokens, string Command); + +VOID +CommandG(vector CommandTokens, string Command); + +VOID +CommandContinue(vector CommandTokens, string Command); + +VOID +CommandGg(vector CommandTokens, string Command); + +VOID +CommandLm(vector CommandTokens, string Command); + +VOID +CommandSleep(vector CommandTokens, string Command); + +VOID +CommandEditMemory(vector CommandTokens, string Command); + +VOID +CommandSearchMemory(vector CommandTokens, string Command); + +VOID +CommandMeasure(vector CommandTokens, string Command); + +VOID +CommandSettings(vector CommandTokens, string Command); + +VOID +CommandFlush(vector CommandTokens, string Command); + +VOID +CommandPause(vector CommandTokens, string Command); + +VOID +CommandListen(vector CommandTokens, string Command); + +VOID +CommandStatus(vector CommandTokens, string Command); + +VOID +CommandAttach(vector CommandTokens, string Command); + +VOID +CommandDetach(vector CommandTokens, string Command); + +VOID +CommandStart(vector CommandTokens, string Command); + +VOID +CommandRestart(vector CommandTokens, string Command); + +VOID +CommandSwitch(vector CommandTokens, string Command); + +VOID +CommandKill(vector CommandTokens, string Command); + +VOID +CommandT(vector CommandTokens, string Command); + +VOID +CommandI(vector CommandTokens, string Command); + +VOID +CommandPrint(vector CommandTokens, string Command); + +VOID +CommandOutput(vector CommandTokens, string Command); + +VOID +CommandDebug(vector CommandTokens, string Command); + +VOID +CommandP(vector CommandTokens, string Command); + +VOID +CommandCore(vector CommandTokens, string Command); + +VOID +CommandProcess(vector CommandTokens, string Command); + +VOID +CommandThread(vector CommandTokens, string Command); + +VOID +CommandEval(vector CommandTokens, string Command); + +VOID +CommandR(vector CommandTokens, string Command); + +VOID +CommandBp(vector CommandTokens, string Command); + +VOID +CommandBl(vector CommandTokens, string Command); + +VOID +CommandBe(vector CommandTokens, string Command); + +VOID +CommandBd(vector CommandTokens, string Command); + +VOID +CommandBc(vector CommandTokens, string Command); + +VOID +CommandSympath(vector CommandTokens, string Command); + +VOID +CommandSym(vector CommandTokens, string Command); + +VOID +CommandX(vector CommandTokens, string Command); + +VOID +CommandPrealloc(vector CommandTokens, string Command); + +VOID +CommandPreactivate(vector CommandTokens, string Command); + +VOID +CommandDtAndStruct(vector CommandTokens, string Command); + +VOID +CommandK(vector CommandTokens, string Command); + +VOID +CommandPe(vector CommandTokens, string Command); + +VOID +CommandRev(vector CommandTokens, string Command); + +VOID +CommandApic(vector CommandTokens, string Command); + +VOID +CommandIoapic(vector CommandTokens, string Command); + +VOID +CommandTrack(vector CommandTokens, string Command); + +VOID +CommandPagein(vector CommandTokens, string Command); + +VOID +CommandDump(vector CommandTokens, string Command); + +VOID +CommandGu(vector CommandTokens, string Command); + +VOID +CommandAssemble(vector CommandTokens, string Command); + +VOID +CommandPcitree(vector CommandTokens, string Command); + +VOID +CommandPcicam(vector CommandTokens, string Command); + +VOID +CommandIdt(vector CommandTokens, string Command); + +VOID +CommandSmi(vector CommandTokens, string Command); + +VOID +CommandLbr(vector CommandTokens, string Command); + +VOID +CommandLbrdump(vector CommandTokens, string Command); + +VOID +CommandPt(vector CommandTokens, string Command); + +// +// hwdbg commands +// +VOID +CommandHwClk(vector CommandTokens, string Command); + +VOID +CommandHw(vector CommandTokens, string Command); + +VOID +CommandXsetbv(vector CommandTokens, string Command); + +VOID +CommandXsetbvHelp(); diff --git a/hyperdbg/hprdbgctrl/header/help.h b/hyperdbg/libhyperdbg/header/debugger/commands/help.h similarity index 87% rename from hyperdbg/hprdbgctrl/header/help.h rename to hyperdbg/libhyperdbg/header/debugger/commands/help.h index 60aa432b..70340e54 100644 --- a/hyperdbg/hprdbgctrl/header/help.h +++ b/hyperdbg/libhyperdbg/header/debugger/commands/help.h @@ -142,7 +142,13 @@ VOID CommandGHelp(); VOID -CommandClearScreenHelp(); +CommandContinueHelp(); + +VOID +CommandGgHelp(); + +VOID +CommandClsHelp(); VOID CommandSleepHelp(); @@ -213,6 +219,12 @@ CommandPHelp(); VOID CommandCoreHelp(); +VOID +CommandApicHelp(); + +VOID +CommandIoapicHelp(); + VOID CommandProcessHelp(); @@ -281,3 +293,36 @@ CommandDumpHelp(); VOID CommandGuHelp(); + +VOID +CommandAssembleHelp(); + +VOID +CommandPcitreeHelp(); + +VOID +CommandPcicamHelp(); + +VOID +CommandIdtHelp(); + +VOID +CommandSmiHelp(); + +VOID +CommandLbrHelp(); + +VOID +CommandLbrdumpHelp(); + +VOID +CommandPtHelp(); + +// +// hwdbg commands +// +VOID +CommandHwClkHelp(); + +VOID +CommandHwHelp(); diff --git a/hyperdbg/hprdbgctrl/header/communication.h b/hyperdbg/libhyperdbg/header/debugger/communication/communication.h similarity index 79% rename from hyperdbg/hprdbgctrl/header/communication.h rename to hyperdbg/libhyperdbg/header/debugger/communication/communication.h index f53325b4..c33e377f 100644 --- a/hyperdbg/hprdbgctrl/header/communication.h +++ b/hyperdbg/libhyperdbg/header/debugger/communication/communication.h @@ -29,13 +29,13 @@ CommunicationServerCreateServerAndWaitForClient(PCSTR Port, SOCKET * ClientSocketArg, SOCKET * ListenSocketArg); -int -CommunicationServerReceiveMessage(SOCKET ClientSocket, char * recvbuf, int recvbuflen); +INT +CommunicationServerReceiveMessage(SOCKET ClientSocket, CHAR * recvbuf, INT recvbuflen); -int -CommunicationServerSendMessage(SOCKET ClientSocket, const char * sendbuf, int length); +INT +CommunicationServerSendMessage(SOCKET ClientSocket, const CHAR * sendbuf, INT length); -int +INT CommunicationServerShutdownAndCleanupConnection(SOCKET ClientSocket, SOCKET ListenSocket); @@ -43,19 +43,19 @@ CommunicationServerShutdownAndCleanupConnection(SOCKET ClientSocket, // Client // ////////////////////////////////////////// -int +INT CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET * ConnectSocketArg); -int -CommunicationClientSendMessage(SOCKET ConnectSocket, const char * sendbuf, int buflen); +INT +CommunicationClientSendMessage(SOCKET ConnectSocket, const CHAR * sendbuf, INT buflen); -int +INT CommunicationClientShutdownConnection(SOCKET ConnectSocket); -int +INT CommunicationClientReceiveMessage(SOCKET ConnectSocket, CHAR * RecvBuf, UINT32 MaxBuffLen, PUINT32 BuffLenRecvd); -int +INT CommunicationClientCleanup(SOCKET ConnectSocket); ////////////////////////////////////////// @@ -68,11 +68,11 @@ RemoteConnectionListen(PCSTR Port); VOID RemoteConnectionConnect(PCSTR Ip, PCSTR Port); -int -RemoteConnectionSendCommand(const char * sendbuf, int len); +INT +RemoteConnectionSendCommand(const CHAR * sendbuf, INT len); -int -RemoteConnectionSendResultsToHost(const char * sendbuf, int len); +INT +RemoteConnectionSendResultsToHost(const CHAR * sendbuf, INT len); -int +INT RemoteConnectionCloseTheConnectionWithDebuggee(); diff --git a/hyperdbg/hprdbgctrl/header/forwarding.h b/hyperdbg/libhyperdbg/header/debugger/communication/forwarding.h similarity index 97% rename from hyperdbg/hprdbgctrl/header/forwarding.h rename to hyperdbg/libhyperdbg/header/debugger/communication/forwarding.h index 2f3b0a0e..467aafae 100644 --- a/hyperdbg/hprdbgctrl/header/forwarding.h +++ b/hyperdbg/libhyperdbg/header/debugger/communication/forwarding.h @@ -19,7 +19,7 @@ * @brief maximum characters for event forwarding source names * */ -typedef void (*hyperdbg_event_forwarding_t)(const char *, unsigned int); +typedef VOID (*hyperdbg_event_forwarding_t)(const CHAR *, UINT32); ////////////////////////////////////////// // Output Source Forwarding // diff --git a/hyperdbg/hprdbgctrl/header/namedpipe.h b/hyperdbg/libhyperdbg/header/debugger/communication/namedpipe.h similarity index 75% rename from hyperdbg/hprdbgctrl/header/namedpipe.h rename to hyperdbg/libhyperdbg/header/debugger/communication/namedpipe.h index 3438376d..5a15c31e 100644 --- a/hyperdbg/hprdbgctrl/header/namedpipe.h +++ b/hyperdbg/libhyperdbg/header/debugger/communication/namedpipe.h @@ -22,12 +22,12 @@ BOOLEAN NamedPipeServerWaitForClientConntection(HANDLE PipeHandle); UINT32 -NamedPipeServerReadClientMessage(HANDLE PipeHandle, char * BufferToSave, int MaximumReadBufferLength); +NamedPipeServerReadClientMessage(HANDLE PipeHandle, CHAR * BufferToSave, INT MaximumReadBufferLength); BOOLEAN NamedPipeServerSendMessageToClient(HANDLE PipeHandle, - char * BufferToSend, - int BufferSize); + CHAR * BufferToSend, + INT BufferSize); VOID NamedPipeServerCloseHandle(HANDLE PipeHandle); @@ -43,10 +43,10 @@ HANDLE NamedPipeClientCreatePipeOverlappedIo(LPCSTR PipeName); BOOLEAN -NamedPipeClientSendMessage(HANDLE PipeHandle, char * BufferToSend, int BufferSize); +NamedPipeClientSendMessage(HANDLE PipeHandle, CHAR * BufferToSend, INT BufferSize); UINT32 -NamedPipeClientReadMessage(HANDLE PipeHandle, char * BufferToRead, int MaximumSizeOfBuffer); +NamedPipeClientReadMessage(HANDLE PipeHandle, CHAR * BufferToRead, INT MaximumSizeOfBuffer); VOID NamedPipeClientClosePipe(HANDLE PipeHandle); diff --git a/hyperdbg/hprdbgctrl/header/debugger.h b/hyperdbg/libhyperdbg/header/debugger/core/debugger.h similarity index 69% rename from hyperdbg/hprdbgctrl/header/debugger.h rename to hyperdbg/libhyperdbg/header/debugger/core/debugger.h index b2629027..9ac1012c 100644 --- a/hyperdbg/hprdbgctrl/header/debugger.h +++ b/hyperdbg/libhyperdbg/header/debugger/core/debugger.h @@ -1,6 +1,7 @@ /** * @file debugger.h * @author Sina Karvandi (sina@hyperdbg.org) + * @author jtaw5649 * @brief General debugger functions * @details * @version 0.1 @@ -55,6 +56,14 @@ #define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_PTE_RESULT 0x17 #define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_SHORT_CIRCUITING_EVENT_STATE 0x18 #define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_PAGE_IN_STATE 0x19 +#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_WRITE_REGISTER 0x1a +#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_PCITREE_RESULT 0x1b +#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS 0x1c +#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_PCIDEVINFO_RESULT 0x1d +#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_IDT_ENTRIES 0x1e +#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_SMI_OPERATION_RESULT 0x1f +#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_LBR_DUMP_RESULT 0x20 +#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_PT_OPERATION_RESULT 0x21 ////////////////////////////////////////////////// // Event Details // @@ -95,7 +104,7 @@ typedef enum _DEBUGGER_EVENT_PARSING_ERROR_CAUSE // // User-debugger // -#define DEBUGGER_SYNCRONIZATION_OBJECT_USER_DEBUGGER_IS_DEBUGGER_RUNNING 0x30 +#define DEBUGGER_SYNCRONIZATION_OBJECT_USER_DEBUGGER_IS_DEBUGGER_RUNNING 0x0 ////////////////////////////////////////////////// // Event Details // @@ -109,15 +118,15 @@ typedef struct _DEBUGGER_SYNCRONIZATION_EVENTS_STATE { HANDLE EventHandle; BOOLEAN IsOnWaitingState; + PVOID RequestData; + UINT32 RequestSize; + } DEBUGGER_SYNCRONIZATION_EVENTS_STATE, *PDEBUGGER_SYNCRONIZATION_EVENTS_STATE; ////////////////////////////////////////////////// // Functions // ////////////////////////////////////////////////// -VOID -InterpreterRemoveComments(char * CommandText); - BOOLEAN ShowErrorMessage(UINT32 Error); @@ -130,15 +139,11 @@ IsTagExist(UINT64 Tag); UINT64 DebuggerGetNtoskrnlBase(); -BOOLEAN -DebuggerPauseDebuggee(); +UINT64 +DebuggerGetKernelBase(); BOOLEAN -InterpretConditionsAndCodes(vector * SplitCommand, - vector * SplitCommandCaseSensitive, - BOOLEAN IsConditionBuffer, - PUINT64 BufferAddress, - PUINT32 BufferLength); +DebuggerPauseDebuggee(); VOID FreeEventsAndActionsMemory(PDEBUGGER_GENERAL_EVENT_DETAIL Event, @@ -161,8 +166,7 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_EVENT_DETAIL Event, BOOLEAN InterpretGeneralEventAndActionsFields( - vector * SplitCommand, - vector * SplitCommandCaseSensitive, + vector * CommandTokens, VMM_EVENT_TYPE_ENUM EventType, PDEBUGGER_GENERAL_EVENT_DETAIL * EventDetailsToFill, PUINT32 EventBufferLength, @@ -193,7 +197,7 @@ DWORD WINAPI ListeningSerialPauseDebuggerThread(PVOID Param); VOID -LogopenSaveToFile(const char * Text); +LogopenSaveToFile(const CHAR * Text); BOOL BreakController(DWORD CtrlType); @@ -222,27 +226,102 @@ GetCommandAttributes(const string & FirstCommand); VOID DetachFromProcess(); -BOOLEAN -CommandLoadVmmModule(); - -VOID -ShowAllRegisters(); - VOID CommandPauseRequest(); VOID CommandGRequest(); -VOID -CommandTrackHandleReceivedInstructions(unsigned char * BufferToDisassemble, - UINT32 BuffLength, - BOOLEAN Isx86_64, - UINT64 RipAddress); +BOOLEAN +CommandBpRequest(UINT64 Address, UINT32 Pid, UINT32 Tid, UINT32 CoreNumer); VOID -CommandTrackHandleReceivedCallInstructions(const char * NameOfFunctionFromSymbols, +CommandTrackHandleReceivedInstructions(UCHAR * BufferToDisassemble, + UINT32 BuffLength, + BOOLEAN Isx86_64, + UINT64 RipAddress); + +VOID +CommandTrackHandleReceivedCallInstructions(const CHAR * NameOfFunctionFromSymbols, UINT64 ComputedAbsoluteAddress); VOID CommandTrackHandleReceivedRetInstructions(UINT64 CurrentRip); + +BOOLEAN +HyperDbgWriteMemory(PVOID DestinationAddress, + DEBUGGER_EDIT_MEMORY_TYPE MemoryType, + UINT32 ProcessId, + PVOID SourceAddress, + UINT32 NumberOfBytes); + +////////////////////////////////////////////////// +// Misc // +////////////////////////////////////////////////// + +BOOLEAN +CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, + PVOID ApicBuffer, + UINT32 ExpectedRequestSize, + PBOOLEAN IsUsingX2APIC); + +////////////////////////////////////////////////// +// SDK Servicing Routines // +////////////////////////////////////////////////// + +BOOLEAN +HyperDbgReadAllRegisters(GUEST_REGS * GuestRegisters, GUEST_EXTRA_REGISTERS * ExtraRegisters); + +BOOLEAN +HyperDbgReadTargetRegister(REGS_ENUM RegisterId, UINT64 * TargetRegister); + +BOOLEAN +HyperDbgWriteTargetRegister(REGS_ENUM RegisterId, UINT64 Value); + +BOOLEAN +HyperDbgRegisterShowAll(); + +BOOLEAN +HyperDbgRegisterShowTargetRegister(REGS_ENUM RegisterId); + +BOOLEAN +HyperDbgDebugRemoteDeviceUsingComPort(const CHAR * PortName, DWORD Baudrate, BOOLEAN PauseAfterConnection); + +BOOLEAN +HyperDbgDebugRemoteDeviceUsingNamedPipe(const CHAR * NamedPipe, BOOLEAN PauseAfterConnection); + +BOOLEAN +HyperDbgDebugCurrentDeviceUsingComPort(const CHAR * PortName, DWORD Baudrate); + +BOOLEAN +HyperDbgDebugCloseRemoteDebugger(); + +BOOLEAN +HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic, PBOOLEAN IsUsingX2APIC); + +BOOLEAN +HyperDbgGetIoApic(IO_APIC_ENTRY_PACKETS * IoApic); + +BOOLEAN +HyperDbgGetIdtEntry(INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS * IdtPacket); + +BOOLEAN +HyperDbgPerformSmiOperation(SMI_OPERATION_PACKETS * SmiOperation); + +BOOLEAN +HyperDbgEnableTransparentMode(UINT32 ProcessId, CHAR * ProcessName, BOOLEAN IsProcessId); + +BOOLEAN +HyperDbgEnableTransparentModeEx(UINT32 ProcessId, CHAR * ProcessName, BOOLEAN IsProcessId, UINT32 EvadeMask); + +BOOLEAN +HyperDbgDisableTransparentMode(); + +BOOLEAN +HyperDbgLbrdumpSendRequest(HYPERTRACE_LBR_DUMP_PACKETS * LbrdumpRequest); + +BOOLEAN +HyperDbgPerformPtOperation(HYPERTRACE_PT_OPERATION_PACKETS * PtRequest); + +BOOLEAN +HyperDbgPtMmapSendRequest(HYPERTRACE_PT_MMAP_PACKETS * MmapRequest); diff --git a/hyperdbg/libhyperdbg/header/debugger/core/steppings.h b/hyperdbg/libhyperdbg/header/debugger/core/steppings.h new file mode 100644 index 00000000..8cb2a011 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/debugger/core/steppings.h @@ -0,0 +1,31 @@ +/** + * @file steppings.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief headers for stepping instructions + * @details + * @version 0.11 + * @date 2024-09-06 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +SteppingInstrumentationStepIn(); + +BOOLEAN +SteppingRegularStepIn(); + +BOOLEAN +SteppingStepOver(); + +BOOLEAN +SteppingInstrumentationStepInForTracking(); + +BOOLEAN +SteppingStepOverForGu(BOOLEAN LastInstruction); diff --git a/hyperdbg/libhyperdbg/header/debugger/driver-loader/install.h b/hyperdbg/libhyperdbg/header/debugger/driver-loader/install.h new file mode 100644 index 00000000..b35aa3d7 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/debugger/driver-loader/install.h @@ -0,0 +1,61 @@ +/** + * @file install.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Main interface to connect applications to driver headers + * @details + * @version 0.1 + * @date 2020-04-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +// +// The following ifdef block is the standard way of creating macros which make +// exporting from a DLL simpler. All files within this DLL are compiled with the +// LIBHYPERDBG_EXPORTS symbol defined on the command line. This symbol should not +// be defined on any project that uses this DLL. This way any other project +// whose source files include this file see LIBHYPERDBG_API functions as being +// imported from a DLL, whereas this DLL sees symbols defined with this macro as +// being exported. +// + +#ifdef LIBHYPERDBG_EXPORTS +# define LIBHYPERDBG_API __declspec(dllexport) +#else +# define LIBHYPERDBG_API __declspec(dllimport) +#endif + +////////////////////////////////////////////////// +// Installer // +////////////////////////////////////////////////// + +#define DRIVER_FUNC_INSTALL 0x01 +#define DRIVER_FUNC_STOP 0x02 +#define DRIVER_FUNC_REMOVE 0x03 + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe); + +BOOLEAN +RemoveDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName); + +BOOLEAN +StartDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName); + +BOOLEAN +StopDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName); + +BOOLEAN +ManageDriver(_In_ LPCTSTR DriverName, _In_ LPCTSTR ServiceName, _In_ UINT16 Function); + +BOOLEAN +SetupPathForFileName(const CHAR * FileName, + _Inout_updates_bytes_all_(BufferLength) PCHAR FileLocation, + ULONG BufferLength, + BOOLEAN CheckFileExists); diff --git a/hyperdbg/hprdbgctrl/header/kd.h b/hyperdbg/libhyperdbg/header/debugger/kernel-level/kd.h similarity index 77% rename from hyperdbg/hprdbgctrl/header/kd.h rename to hyperdbg/libhyperdbg/header/debugger/kernel-level/kd.h index 84d894a9..9a7e2798 100644 --- a/hyperdbg/hprdbgctrl/header/kd.h +++ b/hyperdbg/libhyperdbg/header/debugger/kernel-level/kd.h @@ -11,34 +11,12 @@ */ #pragma once -////////////////////////////////////////////////// -// Definitions // -////////////////////////////////////////////////// - -#define DbgWaitForKernelResponse(KernelSyncObjectId) \ - do \ - { \ - DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ - &g_KernelSyncronizationObjectsHandleTable[KernelSyncObjectId]; \ - \ - SyncronizationObject->IsOnWaitingState = TRUE; \ - WaitForSingleObject(SyncronizationObject->EventHandle, INFINITE); \ - } while (FALSE); - -#define DbgReceivedKernelResponse(KernelSyncObjectId) \ - do \ - { \ - DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ - &g_KernelSyncronizationObjectsHandleTable[KernelSyncObjectId]; \ - \ - SyncronizationObject->IsOnWaitingState = FALSE; \ - SetEvent(SyncronizationObject->EventHandle); \ - } while (FALSE); - ////////////////////////////////////////////////// // Display Windows Details // ////////////////////////////////////////////////// +#ifdef _WIN32 +// HKEY / RegCloseKey are Windows registry APIs; this RAII helper is Windows-only struct HKeyHolder { private: @@ -61,6 +39,7 @@ public: HKEY * operator&() { return &m_Key; } }; +#endif // _WIN32 ////////////////////////////////////////////////// // Functions // @@ -80,10 +59,16 @@ KdCommandPacketAndBufferToDebuggee( BOOLEAN KdPrepareSerialConnectionToRemoteSystem(HANDLE SerialHandle, - BOOLEAN IsNamedPipe); + BOOLEAN IsNamedPipe, + BOOLEAN PauseAfterConnection); BOOLEAN -KdPrepareAndConnectDebugPort(const char * PortName, DWORD Baudrate, UINT32 Port, BOOLEAN IsPreparing, BOOLEAN IsNamedPipe); +KdPrepareAndConnectDebugPort(const CHAR * PortName, + DWORD Baudrate, + UINT32 Port, + BOOLEAN IsPreparing, + BOOLEAN IsNamedPipe, + BOOLEAN PauseAfterConnection); BOOLEAN KdSendPacketToDebuggee(const CHAR * Buffer, UINT32 Length, BOOLEAN SendEndOfBuffer); @@ -127,10 +112,14 @@ KdSendTestQueryPacketWithContextToDebuggee(DEBUGGER_TEST_QUERY_STATE Type, UINT6 BOOLEAN KdSendSymbolReloadPacketToDebuggee(UINT32 ProcessId); -BOOLEAN KdSendReadRegisterPacketToDebuggee(PDEBUGGEE_REGISTER_READ_DESCRIPTION); +BOOLEAN +KdSendReadRegisterPacketToDebuggee(PDEBUGGEE_REGISTER_READ_DESCRIPTION RegDes, UINT32 RegBuffSize); BOOLEAN -KdSendReadMemoryPacketToDebuggee(PDEBUGGER_READ_MEMORY ReadMem); +KdSendWriteRegisterPacketToDebuggee(PDEBUGGEE_REGISTER_WRITE_DESCRIPTION RegDes); + +BOOLEAN +KdSendReadMemoryPacketToDebuggee(PDEBUGGER_READ_MEMORY ReadMem, UINT32 RequestSize); BOOLEAN KdSendEditMemoryPacketToDebuggee(PDEBUGGER_EDIT_MEMORY EditMem, UINT32 Size); @@ -163,6 +152,21 @@ KdSendBpPacketToDebuggee(PDEBUGGEE_BP_PACKET BpPacket); BOOLEAN KdSendVa2paAndPa2vaPacketToDebuggee(PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS Va2paAndPa2vaPacket); +BOOLEAN +KdSendApicActionPacketsToDebuggee(PDEBUGGER_APIC_REQUEST ApicRequest, UINT32 ExpectedRequestSize); + +BOOLEAN +KdSendSmiPacketsToDebuggee(PSMI_OPERATION_PACKETS SmiOperationRequest, UINT32 ExpectedRequestSize); + +BOOLEAN +KdSendHyperTraceLbrdumpPacketsToDebuggee(PHYPERTRACE_LBR_DUMP_PACKETS HyperTraceLbrdumpRequest, UINT32 ExpectedRequestSize); + +BOOLEAN +KdSendHyperTracePtPacketsToDebuggee(PHYPERTRACE_PT_OPERATION_PACKETS HyperTracePtOperationRequest, UINT32 ExpectedRequestSize); + +BOOLEAN +KdSendQueryIdtPacketsToDebuggee(PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS IdtRequest); + BOOLEAN KdSendPtePacketToDebuggee(PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PtePacket); @@ -177,7 +181,7 @@ BOOLEAN KdSendScriptPacketToDebuggee(UINT64 BufferAddress, UINT32 BufferLength, UINT32 Pointer, BOOLEAN IsFormat); BOOLEAN -KdSendUserInputPacketToDebuggee(const char * Sendbuf, int Len, BOOLEAN IgnoreBreakingAgain); +KdSendUserInputPacketToDebuggee(const CHAR * Sendbuf, INT Len, BOOLEAN IgnoreBreakingAgain); BOOLEAN KdSendSearchRequestPacketToDebuggee(UINT64 * SearchRequestBuffer, UINT32 SearchRequestBufferSize); @@ -215,6 +219,12 @@ KdReloadSymbolsInDebuggee(BOOLEAN PauseDebuggee, UINT32 UserProcessId); BOOLEAN KdSendResponseOfThePingPacket(); +BOOLEAN +KdSendPcitreePacketToDebuggee(PDEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET PcitreePacket); + +BOOLEAN +KdSendPcidevinfoPacketToDebuggee(PDEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET PcidevinfoPacket); + VOID KdUninitializeConnection(); @@ -233,7 +243,7 @@ VOID KdTheRemoteSystemIsRunning(); VOID -KdBreakControlCheckAndPauseDebugger(); +KdBreakControlCheckAndPauseDebugger(BOOLEAN SignalRunningFlag); VOID KdBreakControlCheckAndContinueDebugger(); diff --git a/hyperdbg/libhyperdbg/header/debugger/misc/assembler.h b/hyperdbg/libhyperdbg/header/debugger/misc/assembler.h new file mode 100644 index 00000000..5a133a0e --- /dev/null +++ b/hyperdbg/libhyperdbg/header/debugger/misc/assembler.h @@ -0,0 +1,39 @@ +/** + * @file assembler.h + * @author Abbas Masoumi Gorji (AbbasMG@hyperdbg.org) + * @brief Headers for turning assembly codes into bytes + * @details + * @version 0.10 + * @date 2024-07-16 + * + * @copyright This project is released under the GNU Public License v3. + * + */ + +#pragma once + +class AssembleData +{ +public: + std::string AsmRaw {}; + std::string AsmFixed {}; + SIZE_T StatementCount {}; + SIZE_T BytesCount {}; + UCHAR * EncodedBytes {}; + vector EncBytesIntVec {}; + ks_err KsErr {}; + + AssembleData() = default; + + VOID + ParseAssemblyData(); + + INT + Assemble(UINT64 StartAddr, ks_arch Arch = KS_ARCH_X86, INT Mode = KS_MODE_64, INT Syntax = KS_OPT_SYNTAX_INTEL); +}; + +BOOLEAN +HyperDbgAssembleGetLength(const CHAR * AssemblyCode, UINT64 StartAddress, UINT32 * Length); + +BOOLEAN +HyperDbgAssemble(const CHAR * AssemblyCode, UINT64 StartAddress, PVOID BufferToStoreAssembledData, UINT32 BufferSize); diff --git a/hyperdbg/hprdbgctrl/header/inipp.h b/hyperdbg/libhyperdbg/header/debugger/misc/inipp.h similarity index 100% rename from hyperdbg/hprdbgctrl/header/inipp.h rename to hyperdbg/libhyperdbg/header/debugger/misc/inipp.h diff --git a/hyperdbg/libhyperdbg/header/debugger/misc/pci-id.h b/hyperdbg/libhyperdbg/header/debugger/misc/pci-id.h new file mode 100644 index 00000000..b2196274 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/debugger/misc/pci-id.h @@ -0,0 +1,59 @@ +/** + * @file pci-id.h + * @author Bj�rn Ruytenberg (bjorn@bjornweb.nl) + * @brief PCI ID-related data structures + * @details + * @version 0.12 + * @date 2024-12-04 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#define PCI_ID_AS_STR_LENGTH (sizeof(UINT16) * 2) +#define PCI_NAME_STR_LENGTH 255 + +typedef struct SubDevice +{ + UINT16 SubVendorId; + UINT16 SubDeviceId; + CHAR SubSystemName[PCI_NAME_STR_LENGTH]; + struct SubDevice * Next; +} SubDevice; + +typedef struct Device +{ + UINT16 DeviceId; + CHAR DeviceName[PCI_NAME_STR_LENGTH]; + SubDevice * SubDevices; + struct Device * Next; +} Device; + +typedef struct Vendor +{ + UINT16 VendorId; + CHAR VendorName[PCI_NAME_STR_LENGTH]; + Device * Devices; +} Vendor; + +// +// PCI ID database courtesy of PCI ID Database (pciutils) project at +// https://pci-ids.ucw.cz/ +// +#define PCI_ID_DATABASE_PATH "constants\\pci.ids" + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +Vendor * +GetVendorById(UINT16 VendorId); +void +FreeVendor(Vendor * VendorToFree); +void +FreePciIdDatabase(); +Device * +GetDeviceFromVendor(Vendor * VendorToUse, UINT16 DeviceId); +SubDevice * +GetSubDeviceFromDevice(Device * DeviceToUse, UINT16 SubVendorId, UINT16 SubDeviceId); diff --git a/hyperdbg/libhyperdbg/header/debugger/misc/pt-helper.h b/hyperdbg/libhyperdbg/header/debugger/misc/pt-helper.h new file mode 100644 index 00000000..b3f595f4 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/debugger/misc/pt-helper.h @@ -0,0 +1,28 @@ +/** + * @file pt-helper.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for PT helper functions + * @details + * @version 0.21 + * @date 2026-07-03 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +UINT64 +PtHelperDecodeCorePackets(UINT32 Cpu, const UINT8 * Buffer, UINT64 Size, UINT64 ImageBase); + +UINT64 +PtHelperDecodeCore(UINT32 Cpu, const UINT8 * Buffer, UINT64 Size, IMAGE_SYMBOL_CONTEXT * Ctx); + +BOOLEAN +PtHelperCaptureImage(HANDLE Process, UINT64 * TextStart, UINT64 * TextEnd, IMAGE_SYMBOL_CONTEXT * Ctx); + +BOOLEAN +PtHelperResolveFunction(HANDLE Process, const CHAR * Path, const CHAR * Name, UINT64 ImageBase, UINT64 * Start, UINT64 * End); diff --git a/hyperdbg/hprdbgctrl/header/script-engine.h b/hyperdbg/libhyperdbg/header/debugger/script-engine/script-engine.h similarity index 60% rename from hyperdbg/hprdbgctrl/header/script-engine.h rename to hyperdbg/libhyperdbg/header/debugger/script-engine/script-engine.h index 5f416e48..408b4ab1 100644 --- a/hyperdbg/hprdbgctrl/header/script-engine.h +++ b/hyperdbg/libhyperdbg/header/debugger/script-engine/script-engine.h @@ -15,10 +15,10 @@ // Pdb Parser Wrapper (from script-engine) // ////////////////////////////////////////////////// UINT64 -ScriptEngineConvertNameToAddressWrapper(const char * FunctionOrVariableName, PBOOLEAN WasFound); +ScriptEngineConvertNameToAddressWrapper(const CHAR * FunctionOrVariableName, PBOOLEAN WasFound); UINT32 -ScriptEngineLoadFileSymbolWrapper(UINT64 BaseAddress, const char * PdbFileName, const char * CustomModuleName); +ScriptEngineLoadFileSymbolWrapper(UINT64 BaseAddress, const CHAR * PdbFileName, const CHAR * CustomModuleName); VOID ScriptEngineSetTextMessageCallbackWrapper(PVOID Handler); @@ -27,10 +27,10 @@ UINT32 ScriptEngineUnloadAllSymbolsWrapper(); UINT32 -ScriptEngineUnloadModuleSymbolWrapper(char * ModuleName); +ScriptEngineUnloadModuleSymbolWrapper(CHAR * ModuleName); UINT32 -ScriptEngineSearchSymbolForMaskWrapper(const char * SearchMask); +ScriptEngineSearchSymbolForMaskWrapper(const CHAR * SearchMask); BOOLEAN ScriptEngineGetFieldOffsetWrapper(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset); @@ -39,31 +39,39 @@ BOOLEAN ScriptEngineGetDataTypeSizeWrapper(CHAR * TypeName, UINT64 * TypeSize); BOOLEAN -ScriptEngineCreateSymbolTableForDisassemblerWrapper(void * CallbackFunction); +ScriptEngineCreateSymbolTableForDisassemblerWrapper(VOID * CallbackFunction); BOOLEAN -ScriptEngineConvertFileToPdbPathWrapper(const char * LocalFilePath, char * ResultPath); +ScriptEngineConvertFileToPdbPathWrapper(const CHAR * LocalFilePath, CHAR * ResultPath, SIZE_T ResultPathSize); BOOLEAN -ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetailsWrapper(const char * LocalFilePath, - char * PdbFilePath, - char * GuidAndAgeDetails, +ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetailsWrapper(const CHAR * LocalFilePath, + CHAR * PdbFilePath, + CHAR * GuidAndAgeDetails, BOOLEAN Is32BitModule); +BOOLEAN +ScriptEngineConvertLoadedModuleToPdbFileAndGuidAndAgeDetailsWrapper(const BYTE * LoadedImageBytes, + SIZE_T LoadedImageSize, + const CHAR * LocalFilePath, + CHAR * PdbFilePath, + CHAR * GuidAndAgeDetails, + BOOLEAN Is32BitModule); + BOOLEAN ScriptEngineSymbolInitLoadWrapper(PMODULE_SYMBOL_DETAIL BufferToStoreDetails, UINT32 StoredLength, BOOLEAN DownloadIfAvailable, - const char * SymbolPath, + const CHAR * SymbolPath, BOOLEAN IsSilentLoad); BOOLEAN ScriptEngineShowDataBasedOnSymbolTypesWrapper( - const char * TypeName, + const CHAR * TypeName, UINT64 Address, BOOLEAN IsStruct, PVOID BufferAddress, - const char * AdditionalParameters); + const CHAR * AdditionalParameters); VOID ScriptEngineSymbolAbortLoadingWrapper(); @@ -75,11 +83,14 @@ ScriptEngineSymbolAbortLoadingWrapper(); VOID ScriptEngineWrapperTestParser(const string & Expr); +VOID +ScriptEngineWrapperTestParserForHwdbg(const string & Expr); + BOOLEAN ScriptAutomaticStatementsTestWrapper(const string & Expr, UINT64 ExpectationValue, BOOLEAN ExceptError); PVOID -ScriptEngineParseWrapper(char * Expr, BOOLEAN ShowErrorMessageIfAny); +ScriptEngineParseWrapper(CHAR * Expr, BOOLEAN ShowErrorMessageIfAny); VOID PrintSymbolBufferWrapper(PVOID SymbolBuffer); @@ -105,3 +116,6 @@ ScriptEngineEvalUInt64StyleExpressionWrapper(const string & Expr, PBOOLEAN HasEr UINT64 ScriptEngineEvalSingleExpression(string Expr, PBOOLEAN HasError); + +BOOLEAN +ScriptEngineExecuteSingleExpression(CHAR * Expr, BOOLEAN ShowErrorMessageIfAny, BOOLEAN IsFormat); diff --git a/hyperdbg/hprdbgctrl/header/symbol.h b/hyperdbg/libhyperdbg/header/debugger/script-engine/symbol.h similarity index 60% rename from hyperdbg/hprdbgctrl/header/symbol.h rename to hyperdbg/libhyperdbg/header/debugger/script-engine/symbol.h index d15ee454..b80cdc45 100644 --- a/hyperdbg/hprdbgctrl/header/symbol.h +++ b/hyperdbg/libhyperdbg/header/debugger/script-engine/symbol.h @@ -26,6 +26,53 @@ typedef struct _LOCAL_FUNCTION_DESCRIPTION } LOCAL_FUNCTION_DESCRIPTION, *PLOCAL_FUNCTION_DESCRIPTION; +/** + * @brief Save the local module symbols' description + * + */ +typedef struct _IMAGE_SYMBOL_CONTEXT +{ + UINT64 ImageBase; + UINT64 CodeBase; + UINT64 CodeSize; + UINT8 * Code; +} IMAGE_SYMBOL_CONTEXT; + +/* + * @brief Process basic information structure + */ +typedef struct _PROC_BASIC_INFO +{ + LONG ExitStatus; + PVOID PebBaseAddress; + ULONG_PTR Reserved[4]; +} PROC_BASIC_INFO; + +/** + * @brief Thread basic information + * + */ +typedef struct _THREAD_BASIC_INFO_EX +{ + LONG ExitStatus; + PVOID TebBaseAddress; + struct + { + HANDLE UniqueProcess; + HANDLE UniqueThread; + } ClientId; + ULONG_PTR AffinityMask; + LONG Priority; + LONG BasePriority; +} THREAD_BASIC_INFO_EX; + +////////////////////////////////////////////////// +// Function Defs // +////////////////////////////////////////////////// + +typedef LONG(NTAPI * PFN_NT_QIP)(HANDLE, ULONG, PVOID, ULONG, PULONG); +typedef LONG(NTAPI * PFN_NT_QIT)(HANDLE, ULONG, PVOID, ULONG, PULONG); + ////////////////////////////////////////////////// // Pdbex // ////////////////////////////////////////////////// @@ -71,3 +118,9 @@ SymbolPrepareDebuggerWithSymbolInfo(UINT32 UserProcessId); BOOLEAN SymbolReloadSymbolTableInDebuggerMode(UINT32 ProcessId); + +#ifdef _WIN32 +// PRTL_PROCESS_MODULES is from winternl.h — Windows-only +BOOLEAN +SymbolCheckAndAllocateModuleInformation(PRTL_PROCESS_MODULES * Modules); +#endif // _WIN32 diff --git a/hyperdbg/hprdbgctrl/header/tests.h b/hyperdbg/libhyperdbg/header/debugger/tests/tests.h similarity index 81% rename from hyperdbg/hprdbgctrl/header/tests.h rename to hyperdbg/libhyperdbg/header/debugger/tests/tests.h index b6252d85..2f77544d 100644 --- a/hyperdbg/hprdbgctrl/header/tests.h +++ b/hyperdbg/libhyperdbg/header/debugger/tests/tests.h @@ -26,11 +26,14 @@ ////////////////////////////////////////////////// BOOLEAN -CreateProcessAndOpenPipeConnection(PVOID KernelInformation, - UINT32 KernelInformationSize, - PHANDLE ConnectionPipeHandle, +CreateProcessAndOpenPipeConnection(PHANDLE ConnectionPipeHandle, PHANDLE ThreadHandle, PHANDLE ProcessHandle); +BOOLEAN +OpenHyperDbgTestProcess(PHANDLE ThreadHandle, + PHANDLE ProcessHandle, + CHAR * Args); + VOID CloseProcessAndClosePipeConnection(HANDLE ConnectionPipeHandle, HANDLE ThreadHandle, diff --git a/hyperdbg/hprdbgctrl/header/transparency.h b/hyperdbg/libhyperdbg/header/debugger/transparency/transparency.h similarity index 89% rename from hyperdbg/hprdbgctrl/header/transparency.h rename to hyperdbg/libhyperdbg/header/debugger/transparency/transparency.h index 21b2c3e7..99283371 100644 --- a/hyperdbg/hprdbgctrl/header/transparency.h +++ b/hyperdbg/libhyperdbg/header/debugger/transparency/transparency.h @@ -11,6 +11,10 @@ */ #pragma once +////////////////////////////////////////////////// +// Definitions // +////////////////////////////////////////////////// + /** * @brief Number of tests for each instruction sets * @details used to generate test cases for rdts+cpuid+rdtsc diff --git a/hyperdbg/libhyperdbg/header/debugger/user-level/pe-parser.h b/hyperdbg/libhyperdbg/header/debugger/user-level/pe-parser.h new file mode 100644 index 00000000..af5ca293 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/debugger/user-level/pe-parser.h @@ -0,0 +1,57 @@ +/** + * @file pe-parser.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Header for Portable Executable parser + * @details + * @version 0.1 + * @date 2021-12-26 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Structures // +////////////////////////////////////////////////// + +typedef struct _RICH_HEADER_INFO +{ + int Size; + CHAR * PtrToBuffer; + int Entries; +} RICH_HEADER_INFO, *PRICH_HEADER_INFO; + +typedef struct _RICH_HEADER_ENTRY +{ + WORD ProdID; + WORD BuildID; + DWORD UseCount; +} RICH_HEADER_ENTRY, *PRICH_HEADER_ENTRY; + +typedef struct _RICH_HEADER +{ + PRICH_HEADER_ENTRY Entries; +} RICH_HEADER, *PRICH_HEADER; + +typedef struct _PE_RAW_SECTION_RANGE +{ + ULONGLONG Start; + ULONGLONG End; + const IMAGE_SECTION_HEADER * Section; +} PE_RAW_SECTION_RANGE, *PPE_RAW_SECTION_RANGE; + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOLEAN +PeShowSectionInformationAndDump(const WCHAR * AddressOfFile, + const CHAR * SectionToShow, + BOOLEAN Is32Bit); + +BOOLEAN +PeIsPE32BitOr64Bit(const WCHAR * AddressOfFile, PBOOLEAN Is32Bit); + +UINT32 +PeGetSyscallNumber(LPCSTR NtFunctionName); diff --git a/hyperdbg/hprdbgctrl/header/ud.h b/hyperdbg/libhyperdbg/header/debugger/user-level/ud.h similarity index 50% rename from hyperdbg/hprdbgctrl/header/ud.h rename to hyperdbg/libhyperdbg/header/debugger/user-level/ud.h index fdcb7fca..dc4f38cd 100644 --- a/hyperdbg/hprdbgctrl/header/ud.h +++ b/hyperdbg/libhyperdbg/header/debugger/user-level/ud.h @@ -11,30 +11,6 @@ */ #pragma once -////////////////////////////////////////////////// -// Definitions // -////////////////////////////////////////////////// - -#define DbgWaitForUserResponse(UserSyncObjectId) \ - do \ - { \ - DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ - &g_UserSyncronizationObjectsHandleTable[UserSyncObjectId]; \ - \ - SyncronizationObject->IsOnWaitingState = TRUE; \ - WaitForSingleObject(SyncronizationObject->EventHandle, INFINITE); \ - } while (FALSE); - -#define DbgReceivedUserResponse(UserSyncObjectId) \ - do \ - { \ - DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \ - &g_UserSyncronizationObjectsHandleTable[UserSyncObjectId]; \ - \ - SyncronizationObject->IsOnWaitingState = FALSE; \ - SetEvent(SyncronizationObject->EventHandle); \ - } while (FALSE); - ////////////////////////////////////////////////// // Structures // ////////////////////////////////////////////////// @@ -53,7 +29,10 @@ typedef struct _ACTIVE_DEBUGGING_PROCESS BOOLEAN IsPaused; GUEST_REGS Registers; // thread registers UINT64 Context; // $context + UINT64 Rip; BOOLEAN Is32Bit; + BYTE InstructionBytesOnRip[MAXIMUM_INSTR_SIZE]; + } ACTIVE_DEBUGGING_PROCESS, *PACTIVE_DEBUGGING_PROCESS; ////////////////////////////////////////////////// @@ -67,23 +46,25 @@ VOID UdUninitializeUserDebugger(); VOID -UdRemoveActiveDebuggingProcess(BOOLEAN DontSwitchToNewProcess); +UdRemoveActiveDebuggingProcess(); VOID UdHandleUserDebuggerPausing(PDEBUGGEE_UD_PAUSED_PACKET PausePacket); -VOID -UdContinueDebuggee(UINT64 ProcessDetailToken); - -VOID -UdSendStepPacketToDebuggee(UINT64 ThreadDetailToken, UINT32 TargetThreadId, DEBUGGER_REMOTE_STEPPING_REQUEST StepType); - VOID UdSetActiveDebuggingProcess(UINT64 DebuggingId, + UINT64 Rip, UINT32 ProcessId, UINT32 ThreadId, BOOLEAN Is32Bit, - BOOLEAN IsPaused); + BOOLEAN IsPaused, + BYTE InstructionBytesOnRip[]); + +BOOLEAN +UdSendStepPacketToDebuggee(UINT64 ThreadDetailToken, + UINT32 TargetThreadId, + DEBUGGER_REMOTE_STEPPING_REQUEST StepType); + BOOLEAN UdSetActiveDebuggingThreadByPidOrTid(UINT32 TargetPidOrTid, BOOLEAN IsTid); @@ -93,7 +74,7 @@ UdSetActiveDebuggingThreadByPidOrTid(UINT32 TargetPidOrTid, BOOLEAN IsTid); BOOLEAN UdShowListActiveDebuggingProcessesAndThreads(); -BOOL +BOOLEAN UdListProcessThreads(DWORD OwnerPID); BOOLEAN @@ -102,7 +83,7 @@ UdCheckThreadByProcessId(DWORD Pid, DWORD Tid); BOOLEAN UdAttachToProcess(UINT32 TargetPid, const WCHAR * TargetFileAddress, - WCHAR * CommandLine, + const WCHAR * CommandLine, BOOLEAN RunCallbackAtTheFirstInstruction); BOOLEAN @@ -111,5 +92,35 @@ UdKillProcess(UINT32 TargetPid); BOOLEAN UdDetachProcess(UINT32 TargetPid, UINT64 ProcessDetailToken); +BOOLEAN +UdContinueProcess(UINT64 ProcessDebuggingToken); + BOOLEAN UdPauseProcess(UINT64 ProcessDebuggingToken); + +BOOLEAN +UdSendCommand(UINT64 ProcessDetailToken, + UINT32 ThreadId, + DEBUGGER_UD_COMMAND_ACTION_TYPE ActionType, + PVOID OptionalBuffer, + UINT32 OptionalBufferSize, + BOOLEAN ApplyToAllPausedThreads, + BOOLEAN WaitForEventCompletion, + UINT64 OptionalParam1, + UINT64 OptionalParam2, + UINT64 OptionalParam3, + UINT64 OptionalParam4); + +BOOLEAN +UdSendScriptBufferToProcess(UINT64 ProcessDetailToken, + UINT32 TargetThreadId, + UINT64 BufferAddress, + UINT32 BufferLength, + UINT32 Pointer, + BOOLEAN IsFormat); + +BOOLEAN +UdSendReadRegisterToUserDebugger(UINT64 ProcessDetailToken, + UINT32 TargetThreadId, + PDEBUGGEE_REGISTER_READ_DESCRIPTION RegDes, + UINT32 RegBuffSize); diff --git a/hyperdbg/libhyperdbg/header/export/export.h b/hyperdbg/libhyperdbg/header/export/export.h new file mode 100644 index 00000000..425b8eea --- /dev/null +++ b/hyperdbg/libhyperdbg/header/export/export.h @@ -0,0 +1,26 @@ +/** + * @file export.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief headers for controller of the reversing machine's module + * @details + * @version 0.10 + * @date 2024-06-24 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +// +// Some functions are exported to HyperDbgLibImports.h +// + +VOID +ConnectLocalDebugger(); + +BOOLEAN +ConnectRemoteDebugger(const CHAR * Ip, const CHAR * Port); diff --git a/hyperdbg/hprdbgctrl/header/globals.h b/hyperdbg/libhyperdbg/header/globals/globals.h similarity index 89% rename from hyperdbg/hprdbgctrl/header/globals.h rename to hyperdbg/libhyperdbg/header/globals/globals.h index 8f1e54e8..bf8dfd11 100644 --- a/hyperdbg/hprdbgctrl/header/globals.h +++ b/hyperdbg/libhyperdbg/header/globals/globals.h @@ -11,6 +11,28 @@ */ #pragma once +////////////////////////////////////////////////// +// Module Loading Status // +////////////////////////////////////////////////// + +/** + * @brief shows whether the kernel debugger (KD) module is loaded or not + * + */ +BOOLEAN g_IsKdModuleLoaded = FALSE; + +/** + * @brief shows whether the VMM module is loaded or not + * + */ +BOOLEAN g_IsVmmModuleLoaded = FALSE; + +/** + * @brief shows whether the HyperTrace module is loaded or not + * + */ +BOOLEAN g_IsHyperTraceModuleLoaded = FALSE; + ////////////////////////////////////////////////// // Feature Indicators // ////////////////////////////////////////////////// @@ -295,10 +317,12 @@ DEBUGGER_EVENT_AND_ACTION_RESULT g_DebuggeeResultOfAddingActionsToEvent = { * to write simultaneously but it's needed for write) * */ +#ifdef _WIN32 OVERLAPPED g_OverlappedIoStructureForReadDebugger = {0}; OVERLAPPED g_OverlappedIoStructureForWriteDebugger = {0}; OVERLAPPED g_OverlappedIoStructureForReadDebuggee = {0}; +#endif // _WIN32 /** * @brief Shows whether the queried event is enabled or disabled @@ -330,16 +354,10 @@ CommandType g_CommandsList; UINT64 * g_ScriptGlobalVariables; /** - * @brief Holder of local variables for script engine + * @brief Holder of stack buffer for script engine * */ -UINT64 * g_ScriptLocalVariables; - -/** - * @brief Holder of temp variables for script engine - * - */ -UINT64 * g_ScriptTempVariables; +UINT64 * g_ScriptStackBuffer; /** * @brief Is list of command initialized @@ -347,14 +365,6 @@ UINT64 * g_ScriptTempVariables; */ BOOLEAN g_IsCommandListInitialized = FALSE; -/** - * @brief this variable is used to indicate that modules - * are loaded so we make sure to later use a trace of - * loading in 'unload' command (used in Debugger VMM) - * - */ -BOOLEAN g_IsDebuggerModulesLoaded = FALSE; - /** * @brief State of active debugging thread * @@ -422,6 +432,18 @@ LIST_ENTRY g_OutputSources = {0}; */ TCHAR g_DriverLocation[MAX_PATH] = {0}; +/** + * @brief Holds the name of the driver to install it + * + */ +TCHAR g_DriverName[MAX_PATH] = {0}; + +/** + * @brief Whether the user wants to use a custom driver location or not + * + */ +BOOLEAN g_UseCustomDriverLocation = FALSE; + /** * @brief Holds the location test-hyperdbg.exe * @@ -435,13 +457,19 @@ TCHAR g_TestLocation[MAX_PATH] = {0}; * messages * */ -Callback g_MessageHandler = 0; +PVOID g_MessageHandler = 0; /** - * @brief Shows whether the vmxoff process start or not + * @brief The shared buffer for the handler of ShowMessages function * */ -BOOLEAN g_IsVmxOffProcessStart; +PVOID g_MessageHandlerSharedBuffer = 0; + +/** + * @brief Shows whether the message logging window is closed or not + * + */ +BOOLEAN g_IsMessageLoggingWindowClosed; /** * @brief Holds the global handle of device which is used @@ -542,6 +570,11 @@ UINT64 g_RdtscMedian = 0; */ BOOLEAN g_IsInstrumentingInstructions = FALSE; +/** + * @brief Shows the kernel base address + */ +UINT64 g_KernelBaseAddress; + ////////////////////////////////////////////////// // Settings // ////////////////////////////////////////////////// @@ -646,3 +679,31 @@ UINT64 g_CurrentExprEvalResult; * */ BOOLEAN g_CurrentExprEvalResultHasError; + +////////////////////////////////////////////////// +// hwdbg // +////////////////////////////////////////////////// + +/** + * @brief Instance information of the current hwdbg debuggee + * + */ +HWDBG_INSTANCE_INFORMATION g_HwdbgInstanceInfo; + +/** + * @brief Shows whether the instance info is valid (received) or not + * + */ +BOOLEAN g_HwdbgInstanceInfoIsValid; + +/** + * @brief Ports configuration of hwdbg + * + */ +std::vector g_HwdbgPortConfiguration; + +/** + * @brief Holder of pins (and ports) status of hwdbg + * + */ +UINT64 * g_HwdbgPinsStatus; diff --git a/hyperdbg/libhyperdbg/header/hwdbg/hwdbg-interpreter.h b/hyperdbg/libhyperdbg/header/hwdbg/hwdbg-interpreter.h new file mode 100644 index 00000000..fc823d56 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/hwdbg/hwdbg-interpreter.h @@ -0,0 +1,58 @@ +/** + * @file hwdbg-interpreter.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for the interpreter of hwdbg packets and requests + * @details + * @version 0.10 + * @date 2024-06-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +HwdbgShowIntanceInfo(HWDBG_INSTANCE_INFORMATION * InstanceInfo); + +BOOLEAN +HwdbgInterpretPacket(PVOID BufferReceived, UINT32 LengthReceived); + +BOOLEAN +HwdbgInterpreterFillFileFromMemory( + HWDBG_INSTANCE_INFORMATION * InstanceInfo, + const TCHAR * FileName, + UINT32 * MemoryBuffer, + SIZE_T BufferSize, + HWDBG_ACTION_ENUMS RequestedAction); + +BOOLEAN +HwdbgInterpreterFillMemoryFromFile(const TCHAR * FileName, + UINT32 * MemoryBuffer, + SIZE_T BufferSize); + +SIZE_T +HwdbgComputeNumberOfFlipFlopsNeeded( + HWDBG_INSTANCE_INFORMATION * InstanceInfo, + UINT32 NumberOfStages); + +BOOLEAN +HwdbgInterpreterSendPacketAndBufferToHwdbg(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + const TCHAR * FileName, + DEBUGGER_REMOTE_PACKET_TYPE PacketType, + HWDBG_ACTION_ENUMS RequestedAction, + CHAR * Buffer, + UINT32 BufferLength); + +BOOLEAN +HwdbgReadInstanceInfoFromFile(const TCHAR * FileName, UINT32 * MemoryBuffer, SIZE_T BufferSize); + +BOOLEAN +HwdbgWriteTestInstanceInfoRequestIntoFile(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + const CHAR * FileName); + +BOOLEAN +HwdbgLoadInstanceInfo(const TCHAR * InstanceFilePathToRead, UINT32 InitialBramBufferSize); diff --git a/hyperdbg/libhyperdbg/header/hwdbg/hwdbg-scripts.h b/hyperdbg/libhyperdbg/header/hwdbg/hwdbg-scripts.h new file mode 100644 index 00000000..3169b050 --- /dev/null +++ b/hyperdbg/libhyperdbg/header/hwdbg/hwdbg-scripts.h @@ -0,0 +1,44 @@ +/** + * @file hwdbg-scripts.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for the hardware scripts for hwdbg + * @details + * @version 0.11 + * @date 2024-09-30 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +VOID +HwdbgScriptPrintScriptBuffer(CHAR * ScriptBuffer, UINT32 ScriptBufferSize); + +BOOLEAN +HwdbgScriptCreateHwdbgScript(CHAR * ScriptBuffer, + UINT32 ScriptBufferSize, + const TCHAR * HardwareScriptFilePathToSave); + +BOOLEAN +HwdbgScriptSendScriptPacket(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + const TCHAR * FileName, + UINT32 NumberOfSymbols, + HWDBG_SHORT_SYMBOL * Buffer, + UINT32 BufferLength); + +BOOLEAN +HwdbgScriptGetScriptBufferFromRawString(string ScriptString, + PVOID * CodeBuffer, + UINT64 * BufferAddress, + UINT32 * BufferLength, + UINT32 * Pointer); + +BOOLEAN +HwdbgScriptRunScript(const CHAR * Script, + const TCHAR * InstanceFilePathToRead, + const TCHAR * HardwareScriptFilePathToSave, + UINT32 InitialBramBufferSize); diff --git a/hyperdbg/hprdbgctrl/header/objects.h b/hyperdbg/libhyperdbg/header/objects/objects.h similarity index 100% rename from hyperdbg/hprdbgctrl/header/objects.h rename to hyperdbg/libhyperdbg/header/objects/objects.h diff --git a/hyperdbg/hprdbgctrl/header/rev-ctrl.h b/hyperdbg/libhyperdbg/header/rev/rev-ctrl.h similarity index 100% rename from hyperdbg/hprdbgctrl/header/rev-ctrl.h rename to hyperdbg/libhyperdbg/header/rev/rev-ctrl.h diff --git a/hyperdbg/hprdbgctrl/hprdbgctrl.vcxproj b/hyperdbg/libhyperdbg/libhyperdbg.vcxproj similarity index 70% rename from hyperdbg/hprdbgctrl/hprdbgctrl.vcxproj rename to hyperdbg/libhyperdbg/libhyperdbg.vcxproj index 34c460dc..cd1d0655 100644 --- a/hyperdbg/hprdbgctrl/hprdbgctrl.vcxproj +++ b/hyperdbg/libhyperdbg/libhyperdbg.vcxproj @@ -14,21 +14,21 @@ 16.0 {809C3AD5-3211-4992-A472-9D81D124C5FA} Win32Proj - hprdbgctrl + libhyperdbg 10.0 DynamicLibrary true - v143 + v145 NotSet false DynamicLibrary false - v143 + v145 true NotSet false @@ -48,14 +48,14 @@ - HPRDBGCTRL + libhyperdbg true $(SolutionDir)build\bin\$(Configuration)\ $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ true - HPRDBGCTRL + libhyperdbg false $(SolutionDir)build\bin\$(Configuration)\ $(SolutionDir)build\obj\$(ProjectName)\$(Platform)\$(Configuration)\ @@ -68,25 +68,28 @@ ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;WINVER=0x0502;_WIN32_WINNT=0x0502;NTDDI_VERSION=0x05020000;WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_WARNINGS;HPRDBGCTRL_EXPORTS;_USRDLL;%(PreprocessorDefinitions) true pch.h - $(SolutionDir)\dependencies\phnt;$(SolutionDir)\dependencies;$(SolutionDir)\dependencies\zydis\dependencies\zycore\include;$(SolutionDir)\include;$(SolutionDir)\dependencies\zydis\include;$(SolutionDir)\hprdbgctrl;$(SolutionDir)\script-eval;%(AdditionalIncludeDirectories) + $(SolutionDir)\dependencies\phnt;$(SolutionDir)\dependencies;$(SolutionDir)\dependencies\zydis\dependencies\zycore\include;$(SolutionDir)\include;$(SolutionDir)\dependencies\zydis\include;$(SolutionDir)\libhyperdbg;$(SolutionDir)\script-eval;$(SolutionDir)\dependencies\keystone\include;%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp true + stdcpp20 Windows true false - $(SolutionDir)libraries\zydis\user\Zycore.lib;$(SolutionDir)libraries\zydis\user\Zydis.lib;$(SolutionDir)build\bin\$(Configuration)\script-engine.lib;%(AdditionalDependencies) + $(SolutionDir)libraries\zydis\user\Zycore.lib;$(SolutionDir)libraries\zydis\user\Zydis.lib;$(SolutionDir)build\bin\$(Configuration)\script-engine.lib;$(SolutionDir)libraries\keystone\$(Configuration)-lib\keystone.lib;$(SolutionDir)libraries\libipt\libipt.lib;%(AdditionalDependencies) %(AdditionalLibraryDirectories) - true + false - msbuild "$(SolutionDir)dependencies\zydis\msvc\Zydis.sln" /m /p:Configuration="Release MT" /p:Platform=$(Platform) /target:zydis /target:zycore /p:OutDir="$(SolutionDir)libraries\zydis\user" + copy "$(SolutionDir)libraries\libipt\libipt.lib" "$(OutDir)" +copy "$(SolutionDir)libraries\libipt\libipt.dll" "$(OutDir)" +msbuild "$(SolutionDir)dependencies\zydis\msvc\Zydis.sln" /m /p:Configuration="Release MT" /p:Platform=$(Platform) /target:zydis /target:zycore /p:OutDir="$(SolutionDir)libraries\zydis\user" @@ -100,10 +103,12 @@ ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;WINVER=0x0502;_WIN32_WINNT=0x0502;NTDDI_VERSION=0x05020000;WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_WARNINGS;HPRDBGCTRL_EXPORTS;_USRDLL;%(PreprocessorDefinitions) true pch.h - $(SolutionDir)\dependencies\phnt;$(SolutionDir)\dependencies;$(SolutionDir)\dependencies\zydis\dependencies\zycore\include;$(SolutionDir)\include;$(SolutionDir)\dependencies\zydis\include;$(SolutionDir)\hprdbgctrl;$(SolutionDir)\script-eval;%(AdditionalIncludeDirectories) + $(SolutionDir)\dependencies\phnt;$(SolutionDir)\dependencies;$(SolutionDir)\dependencies\zydis\dependencies\zycore\include;$(SolutionDir)\include;$(SolutionDir)\dependencies\zydis\include;$(SolutionDir)\libhyperdbg;$(SolutionDir)\script-eval;$(SolutionDir)\dependencies\keystone\include;%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp true + stdcpp20 + MaxSpeed Windows @@ -111,7 +116,7 @@ true true false - $(SolutionDir)libraries\zydis\user\Zycore.lib;$(SolutionDir)libraries\zydis\user\Zydis.lib;$(SolutionDir)build\bin\$(Configuration)\script-engine.lib;%(AdditionalDependencies) + $(SolutionDir)libraries\zydis\user\Zycore.lib;$(SolutionDir)libraries\zydis\user\Zydis.lib;$(SolutionDir)build\bin\$(Configuration)\script-engine.lib;$(SolutionDir)libraries\keystone\$(Configuration)-lib\keystone.lib;$(SolutionDir)libraries\libipt\libipt.lib;%(AdditionalDependencies) %(AdditionalLibraryDirectories) true @@ -120,49 +125,95 @@ - msbuild "$(SolutionDir)dependencies\zydis\msvc\Zydis.sln" /m /p:Configuration="Release MT" /p:Platform=$(Platform) /target:zydis /target:zycore /p:OutDir="$(SolutionDir)libraries\zydis\user" + copy "$(SolutionDir)libraries\libipt\libipt.lib" "$(OutDir)" +copy "$(SolutionDir)libraries\libipt\libipt.dll" "$(OutDir)" +msbuild "$(SolutionDir)dependencies\zydis\msvc\Zydis.sln" /m /p:Configuration="Release MT" /p:Platform=$(Platform) /target:zydis /target:zycore /p:OutDir="$(SolutionDir)libraries\zydis\user" - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -174,10 +225,14 @@ + + + + @@ -185,6 +240,9 @@ + + + @@ -192,9 +250,8 @@ Create - + - @@ -225,7 +282,6 @@ - diff --git a/hyperdbg/hprdbgctrl/hprdbgctrl.vcxproj.filters b/hyperdbg/libhyperdbg/libhyperdbg.vcxproj.filters similarity index 62% rename from hyperdbg/hprdbgctrl/hprdbgctrl.vcxproj.filters rename to hyperdbg/libhyperdbg/libhyperdbg.vcxproj.filters index 5eeede46..492c7f91 100644 --- a/hyperdbg/hprdbgctrl/hprdbgctrl.vcxproj.filters +++ b/hyperdbg/libhyperdbg/libhyperdbg.vcxproj.filters @@ -69,70 +69,214 @@ {4d49c742-e10d-4d2b-9178-e65c665c99a0} + + {0467199d-cfbb-4020-a550-48df489d65e0} + + + {81ab704c-2463-4499-867a-f259a77bd2ab} + + + {00b0ccc1-7b0a-431a-9b01-8aff285f14cb} + + + {a27149ec-f7ce-4356-998f-79bd2a7e7961} + + + {cfacdcfe-8503-4a00-b7e2-75b0e906f75e} + + + {223523be-9b81-41cc-b708-872e292fd1f5} + + + {8e3c36aa-4263-4c94-9910-884ad9652921} + + + {5b7dcc48-4010-40db-973f-bf46eb1e810b} + + + {b6d17c7a-e6e7-490b-b581-c6a06d0d61a9} + + + {a5552ded-23bb-45ad-85c2-d8d85a5b4e49} + + + {da7e68cc-540c-4efc-b4de-c23b4b13e2ec} + + + {d6010267-4888-46f5-9bdb-2339565710d2} + + + {e81c07d3-5e98-4bdb-a00b-2b99e023553c} + + + {477d3059-08d7-433b-83c3-bbf57658deaf} + + + {559b68f3-8bf0-447a-a714-0e355c22516f} + + + {88de3dbf-90ab-47ef-94fe-8c21ce73c9f1} + + + {c1f438ff-fd3b-4fb4-989b-f145290e3837} + + + {c5b26259-abcc-459f-9b7e-fd90c34ad646} + + + {99425a01-168c-4b6b-a53f-d62fbb7c8cab} + + + {c7f85132-1802-4462-990f-3fffb0365dbc} + + + {4f4eca9f-c1f6-4342-91ef-2b533292e238} + + + {bde7408e-fad9-4329-98ac-e604674f7bbf} + + + {06e9888f-57f0-4d59-8f7e-1fdd336be9cc} + + + {0d88d581-8ff4-40f2-8585-3fdb97d4d211} + + + {439dcb49-1825-4076-affe-17b505e4033a} + + + {16331b3c-c8fd-4b12-abb4-7617d21db9d0} + + + {2d2c16a6-3fdc-4b63-a282-f2762a1f340d} + + + {9dcff6b3-9ebd-46f3-a0c5-c69d06357949} + + + {3e4dda9f-6050-409f-85e2-4cf7c8a95743} + header - - header + + header\platform - - header + + header\platform - - header + + header\platform - - header + + header\platform - - header + + header\platform - - header + + header\platform - - header + + header\platform - - header + + header\platform\windows-only - - header + + header\components\pe - - header + + header\app - - header + + header\app - - header + + header\app - - header + + header\common - - header + + header\common - - header + + header\export - - header + + header\globals - - header + + header\hwdbg - - header + + header\hwdbg - - header + + header\rev - - header + + header\objects + + + header\debugger\commands + + + header\debugger\commands + + + header\debugger\communication + + + header\debugger\communication + + + header\debugger\communication + + + header\debugger\core + + + header\debugger\core + + + header\debugger\driver-loader + + + header\debugger\kernel-level + + + header\debugger\misc + + + header\debugger\misc + + + header\debugger\misc + + + header\debugger\user-level + + + header\debugger\user-level + + + header\debugger\transparency + + + header\debugger\tests + + + header\debugger\script-engine + + + header\debugger\script-engine + + + header\debugger\misc @@ -142,18 +286,12 @@ code\app - + code\app code\common - - code\common - - - code\debugger\commands\debugging-commands - code\debugger\commands\debugging-commands @@ -502,6 +640,102 @@ code\debugger\script-engine + + code\debugger\commands\hwdbg-commands + + + code\hwdbg + + + code\export + + + code\debugger\commands\debugging-commands + + + code\debugger\commands\debugging-commands + + + code\debugger\misc + + + code\debugger\core + + + code\hwdbg + + + code\debugger\commands\hwdbg-commands + + + code\debugger\commands\extension-commands + + + code\debugger\commands\extension-commands + + + code\debugger\commands\extension-commands + + + code\debugger\commands\debugging-commands + + + code\debugger\commands\extension-commands + + + code\debugger\commands\debugging-commands + + + code\debugger\commands\extension-commands + + + code\debugger\commands\extension-commands + + + code\debugger\commands\extension-commands + + + code\debugger\misc + + + code\debugger\commands\extension-commands + + + code\debugger\commands\extension-commands + + + code\debugger\commands\extension-commands + + + code\platform + + + code\platform + + + code\platform + + + code\platform + + + code\platform + + + code\app + + + code\app + + + code\platform\windows-only + + + code\components\pe + + + code\debugger\misc + diff --git a/hyperdbg/hprdbgctrl/pch.cpp b/hyperdbg/libhyperdbg/pch.cpp similarity index 92% rename from hyperdbg/hprdbgctrl/pch.cpp rename to hyperdbg/libhyperdbg/pch.cpp index 92958c22..fa15fce4 100644 --- a/hyperdbg/hprdbgctrl/pch.cpp +++ b/hyperdbg/libhyperdbg/pch.cpp @@ -14,7 +14,7 @@ // // Global variables // -#include "header/globals.h" +#include "header/globals/globals.h" // // When you are using pre-compiled headers, this source file is necessary for diff --git a/hyperdbg/libhyperdbg/pch.h b/hyperdbg/libhyperdbg/pch.h new file mode 100644 index 00000000..6a6eaee8 --- /dev/null +++ b/hyperdbg/libhyperdbg/pch.h @@ -0,0 +1,280 @@ +/** + * @file pch.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief header file corresponding to the pre-compiled header + * @details + * @version 0.1 + * @date 2020-04-11 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +// +// Environment headers +// +#include "platform/general/header/Environment.h" + +// +// Windows SDK headers +// +#define WIN32_LEAN_AND_MEAN + +// +// IA32-doc has structures for the entire intel SDM. +// + +#define USE_LIB_IA32 +#if defined(USE_LIB_IA32) +# pragma warning(push, 0) +// # pragma warning(disable : 4201) // suppress nameless struct/union warning +# include +# pragma warning(pop) +typedef RFLAGS * PRFLAGS; +#endif // USE_LIB_IA32 + +// +// Native API header files for the Process Hacker project. +// +// #define USE__NATIVE_PHNT_HEADERS +#define USE_NATIVE_SDK_HEADERS +#define _AMD64_ + +#ifdef _WIN32 +# if defined(USE__NATIVE_PHNT_HEADERS) + +// +// Dirty fix: the "PCWCHAR" in undefined in "ntrtl.h" so I deifined it here. +// +typedef const wchar_t *LPCWCHAR, *PCWCHAR; + +# define PHNT_MODE PHNT_MODE_USER +# define PHNT_VERSION PHNT_WIN11 // Windows 11 +# define PHNT_PATCH_FOR_HYPERDBG TRUE + +# include +# include + +# elif defined(USE_NATIVE_SDK_HEADERS) + +# include +# include +# include +# include + +# endif + +#endif //_WIN32 + +#ifdef _WIN32 +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif +#include +#include +#include +#include + +// +// STL headers +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Scope definitions +// +#define SCRIPT_ENGINE_USER_MODE +#define HYPERDBG_USER_MODE +#define HYPERDBG_LIBHYPERDBG + +// +// Zydis Debug Disable Flag +// +#ifndef NDEBUG +# define NDEBUG +#endif // !NDEBUG + +// +// HyperDbg defined headers +// +#include "config/Configuration.h" +#include "config/Definition.h" +#include "SDK/HyperDbgSdk.h" + +// +// Keystone +// +#include "keystone/keystone.h" + +// +// Script-engine +// +#include "../script-eval/header/ScriptEngineHeader.h" + +// +// Imports/Exports +// +#include "SDK/imports/user/HyperDbgScriptImports.h" +#include "SDK/imports/user/HyperDbgLibImports.h" + +// +// Platform lib calls (cross-platform wrappers) +// +#include "platform/user/header/platform-lib-calls.h" + +// +// Platform intrinsics (cross-platform CPU instructions and atomic ops) +// +#include "platform/user/header/platform-intrinsics.h" + +// +// Platform serial transport (cross-platform kernel-debugger serial I/O) +// +#include "platform/user/header/platform-serial.h" + +// +// Platform IOCTL transport (cross-platform local kernel-driver device I/O) +// +#include "platform/user/header/platform-ioctl.h" + +// +// Platform signal (cross-platform console-control / CTRL+C handler registration) +// +#include "platform/user/header/platform-signal.h" + +// +// NT-style intrusive linked-list helpers + CONTAINING_RECORD (self-guards to +// non-Windows; Windows gets these from / the native-SDK shim) +// +#include "platform/general/header/nt-list.h" + +// +// Platform-specific intrinsics +// +#ifdef _WIN32 +# include "platform/user/header/windows-only/windows-privilege.h" +#endif + +// +// PCI IDs +// +#include "header/debugger/misc/pci-id.h" + +// +// Intel PT +// +#include "../dependencies/libipt/intel-pt.h" + +// +// General +// +#include "header/app/libhyperdbg.h" +#include "header/export/export.h" +#include "header/debugger/misc/inipp.h" +#include "header/debugger/commands/commands.h" +#include "header/common/common.h" +#include "header/debugger/script-engine/symbol.h" +#include "header/debugger/misc/pt-helper.h" +#include "header/debugger/core/debugger.h" +#include "header/debugger/script-engine/script-engine.h" +#include "header/debugger/commands/help.h" +#ifdef _WIN32 +# include "header/debugger/driver-loader/install.h" +#endif +#include "header/common/list.h" +#include "header/debugger/tests/tests.h" +#include "header/app/messaging.h" +#include "header/app/packets.h" +#include "header/debugger/transparency/transparency.h" +#include "header/debugger/communication/communication.h" +#include "header/debugger/communication/namedpipe.h" +#include "header/debugger/communication/forwarding.h" +#include "header/debugger/kernel-level/kd.h" + +// +// Components +// +#include "../include/components/pe/header/pe-image-reader.h" + +#include "header/debugger/user-level/pe-parser.h" +#include "header/debugger/user-level/ud.h" +#include "header/objects/objects.h" +#include "header/debugger/core/steppings.h" +#include "header/rev/rev-ctrl.h" +#include "header/debugger/misc/assembler.h" + +// +// hwdbg +// +#include "header/hwdbg/hwdbg-interpreter.h" +#include "header/hwdbg/hwdbg-scripts.h" + +// +// Zydis headers +// +#include + +// +// Libraries +// + +#ifdef HYPERDBG_ENV_WINDOWS + +# pragma comment(lib, "ntdll.lib") + +// +// For path combine +// +# pragma comment(lib, "Shlwapi.lib") + +// +// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib +// for tcpclient.cpp and tcpserver.cpp +// +# pragma comment(lib, "Ws2_32.lib") +# pragma comment(lib, "Mswsock.lib") +# pragma comment(lib, "AdvApi32.lib") + +// +// For GetModuleFileNameExA on script-engine for user-mode +// Kernel32.lib is not needed, but seems that it's the library +// for Windows 7 +// +# pragma comment(lib, "Psapi.lib") +# pragma comment(lib, "Kernel32.lib") + +// +// For resolving symbols on Intel PT +// +# pragma comment(lib, "dbghelp.lib") + +#endif // HYPERDBG_ENV_WINDOWS diff --git a/hyperdbg/libraries/DIA/x64/msdia140.dll b/hyperdbg/libraries/DIA/x64/msdia140.dll index a4650510..799c416f 100644 Binary files a/hyperdbg/libraries/DIA/x64/msdia140.dll and b/hyperdbg/libraries/DIA/x64/msdia140.dll differ diff --git a/hyperdbg/libraries/DIA/x64/symsrv.dll b/hyperdbg/libraries/DIA/x64/symsrv.dll index 5e3b5ad3..f4fb438d 100644 Binary files a/hyperdbg/libraries/DIA/x64/symsrv.dll and b/hyperdbg/libraries/DIA/x64/symsrv.dll differ diff --git a/hyperdbg/libraries/DIA/x86/msdia140.dll b/hyperdbg/libraries/DIA/x86/msdia140.dll index adfd67f0..704ceb9e 100644 Binary files a/hyperdbg/libraries/DIA/x86/msdia140.dll and b/hyperdbg/libraries/DIA/x86/msdia140.dll differ diff --git a/hyperdbg/libraries/DIA/x86/symsrv.dll b/hyperdbg/libraries/DIA/x86/symsrv.dll index 4d838919..ebeff2ea 100644 Binary files a/hyperdbg/libraries/DIA/x86/symsrv.dll and b/hyperdbg/libraries/DIA/x86/symsrv.dll differ diff --git a/hyperdbg/libraries/keystone/README.md b/hyperdbg/libraries/keystone/README.md new file mode 100644 index 00000000..98779258 --- /dev/null +++ b/hyperdbg/libraries/keystone/README.md @@ -0,0 +1 @@ +Automatically built from: https://github.com/HyperDbg/keystone/releases/tag/release \ No newline at end of file diff --git a/hyperdbg/libraries/keystone/debug-lib/keystone.lib b/hyperdbg/libraries/keystone/debug-lib/keystone.lib new file mode 100644 index 00000000..87aaef07 Binary files /dev/null and b/hyperdbg/libraries/keystone/debug-lib/keystone.lib differ diff --git a/hyperdbg/libraries/keystone/release-lib/keystone.lib b/hyperdbg/libraries/keystone/release-lib/keystone.lib new file mode 100644 index 00000000..f61ec0b8 Binary files /dev/null and b/hyperdbg/libraries/keystone/release-lib/keystone.lib differ diff --git a/hyperdbg/libraries/libipt/libipt.dll b/hyperdbg/libraries/libipt/libipt.dll new file mode 100644 index 00000000..7c873442 Binary files /dev/null and b/hyperdbg/libraries/libipt/libipt.dll differ diff --git a/hyperdbg/libraries/libipt/libipt.lib b/hyperdbg/libraries/libipt/libipt.lib new file mode 100644 index 00000000..8f04d94f Binary files /dev/null and b/hyperdbg/libraries/libipt/libipt.lib differ diff --git a/hyperdbg/linux/.gitignore b/hyperdbg/linux/.gitignore new file mode 100644 index 00000000..289431e5 --- /dev/null +++ b/hyperdbg/linux/.gitignore @@ -0,0 +1,95 @@ +# +# NOTE! Don't add files that are generated in specific +# subdirectories here. Add them in the ".gitignore" file +# in that subdirectory instead. +# +# NOTE! Please use 'git ls-files -i --exclude-standard' +# command after changing this file, to see if there are +# any tracked files which get ignored after the change. +# +# Normal rules +# +.* +*.o +*.o.* +*.a +*.s +*.ko +*.so +*.so.dbg +*.mod.c +*.i +*.lst +*.symtypes +*.order +modules.builtin +*.elf +*.bin +*.gz +*.bz2 +*.lzma +*.xz +*.lzo +*.patch +*.gcno +*.mod + +# +# Top-level generic files +# +/tags +/TAGS +/linux +/vmlinux +/vmlinuz +/System.map +/Module.markers +Module.symvers + +# +# Debian directory (make deb-pkg) +# +/debian/ + +# +# git files that we don't want to ignore even it they are dot-files +# +!.gitignore +!.mailmap + +# +# Generated include files +# +include/config +include/linux/version.h +include/generated +arch/*/include/generated + +# stgit generated dirs +patches-* + +# quilt's files +patches +series + +# cscope files +cscope.* +ncscope.* + +# gnu global files +GPATH +GRTAGS +GSYMS +GTAGS + +*.orig +*~ +\#*# + +# +# Leavings from module signing +# +extra_certificates +signing_key.priv +signing_key.x509 +x509.genkey diff --git a/hyperdbg/linux/README.md b/hyperdbg/linux/README.md new file mode 100644 index 00000000..7071f314 --- /dev/null +++ b/hyperdbg/linux/README.md @@ -0,0 +1,51 @@ +# HyperDbg for Linux + +## Status + +⚠️ **HyperDbg for Linux is not yet ready.** + +Linux is currently **not supported**. + +We are in the process of porting HyperDbg to Linux. This effort is ongoing and may take some time to complete. + +# Contributing to the Linux Port + +HyperDbg is being ported from Windows to Linux. The work is incremental: most +of the codebase compiles file-by-file as the Win32-specific calls get replaced +with a platform-independent interface. + +## Building + +```bash +cmake . # generate the Makefiles +make # build +``` + +Run these from the repo root (or the relevant subdirectory). `cmake .` only +needs to be re-run when the CMake files change; otherwise `make` is enough. + +## How to contribute + +The port progresses one source file at a time. To pick up work: + +1. Build and find the next file that fails to compile. +2. Go through it and make it Linux-compatible. +3. Where the code calls Windows-only APIs (serial, registry, signals, + threads, etc.), don't `#ifdef` inline — route the call through the + **platform-independent interface** so both Windows and Linux share the same + call site with separate backing implementations. +4. Rebuild until the file is clean, then move to the next one. + +## The platform interface + +User-mode abstractions live in `include/platform/user/` (`header/` for the +interface, `code/` for the implementations). See existing examples such as +`platform-serial`, `platform-signal`, and `platform-ioctl` for the pattern to +follow. Kernel-mode equivalents are under `include/platform/kernel/`. + +## Guidelines + +- Keep platform-specific code behind the platform abstraction, not scattered + through the logic. +- Match the surrounding code's style and conventions. +- Build before submitting — every changed file should compile. \ No newline at end of file diff --git a/hyperdbg/linux/mock/kernel/.gitignore b/hyperdbg/linux/mock/kernel/.gitignore new file mode 100644 index 00000000..69180853 --- /dev/null +++ b/hyperdbg/linux/mock/kernel/.gitignore @@ -0,0 +1,7 @@ +# Ignore all C source and header files copied into this directory +*.c +*.h + +# Except the files that permanently live here +!mock.c +!pch.h \ No newline at end of file diff --git a/hyperdbg/linux/mock/kernel/Makefile b/hyperdbg/linux/mock/kernel/Makefile new file mode 100644 index 00000000..b8e5c4e6 --- /dev/null +++ b/hyperdbg/linux/mock/kernel/Makefile @@ -0,0 +1,27 @@ +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) +obj-m := HyperDbg.o +HyperDbg-objs := mock.o \ + PlatformMem.o \ + PlatformIntrinsicsVmx.o \ + PlatformIntrinsics.o + +ccflags-y += -I$(PWD)/../../../include +ccflags-y += -I$(PWD)/../../../include/platform/kernel/header +ccflags-y += -I$(PWD)/../../../include/platform/kernel/code + +all: clean PlatformMem.c PlatformIntrinsicsVmx.c PlatformIntrinsics.c + $(MAKE) -C $(KDIR) M=$(PWD) modules + +PlatformMem.c: + cp ../../../include/platform/kernel/code/PlatformMem.c $(PWD)/PlatformMem.c +PlatformIntrinsics.c: + cp ../../../include/platform/kernel/code/PlatformIntrinsics.c $(PWD)/PlatformIntrinsics.c +PlatformIntrinsicsVmx.c: + cp ../../../include/platform/kernel/code/PlatformIntrinsicsVmx.c $(PWD)/PlatformIntrinsicsVmx.c + +clean: + $(MAKE) -C $(KDIR) M=$(PWD) clean + rm -f $(PWD)/PlatformMem.c + rm -f $(PWD)/PlatformIntrinsics.c + rm -f $(PWD)/PlatformIntrinsicsVmx.c \ No newline at end of file diff --git a/hyperdbg/linux/mock/kernel/README.md b/hyperdbg/linux/mock/kernel/README.md new file mode 100644 index 00000000..37864ebf --- /dev/null +++ b/hyperdbg/linux/mock/kernel/README.md @@ -0,0 +1,92 @@ +# HyperDbg Linux Kernel Module + +This directory contains a Linux kernel module that demonstrates and tests the +cross-platform memory management APIs (`PlatformMem.c`) from the HyperDbg project. + +The module provides a simple test harness (`mock.c`) that exercises memory +allocation, copy, and deallocation functions in kernel space + +--- +## Prerequisites +Before building the module, ensure you have the necessary development tools +and kernel headers installed: + +```bash +# Install build essentials and kernel module utilities +sudo apt-get update +sudo apt-get install build-essential kmod + +# Install kernel headers for your running kernel +sudo apt-get install linux-headers-`uname -r` +``` + +--- +# project structure + +``` +hyperdbg/ + ├── include/ + │ └── platform/ + │ └── kernel/ + │ ├── header/ + │ └── code/ + └── linux/ + └── mock/ + ├── Makefile + ├── mock.c + └── HyperDbg.ko + +``` + + + +--- +## Build the Module +```bash +cd hyperdbg/linux/mock +``` + +then build module: +```bash +make +``` + +If successful, this will generate: + +```bash +HyperDbg.ko +``` +--- +# Load the Module + +to insert the module into the kernel: + +```bash +sudo insmod HyperDbg.ko +``` + +--- +# Verify Module Loaded Successfully + +you can use `lsmod` : +```bash +lsmod | grep HyperDbg +``` + +or you can inspect kernel module: +```bash +sudo dmesg | tail -10 +``` +--- +# Remove the Module +```bash +sudo rmmod HyperDbg +``` + +--- + +# finally you can clean project: +```bash +make clean +``` + diff --git a/hyperdbg/linux/mock/kernel/mock.c b/hyperdbg/linux/mock/kernel/mock.c new file mode 100644 index 00000000..47d0d516 --- /dev/null +++ b/hyperdbg/linux/mock/kernel/mock.c @@ -0,0 +1,104 @@ +/** + * @file mock.c + * @author Alireza moradi (alish014) + * @brief Mock Linux kernel module for testing cross-platform memory APIs. + * @details This file demonstrates the usage of the unified Platform* memory + * API (Allocate, Write, Set, Free) within a Linux kernel module environment. + * @version 0.18 + * @date 2026-02-05 + * + * @copyright This project is released under the GNU Public License v3. + */ +#include "pch.h" + +/** + * @brief Global pointer to the allocated test buffer. + * @details Stores the address returned by PlatformAllocateMemory so it can be + * freed when the module unloads. + */ +static PVOID g_AllocatedBuffer = NULL; + +/** + * @brief Size of the buffer to allocate during tests. + * @note Default size is 4096 bytes (1 page). + */ +static SIZE_T g_BufferSize = 4096; + +/** + * @brief Module initialization entry point. + * + * @details Performs the following test sequence: + * 1. Allocates memory using the cross-platform wrapper. + * 2. Copies a test string into the allocated memory. + * 3. Prints the content to the kernel log. + * 4. Zeroes out the memory contents. + * + * @return int + * - 0: Initialization successful. + * - -ENOMEM: Memory allocation failed. + */ +static int __init +mock_init(void) +{ + char source_data[] = "This is a test string from Linux kernel module"; + + printk(KERN_INFO "Mock module loading\n"); + + // 1. Allocation + g_AllocatedBuffer = PlatformAllocateMemory(g_BufferSize); + if (!g_AllocatedBuffer) + return -ENOMEM; + + // 2. Copying (Write Memory) + // We pass NULL for 'Process' as the current implementation targets local kernel memory. + PlatformWriteMemory(g_AllocatedBuffer, source_data, sizeof(source_data)); + + printk(KERN_INFO "Copied data: %s\n", (char *)g_AllocatedBuffer); + + // 3. Zeroing (Set Memory) + PlatformSetMemory(g_AllocatedBuffer, 0, g_BufferSize); + + printk(KERN_INFO "Buffer zeroed\n"); + + ///////////////////////////////////////////////////////////////////////////////////// + // Test codes (should be removed if running this kernel module) + // + + VmxVmread64(0, 0); // Just to test the intrinsic wrapper compiles and links correctly + + CpuReadMsr(0x1); // Just to test the intrinsic wrapper compiles and links correctly + + ///////////////////////////////////////////////////////////////////////////////////// + + return 0; +} + +/** + * @brief Module cleanup/exit entry point. + * + * @details Frees the global buffer allocated during initialization to prevent + * memory leaks. + * + * @return void + */ +static void __exit +mock_exit(void) +{ + printk(KERN_INFO "Mock module unloading\n"); + + // 4. Freeing + if (g_AllocatedBuffer) + { + PlatformFreeMemory(g_AllocatedBuffer); + g_AllocatedBuffer = NULL; // Good practice to nullify after free + } +} + +// Register entry and exit points +module_init(mock_init); +module_exit(mock_exit); + +// Module Metadata +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alireza Moradi"); +MODULE_DESCRIPTION("Cross-platform memory API test module"); diff --git a/hyperdbg/linux/mock/kernel/pch.h b/hyperdbg/linux/mock/kernel/pch.h new file mode 100644 index 00000000..d581b542 --- /dev/null +++ b/hyperdbg/linux/mock/kernel/pch.h @@ -0,0 +1,39 @@ +/** + * @file pch.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Pre-compiled headers for Linux mock + * @details + * @version 0.19 + * @date 2026-04-27 + * + * @copyright This project is released under the GNU Public License v3. + * + */ + +// +// Scope definitions +// +#define HYPERDBG_KERNEL_MODE +#define HYPERDBG_LINUX + +// +// General Linux driver headers +// +#include + +// +// SDK headers +// +#include "../../../include/SDK/HyperDbgSdk.h" + +// +// Environment headers +// +#include "../../../include/platform/general/header/Environment.h" + +// +// Platform headers +// +#include "../../../include/platform/kernel/header/PlatformMem.h" +#include "../../../include/platform/kernel/header/PlatformIntrinsics.h" +#include "../../../include/platform/kernel/header/PlatformIntrinsicsVmx.h" diff --git a/hyperdbg/linux/mock/user/Makefile b/hyperdbg/linux/mock/user/Makefile new file mode 100644 index 00000000..229a6c0c --- /dev/null +++ b/hyperdbg/linux/mock/user/Makefile @@ -0,0 +1,27 @@ +CC = gcc +PWD := $(shell pwd) +CFLAGS = -Wall -Wextra -std=c11 -O2 +CFLAGS += -I$(PWD)/../../../include +CFLAGS += -I$(PWD)/../../../include/platform/user/header +CFLAGS += -I$(PWD)/../../../include/platform/user/code +TARGET = mock +SRCS = mock.c \ + platform-intrinsics.c +OBJS = $(SRCS:.c=.o) + +.PHONY: all clean + +all: clean platform-intrinsics.c $(TARGET) + +$(TARGET): $(OBJS) + $(CC) $(CFLAGS) -o $@ $^ + +%.o: %.c pch.h + $(CC) $(CFLAGS) -c -o $@ $< + +platform-intrinsics.c: + cp $(PWD)/../../../include/platform/user/code/platform-intrinsics.c $(PWD)/platform-intrinsics.c + +clean: + rm -f $(OBJS) $(TARGET) + rm -f $(PWD)/platform-intrinsics.c \ No newline at end of file diff --git a/hyperdbg/linux/mock/user/README.md b/hyperdbg/linux/mock/user/README.md new file mode 100644 index 00000000..3fa5fc70 --- /dev/null +++ b/hyperdbg/linux/mock/user/README.md @@ -0,0 +1,53 @@ +# mock — HyperDbg Hello World + +A minimal user-mode Linux application that prints **"Hello world HyperDbg!"** to stdout and imports HyperDbg SDK. + +--- + +--- + +## Requirements + +- GCC (any reasonably recent version) +- GNU Make +- Linux (user-mode, no special privileges needed) + +Install on Debian/Ubuntu: + +```bash +sudo apt update && sudo apt install build-essential +``` + +--- + +## Build + +```bash +make +``` + +This compiles `mock.c` into an executable called `mock`. + +--- + +## Run + +```bash +./mock +``` + +Expected output: + +``` +Hello world HyperDbg! +``` + +--- + +## Clean + +Remove compiled objects and the binary: + +```bash +make clean +``` diff --git a/hyperdbg/linux/mock/user/mock.c b/hyperdbg/linux/mock/user/mock.c new file mode 100644 index 00000000..fea47233 --- /dev/null +++ b/hyperdbg/linux/mock/user/mock.c @@ -0,0 +1,29 @@ +/** + * @file mock.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Mock user-mode application for testing the HyperDbg + * @details + * @version 0.19 + * @date 2026-04-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +int +main(void) +{ + printf("Hello world HyperDbg!\n"); + + ////////////////////////////////////////////////////////////// + // + // Test for working intrinsics + // + CpuReadTsc(); + CpuCpuId(NULL, 0); + + ////////////////////////////////////////////////////////////// + + return 0; +} diff --git a/hyperdbg/linux/mock/user/pch.h b/hyperdbg/linux/mock/user/pch.h new file mode 100644 index 00000000..6bc2c282 --- /dev/null +++ b/hyperdbg/linux/mock/user/pch.h @@ -0,0 +1,37 @@ +/** + * @file mock.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Header for the mock user-mode application for testing the HyperDbg + * @details + * @version 0.19 + * @date 2026-04-28 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#ifndef PCH_H +#define PCH_H + +// +// Scope definitions +// +#define HYPERDBG_USER_MODE +#define HYPERDBG_LINUX + +#include +#include +#include +#include +#include + +// +// SDK headers +// +#include "../../../include/SDK/HyperDbgSdk.h" + +// +// Platform headers +// +#include "../../../include/platform/user/header/platform-intrinsics.h" + +#endif // PCH_H diff --git a/hyperdbg/miscellaneous/constants/pciid b/hyperdbg/miscellaneous/constants/pciid new file mode 160000 index 00000000..7c8139ba --- /dev/null +++ b/hyperdbg/miscellaneous/constants/pciid @@ -0,0 +1 @@ +Subproject commit 7c8139ba5032bf40daad23628c3ed8abe7cbb4ef diff --git a/hyperdbg/script-engine/CMakeLists.txt b/hyperdbg/script-engine/CMakeLists.txt new file mode 100644 index 00000000..85623bea --- /dev/null +++ b/hyperdbg/script-engine/CMakeLists.txt @@ -0,0 +1,25 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "../include/platform/general/header/Environment.h" + "header/common.h" + "header/globals.h" + "header/parse-table.h" + "header/scanner.h" + "header/script-engine.h" + "header/type.h" + "header/pch.h" + "code/common.c" + "code/globals.c" + "code/parse-table.c" + "code/scanner.c" + "code/script-engine.c" + "code/type.c" + "code/pch.c" +) +include_directories( + "header" + "../include" + "." + "../script-eval" +) +add_library(script-engine SHARED ${SourceFiles}) diff --git a/hyperdbg/script-engine/code/common.c b/hyperdbg/script-engine/code/common.c index 974afee1..33118985 100644 --- a/hyperdbg/script-engine/code/common.c +++ b/hyperdbg/script-engine/code/common.c @@ -14,17 +14,17 @@ /** * @brief Allocates a new token * - * @return Token + * @return PSCRIPT_ENGINE_TOKEN the allocated new unknown token */ -PTOKEN +PSCRIPT_ENGINE_TOKEN NewUnknownToken() { - PTOKEN Token; + PSCRIPT_ENGINE_TOKEN Token; // // Allocate memory for token and its value // - Token = (PTOKEN)malloc(sizeof(TOKEN)); + Token = (PSCRIPT_ENGINE_TOKEN)malloc(sizeof(SCRIPT_ENGINE_TOKEN)); if (Token == NULL) { @@ -49,20 +49,29 @@ NewUnknownToken() // Init fields // strcpy(Token->Value, ""); - Token->Type = UNKNOWN; - Token->Len = 0; - Token->MaxLen = TOKEN_VALUE_MAX_LEN; + Token->Type = UNKNOWN; + Token->Len = 0; + Token->MaxLen = TOKEN_VALUE_MAX_LEN; + Token->VariableType = (VARIABLE_TYPE *)VARIABLE_TYPE_LONG; + Token->VariableMemoryIdx = 0; return Token; } -PTOKEN -NewToken(TOKEN_TYPE Type, char * Value) +/** + * @brief Allocates a new token with given type and value + * + * @param Type the type of the token + * @param Value the value string of the token + * @return PSCRIPT_ENGINE_TOKEN the allocated new token + */ +PSCRIPT_ENGINE_TOKEN +NewToken(SCRIPT_ENGINE_TOKEN_TYPE Type, char * Value) { // // Allocate memory for token] // - PTOKEN Token = (PTOKEN)malloc(sizeof(TOKEN)); + PSCRIPT_ENGINE_TOKEN Token = (PSCRIPT_ENGINE_TOKEN)malloc(sizeof(SCRIPT_ENGINE_TOKEN)); if (Token == NULL) { @@ -75,11 +84,13 @@ NewToken(TOKEN_TYPE Type, char * Value) // // Init fields // - unsigned int Len = (unsigned int)strlen(Value); - Token->Type = Type; - Token->Len = Len; - Token->MaxLen = Len; - Token->Value = (char *)calloc(Token->MaxLen + 1, sizeof(char)); + unsigned int Len = (unsigned int)strlen(Value); + Token->Type = Type; + Token->Len = Len; + Token->MaxLen = Len; + Token->Value = (char *)calloc(Token->MaxLen + 1, sizeof(char)); + Token->VariableType = (VARIABLE_TYPE *)VARIABLE_TYPE_LONG; + Token->VariableMemoryIdx = 0; if (Token->Value == NULL) { @@ -99,9 +110,10 @@ NewToken(TOKEN_TYPE Type, char * Value) * @brief Removes allocated memory of a token * * @param Token + * @return void */ void -RemoveToken(PTOKEN * Token) +RemoveToken(PSCRIPT_ENGINE_TOKEN * Token) { free((*Token)->Value); free(*Token); @@ -111,12 +123,13 @@ RemoveToken(PTOKEN * Token) /** * @brief Prints token - * @detail prints value and type of token + * @details prints value and type of token * - * @param Token + * @param Token the token to print + * @return void */ void -PrintToken(PTOKEN Token) +PrintToken(PSCRIPT_ENGINE_TOKEN Token) { // // Prints value of the Token @@ -201,20 +214,18 @@ PrintToken(PTOKEN Token) case UNKNOWN: printf(" UNKNOWN>\n"); break; - case INPUT_VARIABLE_TYPE: - printf(" INPUT_VARIABLE_TYPE>\n"); + case SCRIPT_VARIABLE_TYPE: + printf(" SCRIPT_VARIABLE_TYPE>\n"); break; - case HANDLED_VARIABLE_TYPE: - printf(" HANDLED_VARIABLE_TYPE>\n"); - break; - case FUNCTION_TYPE: - printf(" FUNCTION_TYPE>\n"); + case FUNCTION_ID: + printf(" FUNCTION_ID>\n"); break; case FUNCTION_PARAMETER_ID: printf(" FUNCTION_PARAMETER_ID>\n"); break; - case STACK_TEMP: - printf(" STACK_TEMP>\n"); + case DEFERENCE_TEMP: + printf(" DEFERENCE_TEMP>\n"); + break; default: printf(" ERROR>\n"); break; @@ -225,10 +236,11 @@ PrintToken(PTOKEN Token) * @brief Appends char to the token value * * @param Token - * @param char + * @param c the character to append + * @return void */ void -AppendByte(PTOKEN Token, char c) +AppendByte(PSCRIPT_ENGINE_TOKEN Token, char c) { // // Check overflow of the string @@ -266,10 +278,11 @@ AppendByte(PTOKEN Token, char c) * @brief Appends wchar_t to the token value * * @param Token - * @param char + * @param c the wide character to append + * @return void */ void -AppendWchar(PTOKEN Token, wchar_t c) +AppendWchar(PSCRIPT_ENGINE_TOKEN Token, wchar_t c) { // // Check overflow of the string @@ -306,12 +319,13 @@ AppendWchar(PTOKEN Token, wchar_t c) /** * @brief Copies a PTOKEN * - * @return PTOKEN + * @param Token the token to copy + * @return PSCRIPT_ENGINE_TOKEN the copied token */ -PTOKEN -CopyToken(PTOKEN Token) +PSCRIPT_ENGINE_TOKEN +CopyToken(PSCRIPT_ENGINE_TOKEN Token) { - PTOKEN TokenCopy = (PTOKEN)malloc(sizeof(TOKEN)); + PSCRIPT_ENGINE_TOKEN TokenCopy = (PSCRIPT_ENGINE_TOKEN)malloc(sizeof(SCRIPT_ENGINE_TOKEN)); if (TokenCopy == NULL) { @@ -321,10 +335,11 @@ CopyToken(PTOKEN Token) return NULL; } - TokenCopy->Type = Token->Type; - TokenCopy->MaxLen = Token->MaxLen; - TokenCopy->Len = Token->Len; - TokenCopy->Value = (char *)calloc(strlen(Token->Value) + 1, sizeof(char)); + TokenCopy->Type = Token->Type; + TokenCopy->MaxLen = Token->MaxLen; + TokenCopy->Len = Token->Len; + TokenCopy->Value = (char *)calloc(strlen(Token->Value) + 1, sizeof(char)); + TokenCopy->VariableType = Token->VariableType; if (TokenCopy->Value == NULL) { @@ -341,19 +356,19 @@ CopyToken(PTOKEN Token) } /** - * allocates a new TOKEN_LIST + * @brief Allocates a new SCRIPT_ENGINE_TOKEN_LIST * - * @return TOKEN_LIST + * @return PSCRIPT_ENGINE_TOKEN_LIST the allocated token list */ -PTOKEN_LIST +PSCRIPT_ENGINE_TOKEN_LIST NewTokenList(void) { - PTOKEN_LIST TokenList = NULL; + PSCRIPT_ENGINE_TOKEN_LIST TokenList = NULL; // - // Allocation of memory for TOKEN_LIST structure + // Allocation of memory for SCRIPT_ENGINE_TOKEN_LIST structure // - TokenList = (PTOKEN_LIST)malloc(sizeof(*TokenList)); + TokenList = (PSCRIPT_ENGINE_TOKEN_LIST)malloc(sizeof(*TokenList)); if (TokenList == NULL) { @@ -364,28 +379,29 @@ NewTokenList(void) } // - // Initialize fields of TOKEN_LIST + // Initialize fields of SCRIPT_ENGINE_TOKEN_LIST // TokenList->Pointer = 0; TokenList->Size = TOKEN_LIST_INIT_SIZE; // - // Allocation of memory for TOKEN_LIST buffer + // Allocation of memory for SCRIPT_ENGINE_TOKEN_LIST buffer // - TokenList->Head = (PTOKEN *)malloc(TokenList->Size * sizeof(PTOKEN)); + TokenList->Head = (PSCRIPT_ENGINE_TOKEN *)malloc(TokenList->Size * sizeof(PSCRIPT_ENGINE_TOKEN)); return TokenList; } /** - * @brief Removes allocated memory of a TOKEN_LIST + * @brief Removes allocated memory of a SCRIPT_ENGINE_TOKEN_LIST * * @param TokenList + * @return void */ void -RemoveTokenList(PTOKEN_LIST TokenList) +RemoveTokenList(PSCRIPT_ENGINE_TOKEN_LIST TokenList) { - PTOKEN Token; + PSCRIPT_ENGINE_TOKEN Token; for (uintptr_t i = 0; i < TokenList->Pointer; i++) { Token = *(TokenList->Head + i); @@ -401,11 +417,12 @@ RemoveTokenList(PTOKEN_LIST TokenList) * @brief Prints each Token inside a TokenList * * @param TokenList + * @return void */ void -PrintTokenList(PTOKEN_LIST TokenList) +PrintTokenList(PSCRIPT_ENGINE_TOKEN_LIST TokenList) { - PTOKEN Token; + PSCRIPT_ENGINE_TOKEN Token; for (uintptr_t i = 0; i < TokenList->Pointer; i++) { Token = *(TokenList->Head + i); @@ -416,19 +433,19 @@ PrintTokenList(PTOKEN_LIST TokenList) /** * @brief Adds Token to the last empty position of TokenList * - * @param Token - * @param TokenList - * @return TokenList + * @param TokenList the token list to push into + * @param Token the token to add + * @return PSCRIPT_ENGINE_TOKEN_LIST */ -PTOKEN_LIST -Push(PTOKEN_LIST TokenList, PTOKEN Token) +PSCRIPT_ENGINE_TOKEN_LIST +Push(PSCRIPT_ENGINE_TOKEN_LIST TokenList, PSCRIPT_ENGINE_TOKEN Token) { // // Calculate address to write new token // - uintptr_t Head = (uintptr_t)TokenList->Head; - uintptr_t Pointer = (uintptr_t)TokenList->Pointer; - PTOKEN * WriteAddr = (PTOKEN *)(Head + Pointer * sizeof(PTOKEN)); + uintptr_t Head = (uintptr_t)TokenList->Head; + uintptr_t Pointer = (uintptr_t)TokenList->Pointer; + PSCRIPT_ENGINE_TOKEN * WriteAddr = (PSCRIPT_ENGINE_TOKEN *)(Head + Pointer * sizeof(PSCRIPT_ENGINE_TOKEN)); // // Write Token to appropriate address in TokenList @@ -448,7 +465,7 @@ Push(PTOKEN_LIST TokenList, PTOKEN Token) // // Allocate a new buffer for string list with doubled length // - PTOKEN * NewHead = (PTOKEN *)malloc(2 * TokenList->Size * sizeof(PTOKEN)); + PSCRIPT_ENGINE_TOKEN * NewHead = (PSCRIPT_ENGINE_TOKEN *)malloc(2 * TokenList->Size * sizeof(PSCRIPT_ENGINE_TOKEN)); if (NewHead == NULL) { @@ -459,7 +476,7 @@ Push(PTOKEN_LIST TokenList, PTOKEN Token) // // Copy old buffer to new buffer // - memcpy(NewHead, TokenList->Head, TokenList->Size * sizeof(PTOKEN)); + memcpy(NewHead, TokenList->Head, TokenList->Size * sizeof(PSCRIPT_ENGINE_TOKEN)); // // Free old buffer @@ -479,19 +496,19 @@ Push(PTOKEN_LIST TokenList, PTOKEN Token) * @brief Removes last Token of a TokenList and returns it * * @param TokenList - @ @return Token + * @return PSCRIPT_ENGINE_TOKEN */ -PTOKEN -Pop(PTOKEN_LIST TokenList) +PSCRIPT_ENGINE_TOKEN +Pop(PSCRIPT_ENGINE_TOKEN_LIST TokenList) { // // Calculate address to read most recent token // if (TokenList->Pointer > 0) TokenList->Pointer--; // not consider what if the token's type is string or wstring - uintptr_t Head = (uintptr_t)TokenList->Head; - uintptr_t Pointer = (uintptr_t)TokenList->Pointer; - PTOKEN * ReadAddr = (PTOKEN *)(Head + Pointer * sizeof(PTOKEN)); + uintptr_t Head = (uintptr_t)TokenList->Head; + uintptr_t Pointer = (uintptr_t)TokenList->Pointer; + PSCRIPT_ENGINE_TOKEN * ReadAddr = (PSCRIPT_ENGINE_TOKEN *)(Head + Pointer * sizeof(PSCRIPT_ENGINE_TOKEN)); return *ReadAddr; } @@ -500,17 +517,34 @@ Pop(PTOKEN_LIST TokenList) * @brief Returns last Token of a TokenList * * @param TokenList - * @return Token + * @return PSCRIPT_ENGINE_TOKEN */ -PTOKEN -Top(PTOKEN_LIST TokenList) +PSCRIPT_ENGINE_TOKEN +Top(PSCRIPT_ENGINE_TOKEN_LIST TokenList) { // // Calculate address to read most recent pushed token // - uintptr_t Head = (uintptr_t)TokenList->Head; - uintptr_t Pointer = (uintptr_t)TokenList->Pointer - 1; - PTOKEN * ReadAddr = (PTOKEN *)(Head + Pointer * sizeof(PTOKEN)); + uintptr_t Head = (uintptr_t)TokenList->Head; + uintptr_t Pointer = (uintptr_t)TokenList->Pointer - 1; + PSCRIPT_ENGINE_TOKEN * ReadAddr = (PSCRIPT_ENGINE_TOKEN *)(Head + Pointer * sizeof(PSCRIPT_ENGINE_TOKEN)); + + return *ReadAddr; +} + +/** + * @brief Returns the token at a specific index from the top of the token list + * + * @param TokenList the token list to index into + * @param Index the zero-based index from the top + * @return PSCRIPT_ENGINE_TOKEN + */ +PSCRIPT_ENGINE_TOKEN +TopIndexed(PSCRIPT_ENGINE_TOKEN_LIST TokenList, int Index) +{ + uintptr_t Head = (uintptr_t)TokenList->Head; + uintptr_t Pointer = (uintptr_t)TokenList->Pointer - 1 - Index; + PSCRIPT_ENGINE_TOKEN * ReadAddr = (PSCRIPT_ENGINE_TOKEN *)(Head + Pointer * sizeof(PSCRIPT_ENGINE_TOKEN)); return *ReadAddr; } @@ -518,8 +552,8 @@ Top(PTOKEN_LIST TokenList) /** * @brief Checks whether input char belongs to hexadecimal digit-set or not * - * @param char - * @return bool + * @param c the character to check + * @return char */ char IsHex(char c) @@ -533,8 +567,8 @@ IsHex(char c) /** * @brief Checks whether input char belongs to decimal digit-set or not * - * @param char - * @return bool + * @param c the character to check + * @return char */ char IsDecimal(char c) @@ -548,8 +582,8 @@ IsDecimal(char c) /** * @brief Checks whether input char belongs to alphabet set or not * - * @param char - * @return bool + * @param c the character to check + * @return char */ char IsLetter(char c) @@ -562,11 +596,28 @@ IsLetter(char c) } } +/** + * @brief Checks whether input char is underscore (_) or not + * + * @param c the character to check + * @return char + */ +char +IsUnderscore(char c) +{ + if (c >= '_') + return 1; + else + { + return 0; + } +} + /** * @brief Checks whether input char belongs to binary digit-set or not * - * @param char - * @return bool + * @param c the character to check + * @return char */ char IsBinary(char c) @@ -582,8 +633,8 @@ IsBinary(char c) /** * @brief Checks whether input char belongs to octal digit-set or not * - * @param char - * @return bool + * @param c the character to check + * @return char */ char IsOctal(char c) @@ -597,59 +648,20 @@ IsOctal(char c) /** * @brief Allocates a new temporary variable and returns it * - * @param Error - * @return PTOKEN + * @param Error the error type pointer + * @return PSCRIPT_ENGINE_TOKEN */ -PTOKEN -NewTemp(PSCRIPT_ENGINE_ERROR_TYPE Error, PSYMBOL CurrentFunctionSymbol) -{ - if (CurrentFunctionSymbol) - { - return NewStackTemp(Error); - } - else - { - static unsigned int TempID = 0; - int i; - for (i = 0; i < MAX_TEMP_COUNT; i++) - { - if (TempMap[i] == 0) - { - TempID = i; - TempMap[i] = 1; - break; - } - } - if (i == MAX_TEMP_COUNT) - { - *Error = SCRIPT_ENGINE_ERROR_TEMP_LIST_FULL; - } - PTOKEN Temp = NewUnknownToken(); - char TempValue[8]; - sprintf(TempValue, "%d", TempID); - strcpy(Temp->Value, TempValue); - Temp->Type = TEMP; - return Temp; - } -} - -/** - * @brief Allocates a new temporary variable in stack and returns it - * - * @param Error - * @return PTOKEN - */ -PTOKEN -NewStackTemp(PSCRIPT_ENGINE_ERROR_TYPE Error) +PSCRIPT_ENGINE_TOKEN +NewTemp(PSCRIPT_ENGINE_ERROR_TYPE Error) { static unsigned int TempID = 0; int i; for (i = 0; i < MAX_TEMP_COUNT; i++) { - if (StackTempMap[i] == 0) + if (CurrentUserDefinedFunction->TempMap[i] == 0) { - TempID = i; - StackTempMap[i] = 1; + TempID = i; + CurrentUserDefinedFunction->TempMap[i] = 1; break; } } @@ -657,55 +669,44 @@ NewStackTemp(PSCRIPT_ENGINE_ERROR_TYPE Error) { *Error = SCRIPT_ENGINE_ERROR_TEMP_LIST_FULL; } - PTOKEN Temp = NewUnknownToken(); - char TempValue[8]; + PSCRIPT_ENGINE_TOKEN Temp = NewUnknownToken(); + char TempValue[8]; sprintf(TempValue, "%d", TempID); strcpy(Temp->Value, TempValue); - Temp->Type = STACK_TEMP; + Temp->Type = TEMP; + + if (CurrentUserDefinedFunction->MaxTempNumber < (i + 1)) + { + CurrentUserDefinedFunction->MaxTempNumber = i + 1; + } + return Temp; } /** * @brief Frees the memory allocated by Temp * - * @param Temp + * @param Temp the token representing the temporary variable + * @return VOID */ -void -FreeTemp(PTOKEN Temp) +VOID +FreeTemp(PSCRIPT_ENGINE_TOKEN Temp) { - int id = (int)DecimalToInt(Temp->Value); - if (Temp->Type == TEMP) + INT Id = (INT)DecimalToInt(Temp->Value); + if (Temp->Type == TEMP || Temp->Type == DEFERENCE_TEMP) { - TempMap[id] = 0; - } - else if (Temp->Type == STACK_TEMP) - { - StackTempMap[id] = 0; - } -} - -/** - * @brief Resets the temporary variables map - * - */ -void -CleanTempList(void) -{ - for (int i = 0; i < MAX_TEMP_COUNT; i++) - { - TempMap[i] = 0; - StackTempMap[i] = 0; + CurrentUserDefinedFunction->TempMap[Id] = 0; } } /** * @brief Checks whether this Token type is OneOpFunc1 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType1Func(PTOKEN Operator) +IsType1Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = ONEOPFUNC1_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -721,11 +722,11 @@ IsType1Func(PTOKEN Operator) /** * @brief Checks whether this Token type is OneOpFunc2 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType2Func(PTOKEN Operator) +IsType2Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = ONEOPFUNC2_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -741,11 +742,11 @@ IsType2Func(PTOKEN Operator) /** * @brief Checks whether this Token type is OperatorsTwoOperandList * - * @param Operator + * @param Operator the token to check * @return char */ char -IsTwoOperandOperator(PTOKEN Operator) +IsTwoOperandOperator(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = OPERATORS_TWO_OPERAND_LIST_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -761,11 +762,11 @@ IsTwoOperandOperator(PTOKEN Operator) /** * @brief Checks whether this Token type is OperatorsOneOperandList * - * @param Operator + * @param Operator the token to check * @return char */ char -IsOneOperandOperator(PTOKEN Operator) +IsOneOperandOperator(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = OPERATORS_ONE_OPERAND_LIST_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -781,11 +782,11 @@ IsOneOperandOperator(PTOKEN Operator) /** * @brief Checks whether this Token type is VarArgFunc1 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType4Func(PTOKEN Operator) +IsType4Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = VARARGFUNC1_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -801,11 +802,11 @@ IsType4Func(PTOKEN Operator) /** * @brief Checks whether this Token type is ZeroOpFunc1 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType5Func(PTOKEN Operator) +IsType5Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = ZEROOPFUNC1_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -821,11 +822,11 @@ IsType5Func(PTOKEN Operator) /** * @brief Checks whether this Token type is TwoOpFunc1 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType6Func(PTOKEN Operator) +IsType6Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = TWOOPFUNC1_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -841,11 +842,11 @@ IsType6Func(PTOKEN Operator) /** * @brief Checks whether this Token type is TwoOpFunc2 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType7Func(PTOKEN Operator) +IsType7Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = TWOOPFUNC2_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -861,11 +862,11 @@ IsType7Func(PTOKEN Operator) /** * @brief Checks whether this Token type is ThreeOpFunc1 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType8Func(PTOKEN Operator) +IsType8Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = THREEOPFUNC1_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -881,11 +882,11 @@ IsType8Func(PTOKEN Operator) /** * @brief Checks whether this Token type is OneOpFunc3 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType9Func(PTOKEN Operator) +IsType9Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = ONEOPFUNC3_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -901,11 +902,11 @@ IsType9Func(PTOKEN Operator) /** * @brief Checks whether this Token type is TwoOpFunc3 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType10Func(PTOKEN Operator) +IsType10Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = TWOOPFUNC3_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -921,11 +922,11 @@ IsType10Func(PTOKEN Operator) /** * @brief Checks whether this Token type is ThreeOpFunc3 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType11Func(PTOKEN Operator) +IsType11Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = THREEOPFUNC3_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -941,11 +942,11 @@ IsType11Func(PTOKEN Operator) /** * @brief Checks whether this Token type is OneOpFunc4 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType12Func(PTOKEN Operator) +IsType12Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = ONEOPFUNC4_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -961,11 +962,11 @@ IsType12Func(PTOKEN Operator) /** * @brief Checks whether this Token type is TwoOpFunc4 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType13Func(PTOKEN Operator) +IsType13Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = TWOOPFUNC4_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -981,11 +982,11 @@ IsType13Func(PTOKEN Operator) /** * @brief Checks whether this Token type is ThreeOpFunc2 * - * @param Operator + * @param Operator the token to check * @return char */ char -IsType14Func(PTOKEN Operator) +IsType14Func(PSCRIPT_ENGINE_TOKEN Operator) { unsigned int n = THREEOPFUNC2_LENGTH; for (unsigned int i = 0; i < n; i++) @@ -999,24 +1000,62 @@ IsType14Func(PTOKEN Operator) } /** - * @brief Checks whether this Token type is VariableType + * @brief Checks whether this Token type is ThreeOpFunc4 * - * @param Operator + * @param Operator the token to check * @return char */ - char -IsVariableType(PTOKEN Operator) +IsType15Func(PSCRIPT_ENGINE_TOKEN Operator) { - unsigned int n = VARIABLETYPE_LENGTH; + unsigned int n = THREEOPFUNC4_LENGTH; for (unsigned int i = 0; i < n; i++) { - if (!strcmp(Operator->Value, VARIABLETYPE[i])) + if (!strcmp(Operator->Value, ThreeOpFunc4[i])) { return 1; } } + return 0; +} +/** + * @brief Checks whether this Token type is ZeroOpFunc2 + * + * @param Operator the token to check + * @return char + */ +char +IsType16Func(PSCRIPT_ENGINE_TOKEN Operator) +{ + unsigned int n = ZEROOPFUNC2_LENGTH; + for (unsigned int i = 0; i < n; i++) + { + if (!strcmp(Operator->Value, ZeroOpFunc2[i])) + { + return 1; + } + } + return 0; +} + +/** + * @brief Checks whether this Token type is assignment operator + * + * @param Operator the token to check + * @return char + */ +char +IsAssignmentOperator(PSCRIPT_ENGINE_TOKEN Operator) +{ + unsigned int n = ASSIGNMENT_OPERATOR_LIST_LENGTH; + for (unsigned int i = 0; i < n; i++) + { + if (!strcmp(Operator->Value, AssignmentOperatorList[i])) + { + return 1; + } + } return 0; } @@ -1024,11 +1063,11 @@ IsVariableType(PTOKEN Operator) * @brief Checks whether this Token is noneterminal * NoneTerminal token starts with capital letter * - * @param Token + * @param Token the token to check * @return char */ char -IsNoneTerminal(PTOKEN Token) +IsNoneTerminal(PSCRIPT_ENGINE_TOKEN Token) { if (Token->Value[0] >= 'A' && Token->Value[0] <= 'Z') return 1; @@ -1040,11 +1079,11 @@ IsNoneTerminal(PTOKEN Token) * @brief Checks whether this Token is semantic rule * SemanticRule token starts with '@' * - * @param Token + * @param Token the token to check * @return char */ char -IsSemanticRule(PTOKEN Token) +IsSemanticRule(PSCRIPT_ENGINE_TOKEN Token) { if (Token->Value[0] == '@') return 1; @@ -1055,11 +1094,11 @@ IsSemanticRule(PTOKEN Token) /** * @brief Gets the Non Terminal Id object * - * @param Token - * @return int + * @param Token the token to get the non-terminal ID of + * @return int the non-terminal ID or INVALID */ int -GetNonTerminalId(PTOKEN Token) +GetNonTerminalId(PSCRIPT_ENGINE_TOKEN Token) { for (int i = 0; i < NONETERMINAL_COUNT; i++) { @@ -1072,11 +1111,11 @@ GetNonTerminalId(PTOKEN Token) /** * @brief Gets the Terminal Id object * - * @param Token - * @return int + * @param Token the token to get the terminal ID of + * @return int the terminal ID or INVALID */ int -GetTerminalId(PTOKEN Token) +GetTerminalId(PSCRIPT_ENGINE_TOKEN Token) { for (int i = 0; i < TERMINAL_COUNT; i++) { @@ -1099,6 +1138,13 @@ GetTerminalId(PTOKEN Token) return i; } } + else if (Token->Type == FUNCTION_ID) + { + if (!strcmp("_function_id", TerminalMap[i])) + { + return i; + } + } else if (Token->Type == FUNCTION_PARAMETER_ID) { if (!strcmp("_function_parameter_id", TerminalMap[i])) @@ -1120,6 +1166,13 @@ GetTerminalId(PTOKEN Token) return i; } } + else if (Token->Type == SCRIPT_VARIABLE_TYPE) + { + if (!strcmp("_script_variable_type", TerminalMap[i])) + { + return i; + } + } else if (Token->Type == DECIMAL) { if (!strcmp("_decimal", TerminalMap[i])) @@ -1167,11 +1220,11 @@ GetTerminalId(PTOKEN Token) /** * @brief Gets the Non Terminal Id object * - * @param Token - * @return int + * @param Token the token to get the non-terminal ID of + * @return int the non-terminal ID or INVALID */ int -LalrGetNonTerminalId(PTOKEN Token) +LalrGetNonTerminalId(PSCRIPT_ENGINE_TOKEN Token) { for (int i = 0; i < LALR_NONTERMINAL_COUNT; i++) { @@ -1184,11 +1237,11 @@ LalrGetNonTerminalId(PTOKEN Token) /** * @brief Gets the Terminal Id object * - * @param Token - * @return int + * @param Token the token to get the terminal ID of + * @return int the terminal ID or INVALID */ int -LalrGetTerminalId(PTOKEN Token) +LalrGetTerminalId(PSCRIPT_ENGINE_TOKEN Token) { for (int i = 0; i < LALR_TERMINAL_COUNT; i++) { @@ -1211,6 +1264,13 @@ LalrGetTerminalId(PTOKEN Token) return i; } } + else if (Token->Type == FUNCTION_ID) + { + if (!strcmp("_function_id", LalrTerminalMap[i])) + { + return i; + } + } else if (Token->Type == FUNCTION_PARAMETER_ID) { if (!strcmp("_function_parameter_id", LalrTerminalMap[i])) @@ -1279,12 +1339,12 @@ LalrGetTerminalId(PTOKEN Token) /** * @brief Checks whether the value and type of Token1 and Token2 are the same * - * @param Token1 - * @param Token2 + * @param Token1 the first token to compare + * @param Token2 the second token to compare * @return char */ char -IsEqual(const PTOKEN Token1, const PTOKEN Token2) +IsEqual(const PSCRIPT_ENGINE_TOKEN Token1, const PSCRIPT_ENGINE_TOKEN Token2) { if (Token1->Type == Token2->Type) { @@ -1326,6 +1386,7 @@ IsEqual(const PTOKEN Token1, const PTOKEN Token2) * * @param Val * @param Type + * @return void */ void SetType(unsigned long long * Val, unsigned char Type) @@ -1336,14 +1397,14 @@ SetType(unsigned long long * Val, unsigned char Type) /** * @brief Converts an decimal string to a integer * - * @param str + * @param str the decimal string to convert * @return unsigned long long int */ unsigned long long DecimalToInt(char * str) { unsigned long long Acc = 0; - size_t Len; + SIZE_T Len; Len = strlen(str); for (int i = 0; i < Len; i++) @@ -1357,14 +1418,14 @@ DecimalToInt(char * str) /** * @brief Converts an decimal string to a signed integer * - * @param str + * @param str the decimal string to convert * @return unsigned long long */ unsigned long long DecimalToSignedInt(char * str) { long long Acc = 0; - size_t Len; + SIZE_T Len; if (str[0] == '-') { @@ -1391,31 +1452,31 @@ DecimalToSignedInt(char * str) /** * @brief Converts an hexadecimal string to integer * - * @param str + * @param str the hexadecimal string to convert * @return unsigned long long */ unsigned long long HexToInt(char * str) { - char temp; - size_t len = strlen(str); + CHAR Temp; + SIZE_T Len = strlen(str); unsigned long long Acc = 0; - for (int i = 0; i < len; i++) + for (int i = 0; i < Len; i++) { Acc <<= 4; if (str[i] >= '0' && str[i] <= '9') { - temp = str[i] - '0'; + Temp = str[i] - '0'; } else if (str[i] >= 'a' && str[i] <= 'f') { - temp = str[i] - 'a' + 10; + Temp = str[i] - 'a' + 10; } else { - temp = str[i] - 'A' + 10; + Temp = str[i] - 'A' + 10; } - Acc += temp; + Acc += Temp; } return Acc; @@ -1424,13 +1485,13 @@ HexToInt(char * str) /** * @brief Converts an octal string to integer * - * @param str + * @param str the octal string to convert * @return unsigned long long */ unsigned long long OctalToInt(char * str) { - size_t Len; + SIZE_T Len; unsigned long long Acc = 0; Len = strlen(str); @@ -1446,13 +1507,13 @@ OctalToInt(char * str) /** * @brief Converts a binary string to integer * - * @param str + * @param str the binary string to convert * @return unsigned long long */ unsigned long long BinaryToInt(char * str) { - size_t Len; + SIZE_T Len; unsigned long long Acc = 0; Len = strlen(str); @@ -1468,16 +1529,17 @@ BinaryToInt(char * str) /** * @brief Rotate a character array to the left by one time * - * @param str + * @param str the string to rotate + * @return void */ void RotateLeftStringOnce(char * str) { - int length = (int)strlen(str); - char temp = str[0]; - for (int i = 0; i < (length - 1); i++) + INT Length = (INT)strlen(str); + CHAR Temp = str[0]; + for (int i = 0; i < (Length - 1); i++) { str[i] = str[i + 1]; } - str[length - 1] = temp; + str[Length - 1] = Temp; } diff --git a/hyperdbg/script-engine/code/globals.c b/hyperdbg/script-engine/code/globals.c index 644bb6b1..af68d655 100644 --- a/hyperdbg/script-engine/code/globals.c +++ b/hyperdbg/script-engine/code/globals.c @@ -11,9 +11,14 @@ */ #include "pch.h" -/** - * @brief Temp variable map - * - */ -char TempMap[MAX_TEMP_COUNT] = {0}; -char StackTempMap[MAX_TEMP_COUNT] = {0}; \ No newline at end of file +PSCRIPT_ENGINE_TOKEN_LIST GlobalIdTable; +PUSER_DEFINED_FUNCTION_NODE UserDefinedFunctionHead; +PUSER_DEFINED_FUNCTION_NODE CurrentUserDefinedFunction; +PINCLUDE_NODE IncludeHead; +unsigned int InputIdx; +unsigned int CurrentLine; +unsigned int CurrentLineIdx; +unsigned int CurrentTokenIdx; +HWDBG_INSTANCE_INFORMATION g_HwdbgInstanceInfo; +BOOLEAN g_HwdbgInstanceInfoIsValid; +PVOID g_MessageHandler; diff --git a/hyperdbg/script-engine/code/hardware.c b/hyperdbg/script-engine/code/hardware.c new file mode 100644 index 00000000..2b986898 --- /dev/null +++ b/hyperdbg/script-engine/code/hardware.c @@ -0,0 +1,712 @@ +/** + * @file hardware.c + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Hardware (chip debugger) related functions + * @details + * @version 0.11 + * @date 2024-09-25 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Shows the script capabilities of the target debuggee + * + * @param InstanceInfo + * + * @return VOID + */ +VOID +HardwareScriptInterpreterShowScriptCapabilities(HWDBG_INSTANCE_INFORMATION * InstanceInfo) +{ + ShowMessages("\nThis debuggee supports the following operators:\n"); + ShowMessages("\tlocal and global variable assignments: %s (maximum number of var: %d) \n", + InstanceInfo->scriptCapabilities.assign_local_global_var ? "supported" : "not supported", + InstanceInfo->numberOfSupportedLocalAndGlobalVariables); + ShowMessages("\tregisters (pin/ports) assignment: %s \n", + InstanceInfo->scriptCapabilities.assign_registers ? "supported" : "not supported"); + ShowMessages("\tpseudo-registers assignment: %s \n", + InstanceInfo->scriptCapabilities.assign_pseudo_registers ? "supported" : "not supported"); + ShowMessages("\tconditional statements and comparison operators: %s \n", + InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators ? "supported" : "not supported"); + + ShowMessages("\tor: %s \n", InstanceInfo->scriptCapabilities.func_or ? "supported" : "not supported"); + ShowMessages("\txor: %s \n", InstanceInfo->scriptCapabilities.func_xor ? "supported" : "not supported"); + ShowMessages("\tand: %s \n", InstanceInfo->scriptCapabilities.func_and ? "supported" : "not supported"); + ShowMessages("\tarithmetic shift right: %s \n", InstanceInfo->scriptCapabilities.func_asr ? "supported" : "not supported"); + ShowMessages("\tarithmetic shift left: %s \n", InstanceInfo->scriptCapabilities.func_asl ? "supported" : "not supported"); + ShowMessages("\taddition: %s \n", InstanceInfo->scriptCapabilities.func_add ? "supported" : "not supported"); + ShowMessages("\tsubtraction: %s \n", InstanceInfo->scriptCapabilities.func_sub ? "supported" : "not supported"); + ShowMessages("\tmultiplication: %s \n", InstanceInfo->scriptCapabilities.func_mul ? "supported" : "not supported"); + ShowMessages("\tdivision: %s \n", InstanceInfo->scriptCapabilities.func_div ? "supported" : "not supported"); + ShowMessages("\tmodulus: %s \n", InstanceInfo->scriptCapabilities.func_mod ? "supported" : "not supported"); + + ShowMessages("\tgreater than: %s \n", + (InstanceInfo->scriptCapabilities.func_gt && InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) ? "supported" : "not supported"); + ShowMessages("\tless than: %s \n", + (InstanceInfo->scriptCapabilities.func_lt && InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) ? "supported" : "not supported"); + ShowMessages("\tgreater than or equal to: %s \n", + (InstanceInfo->scriptCapabilities.func_egt && InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) ? "supported" : "not supported"); + ShowMessages("\tless than or equal to: %s \n", + (InstanceInfo->scriptCapabilities.func_elt && InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) ? "supported" : "not supported"); + ShowMessages("\tequal: %s \n", + (InstanceInfo->scriptCapabilities.func_equal && InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) ? "supported" : "not supported"); + ShowMessages("\tnot equal: %s \n", + (InstanceInfo->scriptCapabilities.func_neq && InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) ? "supported" : "not supported"); + ShowMessages("\tjump: %s \n", + (InstanceInfo->scriptCapabilities.func_jmp && InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) ? "supported" : "not supported"); + ShowMessages("\tjump if zero: %s \n", + (InstanceInfo->scriptCapabilities.func_jz && InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) ? "supported" : "not supported"); + ShowMessages("\tjump if not zero: %s \n", + (InstanceInfo->scriptCapabilities.func_jnz && InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) ? "supported" : "not supported"); + ShowMessages("\tmove: %s \n", InstanceInfo->scriptCapabilities.func_mov ? "supported" : "not supported"); + ShowMessages("\tprintf: %s \n", InstanceInfo->scriptCapabilities.func_printf ? "supported" : "not supported"); + ShowMessages("\n"); +} + +/** + * @brief Check the script capabilities with the target script buffer + * + * @param InstanceInfo + * @param ScriptBuffer + * @param CountOfScriptSymbolChunks + * @param NumberOfStages + * @param NumberOfOperands + * @param NumberOfOperandsImplemented + * + * @return BOOLEAN TRUE if the script capabilities support the script, otherwise FALSE + */ +BOOLEAN +HardwareScriptInterpreterCheckScriptBufferWithScriptCapabilities(HWDBG_INSTANCE_INFORMATION * InstanceInfo, + PVOID ScriptBuffer, + UINT32 CountOfScriptSymbolChunks, + UINT32 * NumberOfStages, + UINT32 * NumberOfOperands, + UINT32 * NumberOfOperandsImplemented) +{ + BOOLEAN NotSupported = FALSE; + SYMBOL * SymbolArray = (SYMBOL *)ScriptBuffer; + + UINT32 Stages = 0; + UINT32 Operands = 0; + UINT32 NumberOfGetOperands = 0; + UINT32 NumberOfSetOperands = 0; + + for (size_t i = 0; i < CountOfScriptSymbolChunks; i++) + { + if (SymbolArray[i].Type != SYMBOL_SEMANTIC_RULE_TYPE) + { + // + // *** For operands *** + // + Operands++; + ShowMessages(" \t%lld. found a non-semnatic rule (operand) | type: 0x%llx, value: 0x%llx\n", i, SymbolArray[i].Type, SymbolArray[i].Value); + + // + // Validate the operand + // + switch (SymbolArray[i].Type) + { + case SYMBOL_GLOBAL_ID_TYPE: + case SYMBOL_LOCAL_ID_TYPE: + + if (!InstanceInfo->scriptCapabilities.assign_local_global_var) + { + NotSupported = TRUE; + ShowMessages("err, global/local variable assignment is not supported\n"); + } + + if (SymbolArray[i].Value >= InstanceInfo->numberOfSupportedLocalAndGlobalVariables) + { + NotSupported = TRUE; + ShowMessages("err, global/local variable index is out of range of supported by this instance of hwdbg\n"); + } + + break; + + case SYMBOL_UNDEFINED: + case SYMBOL_NUM_TYPE: + + // + // No need to check + // + break; + + case SYMBOL_REGISTER_TYPE: + + if (!InstanceInfo->scriptCapabilities.assign_registers) + { + NotSupported = TRUE; + ShowMessages("err, register assignment is not supported\n"); + } + break; + + case SYMBOL_PSEUDO_REG_TYPE: + + if (!InstanceInfo->scriptCapabilities.assign_pseudo_registers) + { + NotSupported = TRUE; + ShowMessages("err, pseudo register index is not supported\n"); + } + break; + + case SYMBOL_TEMP_TYPE: + + if (!InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) + { + NotSupported = TRUE; + ShowMessages("err, temporary variables (for conditional statement) is not supported\n"); + } + + if (SymbolArray[i].Value >= InstanceInfo->numberOfSupportedTemporaryVariables) + { + NotSupported = TRUE; + ShowMessages("err, temp variable index (number of operands for conditional statements) is out of range of supported by this instance of hwdbg\n"); + } + + break; + + case SYMBOL_STACK_INDEX_TYPE: + + if (!InstanceInfo->scriptCapabilities.stack_assignments) + { + NotSupported = TRUE; + ShowMessages("err, temporary variables (for conditional statement) is not supported\n"); + } + + break; + + default: + + NotSupported = TRUE; + ShowMessages("err, unknown operand type: %lld (0x%llx)\n", SymbolArray[i].Type, SymbolArray[i].Type); + break; + } + } + else + { + // + // *** For operators *** + // + Stages++; + ShowMessages("- %lld. found a semnatic rule (operator) | type: 0x%llx, value: 0x%llx\n", i, SymbolArray[i].Type, SymbolArray[i].Value); + + if (FuncGetNumberOfOperands(SymbolArray[i].Type, &NumberOfGetOperands, &NumberOfSetOperands) == FALSE) + { + NotSupported = TRUE; + ShowMessages("err, unknown operand type for the operator (0x%llx)\n", + SymbolArray[i].Type); + + return FALSE; + } + + // + // Validate the operator + // + switch (SymbolArray[i].Value) + { + case FUNC_OR: + if (!InstanceInfo->scriptCapabilities.func_or) + { + NotSupported = TRUE; + ShowMessages("err, OR is not supported by the debuggee\n"); + } + break; + + case FUNC_XOR: + if (!InstanceInfo->scriptCapabilities.func_xor) + { + NotSupported = TRUE; + ShowMessages("err, XOR is not supported by the debuggee\n"); + } + break; + + case FUNC_AND: + if (!InstanceInfo->scriptCapabilities.func_and) + { + NotSupported = TRUE; + ShowMessages("err, AND is not supported by the debuggee\n"); + } + break; + + case FUNC_ASR: + if (!InstanceInfo->scriptCapabilities.func_asr) + { + NotSupported = TRUE; + ShowMessages("err, arithmetic shift right is not supported by the debuggee\n"); + } + break; + + case FUNC_ASL: + if (!InstanceInfo->scriptCapabilities.func_asl) + { + NotSupported = TRUE; + ShowMessages("err, arithmetic shift left is not supported by the debuggee\n"); + } + break; + + case FUNC_ADD: + if (!InstanceInfo->scriptCapabilities.func_add) + { + NotSupported = TRUE; + ShowMessages("err, addition is not supported by the debuggee\n"); + } + break; + + case FUNC_SUB: + if (!InstanceInfo->scriptCapabilities.func_sub) + { + NotSupported = TRUE; + ShowMessages("err, subtraction is not supported by the debuggee\n"); + } + break; + + case FUNC_MUL: + if (!InstanceInfo->scriptCapabilities.func_mul) + { + NotSupported = TRUE; + ShowMessages("err, multiplication is not supported by the debuggee\n"); + } + break; + + case FUNC_DIV: + if (!InstanceInfo->scriptCapabilities.func_div) + { + NotSupported = TRUE; + ShowMessages("err, division is not supported by the debuggee\n"); + } + break; + + case FUNC_MOD: + if (!InstanceInfo->scriptCapabilities.func_mod) + { + NotSupported = TRUE; + ShowMessages("err, modulus is not supported by the debuggee\n"); + } + break; + + case FUNC_GT: + + if (!InstanceInfo->scriptCapabilities.func_gt || + !InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) + { + NotSupported = TRUE; + ShowMessages("err, greater than is not supported by the debuggee\n"); + } + break; + + case FUNC_LT: + if (!InstanceInfo->scriptCapabilities.func_lt || + !InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) + { + NotSupported = TRUE; + ShowMessages("err, less than is not supported by the debuggee\n"); + } + break; + + case FUNC_EGT: + if (!InstanceInfo->scriptCapabilities.func_egt || + !InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) + { + NotSupported = TRUE; + ShowMessages("err, greater than or equal to is not supported by the debuggee\n"); + } + break; + + case FUNC_ELT: + if (!InstanceInfo->scriptCapabilities.func_elt || + !InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) + { + NotSupported = TRUE; + ShowMessages("err, less than or equal to is not supported by the debuggee\n"); + } + break; + + case FUNC_EQUAL: + if (!InstanceInfo->scriptCapabilities.func_equal || + !InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) + { + NotSupported = TRUE; + ShowMessages("err, equal is not supported by the debuggee\n"); + } + break; + + case FUNC_NEQ: + if (!InstanceInfo->scriptCapabilities.func_neq || + !InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) + { + NotSupported = TRUE; + ShowMessages("err, not equal is not supported by the debuggee\n"); + } + break; + + case FUNC_JMP: + if (!InstanceInfo->scriptCapabilities.func_jmp || + !InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) + { + NotSupported = TRUE; + ShowMessages("err, jump is not supported by the debuggee\n"); + } + break; + + case FUNC_JZ: + if (!InstanceInfo->scriptCapabilities.func_jz || + !InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) + { + NotSupported = TRUE; + ShowMessages("err, jump if zero is not supported by the debuggee\n"); + } + break; + + case FUNC_JNZ: + if (!InstanceInfo->scriptCapabilities.func_jnz || + !InstanceInfo->scriptCapabilities.conditional_statements_and_comparison_operators) + { + NotSupported = TRUE; + ShowMessages("err, jump if not zero is not supported by the debuggee\n"); + } + break; + + case FUNC_MOV: + if (!InstanceInfo->scriptCapabilities.func_mov) + { + NotSupported = TRUE; + ShowMessages("err, move is not supported by the debuggee\n"); + } + break; + + case FUNC_PRINTF: + if (!InstanceInfo->scriptCapabilities.func_printf) + { + NotSupported = TRUE; + ShowMessages("err, printf is not supported by the debuggee\n"); + } + break; + + default: + + NotSupported = TRUE; + ShowMessages("err, undefined operator for hwdbg: %lld (0x%llx)\n", + SymbolArray[i].Type, + SymbolArray[i].Type); + + break; + } + } + } + + // + // Set the number of stages + // + *NumberOfStages = Stages; + + // + // Set the number of operands + // + *NumberOfOperands = Operands; + + // + // Set the number of operands implemented + // + *NumberOfOperandsImplemented = *NumberOfStages * (InstanceInfo->maximumNumberOfSupportedGetScriptOperators + InstanceInfo->maximumNumberOfSupportedSetScriptOperators); + + // + // Script capabilities support this buffer + // + if (NotSupported) + { + return FALSE; + } + else + { + return TRUE; + } +} + +/** + * @brief Function to compress the buffer + * + * @param Buffer + * @param BufferLength + * @param ScriptVariableLength + * @param BramDataWidth + * @param NewBufferSize + * @param NumberOfBytesPerChunk + * + * @return BOOLEAN + */ +BOOLEAN +HardwareScriptInterpreterCompressBuffer(UINT64 * Buffer, + size_t BufferLength, + UINT32 ScriptVariableLength, + UINT32 BramDataWidth, + size_t * NewBufferSize, + size_t * NumberOfBytesPerChunk) +{ + if (ScriptVariableLength <= 7 || ScriptVariableLength > 64) + { + ShowMessages("err, invalid bit size, it should be between 7 and 64\n"); + return FALSE; + } + + if (ScriptVariableLength > BramDataWidth) + { + ShowMessages("err, script variable length cannot be more than the BRAM data width\n"); + return FALSE; + } + + // + // Calculate the number of 64-bit chunks + // + size_t NumberOfChunks = BufferLength / sizeof(UINT64); + + // + // Calculate the number of bytes needed for the new compressed buffer + // + size_t NewBytesPerChunk = (BramDataWidth + 7) / 8; // ceil(BramDataWidth / 8) + *NumberOfBytesPerChunk = NewBytesPerChunk; + + *NewBufferSize = NumberOfChunks * NewBytesPerChunk; + + // + // Create a temporary buffer to hold the compressed data + // + UINT8 * TempBuffer = (UINT8 *)malloc(*NewBufferSize); + + if (TempBuffer == NULL) + { + ShowMessages("err, memory allocation failed\n"); + return FALSE; + } + + // + // Compress each chunk and store it in the temporary buffer + // + for (size_t i = 0; i < NumberOfChunks; ++i) + { + uint64_t Chunk = Buffer[i]; + for (size_t j = 0; j < NewBytesPerChunk; ++j) + { + TempBuffer[i * NewBytesPerChunk + j] = (uint8_t)((Chunk >> (j * 8)) & 0xFF); + } + } + + // + // Copy the compressed data back to the original buffer + // + RtlZeroMemory(Buffer, BufferLength); + memcpy(Buffer, TempBuffer, *NewBufferSize); + + // + // Free the temporary buffer + // + free(TempBuffer); + + return TRUE; +} + +/** + * @brief Function to compress the buffer + * + * @param InstanceInfo + * @param SymbolBuffer + * @param SymbolBufferLength + * @param NumberOfStages + * @param NewShortSymbolBuffer + * @param NewBufferSize + * + * @return BOOLEAN + */ +BOOLEAN +HardwareScriptInterpreterConvertSymbolToHwdbgShortSymbolBuffer( + HWDBG_INSTANCE_INFORMATION * InstanceInfo, + SYMBOL * SymbolBuffer, + size_t SymbolBufferLength, + UINT32 NumberOfStages, + HWDBG_SHORT_SYMBOL ** NewShortSymbolBuffer, + size_t * NewBufferSize) + +{ + // + // Check if the instance info is valid + // + if (!g_HwdbgInstanceInfoIsValid) + { + ShowMessages("err, instance info is not valid\n"); + return FALSE; + } + + // + // Compute the number of symbol operators + // + UINT32 NumberOfOperands = InstanceInfo->maximumNumberOfSupportedGetScriptOperators + InstanceInfo->maximumNumberOfSupportedSetScriptOperators; + + SIZE_T NumberOfSymbols = SymbolBufferLength / sizeof(SymbolBuffer[0]); + + *NewBufferSize = NumberOfStages * (NumberOfOperands + 1) * sizeof(HWDBG_SHORT_SYMBOL); // number of stage + maximum number of operands + + // + // Create a temporary buffer to hold the compressed data + // + HWDBG_SHORT_SYMBOL * HwdbgShortSymbolBuffer = (HWDBG_SHORT_SYMBOL *)malloc(*NewBufferSize); + + if (!HwdbgShortSymbolBuffer) + { + ShowMessages("err, could not allocate compression buffer\n"); + return FALSE; + } + + // + // Zeroing the short symbol buffer + // + RtlZeroMemory(HwdbgShortSymbolBuffer, *NewBufferSize); + + // + // Filling the short symbol buffer from original buffer + // + UINT32 IndexOfShortSymbolBuffer = 0; + + for (UINT32 i = 0; i < NumberOfSymbols; i++) + { + if (SymbolBuffer[i].Type == SYMBOL_SEMANTIC_RULE_TYPE) + { + // + // *** This is an operator *** + // + + // + // Move the symbol buffer into a short symbol buffer + // + HwdbgShortSymbolBuffer[IndexOfShortSymbolBuffer].Type = SymbolBuffer[i].Type; + HwdbgShortSymbolBuffer[IndexOfShortSymbolBuffer].Value = SymbolBuffer[i].Value; + + // + // Now we read the number of operands (SET and GET) + // + UINT32 NumberOfGetOperands = 0; + UINT32 NumberOfSetOperands = 0; + + if (!FuncGetNumberOfOperands(SymbolBuffer[i].Value, &NumberOfGetOperands, &NumberOfSetOperands)) + { + ShowMessages("err, unknown operand type for the operator (0x%llx)\n", + SymbolBuffer[i].Value); + + free(HwdbgShortSymbolBuffer); + return FALSE; + } + + // + // Check if the number of GET operands is more than the maximum supported GET operands + // + if (NumberOfGetOperands > InstanceInfo->maximumNumberOfSupportedGetScriptOperators) + { + ShowMessages("err, the number of get operands is more than the maximum supported get operands\n"); + free(HwdbgShortSymbolBuffer); + return FALSE; + } + + // + // Check if the number of SET operands is more than the maximum supported SET operands + // + if (NumberOfSetOperands > InstanceInfo->maximumNumberOfSupportedSetScriptOperators) + { + ShowMessages("err, the number of set operands is more than the maximum supported set operands\n"); + free(HwdbgShortSymbolBuffer); + return FALSE; + } + + // + // *** Now we need to fill operands (GET) *** + // + for (size_t j = 0; j < NumberOfGetOperands; j++) + { + i++; + IndexOfShortSymbolBuffer++; + + if (SymbolBuffer[i].Type == SYMBOL_SEMANTIC_RULE_TYPE) + { + ShowMessages("err, not expecting a semantic rule at operand: %llx\n", SymbolBuffer[i].Value); + free(HwdbgShortSymbolBuffer); + return FALSE; + } + + // + // Move the symbol buffer into a short symbol buffer + // + HwdbgShortSymbolBuffer[IndexOfShortSymbolBuffer].Type = SymbolBuffer[i].Type; + HwdbgShortSymbolBuffer[IndexOfShortSymbolBuffer].Value = SymbolBuffer[i].Value; + } + + // + // Leave empty space for GET operands that are not used for this operator + // + IndexOfShortSymbolBuffer = IndexOfShortSymbolBuffer + InstanceInfo->maximumNumberOfSupportedGetScriptOperators - NumberOfGetOperands; + + // + // *** Now we need to fill operands (SET) *** + // + for (size_t j = 0; j < NumberOfSetOperands; j++) + { + i++; + IndexOfShortSymbolBuffer++; + + if (SymbolBuffer[i].Type == SYMBOL_SEMANTIC_RULE_TYPE) + { + ShowMessages("err, not expecting a semantic rule at operand: %llx\n", SymbolBuffer[i].Value); + free(HwdbgShortSymbolBuffer); + return FALSE; + } + + // + // Move the symbol buffer into a short symbol buffer + // + HwdbgShortSymbolBuffer[IndexOfShortSymbolBuffer].Type = SymbolBuffer[i].Type; + HwdbgShortSymbolBuffer[IndexOfShortSymbolBuffer].Value = SymbolBuffer[i].Value; + } + + // + // Leave empty space for SET operands that are not used for this operator + // + IndexOfShortSymbolBuffer = IndexOfShortSymbolBuffer + InstanceInfo->maximumNumberOfSupportedSetScriptOperators - NumberOfSetOperands; + + // + // Increment the index of the short symbol buffer + // + IndexOfShortSymbolBuffer++; + } + else + { + // + // Error, we are not expecting a non-semantic rule here + // + ShowMessages("err, not expecting a non-semantic rule at: %llx\n", SymbolBuffer[i].Type); + free(HwdbgShortSymbolBuffer); + return FALSE; + } + } + + // + // Set the new short symbol buffer address + // + *NewShortSymbolBuffer = (HWDBG_SHORT_SYMBOL *)HwdbgShortSymbolBuffer; + + return TRUE; +} + +/** + * @brief Function free the short symbol buffer + * + * @param NewShortSymbolBuffer + * + * @return VOID + */ +VOID +HardwareScriptInterpreterFreeHwdbgShortSymbolBuffer(HWDBG_SHORT_SYMBOL * NewShortSymbolBuffer) +{ + if (NewShortSymbolBuffer) + { + free(NewShortSymbolBuffer); + } +} diff --git a/hyperdbg/script-engine/code/parse-table.c b/hyperdbg/script-engine/code/parse-table.c index 7bfe2d6b..d5ae0383 100644 --- a/hyperdbg/script-engine/code/parse-table.c +++ b/hyperdbg/script-engine/code/parse-table.c @@ -1,5 +1,5 @@ #include "pch.h" -const struct _TOKEN Lhs[RULES_COUNT]= +const struct _SCRIPT_ENGINE_TOKEN Lhs[RULES_COUNT]= { {NON_TERMINAL, "S"}, {NON_TERMINAL, "S"}, @@ -13,6 +13,8 @@ const struct _TOKEN Lhs[RULES_COUNT]= {NON_TERMINAL, "STATEMENT"}, {NON_TERMINAL, "STATEMENT"}, {NON_TERMINAL, "STATEMENT"}, + {NON_TERMINAL, "STATEMENT"}, + {NON_TERMINAL, "STATEMENT"}, {NON_TERMINAL, "S2"}, {NON_TERMINAL, "S2"}, {NON_TERMINAL, "S2"}, @@ -26,36 +28,74 @@ const struct _TOKEN Lhs[RULES_COUNT]= {NON_TERMINAL, "STATEMENT2"}, {NON_TERMINAL, "STATEMENT2"}, {NON_TERMINAL, "STATEMENT2"}, + {NON_TERMINAL, "STATEMENT2"}, {NON_TERMINAL, "RETURN"}, {NON_TERMINAL, "RETURN"}, {NON_TERMINAL, "VARIABLE_TYPE1"}, - {NON_TERMINAL, "VARIABLE_TYPE1"}, - {NON_TERMINAL, "VARIABLE_TYPE1"}, - {NON_TERMINAL, "VARIABLE_TYPE1"}, - {NON_TERMINAL, "VARIABLE_TYPE1"}, - {NON_TERMINAL, "VARIABLE_TYPE1"}, - {NON_TERMINAL, "VARIABLE_TYPE1"}, - {NON_TERMINAL, "VARIABLE_TYPE1"}, - {NON_TERMINAL, "VARIABLE_TYPE1"}, - {NON_TERMINAL, "VARIABLE_TYPE1"}, + {NON_TERMINAL, "VARIABLE_TYPE2"}, {NON_TERMINAL, "VARIABLE_TYPE2"}, {NON_TERMINAL, "VARIABLE_TYPE2"}, {NON_TERMINAL, "VARIABLE_TYPE3"}, {NON_TERMINAL, "VARIABLE_TYPE4"}, {NON_TERMINAL, "VARIABLE_TYPE4"}, + {NON_TERMINAL, "ARRAY_DIMS"}, + {NON_TERMINAL, "ARRAY_DIMS2"}, + {NON_TERMINAL, "ARRAY_DIMS2"}, + {NON_TERMINAL, "ARRAY_INIT"}, + {NON_TERMINAL, "INIT_LIST"}, + {NON_TERMINAL, "INIT_ITEM"}, + {NON_TERMINAL, "INIT_ITEM"}, + {NON_TERMINAL, "INIT_LIST_TAIL"}, + {NON_TERMINAL, "INIT_LIST_TAIL"}, + {NON_TERMINAL, "INIT_LIST_CONT"}, + {NON_TERMINAL, "INIT_LIST_CONT"}, + {NON_TERMINAL, "VARIABLE_TYPE4"}, {NON_TERMINAL, "VARIABLE_TYPE5"}, {NON_TERMINAL, "VARIABLE_TYPE5"}, {NON_TERMINAL, "VARIABLE_TYPE6"}, {NON_TERMINAL, "VARIABLE_TYPE6"}, - {NON_TERMINAL, "L_VALUE2"}, - {NON_TERMINAL, "L_VALUE2"}, - {NON_TERMINAL, "CALL_USER_DEFINED_FUNCTION_PARAMETER"}, - {NON_TERMINAL, "CALL_USER_DEFINED_FUNCTION_PARAMETER"}, - {NON_TERMINAL, "CALL_USER_DEFINED_FUNCTION_PARAMETER2"}, - {NON_TERMINAL, "CALL_USER_DEFINED_FUNCTION_PARAMETER2"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT"}, + {NON_TERMINAL, "ARRAY_DIMS_WRITE_OPT"}, + {NON_TERMINAL, "ARRAY_DIMS_WRITE_OPT"}, + {NON_TERMINAL, "ARRAY_DIMS_WRITE"}, + {NON_TERMINAL, "ARRAY_DIMS_WRITE2"}, + {NON_TERMINAL, "ARRAY_DIMS_WRITE2"}, {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, + {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, {NON_TERMINAL, "CALL_FUNC_STATEMENT"}, @@ -121,13 +161,26 @@ const struct _TOKEN Lhs[RULES_COUNT]= {NON_TERMINAL, "SIMPLE_ASSIGNMENT"}, {NON_TERMINAL, "SIMPLE_ASSIGNMENT"}, {NON_TERMINAL, "SIMPLE_ASSIGNMENT"}, - {NON_TERMINAL, "SIMPLE_ASSIGNMENT'"}, {NON_TERMINAL, "INC_DEC"}, {NON_TERMINAL, "INC_DEC'"}, {NON_TERMINAL, "INC_DEC'"}, {NON_TERMINAL, "INC_DEC'"}, {NON_TERMINAL, "INC_DEC'"}, + {NON_TERMINAL, "INC_DEC'"}, + {NON_TERMINAL, "INC_DEC'"}, + {NON_TERMINAL, "INC_DEC'"}, + {NON_TERMINAL, "INC_DEC'"}, + {NON_TERMINAL, "INC_DEC'"}, + {NON_TERMINAL, "INC_DEC'"}, + {NON_TERMINAL, "INC_DEC'"}, + {NON_TERMINAL, "INC_DEC'"}, + {NON_TERMINAL, "INC_DEC'"}, + {NON_TERMINAL, "INC_DEC'"}, {NON_TERMINAL, "BOOLEAN_EXPRESSION"}, + {NON_TERMINAL, "MULTIPLE_ASSIGNMENT"}, + {NON_TERMINAL, "MULTIPLE_ASSIGNMENT"}, + {NON_TERMINAL, "MULTIPLE_ASSIGNMENT2"}, + {NON_TERMINAL, "MULTIPLE_ASSIGNMENT2"}, {NON_TERMINAL, "EXPRESSION"}, {NON_TERMINAL, "E0'"}, {NON_TERMINAL, "E0'"}, @@ -181,8 +234,6 @@ const struct _TOKEN Lhs[RULES_COUNT]= {NON_TERMINAL, "E12"}, {NON_TERMINAL, "E12"}, {NON_TERMINAL, "E12"}, - {NON_TERMINAL, "E13"}, - {NON_TERMINAL, "E13"}, {NON_TERMINAL, "E12"}, {NON_TERMINAL, "E12"}, {NON_TERMINAL, "E12"}, @@ -193,18 +244,49 @@ const struct _TOKEN Lhs[RULES_COUNT]= {NON_TERMINAL, "E12"}, {NON_TERMINAL, "E12"}, {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "ARRAY_DIMS_READ_OPT"}, + {NON_TERMINAL, "ARRAY_DIMS_READ_OPT"}, + {NON_TERMINAL, "ARRAY_DIMS_READ"}, + {NON_TERMINAL, "ARRAY_DIMS_READ2"}, + {NON_TERMINAL, "ARRAY_DIMS_READ2"}, + {NON_TERMINAL, "CONST_NUMBER"}, + {NON_TERMINAL, "CONST_NUMBER"}, + {NON_TERMINAL, "CONST_NUMBER"}, + {NON_TERMINAL, "CONST_NUMBER"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, {NON_TERMINAL, "STRING"}, {NON_TERMINAL, "WSTRING"}, {NON_TERMINAL, "L_VALUE"}, {NON_TERMINAL, "L_VALUE"}, {NON_TERMINAL, "L_VALUE"}, {NON_TERMINAL, "L_VALUE"}, + {NON_TERMINAL, "VA2"}, + {NON_TERMINAL, "VA2"}, + {NON_TERMINAL, "VA3"}, + {NON_TERMINAL, "VA3"}, {NON_TERMINAL, "StringNumber"}, {NON_TERMINAL, "StringNumber"}, {NON_TERMINAL, "WstringNumber"}, {NON_TERMINAL, "WstringNumber"} }; -const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= +const struct _SCRIPT_ENGINE_TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= { {{NON_TERMINAL, "STATEMENT"},{NON_TERMINAL, "S"}}, {{SPECIAL_TOKEN, "{"},{NON_TERMINAL, "STATEMENT"},{NON_TERMINAL, "S"},{SPECIAL_TOKEN, "}"}}, @@ -213,11 +295,13 @@ const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= {{NON_TERMINAL, "WHILE_STATEMENT"}}, {{NON_TERMINAL, "DO_WHILE_STATEMENT"}}, {{NON_TERMINAL, "FOR_STATEMENT"}}, - {{NON_TERMINAL, "L_VALUE"},{NON_TERMINAL, "L_VALUE2"}}, + {{NON_TERMINAL, "ASSIGNMENT_STATEMENT"},{SPECIAL_TOKEN, ";"}}, + {{SEMANTIC_RULE, "@PUSH"},{FUNCTION_ID, "_function_id"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "VA2"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE"},{SPECIAL_TOKEN, ";"}}, {{NON_TERMINAL, "CALL_FUNC_STATEMENT"},{SPECIAL_TOKEN, ";"}}, {{KEYWORD, "break"},{SEMANTIC_RULE, "@BREAK"},{SPECIAL_TOKEN, ";"}}, {{KEYWORD, "continue"},{SEMANTIC_RULE, "@CONTINUE"},{SPECIAL_TOKEN, ";"}}, {{NON_TERMINAL, "VARIABLE_TYPE3"}}, + {{KEYWORD, "#include"},{NON_TERMINAL, "STRING"},{SEMANTIC_RULE, "@INCLUDE"},{SPECIAL_TOKEN, ";"}}, {{NON_TERMINAL, "STATEMENT2"},{NON_TERMINAL, "S2"}}, {{SPECIAL_TOKEN, "{"},{NON_TERMINAL, "STATEMENT2"},{NON_TERMINAL, "S2"},{SPECIAL_TOKEN, "}"}}, {{EPSILON, "eps"}}, @@ -225,42 +309,58 @@ const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= {{NON_TERMINAL, "WHILE_STATEMENT"}}, {{NON_TERMINAL, "DO_WHILE_STATEMENT"}}, {{NON_TERMINAL, "FOR_STATEMENT"}}, - {{NON_TERMINAL, "L_VALUE"},{NON_TERMINAL, "L_VALUE2"}}, + {{NON_TERMINAL, "ASSIGNMENT_STATEMENT"},{SPECIAL_TOKEN, ";"}}, + {{SEMANTIC_RULE, "@PUSH"},{FUNCTION_ID, "_function_id"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "VA2"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE"},{SPECIAL_TOKEN, ";"}}, {{NON_TERMINAL, "CALL_FUNC_STATEMENT"},{SPECIAL_TOKEN, ";"}}, {{KEYWORD, "break"},{SEMANTIC_RULE, "@BREAK"},{SPECIAL_TOKEN, ";"}}, {{KEYWORD, "continue"},{SEMANTIC_RULE, "@CONTINUE"},{SPECIAL_TOKEN, ";"}}, - {{NON_TERMINAL, "VARIABLE_TYPE1"},{NON_TERMINAL, "VARIABLE_TYPE2"},{NON_TERMINAL, "L_VALUE"},{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MOV"},{SPECIAL_TOKEN, ";"}}, + {{NON_TERMINAL, "VARIABLE_TYPE1"},{NON_TERMINAL, "VARIABLE_TYPE2"},{NON_TERMINAL, "L_VALUE"},{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "MULTIPLE_ASSIGNMENT"},{SPECIAL_TOKEN, ";"}}, {{KEYWORD, "return"},{NON_TERMINAL, "RETURN"},{SPECIAL_TOKEN, ";"}}, {{EPSILON, "eps"},{SEMANTIC_RULE, "@RETURN_OF_USER_DEFINED_FUNCTION_WITHOUT_VALUE"}}, {{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE"}}, - {{SEMANTIC_RULE, "@VOID"},{KEYWORD, "void"}}, - {{SEMANTIC_RULE, "@BOOL"},{KEYWORD, "bool"}}, - {{SEMANTIC_RULE, "@CHAR"},{KEYWORD, "char"}}, - {{SEMANTIC_RULE, "@SHORT"},{KEYWORD, "short"}}, - {{SEMANTIC_RULE, "@INT"},{KEYWORD, "int"}}, - {{SEMANTIC_RULE, "@LONG"},{KEYWORD, "long"}}, - {{SEMANTIC_RULE, "@UNSIGNED"},{KEYWORD, "unsigned"}}, - {{SEMANTIC_RULE, "@SIGNED"},{KEYWORD, "signed"}}, - {{SEMANTIC_RULE, "@FLOAT"},{KEYWORD, "float"}}, - {{SEMANTIC_RULE, "@DOUBLE"},{KEYWORD, "double"}}, - {{NON_TERMINAL, "VARIABLE_TYPE1"}}, + {{SEMANTIC_RULE, "@PUSH"},{SCRIPT_VARIABLE_TYPE, "_script_variable_type"}}, + {{NON_TERMINAL, "VARIABLE_TYPE1"},{NON_TERMINAL, "VARIABLE_TYPE2"}}, + {{SPECIAL_TOKEN, "*"},{SEMANTIC_RULE, "@DECLARE_POINTER_TYPE"}}, {{EPSILON, "eps"}}, {{NON_TERMINAL, "VARIABLE_TYPE1"},{NON_TERMINAL, "VARIABLE_TYPE2"},{NON_TERMINAL, "L_VALUE"},{NON_TERMINAL, "VARIABLE_TYPE4"}}, - {{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MOV"},{SPECIAL_TOKEN, ";"}}, + {{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "MULTIPLE_ASSIGNMENT"},{SPECIAL_TOKEN, ";"}}, + {{SEMANTIC_RULE, "@ARRAY_L_VALUE"},{NON_TERMINAL, "ARRAY_DIMS"},{SPECIAL_TOKEN, "="},{NON_TERMINAL, "ARRAY_INIT"},{SEMANTIC_RULE, "@ARRAY_DECLARITION"},{SPECIAL_TOKEN, ";"}}, + {{SPECIAL_TOKEN, "["},{NON_TERMINAL, "CONST_NUMBER"},{SEMANTIC_RULE, "@ARRAY_DIM_NUMBER"},{SPECIAL_TOKEN, "]"},{NON_TERMINAL, "ARRAY_DIMS2"}}, + {{NON_TERMINAL, "ARRAY_DIMS"}}, + {{EPSILON, "eps"}}, + {{SPECIAL_TOKEN, "{"},{NON_TERMINAL, "INIT_LIST"},{SPECIAL_TOKEN, "}"},{SEMANTIC_RULE, "@ARRAY_LEFT_BRACKET"}}, + {{NON_TERMINAL, "INIT_ITEM"},{NON_TERMINAL, "INIT_LIST_TAIL"}}, + {{NON_TERMINAL, "ARRAY_INIT"}}, + {{NON_TERMINAL, "EXPRESSION"}}, + {{SPECIAL_TOKEN, ","},{NON_TERMINAL, "INIT_LIST_CONT"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "INIT_ITEM"},{NON_TERMINAL, "INIT_LIST_TAIL"}}, + {{EPSILON, "eps"}}, {{SEMANTIC_RULE, "@START_OF_USER_DEFINED_FUNCTION"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "VARIABLE_TYPE5"},{SPECIAL_TOKEN, ")"},{SPECIAL_TOKEN, "{"},{NON_TERMINAL, "S2"},{SEMANTIC_RULE, "@END_OF_USER_DEFINED_FUNCTION"},{SPECIAL_TOKEN, "}"}}, {{EPSILON, "eps"}}, {{NON_TERMINAL, "VARIABLE_TYPE1"},{NON_TERMINAL, "VARIABLE_TYPE2"},{NON_TERMINAL, "L_VALUE"},{SEMANTIC_RULE, "@FUNCTION_PARAMETER"},{NON_TERMINAL, "VARIABLE_TYPE6"}}, {{SPECIAL_TOKEN, ","},{NON_TERMINAL, "VARIABLE_TYPE1"},{NON_TERMINAL, "VARIABLE_TYPE2"},{NON_TERMINAL, "L_VALUE"},{SEMANTIC_RULE, "@FUNCTION_PARAMETER"},{NON_TERMINAL, "VARIABLE_TYPE6"}}, {{EPSILON, "eps"}}, - {{NON_TERMINAL, "ASSIGNMENT_STATEMENT'"},{SPECIAL_TOKEN, ";"}}, - {{SEMANTIC_RULE, "@CALL_USER_DEFINED_FUNCTION"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "CALL_USER_DEFINED_FUNCTION_PARAMETER"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE"},{SPECIAL_TOKEN, ";"}}, - {{EPSILON, "eps"}}, - {{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@CALL_USER_DEFINED_FUNCTION_PARAMETER"},{NON_TERMINAL, "CALL_USER_DEFINED_FUNCTION_PARAMETER2"}}, - {{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@CALL_USER_DEFINED_FUNCTION_PARAMETER"},{NON_TERMINAL, "CALL_USER_DEFINED_FUNCTION_PARAMETER2"}}, + {{SPECIAL_TOKEN, "*"},{NON_TERMINAL, "L_VALUE"},{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DEREFERENCE"}}, + {{NON_TERMINAL, "L_VALUE"},{NON_TERMINAL, "ARRAY_DIMS_WRITE_OPT"},{NON_TERMINAL, "ASSIGNMENT_STATEMENT'"}}, + {{NON_TERMINAL, "ARRAY_DIMS_WRITE"}}, {{EPSILON, "eps"}}, + {{SPECIAL_TOKEN, "["},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ARRAY_DIM_NUMBER"},{SPECIAL_TOKEN, "]"},{NON_TERMINAL, "ARRAY_DIMS_WRITE2"}}, + {{NON_TERMINAL, "ARRAY_DIMS_WRITE"}}, + {{EPSILON, "eps"},{SEMANTIC_RULE, "@ARRAY_INDEX_WRITE"}}, {{SPECIAL_TOKEN, "++"},{SEMANTIC_RULE, "@INC"}}, {{SPECIAL_TOKEN, "--"},{SEMANTIC_RULE, "@DEC"}}, - {{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MOV"}}, + {{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "MULTIPLE_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "+="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ADD_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "-="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@SUB_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "*="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MUL_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "/="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DIV_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "%="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MOD_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "<<="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ASL_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, ">>="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ASR_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "&="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@AND_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "^="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@XOR_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "|="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@OR_ASSIGNMENT"}}, {{KEYWORD, "print"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@PRINT"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "formats"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@FORMATS"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "event_enable"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EVENT_ENABLE"},{SPECIAL_TOKEN, ")"}}, @@ -270,6 +370,7 @@ const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= {{KEYWORD, "spinlock_lock"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@SPINLOCK_LOCK"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "spinlock_unlock"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@SPINLOCK_UNLOCK"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "event_sc"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EVENT_SC"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "microsleep"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MICROSLEEP"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "printf"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "STRING"},{SEMANTIC_RULE, "@VARGSTART"},{NON_TERMINAL, "VA"},{SEMANTIC_RULE, "@PRINTF"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "pause"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@PAUSE"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "flush"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@FLUSH"},{SPECIAL_TOKEN, ")"}}, @@ -278,6 +379,13 @@ const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= {{KEYWORD, "event_trace_step_out"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@EVENT_TRACE_STEP_OUT"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "event_trace_instrumentation_step"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@EVENT_TRACE_INSTRUMENTATION_STEP"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "event_trace_instrumentation_step_in"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@EVENT_TRACE_INSTRUMENTATION_STEP_IN"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "rdtsc"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@RDTSC"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "rdtscp"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@RDTSCP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "lbr_save"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@LBR_SAVE"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "lbr_dump"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@LBR_DUMP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "lbr_print"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@LBR_PRINT"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "lbr_restore"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@LBR_RESTORE"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "lbr_check"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@LBR_CHECK"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "spinlock_lock_custom_wait"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@SPINLOCK_LOCK_CUSTOM_WAIT"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "event_inject"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EVENT_INJECT"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "poi"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@POI"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, @@ -298,19 +406,33 @@ const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= {{KEYWORD, "reference"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@REFERENCE"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "physical_to_virtual"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@PHYSICAL_TO_VIRTUAL"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "virtual_to_physical"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@VIRTUAL_TO_PHYSICAL"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "poi_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@POI_PA"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "hi_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@HI_PA"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "low_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@LOW_PA"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "db_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DB_PA"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "dd_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DD_PA"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "dw_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DW_PA"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "dq_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DQ_PA"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "lbr_restore_by_filter"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@LBR_RESTORE_BY_FILTER"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "ed"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ED"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "eb"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EB"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "eq"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EQ"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "interlocked_exchange"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@INTERLOCKED_EXCHANGE"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "interlocked_exchange_add"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@INTERLOCKED_EXCHANGE_ADD"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "eb_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EB_PA"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "ed_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ED_PA"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "eq_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EQ_PA"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "interlocked_compare_exchange"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@INTERLOCKED_COMPARE_EXCHANGE"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "strlen"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SEMANTIC_RULE, "@STRLEN"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "strcmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "StringNumber"},{SEMANTIC_RULE, "@STRCMP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "memcmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MEMCMP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, + {{KEYWORD, "strncmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@STRNCMP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "wcslen"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "WstringNumber"},{SEMANTIC_RULE, "@WCSLEN"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "wcscmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "WstringNumber"},{SEMANTIC_RULE, "@WCSCMP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{KEYWORD, "event_inject_error_code"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EVENT_INJECT_ERROR_CODE"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "memcpy"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MEMCPY"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "memcpy_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MEMCPY_PA"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "wcsncmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@WCSNCMP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@IGNORE_LVALUE"}}, {{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "VA"}}, {{EPSILON, "eps"}}, {{KEYWORD, "if"},{SEMANTIC_RULE, "@START_OF_IF"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "BOOLEAN_EXPRESSION"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@JZ"},{SPECIAL_TOKEN, "{"},{NON_TERMINAL, "S2"},{SPECIAL_TOKEN, "}"},{NON_TERMINAL, "ELSIF_STATEMENT"},{NON_TERMINAL, "ELSE_STATEMENT"},{SEMANTIC_RULE, "@END_OF_IF"},{NON_TERMINAL, "END_OF_IF"}}, @@ -323,16 +445,29 @@ const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= {{KEYWORD, "while"},{SEMANTIC_RULE, "@START_OF_WHILE"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "BOOLEAN_EXPRESSION"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@START_OF_WHILE_COMMANDS"},{SPECIAL_TOKEN, "{"},{NON_TERMINAL, "S2"},{SEMANTIC_RULE, "@END_OF_WHILE"},{SPECIAL_TOKEN, "}"}}, {{KEYWORD, "do"},{SEMANTIC_RULE, "@START_OF_DO_WHILE"},{SPECIAL_TOKEN, "{"},{NON_TERMINAL, "S2"},{SPECIAL_TOKEN, "}"},{KEYWORD, "while"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "BOOLEAN_EXPRESSION"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@END_OF_DO_WHILE"},{SPECIAL_TOKEN, ";"}}, {{KEYWORD, "for"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "SIMPLE_ASSIGNMENT"},{SPECIAL_TOKEN, ";"},{SEMANTIC_RULE, "@START_OF_FOR"},{NON_TERMINAL, "BOOLEAN_EXPRESSION"},{SPECIAL_TOKEN, ";"},{SEMANTIC_RULE, "@FOR_INC_DEC"},{NON_TERMINAL, "INC_DEC"},{SPECIAL_TOKEN, ")"},{SPECIAL_TOKEN, "{"},{SEMANTIC_RULE, "@START_OF_FOR_COMMANDS"},{NON_TERMINAL, "S2"},{SEMANTIC_RULE, "@END_OF_FOR"},{SPECIAL_TOKEN, "}"}}, - {{NON_TERMINAL, "VARIABLE_TYPE1"},{NON_TERMINAL, "VARIABLE_TYPE2"},{NON_TERMINAL, "L_VALUE"},{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MOV"},{NON_TERMINAL, "SIMPLE_ASSIGNMENT'"}}, - {{NON_TERMINAL, "L_VALUE"},{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MOV"},{NON_TERMINAL, "SIMPLE_ASSIGNMENT'"}}, - {{EPSILON, "eps"}}, + {{NON_TERMINAL, "VARIABLE_TYPE1"},{NON_TERMINAL, "VARIABLE_TYPE2"},{NON_TERMINAL, "L_VALUE"},{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "MULTIPLE_ASSIGNMENT"}}, + {{NON_TERMINAL, "L_VALUE"},{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "MULTIPLE_ASSIGNMENT"}}, {{EPSILON, "eps"}}, {{NON_TERMINAL, "L_VALUE"},{NON_TERMINAL, "INC_DEC'"}}, {{SPECIAL_TOKEN, "++"},{SEMANTIC_RULE, "@INC"}}, {{SPECIAL_TOKEN, "--"},{SEMANTIC_RULE, "@DEC"}}, - {{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MOV"},{NON_TERMINAL, "SIMPLE_ASSIGNMENT'"}}, + {{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "MULTIPLE_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "+="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ADD_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "-="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@SUB_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "*="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MUL_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "/="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DIV_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "%="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MOD_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "<<="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ASL_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, ">>="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ASR_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "&="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@AND_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "^="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@XOR_ASSIGNMENT"}}, + {{SPECIAL_TOKEN, "|="},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@OR_ASSIGNMENT"}}, {{EPSILON, "eps"}}, {{EPSILON, "eps"}}, + {{EPSILON, "eps"},{SEMANTIC_RULE, "@MOV"}}, + {{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "MULTIPLE_ASSIGNMENT2"}}, + {{SPECIAL_TOKEN, "="},{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "MULTIPLE_ASSIGNMENT2"}}, + {{EPSILON, "eps"},{SEMANTIC_RULE, "@MULTIPLE_ASSIGNMENT"}}, {{NON_TERMINAL, "E1"},{NON_TERMINAL, "E0'"}}, {{SPECIAL_TOKEN, "|"},{NON_TERMINAL, "E1"},{SEMANTIC_RULE, "@OR"},{NON_TERMINAL, "E0'"}}, {{EPSILON, "eps"}}, @@ -355,6 +490,13 @@ const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= {{SPECIAL_TOKEN, "%"},{NON_TERMINAL, "E12"},{SEMANTIC_RULE, "@MOD"},{NON_TERMINAL, "E5'"}}, {{SPECIAL_TOKEN, "*"},{NON_TERMINAL, "E12"},{SEMANTIC_RULE, "@MUL"},{NON_TERMINAL, "E5'"}}, {{EPSILON, "eps"}}, + {{KEYWORD, "rdtsc"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@RDTSC"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "rdtscp"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@RDTSCP"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "lbr_save"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@LBR_SAVE"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "lbr_dump"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@LBR_DUMP"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "lbr_print"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@LBR_PRINT"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "lbr_restore"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@LBR_RESTORE"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "lbr_check"},{SPECIAL_TOKEN, "("},{SEMANTIC_RULE, "@LBR_CHECK"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "poi"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@POI"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "db"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DB"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "dd"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DD"},{SPECIAL_TOKEN, ")"}}, @@ -373,25 +515,43 @@ const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= {{KEYWORD, "reference"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@REFERENCE"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "physical_to_virtual"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@PHYSICAL_TO_VIRTUAL"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "virtual_to_physical"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@VIRTUAL_TO_PHYSICAL"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "poi_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@POI_PA"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "hi_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@HI_PA"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "low_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@LOW_PA"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "db_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DB_PA"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "dd_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DD_PA"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "dw_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DW_PA"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "dq_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@DQ_PA"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "lbr_restore_by_filter"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@LBR_RESTORE_BY_FILTER"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "ed"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ED"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "eb"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EB"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "eq"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EQ"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "interlocked_exchange"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@INTERLOCKED_EXCHANGE"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "interlocked_exchange_add"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@INTERLOCKED_EXCHANGE_ADD"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "eb_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EB_PA"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "ed_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ED_PA"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "eq_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@EQ_PA"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "interlocked_compare_exchange"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@INTERLOCKED_COMPARE_EXCHANGE"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "strlen"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SEMANTIC_RULE, "@STRLEN"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "strcmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "StringNumber"},{SEMANTIC_RULE, "@STRCMP"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "memcmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@MEMCMP"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "strncmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@STRNCMP"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "wcslen"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "WstringNumber"},{SEMANTIC_RULE, "@WCSLEN"},{SPECIAL_TOKEN, ")"}}, {{KEYWORD, "wcscmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "WstringNumber"},{SEMANTIC_RULE, "@WCSCMP"},{SPECIAL_TOKEN, ")"}}, + {{KEYWORD, "wcsncmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@WCSNCMP"},{SPECIAL_TOKEN, ")"}}, {{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXPRESSION"},{SPECIAL_TOKEN, ")"}}, - {{NON_TERMINAL, "L_VALUE"},{NON_TERMINAL, "E13"}}, + {{NON_TERMINAL, "L_VALUE"},{NON_TERMINAL, "ARRAY_DIMS_READ_OPT"}}, + {{SEMANTIC_RULE, "@PUSH"},{FUNCTION_ID, "_function_id"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "VA2"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE"}}, + {{NON_TERMINAL, "ARRAY_DIMS_READ"}}, {{EPSILON, "eps"}}, - {{SEMANTIC_RULE, "@CALL_USER_DEFINED_FUNCTION"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "CALL_USER_DEFINED_FUNCTION_PARAMETER"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE"}}, + {{SPECIAL_TOKEN, "["},{NON_TERMINAL, "EXPRESSION"},{SEMANTIC_RULE, "@ARRAY_DIM_NUMBER"},{SPECIAL_TOKEN, "]"},{NON_TERMINAL, "ARRAY_DIMS_READ2"}}, + {{NON_TERMINAL, "ARRAY_DIMS_READ"}}, + {{EPSILON, "eps"},{SEMANTIC_RULE, "@ARRAY_INDEX_READ"}}, {{SEMANTIC_RULE, "@PUSH"},{HEX, "_hex"}}, {{SEMANTIC_RULE, "@PUSH"},{DECIMAL, "_decimal"}}, {{SEMANTIC_RULE, "@PUSH"},{OCTAL, "_octal"}}, {{SEMANTIC_RULE, "@PUSH"},{BINARY, "_binary"}}, + {{NON_TERMINAL, "CONST_NUMBER"}}, {{SEMANTIC_RULE, "@PUSH"},{PSEUDO_REGISTER, "_pseudo_register"}}, {{SPECIAL_TOKEN, "-"},{NON_TERMINAL, "E12"},{SEMANTIC_RULE, "@NEG"}}, {{SPECIAL_TOKEN, "+"},{NON_TERMINAL, "E12"}}, @@ -404,6 +564,10 @@ const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= {{SEMANTIC_RULE, "@PUSH"},{LOCAL_ID, "_local_id"}}, {{SEMANTIC_RULE, "@PUSH"},{REGISTER, "_register"}}, {{SEMANTIC_RULE, "@PUSH"},{FUNCTION_PARAMETER_ID, "_function_parameter_id"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "VA3"}}, + {{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXPRESSION"},{NON_TERMINAL, "VA3"}}, + {{EPSILON, "eps"}}, {{NON_TERMINAL, "EXPRESSION"}}, {{NON_TERMINAL, "STRING"}}, {{NON_TERMINAL, "EXPRESSION"}}, @@ -419,10 +583,12 @@ const unsigned int RhsSize[RULES_COUNT]= 1, 1, 2, +7, 2, 3, 3, 1, +4, 2, 4, 1, @@ -431,6 +597,7 @@ const unsigned int RhsSize[RULES_COUNT]= 1, 1, 2, +7, 2, 3, 3, @@ -441,30 +608,45 @@ const unsigned int RhsSize[RULES_COUNT]= 2, 2, 2, -2, -2, -2, -2, -2, -2, -2, -1, 1, 4, 4, +6, +5, +1, +1, +4, +2, +1, +1, +2, +1, +2, +1, 8, 1, 5, 6, 1, -2, -6, -1, +5, 3, -4, +1, +1, +5, 1, 2, 2, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, 3, 5, 5, @@ -475,6 +657,7 @@ const unsigned int RhsSize[RULES_COUNT]= 5, 5, 5, +5, 7, 4, 4, @@ -483,6 +666,13 @@ const unsigned int RhsSize[RULES_COUNT]= 4, 4, 4, +5, +5, +5, +5, +5, +5, +5, 7, 7, 6, @@ -503,6 +693,17 @@ const unsigned int RhsSize[RULES_COUNT]= 6, 6, 6, +6, +6, +6, +6, +6, +6, +6, +6, +8, +8, +8, 8, 8, 8, @@ -512,10 +713,13 @@ const unsigned int RhsSize[RULES_COUNT]= 6, 8, 10, +10, 6, 8, 9, 9, +9, +10, 3, 1, 13, @@ -528,56 +732,87 @@ const unsigned int RhsSize[RULES_COUNT]= 10, 11, 15, +6, +4, +1, +2, +2, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +1, +1, +2, +3, +3, +2, +2, +4, +1, +2, +4, +1, +2, +4, +1, +2, +4, +4, +1, +2, +4, +4, +1, +2, +4, +4, +4, +1, +4, +4, +4, +4, +4, +4, +4, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +7, +7, 7, -5, -1, -1, -2, -2, -2, -4, -1, -1, -2, -4, -1, -2, -4, -1, -2, -4, -1, -2, -4, -4, -1, -2, -4, -4, -1, -2, -4, -4, -4, -1, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, 7, 7, 7, @@ -587,17 +822,24 @@ const unsigned int RhsSize[RULES_COUNT]= 5, 7, 9, +9, 5, 7, +9, 3, 2, +6, +1, 1, 5, +1, 2, 2, 2, 2, 2, +1, +2, 3, 2, 3, @@ -610,229 +852,278 @@ const unsigned int RhsSize[RULES_COUNT]= 2, 2, 1, +2, +3, +1, +1, 1, 1, 1 }; const char* NoneTerminalMap[NONETERMINAL_COUNT]= { -"E1'", -"L_VALUE2", -"VARIABLE_TYPE5", -"E5", -"E4'", -"WstringNumber", -"VARIABLE_TYPE1", -"E3'", -"S2", -"E0'", -"STRING", -"RETURN", -"DO_WHILE_STATEMENT", -"INC_DEC'", -"E3", -"END_OF_IF", -"ELSIF_STATEMENT'", -"E1", -"ELSE_STATEMENT", -"S", -"STATEMENT2", -"ELSIF_STATEMENT", -"E2'", -"E4", -"E13", -"VARIABLE_TYPE2", -"E2", -"SIMPLE_ASSIGNMENT", -"E12", -"E5'", -"WHILE_STATEMENT", -"VARIABLE_TYPE6", -"CALL_FUNC_STATEMENT", -"VARIABLE_TYPE3", -"SIMPLE_ASSIGNMENT'", -"INC_DEC", -"StringNumber", -"CALL_USER_DEFINED_FUNCTION_PARAMETER", -"EXPRESSION", -"IF_STATEMENT", -"VA", -"BOOLEAN_EXPRESSION", -"STATEMENT", -"CALL_USER_DEFINED_FUNCTION_PARAMETER2", -"VARIABLE_TYPE4", -"L_VALUE", -"WSTRING", "FOR_STATEMENT", -"ASSIGNMENT_STATEMENT'" +"MULTIPLE_ASSIGNMENT2", +"STATEMENT2", +"E2'", +"WSTRING", +"StringNumber", +"ASSIGNMENT_STATEMENT", +"CONST_NUMBER", +"INIT_LIST", +"IF_STATEMENT", +"END_OF_IF", +"BOOLEAN_EXPRESSION", +"E0'", +"ARRAY_DIMS_WRITE_OPT", +"E2", +"VARIABLE_TYPE2", +"VARIABLE_TYPE5", +"INIT_ITEM", +"ARRAY_DIMS_WRITE2", +"WHILE_STATEMENT", +"MULTIPLE_ASSIGNMENT", +"VARIABLE_TYPE6", +"S", +"INC_DEC", +"ARRAY_DIMS_READ2", +"L_VALUE", +"ARRAY_INIT", +"ARRAY_DIMS_READ_OPT", +"VARIABLE_TYPE3", +"SIMPLE_ASSIGNMENT", +"E3", +"STRING", +"STATEMENT", +"INC_DEC'", +"ASSIGNMENT_STATEMENT'", +"ELSIF_STATEMENT", +"ELSE_STATEMENT", +"E1'", +"VARIABLE_TYPE4", +"CALL_FUNC_STATEMENT", +"WstringNumber", +"E5", +"E4", +"EXPRESSION", +"INIT_LIST_CONT", +"E5'", +"DO_WHILE_STATEMENT", +"VARIABLE_TYPE1", +"E12", +"ARRAY_DIMS", +"VA3", +"VA", +"ARRAY_DIMS2", +"E4'", +"RETURN", +"ARRAY_DIMS_WRITE", +"E1", +"ELSIF_STATEMENT'", +"VA2", +"ARRAY_DIMS_READ", +"INIT_LIST_TAIL", +"E3'", +"S2" }; const char* TerminalMap[TERMINAL_COUNT]= { -"low", -"event_trace_step_in", -"elsif", -"float", -"double", -"interlocked_exchange_add", -"physical_to_virtual", -"printf", -"virtual_to_physical", -"&", "memcpy", -"interlocked_increment", -"if", -"_global_id", -"eb", -"disassemble_len64", -"$", -"interlocked_decrement", -"event_trace_instrumentation_step", -"hi", -"db", -"disassemble_len32", -"wcscmp", -"disassemble_len", -"_string", -"/", -"_function_parameter_id", -";", -"event_inject_error_code", -"signed", -"test_statement", -"(", -"-", -"not", -"flush", -"unsigned", -"check_address", -"interlocked_exchange", -"strcmp", -"interlocked_compare_exchange", -"event_inject", -"for", -"--", -"return", -"+", -"event_trace_instrumentation_step_in", -"neg", -"int", -"_binary", -"pause", -"=", -"{", -"%", -">>", -"++", -"_hex", -"^", -"bool", -"_decimal", -"event_enable", -"<<", -"void", -"~", -"short", -"dq", -"event_clear", -"|", "print", -"poi", -"_octal", -")", +"hi", +"dq", +"check_address", "event_sc", -"event_trace_step", -"_pseudo_register", +"interlocked_increment", +"_string", +">>=", +"virtual_to_physical", +"++", +"rdtsc", +"[", +"_octal", +"^=", +"}", "event_disable", +"memcpy_pa", +"-=", +"^", +"low_pa", +"_wstring", +"db_pa", +"(", +"eb_pa", +"do", +"|", +"/=", +"=", +"pause", +"interlocked_decrement", +"eb", +"lbr_restore", +"--", +"while", +"{", +"interlocked_exchange", +"continue", +"event_trace_step_in", +"%=", +"test_statement", +"_local_id", +"rdtscp", +"_binary", +"*", +"event_clear", +"formats", +"event_inject", +"reference", +"hi_pa", +"wcscmp", +"lbr_check", +"/", +"_function_id", +"low", +"dw_pa", +"lbr_dump", +"else", +"_register", +"]", +"wcslen", +"if", +"-", +"&", +"~", +"break", +"for", +"event_inject_error_code", +"<<", +"lbr_restore_by_filter", +"interlocked_compare_exchange", +"%", +"lbr_print", +"flush", +"$", +"strncmp", +"poi", +"_decimal", +"dd", +"db", +"strlen", +"disassemble_len64", +"return", +"+=", +",", +"strcmp", +"eq_pa", +"lbr_save", +"#include", +"disassemble_len32", +"dq_pa", +"ed_pa", +"|=", +"memcmp", +"spinlock_lock_custom_wait", +"ed", +"_pseudo_register", "spinlock_lock", "eq", -"formats", -"_register", -"}", -"continue", -"*", -"dd", -"char", -"memcmp", -"do", -"while", -"long", -"spinlock_unlock", "dw", +";", +"interlocked_exchange_add", +"wcsncmp", +"+", +"event_trace_instrumentation_step", +"<<=", +"not", +"poi_pa", "event_trace_step_out", -"reference", -"spinlock_lock_custom_wait", -"else", -"break", -",", -"_wstring", -"_local_id", -"ed", -"strlen", -"wcslen" +"physical_to_virtual", +"elsif", +"_global_id", +"_script_variable_type", +"*=", +")", +"event_trace_instrumentation_step_in", +"spinlock_unlock", +"disassemble_len", +"neg", +"&=", +"event_trace_step", +"_hex", +"printf", +"dd_pa", +"event_enable", +"microsleep", +"_function_parameter_id", +">>" }; const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT]= { - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,132 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,131 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,132 ,2147483648 ,2147483648 ,2147483648 ,132 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,132 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,46 ,2147483648 ,2147483648 ,2147483648 ,46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,43 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,43 ,2147483648 ,2147483648 ,2147483648 ,43 ,2147483648 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,43 ,2147483648 ,2147483648 ,2147483648 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {144 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,144 ,144 ,2147483648 ,144 ,144 ,2147483648 ,144 ,2147483648 ,144 ,144 ,144 ,2147483648 ,144 ,2147483648 ,144 ,144 ,144 ,144 ,144 ,2147483648 ,2147483648 ,144 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,144 ,144 ,144 ,2147483648 ,2147483648 ,144 ,144 ,144 ,144 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,144 ,2147483648 ,144 ,2147483648 ,144 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,144 ,2147483648 ,2147483648 ,144 ,2147483648 ,2147483648 ,2147483648 ,144 ,2147483648 ,144 ,2147483648 ,2147483648 ,2147483648 ,144 ,144 ,2147483648 ,2147483648 ,2147483648 ,144 ,2147483648 ,2147483648 ,144 ,2147483648 ,144 ,2147483648 ,2147483648 ,144 ,144 ,2147483648 ,144 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,144 ,2147483648 ,144 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,144 ,144 ,144 ,144 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,143 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,143 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,142 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,141 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,143 ,2147483648 ,2147483648 ,143 ,2147483648 ,2147483648 ,2147483648 ,143 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,143 ,2147483648 ,2147483648 ,2147483648 ,143 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,143 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {200 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,200 ,200 ,2147483648 ,200 ,200 ,2147483648 ,200 ,2147483648 ,200 ,200 ,200 ,2147483648 ,200 ,2147483648 ,200 ,200 ,200 ,200 ,200 ,2147483648 ,2147483648 ,200 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,200 ,200 ,200 ,2147483648 ,2147483648 ,200 ,200 ,200 ,200 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,200 ,2147483648 ,200 ,2147483648 ,200 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,200 ,2147483648 ,2147483648 ,200 ,2147483648 ,2147483648 ,2147483648 ,200 ,2147483648 ,200 ,2147483648 ,2147483648 ,2147483648 ,200 ,200 ,2147483648 ,2147483648 ,2147483648 ,200 ,2147483648 ,2147483648 ,200 ,2147483648 ,200 ,2147483648 ,2147483648 ,200 ,200 ,2147483648 ,200 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,200 ,2147483648 ,200 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,201 ,200 ,200 ,200 ,200 }, - {2147483648 ,2147483648 ,2147483648 ,35 ,36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,28 ,2147483648 ,2147483648 ,2147483648 ,27 ,2147483648 ,30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,29 ,2147483648 ,2147483648 ,2147483648 ,32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,139 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,139 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,137 ,2147483648 ,2147483648 ,139 ,2147483648 ,2147483648 ,2147483648 ,138 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,139 ,2147483648 ,2147483648 ,2147483648 ,139 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,139 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {12 ,12 ,2147483648 ,12 ,12 ,12 ,12 ,12 ,12 ,2147483648 ,12 ,12 ,12 ,12 ,12 ,12 ,2147483648 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,2147483648 ,2147483648 ,12 ,2147483648 ,12 ,12 ,12 ,2147483648 ,2147483648 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,2147483648 ,12 ,2147483648 ,12 ,12 ,12 ,2147483648 ,12 ,2147483648 ,13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,12 ,2147483648 ,12 ,2147483648 ,12 ,2147483648 ,12 ,12 ,12 ,2147483648 ,12 ,12 ,2147483648 ,2147483648 ,12 ,12 ,2147483648 ,12 ,12 ,12 ,12 ,12 ,14 ,12 ,2147483648 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,2147483648 ,12 ,2147483648 ,2147483648 ,12 ,12 ,12 ,12 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,129 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,128 ,2147483648 ,2147483648 ,2147483648 ,129 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,129 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,26 ,26 ,2147483648 ,26 ,26 ,2147483648 ,26 ,2147483648 ,26 ,26 ,26 ,2147483648 ,26 ,2147483648 ,26 ,26 ,26 ,26 ,26 ,2147483648 ,2147483648 ,26 ,25 ,2147483648 ,2147483648 ,2147483648 ,26 ,26 ,26 ,2147483648 ,2147483648 ,26 ,26 ,26 ,26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,26 ,2147483648 ,26 ,2147483648 ,26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,26 ,2147483648 ,2147483648 ,26 ,2147483648 ,2147483648 ,2147483648 ,26 ,2147483648 ,26 ,2147483648 ,2147483648 ,2147483648 ,26 ,26 ,2147483648 ,2147483648 ,2147483648 ,26 ,2147483648 ,2147483648 ,26 ,2147483648 ,26 ,2147483648 ,2147483648 ,26 ,26 ,2147483648 ,26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,26 ,2147483648 ,26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,26 ,26 ,26 ,26 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,123 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,124 ,2147483648 ,2147483648 ,2147483648 ,122 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,125 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {136 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,136 ,136 ,2147483648 ,136 ,136 ,2147483648 ,136 ,2147483648 ,136 ,136 ,136 ,2147483648 ,136 ,2147483648 ,136 ,136 ,136 ,136 ,136 ,2147483648 ,2147483648 ,136 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,136 ,136 ,136 ,2147483648 ,2147483648 ,136 ,136 ,136 ,136 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,136 ,2147483648 ,136 ,2147483648 ,136 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,136 ,2147483648 ,2147483648 ,136 ,2147483648 ,2147483648 ,2147483648 ,136 ,2147483648 ,136 ,2147483648 ,2147483648 ,2147483648 ,136 ,136 ,2147483648 ,2147483648 ,2147483648 ,136 ,2147483648 ,2147483648 ,136 ,2147483648 ,136 ,2147483648 ,2147483648 ,136 ,136 ,2147483648 ,136 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,136 ,2147483648 ,136 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,136 ,136 ,136 ,136 }, - {113 ,113 ,2147483648 ,113 ,113 ,113 ,113 ,113 ,113 ,2147483648 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,2147483648 ,2147483648 ,113 ,2147483648 ,113 ,113 ,113 ,2147483648 ,2147483648 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,2147483648 ,113 ,2147483648 ,113 ,113 ,113 ,2147483648 ,113 ,2147483648 ,113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,113 ,2147483648 ,113 ,2147483648 ,113 ,2147483648 ,113 ,113 ,113 ,2147483648 ,113 ,113 ,2147483648 ,2147483648 ,113 ,113 ,2147483648 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,2147483648 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,113 ,2147483648 ,113 ,2147483648 ,2147483648 ,113 ,113 ,113 ,113 }, - {110 ,110 ,2147483648 ,110 ,110 ,110 ,110 ,110 ,110 ,2147483648 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,2147483648 ,2147483648 ,110 ,2147483648 ,110 ,110 ,110 ,2147483648 ,2147483648 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,2147483648 ,110 ,2147483648 ,110 ,110 ,110 ,2147483648 ,110 ,2147483648 ,110 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,110 ,2147483648 ,110 ,2147483648 ,110 ,2147483648 ,110 ,110 ,110 ,2147483648 ,110 ,110 ,2147483648 ,2147483648 ,110 ,110 ,2147483648 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,2147483648 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,110 ,2147483648 ,2147483648 ,110 ,110 ,110 ,110 }, - {130 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,130 ,130 ,2147483648 ,130 ,130 ,2147483648 ,130 ,2147483648 ,130 ,130 ,130 ,2147483648 ,130 ,2147483648 ,130 ,130 ,130 ,130 ,130 ,2147483648 ,2147483648 ,130 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,130 ,130 ,130 ,2147483648 ,2147483648 ,130 ,130 ,130 ,130 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,130 ,2147483648 ,130 ,2147483648 ,130 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,130 ,2147483648 ,2147483648 ,130 ,2147483648 ,2147483648 ,2147483648 ,130 ,2147483648 ,130 ,2147483648 ,2147483648 ,2147483648 ,130 ,130 ,2147483648 ,2147483648 ,2147483648 ,130 ,2147483648 ,2147483648 ,130 ,2147483648 ,130 ,2147483648 ,2147483648 ,130 ,130 ,2147483648 ,130 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,130 ,2147483648 ,130 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,130 ,130 ,130 ,130 }, - {112 ,112 ,2147483648 ,112 ,112 ,112 ,112 ,112 ,112 ,2147483648 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,2147483648 ,2147483648 ,112 ,2147483648 ,112 ,112 ,112 ,2147483648 ,2147483648 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,2147483648 ,112 ,2147483648 ,112 ,112 ,112 ,2147483648 ,112 ,2147483648 ,112 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,112 ,2147483648 ,112 ,2147483648 ,112 ,2147483648 ,112 ,112 ,112 ,2147483648 ,112 ,112 ,2147483648 ,2147483648 ,112 ,112 ,2147483648 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,2147483648 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,112 ,111 ,112 ,2147483648 ,2147483648 ,112 ,112 ,112 ,112 }, - {0 ,0 ,2147483648 ,0 ,0 ,0 ,0 ,0 ,0 ,2147483648 ,0 ,0 ,0 ,0 ,0 ,0 ,2 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,2147483648 ,2147483648 ,0 ,2147483648 ,0 ,0 ,0 ,2147483648 ,2147483648 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,2147483648 ,2147483648 ,2147483648 ,0 ,0 ,0 ,2147483648 ,0 ,2147483648 ,1 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,0 ,2147483648 ,0 ,2147483648 ,0 ,2147483648 ,0 ,0 ,0 ,2147483648 ,0 ,0 ,2147483648 ,2147483648 ,0 ,0 ,2147483648 ,0 ,0 ,0 ,0 ,0 ,2 ,0 ,2147483648 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,2147483648 ,0 ,2147483648 ,2147483648 ,0 ,0 ,0 ,0 }, - {20 ,20 ,2147483648 ,23 ,23 ,20 ,20 ,20 ,20 ,2147483648 ,20 ,20 ,15 ,19 ,20 ,20 ,2147483648 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,2147483648 ,2147483648 ,19 ,2147483648 ,20 ,23 ,20 ,2147483648 ,2147483648 ,20 ,20 ,23 ,20 ,20 ,20 ,20 ,20 ,18 ,2147483648 ,24 ,2147483648 ,20 ,20 ,23 ,2147483648 ,20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,23 ,2147483648 ,20 ,2147483648 ,23 ,2147483648 ,23 ,20 ,20 ,2147483648 ,20 ,20 ,2147483648 ,2147483648 ,20 ,20 ,2147483648 ,20 ,20 ,20 ,20 ,19 ,2147483648 ,22 ,2147483648 ,20 ,23 ,20 ,17 ,16 ,23 ,20 ,20 ,20 ,20 ,20 ,2147483648 ,21 ,2147483648 ,2147483648 ,19 ,20 ,20 ,20 }, - {109 ,109 ,108 ,109 ,109 ,109 ,109 ,109 ,109 ,2147483648 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,2147483648 ,2147483648 ,109 ,2147483648 ,109 ,109 ,109 ,2147483648 ,2147483648 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,2147483648 ,109 ,2147483648 ,109 ,109 ,109 ,2147483648 ,109 ,2147483648 ,109 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,109 ,2147483648 ,109 ,2147483648 ,109 ,2147483648 ,109 ,109 ,109 ,2147483648 ,109 ,109 ,2147483648 ,2147483648 ,109 ,109 ,2147483648 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,2147483648 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,109 ,2147483648 ,2147483648 ,109 ,109 ,109 ,109 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,134 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,135 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,135 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,135 ,2147483648 ,2147483648 ,2147483648 ,135 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,135 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {140 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,140 ,140 ,2147483648 ,140 ,140 ,2147483648 ,140 ,2147483648 ,140 ,140 ,140 ,2147483648 ,140 ,2147483648 ,140 ,140 ,140 ,140 ,140 ,2147483648 ,2147483648 ,140 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,140 ,140 ,140 ,2147483648 ,2147483648 ,140 ,140 ,140 ,140 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,140 ,2147483648 ,140 ,2147483648 ,140 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,140 ,2147483648 ,2147483648 ,140 ,2147483648 ,2147483648 ,2147483648 ,140 ,2147483648 ,140 ,2147483648 ,2147483648 ,2147483648 ,140 ,140 ,2147483648 ,2147483648 ,2147483648 ,140 ,2147483648 ,2147483648 ,140 ,2147483648 ,140 ,2147483648 ,2147483648 ,140 ,140 ,2147483648 ,140 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,140 ,2147483648 ,140 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,140 ,140 ,140 ,140 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,181 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,180 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,37 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,38 ,2147483648 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,37 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,38 ,2147483648 ,2147483648 ,2147483648 }, - {133 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,133 ,133 ,2147483648 ,133 ,133 ,2147483648 ,133 ,2147483648 ,133 ,133 ,133 ,2147483648 ,133 ,2147483648 ,133 ,133 ,133 ,133 ,133 ,2147483648 ,2147483648 ,133 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,133 ,133 ,133 ,2147483648 ,2147483648 ,133 ,133 ,133 ,133 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,133 ,2147483648 ,133 ,2147483648 ,133 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,133 ,2147483648 ,2147483648 ,133 ,2147483648 ,2147483648 ,2147483648 ,133 ,2147483648 ,133 ,2147483648 ,2147483648 ,2147483648 ,133 ,133 ,2147483648 ,2147483648 ,2147483648 ,133 ,2147483648 ,2147483648 ,133 ,2147483648 ,133 ,2147483648 ,2147483648 ,133 ,133 ,2147483648 ,133 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,133 ,2147483648 ,133 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,133 ,133 ,133 ,133 }, - {2147483648 ,2147483648 ,2147483648 ,117 ,117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,118 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,118 ,119 ,2147483648 ,117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,117 ,2147483648 ,2147483648 ,2147483648 ,117 ,2147483648 ,117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,118 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,117 ,2147483648 ,2147483648 ,2147483648 ,117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,118 ,2147483648 ,2147483648 ,2147483648 }, - {156 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,171 ,165 ,2147483648 ,166 ,191 ,2147483648 ,162 ,2147483648 ,179 ,168 ,161 ,2147483648 ,163 ,2147483648 ,155 ,150 ,160 ,177 ,159 ,2147483648 ,2147483648 ,179 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,178 ,187 ,157 ,2147483648 ,2147483648 ,158 ,170 ,174 ,172 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,188 ,2147483648 ,154 ,2147483648 ,185 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,182 ,2147483648 ,2147483648 ,183 ,2147483648 ,2147483648 ,2147483648 ,189 ,2147483648 ,153 ,2147483648 ,2147483648 ,2147483648 ,149 ,184 ,2147483648 ,2147483648 ,2147483648 ,186 ,2147483648 ,2147483648 ,169 ,2147483648 ,179 ,2147483648 ,2147483648 ,190 ,151 ,2147483648 ,175 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,152 ,2147483648 ,164 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,179 ,167 ,173 ,176 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,148 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,145 ,2147483648 ,148 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,148 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,148 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,146 ,148 ,2147483648 ,2147483648 ,148 ,2147483648 ,2147483648 ,2147483648 ,148 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,148 ,2147483648 ,2147483648 ,2147483648 ,148 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,147 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,148 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,114 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {81 ,68 ,2147483648 ,2147483648 ,2147483648 ,96 ,90 ,64 ,91 ,2147483648 ,104 ,87 ,2147483648 ,2147483648 ,93 ,86 ,2147483648 ,88 ,70 ,80 ,75 ,85 ,102 ,84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,103 ,2147483648 ,60 ,2147483648 ,2147483648 ,82 ,66 ,2147483648 ,83 ,95 ,99 ,97 ,73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,71 ,79 ,2147483648 ,2147483648 ,65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,78 ,59 ,2147483648 ,55 ,74 ,2147483648 ,2147483648 ,63 ,67 ,2147483648 ,58 ,61 ,94 ,56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,76 ,2147483648 ,100 ,2147483648 ,2147483648 ,2147483648 ,62 ,77 ,69 ,89 ,72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,92 ,98 ,101 }, - {2147483648 ,2147483648 ,2147483648 ,39 ,39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,39 ,2147483648 ,2147483648 ,2147483648 ,39 ,2147483648 ,39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,39 ,2147483648 ,2147483648 ,2147483648 ,39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,120 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,120 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,121 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,121 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,121 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,121 ,2147483648 ,2147483648 ,2147483648 }, - {198 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,198 ,198 ,2147483648 ,198 ,198 ,2147483648 ,198 ,2147483648 ,198 ,198 ,198 ,2147483648 ,198 ,2147483648 ,198 ,198 ,198 ,198 ,198 ,199 ,2147483648 ,198 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,198 ,198 ,198 ,2147483648 ,2147483648 ,198 ,198 ,198 ,198 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,198 ,2147483648 ,198 ,2147483648 ,198 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,198 ,2147483648 ,2147483648 ,198 ,2147483648 ,2147483648 ,2147483648 ,198 ,2147483648 ,198 ,2147483648 ,2147483648 ,2147483648 ,198 ,198 ,2147483648 ,2147483648 ,2147483648 ,198 ,2147483648 ,2147483648 ,198 ,2147483648 ,198 ,2147483648 ,2147483648 ,198 ,198 ,2147483648 ,198 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,198 ,2147483648 ,198 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,198 ,198 ,198 ,198 }, - {49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,49 ,49 ,2147483648 ,49 ,49 ,2147483648 ,49 ,2147483648 ,49 ,49 ,49 ,2147483648 ,49 ,2147483648 ,49 ,49 ,49 ,49 ,49 ,2147483648 ,2147483648 ,49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,49 ,49 ,49 ,2147483648 ,2147483648 ,49 ,49 ,49 ,49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,49 ,2147483648 ,49 ,2147483648 ,49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,49 ,2147483648 ,2147483648 ,49 ,2147483648 ,2147483648 ,2147483648 ,49 ,2147483648 ,49 ,2147483648 ,2147483648 ,2147483648 ,49 ,49 ,48 ,2147483648 ,2147483648 ,49 ,2147483648 ,2147483648 ,49 ,2147483648 ,49 ,2147483648 ,2147483648 ,49 ,49 ,2147483648 ,49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,49 ,2147483648 ,49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,49 ,49 ,49 ,49 }, - {127 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,127 ,127 ,2147483648 ,127 ,127 ,2147483648 ,127 ,2147483648 ,127 ,127 ,127 ,2147483648 ,127 ,2147483648 ,127 ,127 ,127 ,127 ,127 ,2147483648 ,2147483648 ,127 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,127 ,127 ,127 ,2147483648 ,2147483648 ,127 ,127 ,127 ,127 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,127 ,2147483648 ,127 ,2147483648 ,127 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,127 ,2147483648 ,2147483648 ,127 ,2147483648 ,2147483648 ,2147483648 ,127 ,2147483648 ,127 ,2147483648 ,2147483648 ,2147483648 ,127 ,127 ,2147483648 ,2147483648 ,2147483648 ,127 ,2147483648 ,2147483648 ,127 ,2147483648 ,127 ,2147483648 ,2147483648 ,127 ,127 ,2147483648 ,127 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,127 ,2147483648 ,127 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,127 ,127 ,127 ,127 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,107 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,106 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,105 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,126 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,126 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {8 ,8 ,2147483648 ,11 ,11 ,8 ,8 ,8 ,8 ,2147483648 ,8 ,8 ,3 ,7 ,8 ,8 ,2147483648 ,8 ,8 ,8 ,8 ,8 ,8 ,8 ,2147483648 ,2147483648 ,7 ,2147483648 ,8 ,11 ,8 ,2147483648 ,2147483648 ,8 ,8 ,11 ,8 ,8 ,8 ,8 ,8 ,6 ,2147483648 ,2147483648 ,2147483648 ,8 ,8 ,11 ,2147483648 ,8 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,2147483648 ,8 ,2147483648 ,11 ,2147483648 ,11 ,8 ,8 ,2147483648 ,8 ,8 ,2147483648 ,2147483648 ,8 ,8 ,2147483648 ,8 ,8 ,8 ,8 ,7 ,2147483648 ,10 ,2147483648 ,8 ,11 ,8 ,5 ,4 ,11 ,8 ,8 ,8 ,8 ,8 ,2147483648 ,9 ,2147483648 ,2147483648 ,7 ,8 ,8 ,8 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,194 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,197 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,196 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,195 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,193 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,54 ,2147483648 ,2147483648 ,2147483648 ,52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 } + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,156 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,178 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,179 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,179 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {23 ,23 ,23 ,23 ,23 ,23 ,23 ,2147483648 ,2147483648 ,23 ,2147483648 ,23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,23 ,23 ,2147483648 ,2147483648 ,23 ,2147483648 ,23 ,2147483648 ,23 ,19 ,2147483648 ,2147483648 ,2147483648 ,23 ,23 ,23 ,23 ,2147483648 ,18 ,2147483648 ,23 ,25 ,23 ,2147483648 ,23 ,21 ,23 ,2147483648 ,21 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,2147483648 ,22 ,23 ,23 ,23 ,2147483648 ,21 ,2147483648 ,23 ,17 ,2147483648 ,2147483648 ,2147483648 ,24 ,20 ,23 ,2147483648 ,23 ,23 ,2147483648 ,23 ,23 ,2147483648 ,23 ,23 ,2147483648 ,23 ,23 ,23 ,23 ,27 ,2147483648 ,2147483648 ,23 ,23 ,23 ,2147483648 ,23 ,23 ,23 ,2147483648 ,23 ,23 ,23 ,2147483648 ,23 ,23 ,23 ,2147483648 ,23 ,23 ,2147483648 ,23 ,2147483648 ,23 ,23 ,23 ,23 ,2147483648 ,21 ,26 ,2147483648 ,2147483648 ,23 ,23 ,23 ,23 ,2147483648 ,23 ,2147483648 ,23 ,23 ,23 ,23 ,21 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,188 ,2147483648 ,2147483648 ,2147483648 ,188 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,188 ,2147483648 ,188 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,188 ,2147483648 ,2147483648 ,2147483648 ,187 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,188 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,188 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,188 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,271 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,280 ,280 ,280 ,2147483648 ,280 ,281 ,2147483648 ,280 ,2147483648 ,280 ,2147483648 ,280 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,280 ,2147483648 ,280 ,280 ,280 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,280 ,280 ,280 ,2147483648 ,2147483648 ,2147483648 ,280 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,280 ,280 ,280 ,280 ,2147483648 ,2147483648 ,2147483648 ,280 ,280 ,280 ,280 ,2147483648 ,280 ,280 ,280 ,280 ,2147483648 ,280 ,2147483648 ,280 ,2147483648 ,280 ,280 ,280 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,280 ,280 ,2147483648 ,280 ,2147483648 ,2147483648 ,280 ,280 ,280 ,280 ,280 ,280 ,280 ,2147483648 ,2147483648 ,2147483648 ,280 ,280 ,280 ,2147483648 ,280 ,280 ,280 ,2147483648 ,280 ,2147483648 ,280 ,280 ,2147483648 ,280 ,280 ,2147483648 ,280 ,280 ,280 ,2147483648 ,2147483648 ,280 ,280 ,2147483648 ,280 ,2147483648 ,280 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,280 ,280 ,2147483648 ,2147483648 ,280 ,2147483648 ,280 ,2147483648 ,2147483648 ,280 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,54 ,2147483648 ,2147483648 ,53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,54 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,261 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,262 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,260 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,259 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,41 ,41 ,41 ,2147483648 ,41 ,2147483648 ,2147483648 ,41 ,2147483648 ,41 ,2147483648 ,41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,41 ,2147483648 ,41 ,41 ,41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,41 ,41 ,41 ,2147483648 ,2147483648 ,41 ,41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,41 ,41 ,41 ,41 ,2147483648 ,2147483648 ,2147483648 ,41 ,41 ,41 ,41 ,2147483648 ,41 ,41 ,41 ,41 ,2147483648 ,41 ,2147483648 ,41 ,2147483648 ,41 ,41 ,41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,41 ,41 ,2147483648 ,41 ,2147483648 ,2147483648 ,41 ,41 ,41 ,41 ,41 ,41 ,41 ,2147483648 ,2147483648 ,2147483648 ,41 ,41 ,41 ,2147483648 ,41 ,41 ,41 ,2147483648 ,41 ,2147483648 ,41 ,41 ,2147483648 ,41 ,41 ,2147483648 ,41 ,41 ,41 ,2147483648 ,2147483648 ,41 ,41 ,2147483648 ,41 ,2147483648 ,41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,41 ,41 ,2147483648 ,2147483648 ,41 ,2147483648 ,41 ,2147483648 ,2147483648 ,41 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,147 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {153 ,153 ,153 ,153 ,153 ,153 ,153 ,2147483648 ,2147483648 ,153 ,2147483648 ,153 ,2147483648 ,2147483648 ,2147483648 ,153 ,153 ,153 ,2147483648 ,2147483648 ,153 ,2147483648 ,153 ,2147483648 ,153 ,153 ,2147483648 ,2147483648 ,2147483648 ,153 ,153 ,153 ,153 ,2147483648 ,153 ,153 ,153 ,153 ,153 ,2147483648 ,153 ,153 ,153 ,2147483648 ,153 ,153 ,153 ,153 ,153 ,153 ,153 ,153 ,2147483648 ,153 ,153 ,153 ,153 ,2147483648 ,153 ,2147483648 ,153 ,153 ,2147483648 ,2147483648 ,2147483648 ,153 ,153 ,153 ,2147483648 ,153 ,153 ,2147483648 ,153 ,153 ,153 ,153 ,153 ,2147483648 ,153 ,153 ,153 ,153 ,153 ,2147483648 ,2147483648 ,153 ,153 ,153 ,153 ,153 ,153 ,153 ,2147483648 ,153 ,153 ,153 ,2147483648 ,153 ,153 ,153 ,2147483648 ,153 ,153 ,2147483648 ,153 ,2147483648 ,153 ,153 ,153 ,153 ,2147483648 ,153 ,153 ,2147483648 ,2147483648 ,153 ,153 ,153 ,153 ,2147483648 ,153 ,2147483648 ,153 ,153 ,153 ,153 ,153 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,175 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,175 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,182 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,181 ,2147483648 ,182 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,182 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,182 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,182 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,182 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,56 ,2147483648 ,56 ,2147483648 ,55 ,2147483648 ,56 ,2147483648 ,2147483648 ,2147483648 ,56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,56 ,56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,186 ,186 ,186 ,2147483648 ,186 ,2147483648 ,2147483648 ,186 ,2147483648 ,186 ,2147483648 ,186 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,186 ,2147483648 ,186 ,186 ,186 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,186 ,186 ,186 ,2147483648 ,2147483648 ,2147483648 ,186 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,186 ,186 ,186 ,186 ,2147483648 ,2147483648 ,2147483648 ,186 ,186 ,186 ,186 ,2147483648 ,186 ,186 ,186 ,186 ,2147483648 ,186 ,2147483648 ,186 ,2147483648 ,186 ,186 ,186 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,186 ,186 ,2147483648 ,186 ,2147483648 ,2147483648 ,186 ,186 ,186 ,186 ,186 ,186 ,186 ,2147483648 ,2147483648 ,2147483648 ,186 ,186 ,186 ,2147483648 ,186 ,186 ,186 ,2147483648 ,186 ,2147483648 ,186 ,186 ,2147483648 ,186 ,186 ,2147483648 ,186 ,186 ,186 ,2147483648 ,2147483648 ,186 ,186 ,2147483648 ,186 ,2147483648 ,186 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,186 ,186 ,2147483648 ,2147483648 ,186 ,2147483648 ,186 ,2147483648 ,2147483648 ,186 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,33 ,2147483648 ,2147483648 ,32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,33 ,31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,33 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,50 ,2147483648 ,49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,43 ,43 ,43 ,2147483648 ,43 ,2147483648 ,2147483648 ,43 ,2147483648 ,43 ,2147483648 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,43 ,2147483648 ,43 ,43 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,43 ,43 ,43 ,2147483648 ,2147483648 ,42 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,43 ,43 ,43 ,43 ,2147483648 ,2147483648 ,2147483648 ,43 ,43 ,43 ,43 ,2147483648 ,43 ,43 ,43 ,43 ,2147483648 ,43 ,2147483648 ,43 ,2147483648 ,43 ,43 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,43 ,43 ,2147483648 ,43 ,2147483648 ,2147483648 ,43 ,43 ,43 ,43 ,43 ,43 ,43 ,2147483648 ,2147483648 ,2147483648 ,43 ,43 ,43 ,2147483648 ,43 ,43 ,43 ,2147483648 ,43 ,2147483648 ,43 ,43 ,2147483648 ,43 ,43 ,2147483648 ,43 ,43 ,43 ,2147483648 ,2147483648 ,43 ,43 ,2147483648 ,43 ,2147483648 ,43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,43 ,43 ,2147483648 ,2147483648 ,43 ,2147483648 ,43 ,2147483648 ,2147483648 ,43 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,59 ,2147483648 ,59 ,2147483648 ,58 ,2147483648 ,59 ,2147483648 ,2147483648 ,2147483648 ,59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,59 ,59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,154 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,177 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,176 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,176 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {0 ,0 ,0 ,0 ,0 ,0 ,0 ,2147483648 ,2147483648 ,0 ,2147483648 ,0 ,2147483648 ,2147483648 ,2147483648 ,2 ,0 ,0 ,2147483648 ,2147483648 ,0 ,2147483648 ,0 ,2147483648 ,0 ,0 ,2147483648 ,2147483648 ,2147483648 ,0 ,0 ,0 ,0 ,2147483648 ,0 ,1 ,0 ,0 ,0 ,2147483648 ,0 ,0 ,0 ,2147483648 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,2147483648 ,0 ,0 ,0 ,0 ,2147483648 ,0 ,2147483648 ,0 ,0 ,2147483648 ,2147483648 ,2147483648 ,0 ,0 ,0 ,2147483648 ,0 ,0 ,2147483648 ,0 ,0 ,2 ,0 ,0 ,2147483648 ,0 ,0 ,0 ,0 ,2147483648 ,2147483648 ,2147483648 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,2147483648 ,0 ,0 ,0 ,2147483648 ,0 ,0 ,0 ,2147483648 ,0 ,0 ,2147483648 ,0 ,2147483648 ,0 ,0 ,0 ,0 ,2147483648 ,0 ,0 ,2147483648 ,2147483648 ,0 ,0 ,0 ,0 ,2147483648 ,0 ,2147483648 ,0 ,0 ,0 ,0 ,0 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,160 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,160 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,160 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,160 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,257 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,258 ,2147483648 ,258 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,258 ,258 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,258 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,273 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,274 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,272 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,275 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,254 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,255 ,2147483648 ,255 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,255 ,255 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,255 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,158 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,158 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,159 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,158 ,157 ,2147483648 ,159 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,158 ,2147483648 }, + {2147483648 ,2147483648 ,189 ,189 ,189 ,2147483648 ,189 ,2147483648 ,2147483648 ,189 ,2147483648 ,189 ,2147483648 ,189 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,189 ,2147483648 ,189 ,189 ,189 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,189 ,189 ,189 ,2147483648 ,2147483648 ,2147483648 ,189 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,189 ,189 ,189 ,189 ,2147483648 ,2147483648 ,2147483648 ,189 ,189 ,189 ,189 ,2147483648 ,189 ,189 ,189 ,189 ,2147483648 ,189 ,2147483648 ,189 ,2147483648 ,189 ,189 ,189 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,189 ,189 ,2147483648 ,189 ,2147483648 ,2147483648 ,189 ,189 ,189 ,189 ,189 ,189 ,189 ,2147483648 ,2147483648 ,2147483648 ,189 ,189 ,189 ,2147483648 ,189 ,189 ,189 ,2147483648 ,189 ,2147483648 ,189 ,189 ,2147483648 ,189 ,189 ,2147483648 ,189 ,189 ,189 ,2147483648 ,2147483648 ,189 ,189 ,2147483648 ,189 ,2147483648 ,189 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,189 ,189 ,2147483648 ,2147483648 ,189 ,2147483648 ,189 ,2147483648 ,2147483648 ,189 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,270 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {9 ,9 ,9 ,9 ,9 ,9 ,9 ,2147483648 ,2147483648 ,9 ,2147483648 ,9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,9 ,9 ,2147483648 ,2147483648 ,9 ,2147483648 ,9 ,2147483648 ,9 ,5 ,2147483648 ,2147483648 ,2147483648 ,9 ,9 ,9 ,9 ,2147483648 ,4 ,2147483648 ,9 ,11 ,9 ,2147483648 ,9 ,7 ,9 ,2147483648 ,7 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,2147483648 ,8 ,9 ,9 ,9 ,2147483648 ,7 ,2147483648 ,9 ,3 ,2147483648 ,2147483648 ,2147483648 ,10 ,6 ,9 ,2147483648 ,9 ,9 ,2147483648 ,9 ,9 ,2147483648 ,9 ,9 ,2147483648 ,9 ,9 ,9 ,9 ,2147483648 ,2147483648 ,2147483648 ,9 ,9 ,9 ,13 ,9 ,9 ,9 ,2147483648 ,9 ,9 ,9 ,2147483648 ,9 ,9 ,9 ,2147483648 ,9 ,9 ,2147483648 ,9 ,2147483648 ,9 ,9 ,9 ,9 ,2147483648 ,7 ,12 ,2147483648 ,2147483648 ,9 ,9 ,9 ,9 ,2147483648 ,9 ,2147483648 ,9 ,9 ,9 ,9 ,7 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,170 ,2147483648 ,161 ,2147483648 ,2147483648 ,2147483648 ,172 ,2147483648 ,2147483648 ,2147483648 ,165 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,167 ,163 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,162 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,168 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,164 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,173 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,174 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,169 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,166 ,174 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,171 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,69 ,2147483648 ,60 ,2147483648 ,2147483648 ,2147483648 ,71 ,2147483648 ,2147483648 ,2147483648 ,64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,66 ,62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {149 ,149 ,149 ,149 ,149 ,149 ,149 ,2147483648 ,2147483648 ,149 ,2147483648 ,149 ,2147483648 ,2147483648 ,2147483648 ,149 ,149 ,149 ,2147483648 ,2147483648 ,149 ,2147483648 ,149 ,2147483648 ,149 ,149 ,2147483648 ,2147483648 ,2147483648 ,149 ,149 ,149 ,149 ,2147483648 ,149 ,149 ,149 ,149 ,149 ,2147483648 ,149 ,149 ,149 ,2147483648 ,149 ,149 ,149 ,149 ,149 ,149 ,149 ,149 ,2147483648 ,149 ,149 ,149 ,149 ,149 ,149 ,2147483648 ,149 ,149 ,2147483648 ,2147483648 ,2147483648 ,149 ,149 ,149 ,2147483648 ,149 ,149 ,2147483648 ,149 ,149 ,149 ,149 ,149 ,2147483648 ,149 ,149 ,149 ,149 ,149 ,2147483648 ,2147483648 ,149 ,149 ,149 ,149 ,149 ,149 ,149 ,2147483648 ,149 ,149 ,149 ,2147483648 ,149 ,149 ,149 ,2147483648 ,149 ,149 ,2147483648 ,149 ,2147483648 ,149 ,149 ,149 ,149 ,148 ,149 ,149 ,2147483648 ,2147483648 ,149 ,149 ,149 ,149 ,2147483648 ,149 ,2147483648 ,149 ,149 ,149 ,149 ,149 ,2147483648 }, + {152 ,152 ,152 ,152 ,152 ,152 ,152 ,2147483648 ,2147483648 ,152 ,2147483648 ,152 ,2147483648 ,2147483648 ,2147483648 ,152 ,152 ,152 ,2147483648 ,2147483648 ,152 ,2147483648 ,152 ,2147483648 ,152 ,152 ,2147483648 ,2147483648 ,2147483648 ,152 ,152 ,152 ,152 ,2147483648 ,152 ,152 ,152 ,152 ,152 ,2147483648 ,152 ,152 ,152 ,2147483648 ,152 ,152 ,152 ,152 ,152 ,152 ,152 ,152 ,2147483648 ,152 ,152 ,152 ,152 ,151 ,152 ,2147483648 ,152 ,152 ,2147483648 ,2147483648 ,2147483648 ,152 ,152 ,152 ,2147483648 ,152 ,152 ,2147483648 ,152 ,152 ,152 ,152 ,152 ,2147483648 ,152 ,152 ,152 ,152 ,152 ,2147483648 ,2147483648 ,152 ,152 ,152 ,152 ,152 ,152 ,152 ,2147483648 ,152 ,152 ,152 ,2147483648 ,152 ,152 ,152 ,2147483648 ,152 ,152 ,2147483648 ,152 ,2147483648 ,152 ,152 ,152 ,152 ,2147483648 ,152 ,152 ,2147483648 ,2147483648 ,152 ,152 ,152 ,152 ,2147483648 ,152 ,2147483648 ,152 ,152 ,152 ,152 ,152 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,185 ,2147483648 ,2147483648 ,2147483648 ,184 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,185 ,2147483648 ,185 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,185 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,185 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,185 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,185 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {142 ,73 ,106 ,104 ,109 ,81 ,113 ,2147483648 ,2147483648 ,117 ,2147483648 ,91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,76 ,143 ,2147483648 ,2147483648 ,120 ,2147483648 ,121 ,2147483648 ,131 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,84 ,114 ,127 ,96 ,2147483648 ,2147483648 ,2147483648 ,129 ,2147483648 ,87 ,2147483648 ,78 ,2147483648 ,92 ,2147483648 ,2147483648 ,77 ,74 ,99 ,115 ,119 ,140 ,97 ,2147483648 ,2147483648 ,107 ,123 ,94 ,2147483648 ,2147483648 ,2147483648 ,139 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,141 ,2147483648 ,125 ,134 ,2147483648 ,95 ,85 ,2147483648 ,138 ,100 ,2147483648 ,102 ,101 ,135 ,112 ,2147483648 ,2147483648 ,2147483648 ,136 ,133 ,93 ,2147483648 ,111 ,124 ,132 ,2147483648 ,137 ,98 ,126 ,2147483648 ,79 ,128 ,103 ,2147483648 ,130 ,144 ,2147483648 ,89 ,2147483648 ,108 ,118 ,88 ,116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,90 ,80 ,110 ,105 ,2147483648 ,86 ,2147483648 ,83 ,122 ,75 ,82 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,282 ,282 ,282 ,2147483648 ,282 ,2147483648 ,2147483648 ,282 ,2147483648 ,282 ,2147483648 ,282 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,282 ,283 ,282 ,282 ,282 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,282 ,282 ,282 ,2147483648 ,2147483648 ,2147483648 ,282 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,282 ,282 ,282 ,282 ,2147483648 ,2147483648 ,2147483648 ,282 ,282 ,282 ,282 ,2147483648 ,282 ,282 ,282 ,282 ,2147483648 ,282 ,2147483648 ,282 ,2147483648 ,282 ,282 ,282 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,282 ,282 ,2147483648 ,282 ,2147483648 ,2147483648 ,282 ,282 ,282 ,282 ,282 ,282 ,282 ,2147483648 ,2147483648 ,2147483648 ,282 ,282 ,282 ,2147483648 ,282 ,282 ,282 ,2147483648 ,282 ,2147483648 ,282 ,282 ,2147483648 ,282 ,282 ,2147483648 ,282 ,282 ,282 ,2147483648 ,2147483648 ,282 ,282 ,2147483648 ,282 ,2147483648 ,282 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,282 ,282 ,2147483648 ,2147483648 ,282 ,2147483648 ,282 ,2147483648 ,2147483648 ,282 ,2147483648 }, + {2147483648 ,2147483648 ,197 ,197 ,197 ,2147483648 ,197 ,2147483648 ,2147483648 ,197 ,2147483648 ,197 ,2147483648 ,197 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,197 ,2147483648 ,197 ,197 ,197 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,197 ,197 ,197 ,2147483648 ,2147483648 ,2147483648 ,197 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,197 ,197 ,197 ,197 ,2147483648 ,2147483648 ,2147483648 ,197 ,197 ,197 ,197 ,2147483648 ,197 ,197 ,197 ,197 ,2147483648 ,197 ,2147483648 ,197 ,2147483648 ,197 ,197 ,197 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,197 ,197 ,2147483648 ,197 ,2147483648 ,2147483648 ,197 ,197 ,197 ,197 ,197 ,197 ,197 ,2147483648 ,2147483648 ,2147483648 ,197 ,197 ,197 ,2147483648 ,197 ,197 ,197 ,2147483648 ,197 ,2147483648 ,197 ,197 ,2147483648 ,197 ,197 ,2147483648 ,197 ,197 ,197 ,2147483648 ,2147483648 ,197 ,197 ,2147483648 ,197 ,2147483648 ,197 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,197 ,197 ,2147483648 ,2147483648 ,197 ,2147483648 ,197 ,2147483648 ,2147483648 ,197 ,2147483648 }, + {2147483648 ,2147483648 ,193 ,193 ,193 ,2147483648 ,193 ,2147483648 ,2147483648 ,193 ,2147483648 ,193 ,2147483648 ,193 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,193 ,2147483648 ,193 ,193 ,193 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,193 ,193 ,193 ,2147483648 ,2147483648 ,2147483648 ,193 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,193 ,193 ,193 ,193 ,2147483648 ,2147483648 ,2147483648 ,193 ,193 ,193 ,193 ,2147483648 ,193 ,193 ,193 ,193 ,2147483648 ,193 ,2147483648 ,193 ,2147483648 ,193 ,193 ,193 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,193 ,193 ,2147483648 ,193 ,2147483648 ,2147483648 ,193 ,193 ,193 ,193 ,193 ,193 ,193 ,2147483648 ,2147483648 ,2147483648 ,193 ,193 ,193 ,2147483648 ,193 ,193 ,193 ,2147483648 ,193 ,2147483648 ,193 ,193 ,2147483648 ,193 ,193 ,2147483648 ,193 ,193 ,193 ,2147483648 ,2147483648 ,193 ,193 ,2147483648 ,193 ,2147483648 ,193 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,193 ,193 ,2147483648 ,2147483648 ,193 ,2147483648 ,193 ,2147483648 ,2147483648 ,193 ,2147483648 }, + {2147483648 ,2147483648 ,180 ,180 ,180 ,2147483648 ,180 ,2147483648 ,2147483648 ,180 ,2147483648 ,180 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,180 ,180 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,180 ,180 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,180 ,180 ,180 ,2147483648 ,2147483648 ,2147483648 ,180 ,180 ,180 ,180 ,2147483648 ,180 ,180 ,180 ,180 ,2147483648 ,180 ,2147483648 ,180 ,2147483648 ,180 ,180 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,180 ,2147483648 ,180 ,2147483648 ,2147483648 ,180 ,180 ,180 ,180 ,180 ,180 ,180 ,2147483648 ,2147483648 ,2147483648 ,180 ,180 ,180 ,2147483648 ,180 ,180 ,180 ,2147483648 ,180 ,2147483648 ,180 ,180 ,2147483648 ,180 ,180 ,2147483648 ,180 ,180 ,180 ,2147483648 ,2147483648 ,180 ,180 ,2147483648 ,180 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,180 ,2147483648 ,2147483648 ,180 ,2147483648 ,180 ,2147483648 ,2147483648 ,180 ,2147483648 }, + {2147483648 ,2147483648 ,46 ,46 ,46 ,2147483648 ,46 ,2147483648 ,2147483648 ,46 ,2147483648 ,46 ,2147483648 ,46 ,2147483648 ,47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,46 ,2147483648 ,46 ,46 ,46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,46 ,46 ,46 ,2147483648 ,2147483648 ,46 ,46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,46 ,46 ,46 ,46 ,2147483648 ,2147483648 ,2147483648 ,46 ,46 ,46 ,46 ,2147483648 ,46 ,46 ,46 ,46 ,2147483648 ,46 ,2147483648 ,46 ,2147483648 ,46 ,46 ,46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,46 ,46 ,2147483648 ,46 ,2147483648 ,2147483648 ,46 ,46 ,46 ,46 ,46 ,46 ,46 ,2147483648 ,2147483648 ,2147483648 ,46 ,46 ,46 ,2147483648 ,46 ,46 ,46 ,2147483648 ,46 ,2147483648 ,46 ,46 ,2147483648 ,46 ,46 ,2147483648 ,46 ,46 ,46 ,2147483648 ,2147483648 ,46 ,46 ,2147483648 ,46 ,2147483648 ,46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,46 ,46 ,2147483648 ,2147483648 ,46 ,2147483648 ,46 ,2147483648 ,2147483648 ,46 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,201 ,2147483648 ,2147483648 ,2147483648 ,201 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,201 ,2147483648 ,201 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,200 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,198 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,201 ,2147483648 ,2147483648 ,201 ,201 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,201 ,2147483648 ,2147483648 ,199 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,201 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,201 ,2147483648 ,2147483648 ,201 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,201 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,201 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,155 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,215 ,213 ,218 ,2147483648 ,222 ,2147483648 ,2147483648 ,226 ,2147483648 ,202 ,2147483648 ,263 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,229 ,2147483648 ,230 ,251 ,240 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,223 ,236 ,207 ,2147483648 ,2147483648 ,2147483648 ,238 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,252 ,203 ,263 ,268 ,2147483648 ,2147483648 ,2147483648 ,224 ,228 ,249 ,208 ,2147483648 ,253 ,216 ,232 ,205 ,2147483648 ,252 ,2147483648 ,248 ,2147483648 ,265 ,269 ,267 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,234 ,243 ,2147483648 ,206 ,2147483648 ,2147483648 ,247 ,209 ,263 ,211 ,210 ,244 ,221 ,2147483648 ,2147483648 ,2147483648 ,245 ,242 ,204 ,2147483648 ,220 ,233 ,241 ,2147483648 ,246 ,2147483648 ,235 ,264 ,2147483648 ,237 ,212 ,2147483648 ,239 ,250 ,266 ,2147483648 ,2147483648 ,217 ,227 ,2147483648 ,225 ,2147483648 ,252 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,219 ,214 ,2147483648 ,2147483648 ,263 ,2147483648 ,231 ,2147483648 ,2147483648 ,252 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,278 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,279 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,145 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,146 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,196 ,2147483648 ,2147483648 ,2147483648 ,196 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,196 ,2147483648 ,196 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,196 ,2147483648 ,2147483648 ,195 ,196 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,196 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,196 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,196 ,2147483648 ,2147483648 ,194 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,196 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,196 }, + {2147483648 ,2147483648 ,29 ,29 ,29 ,2147483648 ,29 ,2147483648 ,2147483648 ,29 ,2147483648 ,29 ,2147483648 ,29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,29 ,2147483648 ,29 ,29 ,29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,29 ,29 ,29 ,2147483648 ,2147483648 ,2147483648 ,29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,29 ,29 ,29 ,29 ,2147483648 ,2147483648 ,2147483648 ,29 ,29 ,29 ,29 ,2147483648 ,29 ,29 ,29 ,29 ,2147483648 ,29 ,2147483648 ,29 ,2147483648 ,29 ,29 ,29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,29 ,29 ,2147483648 ,29 ,2147483648 ,2147483648 ,29 ,29 ,29 ,29 ,29 ,29 ,29 ,2147483648 ,2147483648 ,2147483648 ,29 ,29 ,29 ,2147483648 ,29 ,29 ,29 ,2147483648 ,29 ,2147483648 ,29 ,29 ,2147483648 ,29 ,29 ,28 ,29 ,29 ,29 ,2147483648 ,2147483648 ,29 ,29 ,2147483648 ,29 ,2147483648 ,29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,29 ,29 ,2147483648 ,2147483648 ,29 ,2147483648 ,29 ,2147483648 ,2147483648 ,29 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,183 ,183 ,183 ,2147483648 ,183 ,2147483648 ,2147483648 ,183 ,2147483648 ,183 ,2147483648 ,183 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,183 ,2147483648 ,183 ,183 ,183 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,183 ,183 ,183 ,2147483648 ,2147483648 ,2147483648 ,183 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,183 ,183 ,183 ,183 ,2147483648 ,2147483648 ,2147483648 ,183 ,183 ,183 ,183 ,2147483648 ,183 ,183 ,183 ,183 ,2147483648 ,183 ,2147483648 ,183 ,2147483648 ,183 ,183 ,183 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,183 ,183 ,2147483648 ,183 ,2147483648 ,2147483648 ,183 ,183 ,183 ,183 ,183 ,183 ,183 ,2147483648 ,2147483648 ,2147483648 ,183 ,183 ,183 ,2147483648 ,183 ,183 ,183 ,2147483648 ,183 ,2147483648 ,183 ,183 ,2147483648 ,183 ,183 ,2147483648 ,183 ,183 ,183 ,2147483648 ,2147483648 ,183 ,183 ,2147483648 ,183 ,2147483648 ,183 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,183 ,183 ,2147483648 ,2147483648 ,183 ,2147483648 ,183 ,2147483648 ,2147483648 ,183 ,2147483648 }, + {150 ,150 ,150 ,150 ,150 ,150 ,150 ,2147483648 ,2147483648 ,150 ,2147483648 ,150 ,2147483648 ,2147483648 ,2147483648 ,150 ,150 ,150 ,2147483648 ,2147483648 ,150 ,2147483648 ,150 ,2147483648 ,150 ,150 ,2147483648 ,2147483648 ,2147483648 ,150 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,150 ,150 ,150 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,150 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,2147483648 ,2147483648 ,2147483648 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,2147483648 ,150 ,150 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,150 ,150 ,150 ,2147483648 ,2147483648 ,150 ,150 ,150 ,150 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,2147483648 ,150 ,2147483648 ,150 ,150 ,150 ,150 ,2147483648 ,150 ,150 ,2147483648 ,2147483648 ,150 ,150 ,150 ,150 ,2147483648 ,150 ,2147483648 ,150 ,150 ,150 ,150 ,150 ,2147483648 }, + {2147483648 ,2147483648 ,277 ,277 ,277 ,2147483648 ,277 ,2147483648 ,2147483648 ,277 ,2147483648 ,277 ,2147483648 ,277 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,277 ,2147483648 ,277 ,277 ,277 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,277 ,277 ,277 ,2147483648 ,2147483648 ,2147483648 ,277 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,277 ,277 ,277 ,277 ,2147483648 ,2147483648 ,2147483648 ,277 ,277 ,277 ,277 ,2147483648 ,277 ,277 ,277 ,277 ,2147483648 ,277 ,2147483648 ,277 ,2147483648 ,277 ,277 ,277 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,277 ,277 ,2147483648 ,277 ,2147483648 ,2147483648 ,277 ,277 ,277 ,277 ,277 ,277 ,277 ,2147483648 ,2147483648 ,2147483648 ,277 ,277 ,277 ,2147483648 ,277 ,277 ,277 ,2147483648 ,277 ,2147483648 ,277 ,277 ,2147483648 ,277 ,277 ,2147483648 ,277 ,277 ,277 ,2147483648 ,2147483648 ,277 ,277 ,2147483648 ,277 ,2147483648 ,277 ,2147483648 ,2147483648 ,276 ,2147483648 ,2147483648 ,277 ,277 ,2147483648 ,2147483648 ,277 ,2147483648 ,277 ,2147483648 ,2147483648 ,277 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,256 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,191 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,190 }, + {14 ,14 ,14 ,14 ,14 ,14 ,14 ,2147483648 ,2147483648 ,14 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 ,16 ,14 ,14 ,2147483648 ,2147483648 ,14 ,2147483648 ,14 ,2147483648 ,14 ,14 ,2147483648 ,2147483648 ,2147483648 ,14 ,14 ,14 ,14 ,2147483648 ,14 ,15 ,14 ,14 ,14 ,2147483648 ,14 ,14 ,14 ,2147483648 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,2147483648 ,14 ,14 ,14 ,14 ,2147483648 ,14 ,2147483648 ,14 ,14 ,2147483648 ,2147483648 ,2147483648 ,14 ,14 ,14 ,2147483648 ,14 ,14 ,2147483648 ,14 ,14 ,2147483648 ,14 ,14 ,2147483648 ,14 ,14 ,14 ,14 ,14 ,2147483648 ,2147483648 ,14 ,14 ,14 ,2147483648 ,14 ,14 ,14 ,2147483648 ,14 ,14 ,14 ,2147483648 ,14 ,14 ,14 ,2147483648 ,14 ,14 ,2147483648 ,14 ,2147483648 ,14 ,14 ,14 ,14 ,2147483648 ,14 ,14 ,2147483648 ,2147483648 ,14 ,14 ,14 ,14 ,2147483648 ,14 ,2147483648 ,14 ,14 ,14 ,14 ,14 ,2147483648 } }; const char* KeywordList[]= { -"void", -"bool", -"char", -"short", -"int", -"long", -"unsigned", -"signed", -"float", -"double", "print", "formats", "event_enable", @@ -842,6 +1133,7 @@ const char* KeywordList[]= { "spinlock_lock", "spinlock_unlock", "event_sc", +"microsleep", "printf", "pause", "flush", @@ -850,6 +1142,13 @@ const char* KeywordList[]= { "event_trace_step_out", "event_trace_instrumentation_step", "event_trace_instrumentation_step_in", +"rdtsc", +"rdtscp", +"lbr_save", +"lbr_dump", +"lbr_print", +"lbr_restore", +"lbr_check", "spinlock_lock_custom_wait", "event_inject", "poi", @@ -870,19 +1169,40 @@ const char* KeywordList[]= { "reference", "physical_to_virtual", "virtual_to_physical", +"poi_pa", +"hi_pa", +"low_pa", +"db_pa", +"dd_pa", +"dw_pa", +"dq_pa", +"lbr_restore_by_filter", "ed", "eb", "eq", "interlocked_exchange", "interlocked_exchange_add", +"eb_pa", +"ed_pa", +"eq_pa", "interlocked_compare_exchange", "strlen", "strcmp", "memcmp", +"strncmp", "wcslen", "wcscmp", "event_inject_error_code", "memcpy", +"memcpy_pa", +"wcsncmp", +"rdtsc", +"rdtscp", +"lbr_save", +"lbr_dump", +"lbr_print", +"lbr_restore", +"lbr_check", "poi", "db", "dd", @@ -901,17 +1221,30 @@ const char* KeywordList[]= { "reference", "physical_to_virtual", "virtual_to_physical", +"poi_pa", +"hi_pa", +"low_pa", +"db_pa", +"dd_pa", +"dw_pa", +"dq_pa", +"lbr_restore_by_filter", "ed", "eb", "eq", "interlocked_exchange", "interlocked_exchange_add", +"eb_pa", +"ed_pa", +"eq_pa", "interlocked_compare_exchange", "strlen", "strcmp", "memcmp", +"strncmp", "wcslen", -"wcscmp" +"wcscmp", +"wcsncmp" }; const char* OperatorsTwoOperandList[]= { "@OR", @@ -934,8 +1267,19 @@ const char* OperatorsTwoOperandList[]= { const char* OperatorsOneOperandList[]= { "@INC", "@DEC", -"@REFERENCE", -"@DEREFERENCE" +"@REFERENCE" +}; +const char* AssignmentOperatorList[]= { +"@ADD_ASSIGNMENT", +"@SUB_ASSIGNMENT", +"@MUL_ASSIGNMENT", +"@DIV_ASSIGNMENT", +"@MOD_ASSIGNMENT", +"@ASL_ASSIGNMENT", +"@ASR_ASSIGNMENT", +"@AND_ASSIGNMENT", +"@XOR_ASSIGNMENT", +"@OR_ASSIGNMENT" }; const char* ThreeOpFunc1[] = { "@INTERLOCKED_COMPARE_EXCHANGE" @@ -943,6 +1287,7 @@ const char* ThreeOpFunc1[] = { const char* ThreeOpFunc2[] = { "@EVENT_INJECT_ERROR_CODE", "@MEMCPY", +"@MEMCPY_PA", }; const char* TwoOpFunc1[] = { "@ED", @@ -950,6 +1295,9 @@ const char* TwoOpFunc1[] = { "@EQ", "@INTERLOCKED_EXCHANGE", "@INTERLOCKED_EXCHANGE_ADD", +"@EB_PA", +"@ED_PA", +"@EQ_PA", }; const char* TwoOpFunc2[] = { "@SPINLOCK_LOCK_CUSTOM_WAIT", @@ -974,6 +1322,14 @@ const char* OneOpFunc1[] = { "@REFERENCE", "@PHYSICAL_TO_VIRTUAL", "@VIRTUAL_TO_PHYSICAL", +"@POI_PA", +"@HI_PA", +"@LOW_PA", +"@DB_PA", +"@DD_PA", +"@DW_PA", +"@DQ_PA", +"@LBR_RESTORE_BY_FILTER", }; const char* OneOpFunc2[] = { "@PRINT", @@ -985,6 +1341,7 @@ const char* OneOpFunc2[] = { "@SPINLOCK_LOCK", "@SPINLOCK_UNLOCK", "@EVENT_SC", +"@MICROSLEEP", }; const char* OneOpFunc3[] = { "@STRLEN" @@ -993,7 +1350,11 @@ const char* TwoOpFunc3[] = { "@STRCMP" }; const char* ThreeOpFunc3[] = { -"@MEMCMP" +"@MEMCMP", +"@STRNCMP", +}; +const char* ThreeOpFunc4[] = { +"@WCSNCMP" }; const char* OneOpFunc4[] = { "@WCSLEN" @@ -1010,26 +1371,22 @@ const char* ZeroOpFunc1[] = { "@EVENT_TRACE_INSTRUMENTATION_STEP", "@EVENT_TRACE_INSTRUMENTATION_STEP_IN", }; +const char* ZeroOpFunc2[] = { +"@RDTSC", +"@RDTSCP", +"@LBR_SAVE", +"@LBR_DUMP", +"@LBR_PRINT", +"@LBR_RESTORE", +"@LBR_CHECK", +}; const char* VarArgFunc1[] = { "@PRINTF" }; -const char* VARIABLETYPE[] = { -"@VOID", -"@BOOL", -"@CHAR", -"@SHORT", -"@INT", -"@LONG", -"@UNSIGNED", -"@SIGNED", -"@FLOAT", -"@DOUBLE", -}; const SYMBOL_MAP SemanticRulesMapList[]= { {"@INC", FUNC_INC}, {"@DEC", FUNC_DEC}, {"@REFERENCE", FUNC_REFERENCE}, -{"@DEREFERENCE", FUNC_DEREFERENCE}, {"@OR", FUNC_OR}, {"@XOR", FUNC_XOR}, {"@AND", FUNC_AND}, @@ -1046,18 +1403,11 @@ const SYMBOL_MAP SemanticRulesMapList[]= { {"@ELT", FUNC_ELT}, {"@EQUAL", FUNC_EQUAL}, {"@NEQ", FUNC_NEQ}, -{"@START_OF_IF", FUNC_START_OF_IF}, {"@JMP", FUNC_JMP}, {"@JZ", FUNC_JZ}, {"@JNZ", FUNC_JNZ}, -{"@JMP_TO_END_AND_JZCOMPLETED", FUNC_JMP_TO_END_AND_JZCOMPLETED}, -{"@END_OF_IF", FUNC_END_OF_IF}, -{"@START_OF_WHILE", FUNC_START_OF_WHILE}, -{"@END_OF_WHILE", FUNC_END_OF_WHILE}, -{"@VARGSTART", FUNC_VARGSTART}, {"@MOV", FUNC_MOV}, {"@START_OF_DO_WHILE", FUNC_START_OF_DO_WHILE}, -{"@", FUNC_}, {"@START_OF_DO_WHILE_COMMANDS", FUNC_START_OF_DO_WHILE_COMMANDS}, {"@END_OF_DO_WHILE", FUNC_END_OF_DO_WHILE}, {"@START_OF_FOR", FUNC_START_OF_FOR}, @@ -1065,25 +1415,10 @@ const SYMBOL_MAP SemanticRulesMapList[]= { {"@START_OF_FOR_OMMANDS", FUNC_START_OF_FOR_OMMANDS}, {"@END_OF_IF", FUNC_END_OF_IF}, {"@IGNORE_LVALUE", FUNC_IGNORE_LVALUE}, -{"@END_OF_USER_DEFINED_FUNCTION", FUNC_END_OF_USER_DEFINED_FUNCTION}, -{"@RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE", FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE}, -{"@RETURN_OF_USER_DEFINED_FUNCTION_WITHOUT_VALUE", FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITHOUT_VALUE}, -{"@CALL_USER_DEFINED_FUNCTION_PARAMETER", FUNC_CALL_USER_DEFINED_FUNCTION_PARAMETER}, -{"@END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE", FUNC_END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE}, -{"@END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE", FUNC_END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE}, -{"@CALL_USER_DEFINED_FUNCTION", FUNC_CALL_USER_DEFINED_FUNCTION}, -{"@START_OF_USER_DEFINED_FUNCTION", FUNC_START_OF_USER_DEFINED_FUNCTION}, -{"@MOV_RETURN_VALUE", FUNC_MOV_RETURN_VALUE}, -{"@VOID", FUNC_VOID}, -{"@BOOL", FUNC_BOOL}, -{"@CHAR", FUNC_CHAR}, -{"@SHORT", FUNC_SHORT}, -{"@INT", FUNC_INT}, -{"@LONG", FUNC_LONG}, -{"@UNSIGNED", FUNC_UNSIGNED}, -{"@SIGNED", FUNC_SIGNED}, -{"@FLOAT", FUNC_FLOAT}, -{"@DOUBLE", FUNC_DOUBLE}, +{"@PUSH", FUNC_PUSH}, +{"@POP", FUNC_POP}, +{"@CALL", FUNC_CALL}, +{"@RET", FUNC_RET}, {"@PRINT", FUNC_PRINT}, {"@FORMATS", FUNC_FORMATS}, {"@EVENT_ENABLE", FUNC_EVENT_ENABLE}, @@ -1093,6 +1428,7 @@ const SYMBOL_MAP SemanticRulesMapList[]= { {"@SPINLOCK_LOCK", FUNC_SPINLOCK_LOCK}, {"@SPINLOCK_UNLOCK", FUNC_SPINLOCK_UNLOCK}, {"@EVENT_SC", FUNC_EVENT_SC}, +{"@MICROSLEEP", FUNC_MICROSLEEP}, {"@PRINTF", FUNC_PRINTF}, {"@PAUSE", FUNC_PAUSE}, {"@FLUSH", FUNC_FLUSH}, @@ -1101,6 +1437,13 @@ const SYMBOL_MAP SemanticRulesMapList[]= { {"@EVENT_TRACE_STEP_OUT", FUNC_EVENT_TRACE_STEP_OUT}, {"@EVENT_TRACE_INSTRUMENTATION_STEP", FUNC_EVENT_TRACE_INSTRUMENTATION_STEP}, {"@EVENT_TRACE_INSTRUMENTATION_STEP_IN", FUNC_EVENT_TRACE_INSTRUMENTATION_STEP_IN}, +{"@RDTSC", FUNC_RDTSC}, +{"@RDTSCP", FUNC_RDTSCP}, +{"@LBR_SAVE", FUNC_LBR_SAVE}, +{"@LBR_DUMP", FUNC_LBR_DUMP}, +{"@LBR_PRINT", FUNC_LBR_PRINT}, +{"@LBR_RESTORE", FUNC_LBR_RESTORE}, +{"@LBR_CHECK", FUNC_LBR_CHECK}, {"@SPINLOCK_LOCK_CUSTOM_WAIT", FUNC_SPINLOCK_LOCK_CUSTOM_WAIT}, {"@EVENT_INJECT", FUNC_EVENT_INJECT}, {"@POI", FUNC_POI}, @@ -1121,19 +1464,40 @@ const SYMBOL_MAP SemanticRulesMapList[]= { {"@REFERENCE", FUNC_REFERENCE}, {"@PHYSICAL_TO_VIRTUAL", FUNC_PHYSICAL_TO_VIRTUAL}, {"@VIRTUAL_TO_PHYSICAL", FUNC_VIRTUAL_TO_PHYSICAL}, +{"@POI_PA", FUNC_POI_PA}, +{"@HI_PA", FUNC_HI_PA}, +{"@LOW_PA", FUNC_LOW_PA}, +{"@DB_PA", FUNC_DB_PA}, +{"@DD_PA", FUNC_DD_PA}, +{"@DW_PA", FUNC_DW_PA}, +{"@DQ_PA", FUNC_DQ_PA}, +{"@LBR_RESTORE_BY_FILTER", FUNC_LBR_RESTORE_BY_FILTER}, {"@ED", FUNC_ED}, {"@EB", FUNC_EB}, {"@EQ", FUNC_EQ}, {"@INTERLOCKED_EXCHANGE", FUNC_INTERLOCKED_EXCHANGE}, {"@INTERLOCKED_EXCHANGE_ADD", FUNC_INTERLOCKED_EXCHANGE_ADD}, +{"@EB_PA", FUNC_EB_PA}, +{"@ED_PA", FUNC_ED_PA}, +{"@EQ_PA", FUNC_EQ_PA}, {"@INTERLOCKED_COMPARE_EXCHANGE", FUNC_INTERLOCKED_COMPARE_EXCHANGE}, {"@STRLEN", FUNC_STRLEN}, {"@STRCMP", FUNC_STRCMP}, {"@MEMCMP", FUNC_MEMCMP}, +{"@STRNCMP", FUNC_STRNCMP}, {"@WCSLEN", FUNC_WCSLEN}, {"@WCSCMP", FUNC_WCSCMP}, {"@EVENT_INJECT_ERROR_CODE", FUNC_EVENT_INJECT_ERROR_CODE}, {"@MEMCPY", FUNC_MEMCPY}, +{"@MEMCPY_PA", FUNC_MEMCPY_PA}, +{"@WCSNCMP", FUNC_WCSNCMP}, +{"@RDTSC", FUNC_RDTSC}, +{"@RDTSCP", FUNC_RDTSCP}, +{"@LBR_SAVE", FUNC_LBR_SAVE}, +{"@LBR_DUMP", FUNC_LBR_DUMP}, +{"@LBR_PRINT", FUNC_LBR_PRINT}, +{"@LBR_RESTORE", FUNC_LBR_RESTORE}, +{"@LBR_CHECK", FUNC_LBR_CHECK}, {"@POI", FUNC_POI}, {"@DB", FUNC_DB}, {"@DD", FUNC_DD}, @@ -1152,17 +1516,40 @@ const SYMBOL_MAP SemanticRulesMapList[]= { {"@REFERENCE", FUNC_REFERENCE}, {"@PHYSICAL_TO_VIRTUAL", FUNC_PHYSICAL_TO_VIRTUAL}, {"@VIRTUAL_TO_PHYSICAL", FUNC_VIRTUAL_TO_PHYSICAL}, +{"@POI_PA", FUNC_POI_PA}, +{"@HI_PA", FUNC_HI_PA}, +{"@LOW_PA", FUNC_LOW_PA}, +{"@DB_PA", FUNC_DB_PA}, +{"@DD_PA", FUNC_DD_PA}, +{"@DW_PA", FUNC_DW_PA}, +{"@DQ_PA", FUNC_DQ_PA}, +{"@LBR_RESTORE_BY_FILTER", FUNC_LBR_RESTORE_BY_FILTER}, {"@ED", FUNC_ED}, {"@EB", FUNC_EB}, {"@EQ", FUNC_EQ}, {"@INTERLOCKED_EXCHANGE", FUNC_INTERLOCKED_EXCHANGE}, {"@INTERLOCKED_EXCHANGE_ADD", FUNC_INTERLOCKED_EXCHANGE_ADD}, +{"@EB_PA", FUNC_EB_PA}, +{"@ED_PA", FUNC_ED_PA}, +{"@EQ_PA", FUNC_EQ_PA}, {"@INTERLOCKED_COMPARE_EXCHANGE", FUNC_INTERLOCKED_COMPARE_EXCHANGE}, {"@STRLEN", FUNC_STRLEN}, {"@STRCMP", FUNC_STRCMP}, {"@MEMCMP", FUNC_MEMCMP}, +{"@STRNCMP", FUNC_STRNCMP}, {"@WCSLEN", FUNC_WCSLEN}, {"@WCSCMP", FUNC_WCSCMP}, +{"@WCSNCMP", FUNC_WCSNCMP}, +{"@ADD_ASSIGNMENT", FUNC_ADD}, +{"@SUB_ASSIGNMENT", FUNC_SUB}, +{"@MUL_ASSIGNMENT", FUNC_MUL}, +{"@DIV_ASSIGNMENT", FUNC_DIV}, +{"@MOD_ASSIGNMENT", FUNC_MOD}, +{"@ASL_ASSIGNMENT", FUNC_ASL}, +{"@ASR_ASSIGNMENT", FUNC_ASR}, +{"@AND_ASSIGNMENT", FUNC_AND}, +{"@XOR_ASSIGNMENT", FUNC_XOR}, +{"@OR_ASSIGNMENT", FUNC_OR}, }; const SYMBOL_MAP RegisterMapList[]= { {"rax", REGISTER_RAX}, @@ -1300,9 +1687,23 @@ const SYMBOL_MAP PseudoRegisterMapList[]= { {"context", PSEUDO_REGISTER_CONTEXT}, {"event_tag", PSEUDO_REGISTER_EVENT_TAG}, {"event_id", PSEUDO_REGISTER_EVENT_ID}, -{"event_stage", PSEUDO_REGISTER_EVENT_STAGE} +{"event_stage", PSEUDO_REGISTER_EVENT_STAGE}, +{"date", PSEUDO_REGISTER_DATE}, +{"time", PSEUDO_REGISTER_TIME} }; -const struct _TOKEN LalrLhs[RULES_COUNT]= +const char* ScriptVariableTypeList[]= { +"void", +"bool", +"char", +"short", +"int", +"long", +"unsigned", +"signed", +"float", +"double" +}; +const struct _SCRIPT_ENGINE_TOKEN LalrLhs[RULES_COUNT]= { {NON_TERMINAL, "S"}, {NON_TERMINAL, "BE"}, @@ -1383,14 +1784,46 @@ const struct _TOKEN LalrLhs[RULES_COUNT]= {NON_TERMINAL, "E12"}, {NON_TERMINAL, "E12"}, {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E12"}, + {NON_TERMINAL, "E13"}, + {NON_TERMINAL, "VA2"}, + {NON_TERMINAL, "VA2"}, + {NON_TERMINAL, "VA3"}, + {NON_TERMINAL, "VA3"}, {NON_TERMINAL, "STRING"}, {NON_TERMINAL, "WSTRING"}, {NON_TERMINAL, "StringNumber"}, {NON_TERMINAL, "StringNumber"}, {NON_TERMINAL, "WstringNumber"}, - {NON_TERMINAL, "WstringNumber"} + {NON_TERMINAL, "WstringNumber"}, + {NON_TERMINAL, "ARRAY1"}, + {NON_TERMINAL, "ARRAY2"}, + {NON_TERMINAL, "ARRAY3"}, + {NON_TERMINAL, "ARRAY4"}, + {NON_TERMINAL, "ARRAY4"} }; -const struct _TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN]= +const struct _SCRIPT_ENGINE_TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN]= { {{NON_TERMINAL, "BE"}}, {{NON_TERMINAL, "B1"}}, @@ -1429,6 +1862,13 @@ const struct _TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN]= {{KEYWORD, "~"},{NON_TERMINAL, "E12"},{SEMANTIC_RULE, "@NOT"}}, {{SPECIAL_TOKEN, "*"},{NON_TERMINAL, "E12"},{SEMANTIC_RULE, "@POI"}}, {{SPECIAL_TOKEN, "&"},{NON_TERMINAL, "E12"},{SEMANTIC_RULE, "@REFERENCE"}}, + {{KEYWORD, "rdtsc"},{SPECIAL_TOKEN, "("},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@RDTSC"}}, + {{KEYWORD, "rdtscp"},{SPECIAL_TOKEN, "("},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@RDTSCP"}}, + {{KEYWORD, "lbr_save"},{SPECIAL_TOKEN, "("},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@LBR_SAVE"}}, + {{KEYWORD, "lbr_dump"},{SPECIAL_TOKEN, "("},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@LBR_DUMP"}}, + {{KEYWORD, "lbr_print"},{SPECIAL_TOKEN, "("},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@LBR_PRINT"}}, + {{KEYWORD, "lbr_restore"},{SPECIAL_TOKEN, "("},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@LBR_RESTORE"}}, + {{KEYWORD, "lbr_check"},{SPECIAL_TOKEN, "("},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@LBR_CHECK"}}, {{KEYWORD, "poi"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@POI"}}, {{KEYWORD, "db"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@DB"}}, {{KEYWORD, "dd"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@DD"}}, @@ -1449,34 +1889,59 @@ const struct _TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN]= {{KEYWORD, "reference"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@REFERENCE"}}, {{KEYWORD, "physical_to_virtual"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@PHYSICAL_TO_VIRTUAL"}}, {{KEYWORD, "virtual_to_physical"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@VIRTUAL_TO_PHYSICAL"}}, + {{KEYWORD, "poi_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@POI_PA"}}, + {{KEYWORD, "hi_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@HI_PA"}}, + {{KEYWORD, "low_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@LOW_PA"}}, + {{KEYWORD, "db_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@DB_PA"}}, + {{KEYWORD, "dd_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@DD_PA"}}, + {{KEYWORD, "dw_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@DW_PA"}}, + {{KEYWORD, "dq_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@DQ_PA"}}, + {{KEYWORD, "lbr_restore_by_filter"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@LBR_RESTORE_BY_FILTER"}}, {{KEYWORD, "ed"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@ED"}}, {{KEYWORD, "eb"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@EB"}}, {{KEYWORD, "eq"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@EQ"}}, {{KEYWORD, "interlocked_exchange"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@INTERLOCKED_EXCHANGE"}}, {{KEYWORD, "interlocked_exchange_add"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@INTERLOCKED_EXCHANGE_ADD"}}, {{KEYWORD, "wcscmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@WCSCMP"}}, + {{KEYWORD, "eb_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@EB_PA"}}, + {{KEYWORD, "ed_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@ED_PA"}}, + {{KEYWORD, "eq_pa"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@EQ_PA"}}, {{KEYWORD, "interlocked_compare_exchange"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@INTERLOCKED_COMPARE_EXCHANGE"}}, {{KEYWORD, "strlen"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@STRLEN"}}, {{KEYWORD, "strcmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@STRCMP"}}, {{KEYWORD, "memcmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@MEMCMP"}}, + {{KEYWORD, "strncmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "StringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@STRNCMP"}}, {{KEYWORD, "wcslen"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@WCSLEN"}}, {{KEYWORD, "wcscmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@WCSCMP"}}, + {{KEYWORD, "wcsncmp"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "WstringNumber"},{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@WCSNCMP"}}, {{SPECIAL_TOKEN, "("},{NON_TERMINAL, "BE"},{SPECIAL_TOKEN, ")"}}, {{REGISTER, "_register"},{SEMANTIC_RULE, "@PUSH"}}, {{GLOBAL_ID, "_global_id"},{SEMANTIC_RULE, "@PUSH"}}, {{LOCAL_ID, "_local_id"},{SEMANTIC_RULE, "@PUSH"}}, {{FUNCTION_PARAMETER_ID, "_function_parameter_id"},{SEMANTIC_RULE, "@PUSH"}}, + {{NON_TERMINAL, "ARRAY1"}}, {{HEX, "_hex"},{SEMANTIC_RULE, "@PUSH"}}, {{DECIMAL, "_decimal"},{SEMANTIC_RULE, "@PUSH"}}, {{OCTAL, "_octal"},{SEMANTIC_RULE, "@PUSH"}}, {{BINARY, "_binary"},{SEMANTIC_RULE, "@PUSH"}}, {{PSEUDO_REGISTER, "_pseudo_register"},{SEMANTIC_RULE, "@PUSH"}}, + {{NON_TERMINAL, "E13"},{SPECIAL_TOKEN, "("},{NON_TERMINAL, "VA2"},{SPECIAL_TOKEN, ")"},{SEMANTIC_RULE, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE"}}, + {{FUNCTION_ID, "_function_id"},{SEMANTIC_RULE, "@PUSH"}}, + {{EPSILON, "eps"}}, + {{NON_TERMINAL, "EXP"},{NON_TERMINAL, "VA3"}}, + {{SPECIAL_TOKEN, ","},{NON_TERMINAL, "EXP"},{NON_TERMINAL, "VA3"}}, + {{EPSILON, "eps"}}, {{STRING, "_string"},{SEMANTIC_RULE, "@PUSH"}}, {{WSTRING, "_wstring"},{SEMANTIC_RULE, "@PUSH"}}, {{NON_TERMINAL, "EXP"}}, {{NON_TERMINAL, "STRING"}}, {{NON_TERMINAL, "EXP"}}, - {{NON_TERMINAL, "WSTRING"}} + {{NON_TERMINAL, "WSTRING"}}, + {{NON_TERMINAL, "ARRAY2"},{NON_TERMINAL, "ARRAY3"},{NON_TERMINAL, "ARRAY4"},{SEMANTIC_RULE, "@ARRAY_INDEX_READ"}}, + {{LOCAL_ID, "_local_id"},{SEMANTIC_RULE, "@PUSH"}}, + {{SPECIAL_TOKEN, "["},{NON_TERMINAL, "EXP"},{SPECIAL_TOKEN, "]"},{SEMANTIC_RULE, "@ARRAY_DIM_NUMBER"}}, + {{NON_TERMINAL, "ARRAY3"},{NON_TERMINAL, "ARRAY4"}}, + {{EPSILON, "eps"}} }; const unsigned int LalrRhsSize[RULES_COUNT]= { @@ -1517,6 +1982,13 @@ const unsigned int LalrRhsSize[RULES_COUNT]= 3, 3, 3, +4, +4, +4, +4, +4, +4, +4, 5, 5, 5, @@ -1537,6 +2009,17 @@ const unsigned int LalrRhsSize[RULES_COUNT]= 5, 5, 5, +5, +5, +5, +5, +5, +5, +5, +5, +7, +7, +7, 7, 7, 7, @@ -1547,572 +2030,828 @@ const unsigned int LalrRhsSize[RULES_COUNT]= 5, 7, 9, +9, 5, 7, +9, 3, 2, 2, 2, 2, +1, 2, 2, 2, 2, 2, +5, +2, +1, +2, +3, +1, 2, 2, 1, 1, 1, +1, +4, +2, +4, +2, 1 }; const char* LalrNoneTerminalMap[NONETERMINAL_COUNT]= { -"E5", -"WstringNumber", -"B3", -"B2", -"B5", -"STRING", -"E3", -"E4", -"S", -"B1", -"BE", -"EXP", -"E12", -"B6", "StringNumber", -"E10", -"CMP", "WSTRING", -"B4" +"ARRAY1", +"ARRAY2", +"EXP", +"E10", +"S", +"B5", +"E3", +"STRING", +"BE", +"ARRAY3", +"WstringNumber", +"E13", +"E5", +"E4", +"E12", +"CMP", +"VA3", +"ARRAY4", +"B2", +"B4", +"VA2", +"B3", +"B6", +"B1" }; const char* LalrTerminalMap[TERMINAL_COUNT]= { -"low", "hi", -"||", -"_register", -"==", -"db", -"disassemble_len32", -"!=", -"wcscmp", -"disassemble_len", -"%", -">>", -"*", -"dd", -"_string", -"/", -"_function_parameter_id", -"memcmp", -"_hex", -"interlocked_exchange_add", -">=", -"physical_to_virtual", -"^", -"_decimal", -"&&", -"virtual_to_physical", -"&", -"<<", -"(", -"-", -"<=", -"eq", -"~", -"dw", "dq", -"|", -"not", -"interlocked_increment", -">", "check_address", -"<", -"reference", -"interlocked_exchange", -"_global_id", -"strcmp", -"poi", -"disassemble_len64", -"eb", -"interlocked_compare_exchange", +"interlocked_increment", +"_string", +"virtual_to_physical", +"!=", +"rdtsc", +"[", "_octal", -"$", -")", -"_pseudo_register", -",", +"^", +"low_pa", "_wstring", -"+", +"db_pa", +"(", +"|", +"eb_pa", "interlocked_decrement", +"eb", +"lbr_restore", +"<", +"interlocked_exchange", "_local_id", -"neg", -"ed", -"strlen", +"rdtscp", "_binary", -"wcslen" +"*", +"reference", +"hi_pa", +"wcscmp", +"/", +"lbr_check", +"dw_pa", +"low", +"_function_id", +"lbr_dump", +"_register", +"]", +"wcslen", +"-", +"&", +"~", +">=", +"<<", +">", +"lbr_restore_by_filter", +"interlocked_compare_exchange", +"%", +"lbr_print", +"$", +"strncmp", +"poi", +"_decimal", +"dd", +"&&", +"db", +"strlen", +"disassemble_len64", +",", +"strcmp", +"eq_pa", +"lbr_save", +"disassemble_len32", +"dq_pa", +"ed_pa", +"||", +"<=", +"memcmp", +"ed", +"_pseudo_register", +"eq", +"dw", +"interlocked_exchange_add", +"wcsncmp", +"+", +"==", +"not", +"poi_pa", +"physical_to_virtual", +"_global_id", +")", +"disassemble_len", +"neg", +"_hex", +"dd_pa", +"_function_parameter_id", +">>" }; const int LalrGotoTable[LALR_STATE_COUNT][LALR_NONTERMINAL_COUNT]= { - {13 ,2147483648 ,5 ,4 ,7 ,2147483648 ,11 ,12 ,1 ,3 ,2 ,10 ,15 ,8 ,2147483648 ,14 ,9 ,2147483648 ,6 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,90 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,97 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,103 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,5 ,4 ,7 ,2147483648 ,11 ,12 ,2147483648 ,3 ,111 ,10 ,15 ,8 ,2147483648 ,14 ,9 ,2147483648 ,6 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,112 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,5 ,113 ,7 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,10 ,15 ,8 ,2147483648 ,14 ,9 ,2147483648 ,6 }, - {13 ,2147483648 ,114 ,2147483648 ,7 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,10 ,15 ,8 ,2147483648 ,14 ,9 ,2147483648 ,6 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,7 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,10 ,15 ,8 ,2147483648 ,14 ,9 ,2147483648 ,115 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,116 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,10 ,15 ,8 ,2147483648 ,14 ,9 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,10 ,15 ,117 ,2147483648 ,14 ,9 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,118 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,119 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,120 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,121 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,122 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,123 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,124 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,125 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {126 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {127 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,15 ,2147483648 ,2147483648 ,128 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,15 ,2147483648 ,2147483648 ,129 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,15 ,2147483648 ,2147483648 ,130 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,131 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,132 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,135 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,133 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,134 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,137 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,138 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,139 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,141 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,140 ,15 ,2147483648 ,142 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,144 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,145 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,146 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,147 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,148 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,149 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,151 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,150 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,134 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,152 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,153 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,154 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,155 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,156 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,157 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,158 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,159 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,141 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,160 ,15 ,2147483648 ,161 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,162 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,141 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,140 ,15 ,2147483648 ,163 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,164 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,165 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,166 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,167 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,201 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,203 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,202 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,134 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,204 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,141 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,140 ,15 ,2147483648 ,205 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,206 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,207 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,208 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,209 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,210 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,141 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,140 ,15 ,2147483648 ,211 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,222 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,11 ,12 ,2147483648 ,2147483648 ,2147483648 ,223 ,15 ,2147483648 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 } + {2147483648 ,2147483648 ,17 ,18 ,10 ,14 ,1 ,7 ,11 ,2147483648 ,2 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,9 ,2147483648 ,2147483648 ,4 ,6 ,2147483648 ,5 ,8 ,3 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,103 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,2147483648 ,2147483648 ,108 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,10 ,14 ,2147483648 ,7 ,11 ,2147483648 ,137 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,9 ,2147483648 ,2147483648 ,4 ,6 ,2147483648 ,5 ,8 ,3 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,2147483648 ,2147483648 ,148 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,2147483648 ,2147483648 ,153 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,2147483648 ,2147483648 ,157 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,2147483648 ,2147483648 ,158 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,10 ,14 ,2147483648 ,7 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,9 ,2147483648 ,2147483648 ,160 ,6 ,2147483648 ,5 ,8 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,10 ,14 ,2147483648 ,7 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,9 ,2147483648 ,2147483648 ,2147483648 ,6 ,2147483648 ,161 ,8 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,10 ,14 ,2147483648 ,7 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,9 ,2147483648 ,2147483648 ,2147483648 ,162 ,2147483648 ,2147483648 ,8 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,10 ,14 ,2147483648 ,163 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,8 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,10 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,164 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,165 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,166 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,167 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,168 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,169 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,170 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,171 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,172 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,173 ,2147483648 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,174 ,2147483648 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,175 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,2147483648 ,2147483648 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,176 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,2147483648 ,2147483648 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,2147483648 ,177 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,2147483648 ,2147483648 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,178 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,179 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,181 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,182 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,184 ,17 ,18 ,183 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,185 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,187 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,189 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,190 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {195 ,2147483648 ,17 ,18 ,193 ,14 ,2147483648 ,2147483648 ,11 ,194 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,197 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {198 ,2147483648 ,17 ,18 ,193 ,14 ,2147483648 ,2147483648 ,11 ,194 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {199 ,2147483648 ,17 ,18 ,193 ,14 ,2147483648 ,2147483648 ,11 ,194 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,200 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,201 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,184 ,17 ,18 ,202 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,203 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {205 ,2147483648 ,17 ,18 ,204 ,14 ,2147483648 ,2147483648 ,11 ,194 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,206 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,208 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,209 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,212 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,184 ,17 ,18 ,213 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,214 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,215 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,216 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,217 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,218 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,219 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,220 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,221 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,222 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,224 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,225 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,227 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,228 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,229 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,230 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,231 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,232 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,233 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,234 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,235 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,236 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,237 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,238 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,239 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,240 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,241 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,242 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,245 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,292 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,293 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,184 ,17 ,18 ,213 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,294 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {295 ,2147483648 ,17 ,18 ,193 ,14 ,2147483648 ,2147483648 ,11 ,194 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {296 ,2147483648 ,17 ,18 ,193 ,14 ,2147483648 ,2147483648 ,11 ,194 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {297 ,2147483648 ,17 ,18 ,193 ,14 ,2147483648 ,2147483648 ,11 ,194 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,298 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,299 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,184 ,17 ,18 ,213 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,300 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,301 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,302 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,303 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,304 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,305 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,306 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,307 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,308 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,324 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,325 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,326 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,17 ,18 ,327 ,14 ,2147483648 ,2147483648 ,11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,16 ,13 ,12 ,15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 } }; const int LalrActionTable[LALR_STATE_COUNT][LALR_TERMINAL_COUNT]= { - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483647 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-1 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-2 ,-2 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-4 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-4 ,-4 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-6 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-6 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-6 ,-6 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-8 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,63 ,2147483648 ,-8 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-8 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-8 ,-8 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-10 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-10 ,2147483648 ,-10 ,2147483648 ,64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-10 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-10 ,-10 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-12 ,2147483648 ,-12 ,2147483648 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-12 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-13 ,2147483648 ,65 ,2147483648 ,2147483648 ,70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,69 ,2147483648 ,-13 ,2147483648 ,-13 ,2147483648 ,-13 ,2147483648 ,2147483648 ,2147483648 ,67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-13 ,2147483648 ,2147483648 ,68 ,2147483648 ,66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-13 ,-13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-20 ,2147483648 ,-20 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,-20 ,2147483648 ,-20 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,-20 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-21 ,2147483648 ,-21 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,-21 ,2147483648 ,-21 ,2147483648 ,-21 ,71 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,-21 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,-21 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-24 ,2147483648 ,-24 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,-24 ,2147483648 ,-24 ,2147483648 ,-24 ,-24 ,2147483648 ,74 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,-24 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,-24 ,2147483648 ,-24 ,2147483648 ,73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-27 ,2147483648 ,-27 ,2147483648 ,2147483648 ,-27 ,2147483648 ,2147483648 ,75 ,-27 ,76 ,2147483648 ,2147483648 ,77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,2147483648 ,-27 ,2147483648 ,-27 ,2147483648 ,-27 ,-27 ,2147483648 ,-27 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,2147483648 ,2147483648 ,-27 ,2147483648 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,-27 ,2147483648 ,-27 ,2147483648 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-31 ,2147483648 ,-31 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,-31 ,-31 ,-31 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,-31 ,2147483648 ,-31 ,2147483648 ,-31 ,-31 ,2147483648 ,-31 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,-31 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,-31 ,2147483648 ,-31 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-32 ,2147483648 ,-32 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,-32 ,-32 ,-32 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,-32 ,2147483648 ,-32 ,2147483648 ,-32 ,-32 ,2147483648 ,-32 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,-32 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,-32 ,2147483648 ,-32 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-74 ,2147483648 ,-74 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,-74 ,-74 ,-74 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,-74 ,2147483648 ,-74 ,2147483648 ,-74 ,-74 ,2147483648 ,-74 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,-74 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,-74 ,2147483648 ,-74 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-79 ,2147483648 ,-79 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,-79 ,-79 ,-79 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,-79 ,2147483648 ,-79 ,2147483648 ,-79 ,-79 ,2147483648 ,-79 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,-79 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,-79 ,2147483648 ,-79 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,2147483648 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,2147483648 ,2147483648 ,57 ,2147483648 ,2147483648 ,37 ,2147483648 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,2147483648 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-72 ,2147483648 ,-72 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,-72 ,-72 ,-72 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,-72 ,2147483648 ,-72 ,2147483648 ,-72 ,-72 ,2147483648 ,-72 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,-72 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,-72 ,2147483648 ,-72 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,2147483648 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,2147483648 ,2147483648 ,57 ,2147483648 ,2147483648 ,37 ,2147483648 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,2147483648 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,93 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,95 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,96 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,2147483648 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,2147483648 ,2147483648 ,57 ,2147483648 ,2147483648 ,37 ,2147483648 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,2147483648 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-71 ,2147483648 ,-71 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,-71 ,-71 ,-71 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,-71 ,2147483648 ,-71 ,2147483648 ,-71 ,-71 ,2147483648 ,-71 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,-71 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,-71 ,2147483648 ,-71 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-76 ,2147483648 ,-76 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,-76 ,-76 ,-76 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,-76 ,2147483648 ,-76 ,2147483648 ,-76 ,-76 ,2147483648 ,-76 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,-76 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,-76 ,2147483648 ,-76 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,98 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,99 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,101 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-78 ,2147483648 ,-78 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,-78 ,-78 ,-78 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,-78 ,2147483648 ,-78 ,2147483648 ,-78 ,-78 ,2147483648 ,-78 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,-78 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,-78 ,2147483648 ,-78 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,102 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,2147483648 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,2147483648 ,2147483648 ,57 ,2147483648 ,2147483648 ,37 ,2147483648 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,2147483648 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-77 ,2147483648 ,-77 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,-77 ,-77 ,-77 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,-77 ,2147483648 ,-77 ,2147483648 ,-77 ,-77 ,2147483648 ,-77 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,-77 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,-77 ,2147483648 ,-77 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,104 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,105 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,106 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-75 ,2147483648 ,-75 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,-75 ,-75 ,-75 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,-75 ,2147483648 ,-75 ,2147483648 ,-75 ,-75 ,2147483648 ,-75 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,-75 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,-75 ,2147483648 ,-75 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,107 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,108 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,109 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,110 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,2147483648 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,2147483648 ,2147483648 ,57 ,2147483648 ,2147483648 ,37 ,2147483648 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,2147483648 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-73 ,2147483648 ,-73 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,-73 ,-73 ,-73 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,-73 ,2147483648 ,-73 ,2147483648 ,-73 ,-73 ,2147483648 ,-73 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,-73 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,-73 ,2147483648 ,-73 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,136 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,143 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-34 ,2147483648 ,-34 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,-34 ,-34 ,-34 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,-34 ,2147483648 ,-34 ,2147483648 ,-34 ,-34 ,2147483648 ,-34 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,-34 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,-34 ,2147483648 ,-34 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-35 ,2147483648 ,-35 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,-35 ,-35 ,-35 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,-35 ,2147483648 ,-35 ,2147483648 ,-35 ,-35 ,2147483648 ,-35 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,-35 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,-35 ,2147483648 ,-35 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,136 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-36 ,2147483648 ,-36 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,-36 ,-36 ,-36 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,-36 ,2147483648 ,-36 ,2147483648 ,-36 ,-36 ,2147483648 ,-36 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,-36 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,-36 ,2147483648 ,-36 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-33 ,2147483648 ,-33 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,-33 ,-33 ,-33 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,-33 ,2147483648 ,-33 ,2147483648 ,-33 ,-33 ,2147483648 ,-33 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,-33 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,-33 ,2147483648 ,-33 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,143 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,143 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,168 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-37 ,2147483648 ,-37 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,-37 ,-37 ,-37 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,-37 ,2147483648 ,-37 ,2147483648 ,-37 ,-37 ,2147483648 ,-37 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,-37 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,-37 ,2147483648 ,-37 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-3 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-3 ,-3 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-5 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-5 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-5 ,-5 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-7 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,63 ,2147483648 ,-7 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-7 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-7 ,-7 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-9 ,2147483648 ,-9 ,2147483648 ,64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-9 ,-9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-11 ,2147483648 ,-11 ,2147483648 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-11 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-18 ,2147483648 ,-18 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,-18 ,2147483648 ,-18 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,-18 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-15 ,2147483648 ,-15 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,-15 ,2147483648 ,-15 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,-15 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-17 ,2147483648 ,-17 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,-17 ,2147483648 ,-17 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,-17 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-14 ,2147483648 ,-14 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,-14 ,2147483648 ,-14 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,-14 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-16 ,2147483648 ,-16 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,-16 ,2147483648 ,-16 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,-16 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-19 ,2147483648 ,-19 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,-19 ,2147483648 ,-19 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,-19 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-23 ,2147483648 ,-23 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,-23 ,2147483648 ,-23 ,2147483648 ,-23 ,-23 ,2147483648 ,74 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,-23 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,-23 ,2147483648 ,-23 ,2147483648 ,73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-22 ,2147483648 ,-22 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,-22 ,2147483648 ,-22 ,2147483648 ,-22 ,-22 ,2147483648 ,74 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,-22 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,-22 ,2147483648 ,-22 ,2147483648 ,73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-25 ,2147483648 ,-25 ,2147483648 ,2147483648 ,-25 ,2147483648 ,2147483648 ,75 ,-25 ,76 ,2147483648 ,2147483648 ,77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,2147483648 ,-25 ,2147483648 ,-25 ,2147483648 ,-25 ,-25 ,2147483648 ,-25 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,2147483648 ,2147483648 ,-25 ,2147483648 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,-25 ,2147483648 ,-25 ,2147483648 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-26 ,2147483648 ,-26 ,2147483648 ,2147483648 ,-26 ,2147483648 ,2147483648 ,75 ,-26 ,76 ,2147483648 ,2147483648 ,77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,2147483648 ,-26 ,2147483648 ,-26 ,2147483648 ,-26 ,-26 ,2147483648 ,-26 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,2147483648 ,2147483648 ,-26 ,2147483648 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,-26 ,2147483648 ,-26 ,2147483648 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-29 ,2147483648 ,-29 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,-29 ,-29 ,-29 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,-29 ,2147483648 ,-29 ,2147483648 ,-29 ,-29 ,2147483648 ,-29 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,-29 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,-29 ,2147483648 ,-29 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-30 ,2147483648 ,-30 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,-30 ,-30 ,-30 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,-30 ,2147483648 ,-30 ,2147483648 ,-30 ,-30 ,2147483648 ,-30 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,-30 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,-30 ,2147483648 ,-30 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-28 ,2147483648 ,-28 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,-28 ,-28 ,-28 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,-28 ,2147483648 ,-28 ,2147483648 ,-28 ,-28 ,2147483648 ,-28 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,-28 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,-28 ,2147483648 ,-28 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,169 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,170 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,171 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,172 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,173 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,174 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,175 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,176 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,177 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,178 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,179 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,180 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,181 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,182 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,183 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,184 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,185 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,186 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,187 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,188 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,189 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,190 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,191 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,194 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,195 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,196 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,197 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,198 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,199 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,200 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-70 ,2147483648 ,-70 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,-70 ,-70 ,-70 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,-70 ,2147483648 ,-70 ,2147483648 ,-70 ,-70 ,2147483648 ,-70 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,-70 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,-70 ,2147483648 ,-70 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-44 ,2147483648 ,-44 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,-44 ,-44 ,-44 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,-44 ,2147483648 ,-44 ,2147483648 ,-44 ,-44 ,2147483648 ,-44 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,-44 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,-44 ,2147483648 ,-44 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-46 ,2147483648 ,-46 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,-46 ,-46 ,-46 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,-46 ,2147483648 ,-46 ,2147483648 ,-46 ,-46 ,2147483648 ,-46 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,-46 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,-46 ,2147483648 ,-46 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,136 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-38 ,2147483648 ,-38 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,-38 ,-38 ,-38 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,-38 ,2147483648 ,-38 ,2147483648 ,-38 ,-38 ,2147483648 ,-38 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,-38 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,-38 ,2147483648 ,-38 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-56 ,2147483648 ,-56 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,-56 ,-56 ,-56 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,-56 ,2147483648 ,-56 ,2147483648 ,-56 ,-56 ,2147483648 ,-56 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,-56 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,-56 ,2147483648 ,-56 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,143 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-40 ,2147483648 ,-40 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,-40 ,-40 ,-40 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,-40 ,2147483648 ,-40 ,2147483648 ,-40 ,-40 ,2147483648 ,-40 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,-40 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,-40 ,2147483648 ,-40 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-45 ,2147483648 ,-45 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,-45 ,-45 ,-45 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,-45 ,2147483648 ,-45 ,2147483648 ,-45 ,-45 ,2147483648 ,-45 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,-45 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,-45 ,2147483648 ,-45 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-50 ,2147483648 ,-50 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,-50 ,-50 ,-50 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,-50 ,2147483648 ,-50 ,2147483648 ,-50 ,-50 ,2147483648 ,-50 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,-50 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,-50 ,2147483648 ,-50 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-55 ,2147483648 ,-55 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,-55 ,-55 ,-55 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,-55 ,2147483648 ,-55 ,2147483648 ,-55 ,-55 ,2147483648 ,-55 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,-55 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,-55 ,2147483648 ,-55 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-52 ,2147483648 ,-52 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,-52 ,-52 ,-52 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,-52 ,2147483648 ,-52 ,2147483648 ,-52 ,-52 ,2147483648 ,-52 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,-52 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,-52 ,2147483648 ,-52 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-49 ,2147483648 ,-49 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,-49 ,-49 ,-49 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,-49 ,2147483648 ,-49 ,2147483648 ,-49 ,-49 ,2147483648 ,-49 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,-49 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,-49 ,2147483648 ,-49 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-68 ,2147483648 ,-68 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,-68 ,-68 ,-68 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,-68 ,2147483648 ,-68 ,2147483648 ,-68 ,-68 ,2147483648 ,-68 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,-68 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,-68 ,2147483648 ,-68 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-39 ,2147483648 ,-39 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,-39 ,-39 ,-39 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,-39 ,2147483648 ,-39 ,2147483648 ,-39 ,-39 ,2147483648 ,-39 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,-39 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,-39 ,2147483648 ,-39 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-41 ,2147483648 ,-41 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,-41 ,-41 ,-41 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,-41 ,2147483648 ,-41 ,2147483648 ,-41 ,-41 ,2147483648 ,-41 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,-41 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,-41 ,2147483648 ,-41 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-54 ,2147483648 ,-54 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,-54 ,-54 ,-54 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,-54 ,2147483648 ,-54 ,2147483648 ,-54 ,-54 ,2147483648 ,-54 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,-54 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,-54 ,2147483648 ,-54 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-53 ,2147483648 ,-53 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,-53 ,-53 ,-53 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,-53 ,2147483648 ,-53 ,2147483648 ,-53 ,-53 ,2147483648 ,-53 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,-53 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,-53 ,2147483648 ,-53 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-48 ,2147483648 ,-48 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,-48 ,-48 ,-48 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,-48 ,2147483648 ,-48 ,2147483648 ,-48 ,-48 ,2147483648 ,-48 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,-48 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,-48 ,2147483648 ,-48 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-65 ,2147483648 ,-65 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,-65 ,-65 ,-65 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,-65 ,2147483648 ,-65 ,2147483648 ,-65 ,-65 ,2147483648 ,-65 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,-65 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,-65 ,2147483648 ,-65 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-51 ,2147483648 ,-51 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,-51 ,-51 ,-51 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,-51 ,2147483648 ,-51 ,2147483648 ,-51 ,-51 ,2147483648 ,-51 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,-51 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,-51 ,2147483648 ,-51 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,143 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-42 ,2147483648 ,-42 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,-42 ,-42 ,-42 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,-42 ,2147483648 ,-42 ,2147483648 ,-42 ,-42 ,2147483648 ,-42 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,-42 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,-42 ,2147483648 ,-42 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-43 ,2147483648 ,-43 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,-43 ,-43 ,-43 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,-43 ,2147483648 ,-43 ,2147483648 ,-43 ,-43 ,2147483648 ,-43 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,-43 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,-43 ,2147483648 ,-43 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-47 ,2147483648 ,-47 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,-47 ,-47 ,-47 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,-47 ,2147483648 ,-47 ,2147483648 ,-47 ,-47 ,2147483648 ,-47 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,-47 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,-47 ,2147483648 ,-47 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-57 ,2147483648 ,-57 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,-57 ,-57 ,-57 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,-57 ,2147483648 ,-57 ,2147483648 ,-57 ,-57 ,2147483648 ,-57 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,-57 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,-57 ,2147483648 ,-57 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,212 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,213 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,214 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,215 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,216 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,217 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,218 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,219 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,220 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,221 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-63 ,2147483648 ,-63 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,-63 ,-63 ,-63 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,-63 ,2147483648 ,-63 ,2147483648 ,-63 ,-63 ,2147483648 ,-63 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,-63 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,-63 ,2147483648 ,-63 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-69 ,2147483648 ,-69 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,-69 ,-69 ,-69 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,-69 ,2147483648 ,-69 ,2147483648 ,-69 ,-69 ,2147483648 ,-69 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,-69 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,-69 ,2147483648 ,-69 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,-66 ,2147483648 ,-66 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,-66 ,-66 ,-66 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,-66 ,2147483648 ,-66 ,2147483648 ,-66 ,-66 ,2147483648 ,-66 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,-66 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,-66 ,2147483648 ,-66 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-59 ,2147483648 ,-59 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,-59 ,-59 ,-59 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,-59 ,2147483648 ,-59 ,2147483648 ,-59 ,-59 ,2147483648 ,-59 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,-59 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,-59 ,2147483648 ,-59 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-60 ,2147483648 ,-60 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,-60 ,-60 ,-60 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,-60 ,2147483648 ,-60 ,2147483648 ,-60 ,-60 ,2147483648 ,-60 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,-60 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,-60 ,2147483648 ,-60 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-58 ,2147483648 ,-58 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,-58 ,-58 ,-58 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,-58 ,2147483648 ,-58 ,2147483648 ,-58 ,-58 ,2147483648 ,-58 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,-58 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,-58 ,2147483648 ,-58 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-61 ,2147483648 ,-61 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,-61 ,-61 ,-61 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,-61 ,2147483648 ,-61 ,2147483648 ,-61 ,-61 ,2147483648 ,-61 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,-61 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,-61 ,2147483648 ,-61 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-62 ,2147483648 ,-62 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,-62 ,-62 ,-62 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,-62 ,2147483648 ,-62 ,2147483648 ,-62 ,-62 ,2147483648 ,-62 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,-62 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,-62 ,2147483648 ,-62 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {25 ,16 ,2147483648 ,39 ,2147483648 ,35 ,50 ,2147483648 ,18 ,29 ,2147483648 ,2147483648 ,38 ,24 ,2147483648 ,2147483648 ,26 ,51 ,52 ,46 ,2147483648 ,20 ,2147483648 ,40 ,2147483648 ,56 ,58 ,2147483648 ,57 ,47 ,2147483648 ,37 ,31 ,36 ,53 ,2147483648 ,17 ,44 ,2147483648 ,55 ,2147483648 ,32 ,43 ,30 ,22 ,19 ,33 ,23 ,21 ,48 ,2147483648 ,2147483648 ,27 ,2147483648 ,2147483648 ,28 ,41 ,59 ,54 ,42 ,49 ,45 ,34 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,224 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,225 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-64 ,2147483648 ,-64 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,-64 ,-64 ,-64 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,-64 ,2147483648 ,-64 ,2147483648 ,-64 ,-64 ,2147483648 ,-64 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,-64 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,-64 ,2147483648 ,-64 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, - {2147483648 ,2147483648 ,-67 ,2147483648 ,-67 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,-67 ,-67 ,-67 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,-67 ,2147483648 ,-67 ,2147483648 ,-67 ,-67 ,2147483648 ,-67 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,-67 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,-67 ,2147483648 ,-67 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 } + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483647 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-1 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-2 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-2 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-4 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-4 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-4 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-6 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-6 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-6 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-6 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-8 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-8 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-8 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-8 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-8 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-10 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-10 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-10 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-10 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-10 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-10 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-12 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,93 ,2147483648 ,2147483648 ,2147483648 ,-13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-13 ,2147483648 ,90 ,2147483648 ,94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-13 ,92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-13 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,-20 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-20 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,-21 ,2147483648 ,-21 ,95 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-21 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,96 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,98 ,-24 ,2147483648 ,-24 ,-24 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,97 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-24 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,2147483648 ,2147483648 ,2147483648 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,101 ,2147483648 ,2147483648 ,2147483648 ,100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,2147483648 ,-27 ,-27 ,2147483648 ,-27 ,-27 ,-27 ,2147483648 ,2147483648 ,99 ,2147483648 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,2147483648 ,2147483648 ,2147483648 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-27 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,-31 ,-31 ,2147483648 ,-31 ,-31 ,-31 ,2147483648 ,2147483648 ,-31 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-31 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,-32 ,-32 ,2147483648 ,-32 ,-32 ,-32 ,2147483648 ,2147483648 ,-32 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-32 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,102 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-95 ,2147483648 ,2147483648 ,2147483648 ,-95 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-95 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-95 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-95 ,2147483648 ,2147483648 ,2147483648 ,-95 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-95 ,2147483648 ,-95 ,-95 ,2147483648 ,-95 ,-95 ,-95 ,2147483648 ,2147483648 ,-95 ,2147483648 ,-95 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-95 ,2147483648 ,2147483648 ,2147483648 ,-95 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-95 ,-95 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-95 ,-95 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-95 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-95 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,104 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,105 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,106 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,107 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-97 ,2147483648 ,2147483648 ,2147483648 ,-97 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-97 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-97 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-97 ,2147483648 ,2147483648 ,2147483648 ,-97 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-97 ,2147483648 ,-97 ,-97 ,2147483648 ,-97 ,-97 ,-97 ,2147483648 ,2147483648 ,-97 ,2147483648 ,-97 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-97 ,2147483648 ,2147483648 ,2147483648 ,-97 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-97 ,-97 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-97 ,-97 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-97 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-97 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,2147483648 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,2147483648 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-94 ,2147483648 ,2147483648 ,2147483648 ,-94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-94 ,2147483648 ,2147483648 ,2147483648 ,-94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-94 ,2147483648 ,-94 ,-94 ,2147483648 ,-94 ,-94 ,-94 ,2147483648 ,2147483648 ,-94 ,2147483648 ,-94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-94 ,2147483648 ,2147483648 ,2147483648 ,-94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-94 ,-94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-94 ,-94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-94 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-94 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,109 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,110 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,111 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-102 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,112 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,114 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-96 ,2147483648 ,2147483648 ,2147483648 ,-96 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-96 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-96 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-96 ,2147483648 ,2147483648 ,2147483648 ,-96 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-96 ,2147483648 ,-96 ,-96 ,2147483648 ,-96 ,-96 ,-96 ,2147483648 ,2147483648 ,-96 ,2147483648 ,-96 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-96 ,2147483648 ,2147483648 ,2147483648 ,-96 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-96 ,-96 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-96 ,-96 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-96 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-96 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,118 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,119 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-98 ,2147483648 ,2147483648 ,2147483648 ,-98 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-98 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-98 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-98 ,2147483648 ,2147483648 ,2147483648 ,-98 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-98 ,2147483648 ,-98 ,-98 ,2147483648 ,-98 ,-98 ,-98 ,2147483648 ,2147483648 ,-98 ,2147483648 ,-98 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-98 ,2147483648 ,2147483648 ,2147483648 ,-98 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-98 ,-98 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-98 ,-98 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-98 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-98 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,120 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,121 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,122 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,123 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,124 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-93 ,2147483648 ,-114 ,2147483648 ,-93 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-93 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-93 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-93 ,2147483648 ,2147483648 ,2147483648 ,-93 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-93 ,2147483648 ,-93 ,-93 ,2147483648 ,-93 ,-93 ,-93 ,2147483648 ,2147483648 ,-93 ,2147483648 ,-93 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-93 ,2147483648 ,2147483648 ,2147483648 ,-93 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-93 ,-93 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-93 ,-93 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-93 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-93 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,125 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,126 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,127 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,128 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,129 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,130 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,131 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,132 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,133 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,134 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,135 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,136 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-99 ,2147483648 ,2147483648 ,2147483648 ,-99 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-99 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-99 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-99 ,2147483648 ,2147483648 ,2147483648 ,-99 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-99 ,2147483648 ,-99 ,-99 ,2147483648 ,-99 ,-99 ,-99 ,2147483648 ,2147483648 ,-99 ,2147483648 ,-99 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-99 ,2147483648 ,2147483648 ,2147483648 ,-99 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-99 ,-99 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-99 ,-99 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-99 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-99 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,138 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,139 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,140 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,141 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,142 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,143 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,144 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,145 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,146 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,147 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,2147483648 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,2147483648 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-91 ,2147483648 ,2147483648 ,2147483648 ,-91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-91 ,2147483648 ,2147483648 ,2147483648 ,-91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-91 ,2147483648 ,-91 ,-91 ,2147483648 ,-91 ,-91 ,-91 ,2147483648 ,2147483648 ,-91 ,2147483648 ,-91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-91 ,2147483648 ,2147483648 ,2147483648 ,-91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-91 ,-91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-91 ,-91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-91 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-91 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,149 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,150 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,151 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,152 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,2147483648 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,2147483648 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,154 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,155 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,156 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,2147483648 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,2147483648 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-92 ,2147483648 ,2147483648 ,2147483648 ,-92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-92 ,2147483648 ,2147483648 ,2147483648 ,-92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-92 ,2147483648 ,-92 ,-92 ,2147483648 ,-92 ,-92 ,-92 ,2147483648 ,2147483648 ,-92 ,2147483648 ,-92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-92 ,2147483648 ,2147483648 ,2147483648 ,-92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-92 ,-92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-92 ,-92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-92 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-92 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,2147483648 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,2147483648 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-100 ,2147483648 ,2147483648 ,2147483648 ,-100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-100 ,2147483648 ,2147483648 ,2147483648 ,-100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-100 ,2147483648 ,-100 ,-100 ,2147483648 ,-100 ,-100 ,-100 ,2147483648 ,2147483648 ,-100 ,2147483648 ,-100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-100 ,2147483648 ,2147483648 ,2147483648 ,-100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-100 ,-100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-100 ,-100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-100 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,159 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,-103 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,104 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,-117 ,-117 ,2147483648 ,-117 ,-117 ,-117 ,2147483648 ,2147483648 ,-117 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,186 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,188 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,-37 ,-37 ,2147483648 ,-37 ,-37 ,-37 ,2147483648 ,2147483648 ,-37 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-37 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,191 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,192 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {78 ,59 ,74 ,67 ,196 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,196 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,196 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,186 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,196 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,207 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,210 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,211 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,186 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,223 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,226 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,-36 ,-36 ,2147483648 ,-36 ,-36 ,-36 ,2147483648 ,2147483648 ,-36 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-36 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,-35 ,-35 ,2147483648 ,-35 ,-35 ,-35 ,2147483648 ,2147483648 ,-35 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-35 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,-34 ,-34 ,2147483648 ,-34 ,-34 ,-34 ,2147483648 ,2147483648 ,-34 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-34 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,-33 ,-33 ,2147483648 ,-33 ,-33 ,-33 ,2147483648 ,2147483648 ,-33 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-33 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-3 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-3 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-3 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-5 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-5 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-5 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-5 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-7 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-7 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-7 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-7 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-7 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-9 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-11 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,-15 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-15 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,-16 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-16 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,-18 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-18 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,-17 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-17 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,-19 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-19 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,-14 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-14 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,98 ,-23 ,2147483648 ,-23 ,-23 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,97 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-23 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,98 ,-22 ,2147483648 ,-22 ,-22 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,97 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-22 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,2147483648 ,2147483648 ,2147483648 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,101 ,2147483648 ,2147483648 ,2147483648 ,100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,2147483648 ,-25 ,-25 ,2147483648 ,-25 ,-25 ,-25 ,2147483648 ,2147483648 ,99 ,2147483648 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,2147483648 ,2147483648 ,2147483648 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-25 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,2147483648 ,2147483648 ,2147483648 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,101 ,2147483648 ,2147483648 ,2147483648 ,100 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,2147483648 ,-26 ,-26 ,2147483648 ,-26 ,-26 ,-26 ,2147483648 ,2147483648 ,99 ,2147483648 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,2147483648 ,2147483648 ,2147483648 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-26 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,-29 ,-29 ,2147483648 ,-29 ,-29 ,-29 ,2147483648 ,2147483648 ,-29 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-29 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,-28 ,-28 ,2147483648 ,-28 ,-28 ,-28 ,2147483648 ,2147483648 ,-28 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-28 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,-30 ,-30 ,2147483648 ,-30 ,-30 ,-30 ,2147483648 ,2147483648 ,-30 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-30 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,243 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-106 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,244 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,104 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,-117 ,-117 ,2147483648 ,-117 ,-117 ,-117 ,2147483648 ,2147483648 ,-117 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-117 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-113 ,2147483648 ,2147483648 ,2147483648 ,-113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-113 ,2147483648 ,2147483648 ,2147483648 ,-113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-113 ,2147483648 ,-113 ,-113 ,2147483648 ,-113 ,-113 ,-113 ,2147483648 ,2147483648 ,-113 ,2147483648 ,-113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-113 ,2147483648 ,2147483648 ,2147483648 ,-113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-113 ,-113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-113 ,-113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-113 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-113 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,246 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,247 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-112 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-112 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,248 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-108 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-108 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,249 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,-39 ,-39 ,2147483648 ,-39 ,-39 ,-39 ,2147483648 ,2147483648 ,-39 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-39 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,250 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,251 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,-44 ,-44 ,2147483648 ,-44 ,-44 ,-44 ,2147483648 ,2147483648 ,-44 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-44 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,-41 ,-41 ,2147483648 ,-41 ,-41 ,-41 ,2147483648 ,2147483648 ,-41 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-41 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-109 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-109 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-110 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-110 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,252 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-107 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-107 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,253 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,254 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,255 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,256 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,257 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,258 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,259 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-109 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,261 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,262 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,-38 ,-38 ,2147483648 ,-38 ,-38 ,-38 ,2147483648 ,2147483648 ,-38 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-38 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,263 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,264 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,-40 ,-40 ,2147483648 ,-40 ,-40 ,-40 ,2147483648 ,2147483648 ,-40 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-40 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,-43 ,-43 ,2147483648 ,-43 ,-43 ,-43 ,2147483648 ,2147483648 ,-43 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-43 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,265 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-111 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-111 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,266 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,267 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,268 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,269 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,270 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,271 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,272 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,273 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,274 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-90 ,2147483648 ,2147483648 ,2147483648 ,-90 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-90 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-90 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-90 ,2147483648 ,2147483648 ,2147483648 ,-90 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-90 ,2147483648 ,-90 ,-90 ,2147483648 ,-90 ,-90 ,-90 ,2147483648 ,2147483648 ,-90 ,2147483648 ,-90 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-90 ,2147483648 ,2147483648 ,2147483648 ,-90 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-90 ,-90 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-90 ,-90 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-90 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-90 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,275 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,276 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,-42 ,-42 ,2147483648 ,-42 ,-42 ,-42 ,2147483648 ,2147483648 ,-42 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-42 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,277 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,278 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,279 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,280 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,281 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,282 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,283 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,284 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,285 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,286 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,287 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,288 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,289 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,290 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,291 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-104 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-101 ,2147483648 ,2147483648 ,2147483648 ,-101 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-101 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-101 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-101 ,2147483648 ,2147483648 ,2147483648 ,-101 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-101 ,2147483648 ,-101 ,-101 ,2147483648 ,-101 ,-101 ,-101 ,2147483648 ,2147483648 ,-101 ,2147483648 ,-101 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-101 ,2147483648 ,2147483648 ,2147483648 ,-101 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-101 ,-101 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-101 ,-101 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-101 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-101 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-116 ,2147483648 ,2147483648 ,2147483648 ,-116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-116 ,2147483648 ,2147483648 ,2147483648 ,-116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-116 ,2147483648 ,-116 ,-116 ,2147483648 ,-116 ,-116 ,-116 ,2147483648 ,2147483648 ,-116 ,2147483648 ,-116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-116 ,2147483648 ,2147483648 ,2147483648 ,-116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-116 ,-116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-116 ,-116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-116 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-116 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-115 ,2147483648 ,-115 ,2147483648 ,-115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-115 ,2147483648 ,2147483648 ,2147483648 ,-115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-115 ,2147483648 ,-115 ,-115 ,2147483648 ,-115 ,-115 ,-115 ,2147483648 ,2147483648 ,-115 ,2147483648 ,-115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-115 ,2147483648 ,2147483648 ,2147483648 ,-115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-115 ,-115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-115 ,-115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-115 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-115 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,186 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,-52 ,-52 ,2147483648 ,-52 ,-52 ,-52 ,2147483648 ,2147483648 ,-52 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-52 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,-64 ,-64 ,2147483648 ,-64 ,-64 ,-64 ,2147483648 ,2147483648 ,-64 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-64 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,-53 ,-53 ,2147483648 ,-53 ,-53 ,-53 ,2147483648 ,2147483648 ,-53 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-53 }, + {78 ,59 ,74 ,67 ,196 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,-67 ,-67 ,2147483648 ,-67 ,-67 ,-67 ,2147483648 ,2147483648 ,-67 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-67 }, + {78 ,59 ,74 ,67 ,196 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,196 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,-66 ,-66 ,2147483648 ,-66 ,-66 ,-66 ,2147483648 ,2147483648 ,-66 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-66 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,-59 ,-59 ,2147483648 ,-59 ,-59 ,-59 ,2147483648 ,2147483648 ,-59 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-59 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,-56 ,-56 ,2147483648 ,-56 ,-56 ,-56 ,2147483648 ,2147483648 ,-56 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-56 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-87 ,2147483648 ,2147483648 ,2147483648 ,-87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-87 ,2147483648 ,2147483648 ,2147483648 ,-87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-87 ,2147483648 ,-87 ,-87 ,2147483648 ,-87 ,-87 ,-87 ,2147483648 ,2147483648 ,-87 ,2147483648 ,-87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-87 ,2147483648 ,2147483648 ,2147483648 ,-87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-87 ,-87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-87 ,-87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-87 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-87 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,-55 ,-55 ,2147483648 ,-55 ,-55 ,-55 ,2147483648 ,2147483648 ,-55 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-55 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,-83 ,-83 ,2147483648 ,-83 ,-83 ,-83 ,2147483648 ,2147483648 ,-83 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 ,-83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 ,-83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-83 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,-50 ,-50 ,2147483648 ,-50 ,-50 ,-50 ,2147483648 ,2147483648 ,-50 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-50 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,-71 ,-71 ,2147483648 ,-71 ,-71 ,-71 ,2147483648 ,2147483648 ,-71 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-71 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,186 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,-62 ,-62 ,2147483648 ,-62 ,-62 ,-62 ,2147483648 ,2147483648 ,-62 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-62 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,-69 ,-69 ,2147483648 ,-69 ,-69 ,-69 ,2147483648 ,2147483648 ,-69 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-69 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,-72 ,-72 ,2147483648 ,-72 ,-72 ,-72 ,2147483648 ,2147483648 ,-72 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-72 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,-61 ,-61 ,2147483648 ,-61 ,-61 ,-61 ,2147483648 ,2147483648 ,-61 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-61 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,-63 ,-63 ,2147483648 ,-63 ,-63 ,-63 ,2147483648 ,2147483648 ,-63 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-63 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,-45 ,-45 ,2147483648 ,-45 ,-45 ,-45 ,2147483648 ,2147483648 ,-45 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-45 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,-49 ,-49 ,2147483648 ,-49 ,-49 ,-49 ,2147483648 ,2147483648 ,-49 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-49 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,-68 ,-68 ,2147483648 ,-68 ,-68 ,-68 ,2147483648 ,2147483648 ,-68 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-68 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,-65 ,-65 ,2147483648 ,-65 ,-65 ,-65 ,2147483648 ,2147483648 ,-65 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-65 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,-48 ,-48 ,2147483648 ,-48 ,-48 ,-48 ,2147483648 ,2147483648 ,-48 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-48 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,-60 ,-60 ,2147483648 ,-60 ,-60 ,-60 ,2147483648 ,2147483648 ,-60 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-60 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,-47 ,-47 ,2147483648 ,-47 ,-47 ,-47 ,2147483648 ,2147483648 ,-47 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-47 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,-70 ,-70 ,2147483648 ,-70 ,-70 ,-70 ,2147483648 ,2147483648 ,-70 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-70 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,-57 ,-57 ,2147483648 ,-57 ,-57 ,-57 ,2147483648 ,2147483648 ,-57 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-57 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,-54 ,-54 ,2147483648 ,-54 ,-54 ,-54 ,2147483648 ,2147483648 ,-54 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-54 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,-58 ,-58 ,2147483648 ,-58 ,-58 ,-58 ,2147483648 ,2147483648 ,-58 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-58 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,-51 ,-51 ,2147483648 ,-51 ,-51 ,-51 ,2147483648 ,2147483648 ,-51 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-51 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,-46 ,-46 ,2147483648 ,-46 ,-46 ,-46 ,2147483648 ,2147483648 ,-46 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-46 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,243 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-106 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,309 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,310 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,311 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,312 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,313 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,314 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,315 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,316 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,317 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,318 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,319 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,320 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,321 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,322 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,323 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-105 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,-78 ,-78 ,2147483648 ,-78 ,-78 ,-78 ,2147483648 ,2147483648 ,-78 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-78 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-88 ,2147483648 ,2147483648 ,2147483648 ,-88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-88 ,2147483648 ,2147483648 ,2147483648 ,-88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-88 ,2147483648 ,-88 ,-88 ,2147483648 ,-88 ,-88 ,-88 ,2147483648 ,2147483648 ,-88 ,2147483648 ,-88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-88 ,2147483648 ,2147483648 ,2147483648 ,-88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-88 ,-88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-88 ,-88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-88 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-88 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,-84 ,-84 ,2147483648 ,-84 ,-84 ,-84 ,2147483648 ,2147483648 ,-84 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 ,-84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 ,-84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-84 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,-80 ,-80 ,2147483648 ,-80 ,-80 ,-80 ,2147483648 ,2147483648 ,-80 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 ,-80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 ,-80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-80 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,-74 ,-74 ,2147483648 ,-74 ,-74 ,-74 ,2147483648 ,2147483648 ,-74 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-74 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,-79 ,-79 ,2147483648 ,-79 ,-79 ,-79 ,2147483648 ,2147483648 ,-79 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-79 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,-73 ,-73 ,2147483648 ,-73 ,-73 ,-73 ,2147483648 ,2147483648 ,-73 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-73 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,-81 ,-81 ,2147483648 ,-81 ,-81 ,-81 ,2147483648 ,2147483648 ,-81 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 ,-81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 ,-81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-81 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,-75 ,-75 ,2147483648 ,-75 ,-75 ,-75 ,2147483648 ,2147483648 ,-75 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-75 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,-77 ,-77 ,2147483648 ,-77 ,-77 ,-77 ,2147483648 ,2147483648 ,-77 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-77 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,-76 ,-76 ,2147483648 ,-76 ,-76 ,-76 ,2147483648 ,2147483648 ,-76 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-76 }, + {78 ,59 ,74 ,67 ,2147483648 ,25 ,2147483648 ,41 ,2147483648 ,38 ,2147483648 ,31 ,2147483648 ,62 ,58 ,2147483648 ,52 ,53 ,43 ,46 ,2147483648 ,71 ,44 ,21 ,57 ,69 ,49 ,35 ,19 ,2147483648 ,27 ,72 ,20 ,28 ,29 ,70 ,2147483648 ,37 ,81 ,23 ,75 ,2147483648 ,2147483648 ,2147483648 ,51 ,76 ,2147483648 ,61 ,2147483648 ,32 ,55 ,22 ,68 ,2147483648 ,83 ,39 ,36 ,2147483648 ,30 ,60 ,45 ,77 ,47 ,42 ,2147483648 ,2147483648 ,34 ,56 ,82 ,64 ,66 ,65 ,48 ,79 ,2147483648 ,26 ,63 ,54 ,80 ,2147483648 ,73 ,40 ,33 ,50 ,24 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,328 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,329 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,330 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,331 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-86 ,2147483648 ,2147483648 ,2147483648 ,-86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-86 ,2147483648 ,2147483648 ,2147483648 ,-86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-86 ,2147483648 ,-86 ,-86 ,2147483648 ,-86 ,-86 ,-86 ,2147483648 ,2147483648 ,-86 ,2147483648 ,-86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-86 ,2147483648 ,2147483648 ,2147483648 ,-86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-86 ,-86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-86 ,-86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-86 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-86 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,-85 ,-85 ,2147483648 ,-85 ,-85 ,-85 ,2147483648 ,2147483648 ,-85 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 ,-85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 ,-85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-85 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-89 ,2147483648 ,2147483648 ,2147483648 ,-89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-89 ,2147483648 ,2147483648 ,2147483648 ,-89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-89 ,2147483648 ,-89 ,-89 ,2147483648 ,-89 ,-89 ,-89 ,2147483648 ,2147483648 ,-89 ,2147483648 ,-89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-89 ,2147483648 ,2147483648 ,2147483648 ,-89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-89 ,-89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-89 ,-89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-89 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-89 }, + {2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,-82 ,-82 ,2147483648 ,-82 ,-82 ,-82 ,2147483648 ,2147483648 ,-82 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,2147483648 ,-82 } }; -const struct _TOKEN LalrSemanticRules[RULES_COUNT]= +const struct _SCRIPT_ENGINE_TOKEN LalrSemanticRules[RULES_COUNT]= { {UNKNOWN, ""}, {UNKNOWN, ""}, @@ -2151,6 +2890,13 @@ const struct _TOKEN LalrSemanticRules[RULES_COUNT]= {SEMANTIC_RULE, "@NOT"}, {SEMANTIC_RULE, "@POI"}, {SEMANTIC_RULE, "@REFERENCE"}, + {SEMANTIC_RULE, "@RDTSC"}, + {SEMANTIC_RULE, "@RDTSCP"}, + {SEMANTIC_RULE, "@LBR_SAVE"}, + {SEMANTIC_RULE, "@LBR_DUMP"}, + {SEMANTIC_RULE, "@LBR_PRINT"}, + {SEMANTIC_RULE, "@LBR_RESTORE"}, + {SEMANTIC_RULE, "@LBR_CHECK"}, {SEMANTIC_RULE, "@POI"}, {SEMANTIC_RULE, "@DB"}, {SEMANTIC_RULE, "@DD"}, @@ -2171,32 +2917,57 @@ const struct _TOKEN LalrSemanticRules[RULES_COUNT]= {SEMANTIC_RULE, "@REFERENCE"}, {SEMANTIC_RULE, "@PHYSICAL_TO_VIRTUAL"}, {SEMANTIC_RULE, "@VIRTUAL_TO_PHYSICAL"}, + {SEMANTIC_RULE, "@POI_PA"}, + {SEMANTIC_RULE, "@HI_PA"}, + {SEMANTIC_RULE, "@LOW_PA"}, + {SEMANTIC_RULE, "@DB_PA"}, + {SEMANTIC_RULE, "@DD_PA"}, + {SEMANTIC_RULE, "@DW_PA"}, + {SEMANTIC_RULE, "@DQ_PA"}, + {SEMANTIC_RULE, "@LBR_RESTORE_BY_FILTER"}, {SEMANTIC_RULE, "@ED"}, {SEMANTIC_RULE, "@EB"}, {SEMANTIC_RULE, "@EQ"}, {SEMANTIC_RULE, "@INTERLOCKED_EXCHANGE"}, {SEMANTIC_RULE, "@INTERLOCKED_EXCHANGE_ADD"}, {SEMANTIC_RULE, "@WCSCMP"}, + {SEMANTIC_RULE, "@EB_PA"}, + {SEMANTIC_RULE, "@ED_PA"}, + {SEMANTIC_RULE, "@EQ_PA"}, {SEMANTIC_RULE, "@INTERLOCKED_COMPARE_EXCHANGE"}, {SEMANTIC_RULE, "@STRLEN"}, {SEMANTIC_RULE, "@STRCMP"}, {SEMANTIC_RULE, "@MEMCMP"}, + {SEMANTIC_RULE, "@STRNCMP"}, {SEMANTIC_RULE, "@WCSLEN"}, {SEMANTIC_RULE, "@WCSCMP"}, + {SEMANTIC_RULE, "@WCSNCMP"}, + {UNKNOWN, ""}, + {SEMANTIC_RULE, "@PUSH"}, + {SEMANTIC_RULE, "@PUSH"}, + {SEMANTIC_RULE, "@PUSH"}, + {SEMANTIC_RULE, "@PUSH"}, {UNKNOWN, ""}, {SEMANTIC_RULE, "@PUSH"}, {SEMANTIC_RULE, "@PUSH"}, {SEMANTIC_RULE, "@PUSH"}, {SEMANTIC_RULE, "@PUSH"}, {SEMANTIC_RULE, "@PUSH"}, + {SEMANTIC_RULE, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE"}, {SEMANTIC_RULE, "@PUSH"}, - {SEMANTIC_RULE, "@PUSH"}, - {SEMANTIC_RULE, "@PUSH"}, - {SEMANTIC_RULE, "@PUSH"}, + {UNKNOWN, ""}, + {UNKNOWN, ""}, + {UNKNOWN, ""}, + {UNKNOWN, ""}, {SEMANTIC_RULE, "@PUSH"}, {SEMANTIC_RULE, "@PUSH"}, {UNKNOWN, ""}, {UNKNOWN, ""}, {UNKNOWN, ""}, + {UNKNOWN, ""}, + {SEMANTIC_RULE, "@ARRAY_INDEX_READ"}, + {SEMANTIC_RULE, "@PUSH"}, + {SEMANTIC_RULE, "@ARRAY_DIM_NUMBER"}, + {UNKNOWN, ""}, {UNKNOWN, ""} }; diff --git a/hyperdbg/script-engine/pch.c b/hyperdbg/script-engine/code/pch.c similarity index 100% rename from hyperdbg/script-engine/pch.c rename to hyperdbg/script-engine/code/pch.c diff --git a/hyperdbg/script-engine/code/scanner.c b/hyperdbg/script-engine/code/scanner.c index 8cd83c11..b61bf994 100644 --- a/hyperdbg/script-engine/code/scanner.c +++ b/hyperdbg/script-engine/code/scanner.c @@ -16,12 +16,12 @@ * * @param c * @param str - * @return PTOKEN + * @return PSCRIPT_ENGINE_TOKEN */ -PTOKEN +PSCRIPT_ENGINE_TOKEN GetToken(char * c, char * str) { - PTOKEN Token = NewUnknownToken(); + PSCRIPT_ENGINE_TOKEN Token = NewUnknownToken(); switch (*c) { @@ -51,16 +51,16 @@ GetToken(char * c, char * str) else if (*c == 'x') { char ByteString[] = "000"; - int len = (int)strlen(ByteString); + INT Len = (INT)strlen(ByteString); int i = 0; - for (; i < len; i++) + for (; i < Len; i++) { *c = sgetc(str); if (!IsHex(*c)) break; RotateLeftStringOnce(ByteString); - ByteString[len - 1] = *c; + ByteString[Len - 1] = *c; } if (i == 0 || i == 3) @@ -72,8 +72,8 @@ GetToken(char * c, char * str) else { InputIdx--; - char num = (char)strtol(ByteString, NULL, 16); - AppendByte(Token, num); + CHAR Num = (CHAR)strtol(ByteString, NULL, 16); + AppendByte(Token, Num); } } else if (*c == '"') @@ -171,10 +171,20 @@ GetToken(char * c, char * str) *c = sgetc(str); if (*c == '>') { - strcpy(Token->Value, ">>"); - Token->Type = SPECIAL_TOKEN; - *c = sgetc(str); - return Token; + *c = sgetc(str); + if (*c == '=') + { + strcpy(Token->Value, ">>="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else + { + strcpy(Token->Value, ">>"); + Token->Type = SPECIAL_TOKEN; + return Token; + } } else if (*c == '=') { @@ -193,10 +203,20 @@ GetToken(char * c, char * str) *c = sgetc(str); if (*c == '<') { - strcpy(Token->Value, "<<"); - Token->Type = SPECIAL_TOKEN; - *c = sgetc(str); - return Token; + *c = sgetc(str); + if (*c == '=') + { + strcpy(Token->Value, "<<="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else + { + strcpy(Token->Value, "<<"); + Token->Type = SPECIAL_TOKEN; + return Token; + } } else if (*c == '=') { @@ -293,9 +313,19 @@ GetToken(char * c, char * str) return Token; } case '%': - strcpy(Token->Value, "%"); - Token->Type = SPECIAL_TOKEN; - *c = sgetc(str); + *c = sgetc(str); + if (*c == '=') + { + strcpy(Token->Value, "%="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else + { + strcpy(Token->Value, "%"); + Token->Type = SPECIAL_TOKEN; + } return Token; case ',': @@ -336,6 +366,16 @@ GetToken(char * c, char * str) Token->Type = SPECIAL_TOKEN; *c = sgetc(str); return Token; + case '[': + strcpy(Token->Value, "["); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + case ']': + strcpy(Token->Value, "]"); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; case '|': *c = sgetc(str); if (*c == '|') @@ -345,6 +385,13 @@ GetToken(char * c, char * str) *c = sgetc(str); return Token; } + else if (*c == '=') + { + strcpy(Token->Value, "|="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } else { strcpy(Token->Value, "|"); @@ -360,6 +407,13 @@ GetToken(char * c, char * str) *c = sgetc(str); return Token; } + else if (*c == '=') + { + strcpy(Token->Value, "&="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } else { strcpy(Token->Value, "&"); @@ -368,15 +422,25 @@ GetToken(char * c, char * str) } case '^': - strcpy(Token->Value, "^"); - Token->Type = SPECIAL_TOKEN; - *c = sgetc(str); + *c = sgetc(str); + if (*c == '=') + { + strcpy(Token->Value, "^="); + Token->Type = SPECIAL_TOKEN; + *c = sgetc(str); + return Token; + } + else + { + strcpy(Token->Value, "^"); + Token->Type = SPECIAL_TOKEN; + } return Token; case '@': *c = sgetc(str); if (IsLetter(*c)) { - while (IsLetter(*c) || IsDecimal(*c)) + while (IsLetter(*c) || IsDecimal(*c) || IsUnderscore(*c)) { AppendByte(Token, *c); *c = sgetc(str); @@ -439,9 +503,9 @@ GetToken(char * c, char * str) if (WasFound) { RemoveToken(&Token); - char str[20] = {0}; - sprintf(str, "%llx", Address); - Token = NewToken(HEX, str); + char HexStr[20] = {0}; + sprintf(HexStr, "%llx", Address); + Token = NewToken(HEX, HexStr); } else { @@ -454,7 +518,8 @@ GetToken(char * c, char * str) { if (GetGlobalIdentifierVal(Token) != -1) { - Token->Type = GLOBAL_ID; + Token->Type = GLOBAL_ID; + Token->VariableType = GetGlobalIdentifierVariableType(Token); } else { @@ -470,6 +535,23 @@ GetToken(char * c, char * str) } return Token; + case '#': + do + { + if (*c != '`') + AppendByte(Token, *c); + *c = sgetc(str); + } while (IsLetter(*c) || IsHex(*c) || (*c == '_') || (*c == '!')); + if (IsKeyword(Token->Value)) + { + Token->Type = KEYWORD; + } + else + { + Token->Type = UNKNOWN; + } + return Token; + case ' ': case '\t': strcpy(Token->Value, ""); @@ -580,16 +662,16 @@ GetToken(char * c, char * str) else if (*c == 'x') { char ByteString[] = "00000"; - int len = (int)strlen(ByteString); + INT Len = (INT)strlen(ByteString); int i = 0; - for (; i < len; i++) + for (; i < Len; i++) { *c = sgetc(str); if (!IsHex(*c)) break; RotateLeftStringOnce(ByteString); - ByteString[len - 1] = *c; + ByteString[Len - 1] = *c; } if (i == 0 || i == 5) @@ -601,8 +683,8 @@ GetToken(char * c, char * str) else { InputIdx--; - wchar_t num = (wchar_t)strtol(ByteString, NULL, 16); - AppendWchar(Token, num); + WCHAR Num = (WCHAR)strtol(ByteString, NULL, 16); + AppendWchar(Token, Num); } } else if (*c == '"') @@ -633,167 +715,42 @@ GetToken(char * c, char * str) return Token; } - default: - if (*c >= '0' && *c <= '9') + default: + if (*c >= '0' && *c <= '9') + { + do { - do - { - if (*c != '`') - AppendByte(Token, *c); - *c = sgetc(str); - } while (IsHex(*c) || *c == '`'); - Token->Type = HEX; - return Token; - } - else if ((*c >= 'a' && *c <= 'f') || (*c >= 'A' && *c <= 'F') || (*c == '_') || (*c == '!')) + if (*c != '`') + AppendByte(Token, *c); + *c = sgetc(str); + } while (IsHex(*c) || *c == '`'); + Token->Type = HEX; + return Token; + } + else if ((*c >= 'a' && *c <= 'f') || (*c >= 'A' && *c <= 'F') || (*c == '_') || (*c == '!')) + { + UINT8 NotHex = 0; + do { - uint8_t NotHex = 0; - do + if (*c != '`') + AppendByte(Token, *c); + + *c = sgetc(str); + if (IsHex(*c) || *c == '`' || *c == '_') { - if (*c != '`') - AppendByte(Token, *c); - - *c = sgetc(str); - if (IsHex(*c) || *c == '`') - { - // Nothing - } - else if ((*c >= 'G' && *c <= 'Z') || (*c >= 'g' && *c <= 'z')) - { - NotHex = 1; - break; - } - else - { - break; - } - } while (1); - if (NotHex) + // Nothing + } + else if ((*c >= 'G' && *c <= 'Z') || (*c >= 'g' && *c <= 'z')) { - do - { - if (*c != '`') - AppendByte(Token, *c); - *c = sgetc(str); - } while (IsLetter(*c) || IsHex(*c) || (*c == '_') || (*c == '!')); - if (IsKeyword(Token->Value)) - { - Token->Type = KEYWORD; - } - else if (IsRegister(Token->Value)) - { - Token->Type = REGISTER; - } - else - { - BOOLEAN WasFound = FALSE; - BOOLEAN HasBang = strstr(Token->Value, "!") != 0; - UINT64 Address = 0; - - if (HasBang) - { - Address = ScriptEngineConvertNameToAddress(Token->Value, &WasFound); - } - - if (WasFound) - { - RemoveToken(&Token); - char str[20] = {0}; - sprintf(str, "%llx", Address); - Token = NewToken(HEX, str); - } - else - { - if (HasBang) - { - Token->Type = UNKNOWN; - return Token; - } - else - { - if (GetFunctionParameterIdentifier(Token) != -1) - { - Token->Type = FUNCTION_PARAMETER_ID; - } - else - { - if (GetLocalIdentifierVal(Token) != -1) - { - Token->Type = LOCAL_ID; - } - else - { - Token->Type = LOCAL_UNRESOLVED_ID; - } - } - } - } - } - return Token; + NotHex = 1; + break; } else { - if (IsKeyword(Token->Value)) - { - Token->Type = KEYWORD; - } - else if (IsRegister(Token->Value)) - { - Token->Type = REGISTER; - } - else if (IsId(Token->Value)) - { - BOOLEAN WasFound = FALSE; - BOOLEAN HasBang = strstr(Token->Value, "!") != 0; - UINT64 Address = 0; - - if (HasBang) - { - Address = ScriptEngineConvertNameToAddress(Token->Value, &WasFound); - } - - if (WasFound) - { - RemoveToken(&Token); - char str[20] = {0}; - sprintf(str, "%llx", Address); - Token = NewToken(HEX, str); - } - else - { - if (HasBang) - { - Token->Type = UNKNOWN; - return Token; - } - else - { - if (GetFunctionParameterIdentifier(Token) != -1) - { - Token->Type = FUNCTION_PARAMETER_ID; - } - else - { - if (GetLocalIdentifierVal(Token) != -1) - { - Token->Type = LOCAL_ID; - } - else - { - Token->Type = LOCAL_UNRESOLVED_ID; - } - } - } - } - } - else - { - Token->Type = HEX; - } - return Token; + break; } - } - else if ((*c >= 'G' && *c <= 'Z') || (*c >= 'g' && *c <= 'z') || (*c == '_') || (*c == '!')) + } while (1); + if (NotHex) { do { @@ -809,6 +766,10 @@ GetToken(char * c, char * str) { Token->Type = REGISTER; } + else if (IsVariableType(Token->Value)) + { + Token->Type = SCRIPT_VARIABLE_TYPE; + } else { BOOLEAN WasFound = FALSE; @@ -836,26 +797,166 @@ GetToken(char * c, char * str) } else { - if (GetFunctionParameterIdentifier(Token) != -1) + if (GetUserDefinedFunctionNode(Token)) + { + Token->Type = FUNCTION_ID; + } + else if (GetFunctionParameterIdentifier(Token) != -1) { Token->Type = FUNCTION_PARAMETER_ID; } + else if (GetLocalIdentifierVal(Token) != -1) + { + Token->Type = LOCAL_ID; + Token->VariableType = GetLocalIdentifierVariableType(Token); + } else { - if (GetLocalIdentifierVal(Token) != -1) - { - Token->Type = LOCAL_ID; - } - else - { - Token->Type = LOCAL_UNRESOLVED_ID; - } + Token->Type = LOCAL_UNRESOLVED_ID; } } } } return Token; } + else + { + if (IsKeyword(Token->Value)) + { + Token->Type = KEYWORD; + } + else if (IsRegister(Token->Value)) + { + Token->Type = REGISTER; + } + else if (IsVariableType(Token->Value)) + { + Token->Type = SCRIPT_VARIABLE_TYPE; + } + else if (IsId(Token->Value)) + { + BOOLEAN WasFound = FALSE; + BOOLEAN HasBang = strstr(Token->Value, "!") != 0; + UINT64 Address = 0; + + if (HasBang) + { + Address = ScriptEngineConvertNameToAddress(Token->Value, &WasFound); + } + + if (WasFound) + { + RemoveToken(&Token); + char HexStr[20] = {0}; + sprintf(HexStr, "%llx", Address); + Token = NewToken(HEX, HexStr); + } + else + { + if (HasBang) + { + Token->Type = UNKNOWN; + return Token; + } + else + { + if (GetUserDefinedFunctionNode(Token)) + { + Token->Type = FUNCTION_ID; + } + else if (GetFunctionParameterIdentifier(Token) != -1) + { + Token->Type = FUNCTION_PARAMETER_ID; + } + else if (GetLocalIdentifierVal(Token) != -1) + { + Token->Type = LOCAL_ID; + Token->VariableType = GetLocalIdentifierVariableType(Token); + } + else + { + Token->Type = LOCAL_UNRESOLVED_ID; + } + Token->VariableType; + } + } + } + else + { + Token->Type = HEX; + } + return Token; + } + } + else if ((*c >= 'G' && *c <= 'Z') || (*c >= 'g' && *c <= 'z') || (*c == '_') || (*c == '!')) + { + do + { + if (*c != '`') + AppendByte(Token, *c); + *c = sgetc(str); + } while (IsLetter(*c) || IsHex(*c) || (*c == '_') || (*c == '!')); + if (IsKeyword(Token->Value)) + { + Token->Type = KEYWORD; + } + else if (IsRegister(Token->Value)) + { + Token->Type = REGISTER; + } + else if (IsVariableType(Token->Value)) + { + Token->Type = SCRIPT_VARIABLE_TYPE; + } + else + { + BOOLEAN WasFound = FALSE; + BOOLEAN HasBang = strstr(Token->Value, "!") != 0; + UINT64 Address = 0; + + if (HasBang) + { + Address = ScriptEngineConvertNameToAddress(Token->Value, &WasFound); + } + + if (WasFound) + { + RemoveToken(&Token); + char HexStr[20] = {0}; + sprintf(HexStr, "%llx", Address); + Token = NewToken(HEX, HexStr); + } + else + { + if (HasBang) + { + Token->Type = UNKNOWN; + return Token; + } + else + { + if (GetUserDefinedFunctionNode(Token)) + { + Token->Type = FUNCTION_ID; + } + else if (GetFunctionParameterIdentifier(Token) != -1) + { + Token->Type = FUNCTION_PARAMETER_ID; + } + else if (GetLocalIdentifierVal(Token) != -1) + { + Token->Type = LOCAL_ID; + Token->VariableType = GetLocalIdentifierVariableType(Token); + } + else + { + Token->Type = LOCAL_UNRESOLVED_ID; + } + } + } + } + return Token; + } Token->Type = UNKNOWN; *c = sgetc(str); @@ -869,13 +970,13 @@ GetToken(char * c, char * str) * * @param str * @param c - * @return PTOKEN + * @return PSCRIPT_ENGINE_TOKEN */ -PTOKEN +PSCRIPT_ENGINE_TOKEN Scan(char * str, char * c) { - static BOOLEAN ReturnEndOfString; - PTOKEN Token; + static BOOLEAN ReturnEndOfString; + PSCRIPT_ENGINE_TOKEN Token; if (InputIdx <= 1) { @@ -932,10 +1033,10 @@ Scan(char * str, char * c) } /** - * @brief returns last character of string + * @brief Returns the next character in the input string * * @param str - * @return last character + * @return CHAR the next character at the current position in the string */ char sgetc(char * str) @@ -997,7 +1098,27 @@ IsRegister(char * str) } /** - * @brief eck if string is Id or not + * @brief Check if string is variable type or not + * + * @param str + * @return char + */ +char +IsVariableType(char * str) +{ + for (int i = 0; i < SCRIPT_VARIABLE_TYPE_LIST_LENGTH; i++) + { + if (!strcmp(str, ScriptVariableTypeList[i])) + { + return 1; + } + } + + return 0; +} + +/** + * @brief Check if string is Id or not * * @param str * @return char diff --git a/hyperdbg/script-engine/code/script-engine.c b/hyperdbg/script-engine/code/script-engine.c index cafddf5c..a485631b 100644 --- a/hyperdbg/script-engine/code/script-engine.c +++ b/hyperdbg/script-engine/code/script-engine.c @@ -11,11 +11,53 @@ * */ #include "pch.h" +#include "platform/user/header/platform-lib-calls.h" // #define _SCRIPT_ENGINE_LALR_DBG_EN // #define _SCRIPT_ENGINE_LL1_DBG_EN // #define _SCRIPT_ENGINE_CODEGEN_DBG_EN +// +// Global Variables +// +extern HWDBG_INSTANCE_INFORMATION g_HwdbgInstanceInfo; +extern BOOLEAN g_HwdbgInstanceInfoIsValid; +extern PVOID g_MessageHandler; + +/** + * @brief Show messages + * + * @param Fmt format string message + */ +VOID +ShowMessages(const char * Fmt, ...) +{ + va_list ArgList; + va_list Args; + + if (g_MessageHandler == NULL) + { + va_start(Args, Fmt); + vprintf(Fmt, Args); + va_end(Args); + } + else + { + char TempMessage[COMMUNICATION_BUFFER_SIZE + TCP_END_OF_BUFFER_CHARS_COUNT] = {0}; + va_start(ArgList, Fmt); + INT SprintfResult = PlatformVsnprintf(TempMessage, COMMUNICATION_BUFFER_SIZE + TCP_END_OF_BUFFER_CHARS_COUNT, Fmt, ArgList); + va_end(ArgList); + + if (SprintfResult != -1) + { + // + // There is another handler + // + ((SendMessageWithParamCallback)g_MessageHandler)(TempMessage); + } + } +} + /** * @brief Converts name to address * @@ -61,6 +103,14 @@ ScriptEngineLoadFileSymbol(UINT64 BaseAddress, const char * PdbFileName, const c VOID ScriptEngineSetTextMessageCallback(PVOID Handler) { + // + // Set the script engine message handler + // + g_MessageHandler = Handler; + + // + // Call message handler of the symbol parser + // SymSetTextMessageCallback(Handler); } @@ -164,12 +214,12 @@ ScriptEngineCreateSymbolTableForDisassembler(void * CallbackFunction) * @return BOOLEAN */ BOOLEAN -ScriptEngineConvertFileToPdbPath(const char * LocalFilePath, char * ResultPath) +ScriptEngineConvertFileToPdbPath(const char * LocalFilePath, char * ResultPath, SIZE_T ResultPathSize) { // // A wrapper for pdb to path converter // - return SymConvertFileToPdbPath(LocalFilePath, ResultPath); + return SymConvertFileToPdbPath(LocalFilePath, ResultPath, ResultPathSize); } /** @@ -251,40 +301,79 @@ ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetails(const char * LocalFilePath, return SymConvertFileToPdbFileAndGuidAndAgeDetails(LocalFilePath, PdbFilePath, GuidAndAgeDetails, Is32BitModule); } +/** + * @brief Convert loaded module bytes to pdb attributes for symbols + * + * @param LoadedImageBytes + * @param LoadedImageSize + * @param LocalFilePath + * @param PdbFilePath + * @param GuidAndAgeDetails + * @param Is32BitModule + * + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineConvertLoadedModuleToPdbFileAndGuidAndAgeDetails(const BYTE * LoadedImageBytes, + SIZE_T LoadedImageSize, + const char * LocalFilePath, + char * PdbFilePath, + char * GuidAndAgeDetails, + BOOLEAN Is32BitModule) +{ + // + // A wrapper for loaded module pdb to path file and guid and age detail converter + // + return SymConvertLoadedModuleToPdbFileAndGuidAndAgeDetails( + LoadedImageBytes, + LoadedImageSize, + LocalFilePath, + PdbFilePath, + GuidAndAgeDetails, + Is32BitModule); +} + /** * @brief The entry point of script engine * * @param str - * @return PSYMBOL_BUFFER + * @return PVOID */ -PSYMBOL_BUFFER +PVOID ScriptEngineParse(char * str) { - PTOKEN_LIST Stack = NewTokenList(); + char * ScriptSource = PlatformStrDup(str); - PTOKEN_LIST MatchedStack = NewTokenList(); - PSYMBOL_BUFFER CodeBuffer = NewSymbolBuffer(); + PSCRIPT_ENGINE_TOKEN_LIST Stack = NewTokenList(); + PSCRIPT_ENGINE_TOKEN_LIST MatchedStack = NewTokenList(); + PSYMBOL_BUFFER CodeBuffer = NewSymbolBuffer(); - // will modify here later - PSYMBOL_BUFFER UserDefinedFunctions = NewSymbolBuffer(); + UserDefinedFunctionHead = malloc(sizeof(USER_DEFINED_FUNCTION_NODE)); + PlatformZeroMemory(UserDefinedFunctionHead, sizeof(USER_DEFINED_FUNCTION_NODE)); + UserDefinedFunctionHead->Name = PlatformStrDup("main"); + UserDefinedFunctionHead->IdTable = (unsigned long long)NewTokenList(); + UserDefinedFunctionHead->FunctionParameterIdTable = (unsigned long long)NewTokenList(); + UserDefinedFunctionHead->TempMap = calloc(MAX_TEMP_COUNT, 1); + UserDefinedFunctionHead->VariableType = (unsigned long long)VARIABLE_TYPE_VOID; + + CurrentUserDefinedFunction = UserDefinedFunctionHead; SCRIPT_ENGINE_ERROR_TYPE Error = SCRIPT_ENGINE_ERROR_FREE; char * ErrorMessage = NULL; - static FirstCall = 1; + static INT FirstCall = 1; if (FirstCall) { - IdTable = NewTokenList(); - FunctionParameterIdTable = NewTokenList(); - FirstCall = 0; + GlobalIdTable = NewTokenList(); + FirstCall = 0; } - PTOKEN TopToken = NewUnknownToken(); + PSCRIPT_ENGINE_TOKEN TopToken = NewUnknownToken(); int NonTerminalId; int TerminalId; int RuleId; - char c; + CHAR C; BOOL WaitForWaitStatementBooleanExpression = FALSE; // @@ -297,31 +386,58 @@ ScriptEngineParse(char * str) // // End of File Token // - PTOKEN EndToken = NewToken(END_OF_STACK, "$"); + PSCRIPT_ENGINE_TOKEN EndToken = NewToken(END_OF_STACK, "$"); // // Start Token // - PTOKEN StartToken = NewToken(NON_TERMINAL, START_VARIABLE); + PSCRIPT_ENGINE_TOKEN StartToken = NewToken(NON_TERMINAL, START_VARIABLE); Push(Stack, EndToken); Push(Stack, StartToken); - c = sgetc(str); + C = sgetc(ScriptSource); - PTOKEN CurrentIn = Scan(str, &c); + PSCRIPT_ENGINE_TOKEN CurrentIn = Scan(ScriptSource, &C); if (CurrentIn->Type == UNKNOWN) { Error = SCRIPT_ENGINE_ERROR_SYNTAX; - ErrorMessage = HandleError(&Error, str); + ErrorMessage = HandleError(&Error, ScriptSource); CodeBuffer->Message = ErrorMessage; RemoveTokenList(Stack); RemoveTokenList(MatchedStack); RemoveToken(&CurrentIn); - return CodeBuffer; + return (PVOID)CodeBuffer; } + // + // add stack index + // + PSYMBOL TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + TempSymbol->Value = FUNC_ADD; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_NUM_TYPE; + TempSymbol->Value = 0xffffffffffffffff; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_STACK_INDEX_TYPE; + TempSymbol->Value = 0; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_STACK_INDEX_TYPE; + TempSymbol->Value = 0; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + do { RemoveToken(&TopToken); @@ -339,16 +455,16 @@ ScriptEngineParse(char * str) { if (!strcmp(TopToken->Value, "BOOLEAN_EXPRESSION")) { - UINT64 BooleanExpressionSize = BooleanExpressionExtractEnd(str, &WaitForWaitStatementBooleanExpression, CurrentIn); + UINT64 BooleanExpressionSize = BooleanExpressionExtractEnd(ScriptSource, &WaitForWaitStatementBooleanExpression, CurrentIn); - ScriptEngineBooleanExpresssionParse(BooleanExpressionSize, CurrentIn, MatchedStack, UserDefinedFunctions, CodeBuffer, str, &c, &Error); + ScriptEngineBooleanExpresssionParse(BooleanExpressionSize, CurrentIn, MatchedStack, CodeBuffer, ScriptSource, &C, &Error); if (Error != SCRIPT_ENGINE_ERROR_FREE) { break; } RemoveToken(&CurrentIn); - CurrentIn = Scan(str, &c); + CurrentIn = Scan(ScriptSource, &C); if (CurrentIn->Type == UNKNOWN) { Error = SCRIPT_ENGINE_ERROR_UNKNOWN_TOKEN; @@ -356,7 +472,7 @@ ScriptEngineParse(char * str) } RemoveToken(&CurrentIn); - CurrentIn = Scan(str, &c); + CurrentIn = Scan(ScriptSource, &C); if (CurrentIn->Type == UNKNOWN) { Error = SCRIPT_ENGINE_ERROR_UNKNOWN_TOKEN; @@ -393,12 +509,12 @@ ScriptEngineParse(char * str) // for (int i = RhsSize[RuleId] - 1; i >= 0; i--) { - PTOKEN Token = (PTOKEN)&Rhs[RuleId][i]; + PSCRIPT_ENGINE_TOKEN Token = (PSCRIPT_ENGINE_TOKEN)&Rhs[RuleId][i]; if (Token->Type == EPSILON) break; - PTOKEN DuplicatedToken = CopyToken(Token); + PSCRIPT_ENGINE_TOKEN DuplicatedToken = CopyToken(Token); Push(Stack, DuplicatedToken); } } @@ -412,7 +528,7 @@ ScriptEngineParse(char * str) Push(MatchedStack, CurrentIn); - CurrentIn = Scan(str, &c); + CurrentIn = Scan(ScriptSource, &C); if (CurrentIn->Type == UNKNOWN) { Error = SCRIPT_ENGINE_ERROR_SYNTAX; @@ -426,7 +542,7 @@ ScriptEngineParse(char * str) { WaitForWaitStatementBooleanExpression = TRUE; } - CodeGen(MatchedStack, UserDefinedFunctions, CodeBuffer, TopToken, &Error); + CodeGen(MatchedStack, CodeBuffer, TopToken, &Error, &ScriptSource); if (Error != SCRIPT_ENGINE_ERROR_FREE) { break; @@ -443,7 +559,7 @@ ScriptEngineParse(char * str) else { RemoveToken(&CurrentIn); - CurrentIn = Scan(str, &c); + CurrentIn = Scan(ScriptSource, &C); if (CurrentIn->Type == UNKNOWN) { @@ -461,12 +577,65 @@ ScriptEngineParse(char * str) if (Error != SCRIPT_ENGINE_ERROR_FREE) { - ErrorMessage = HandleError(&Error, str); - CleanTempList(); + ErrorMessage = HandleError(&Error, ScriptSource); } else { ErrorMessage = NULL; + + PSYMBOL Symbol; + // + // change local id to stack temp + // + for (UINT64 i = 0; i < CodeBuffer->Pointer; i++) + { + Symbol = CodeBuffer->Head + i; + if (Symbol->Type == SYMBOL_LOCAL_ID_TYPE) + { + Symbol->Type = SYMBOL_TEMP_TYPE; + Symbol->Value += UserDefinedFunctionHead->MaxTempNumber; + } + else if (Symbol->Type == SYMBOL_REFERENCE_LOCAL_ID_TYPE) + { + Symbol->Type = SYMBOL_REFERENCE_TEMP_TYPE; + Symbol->Value += UserDefinedFunctionHead->MaxTempNumber; + } + else if (Symbol->Type == SYMBOL_DEREFERENCE_LOCAL_ID_TYPE) + { + Symbol->Type = SYMBOL_DEREFERENCE_TEMP_TYPE; + Symbol->Value += UserDefinedFunctionHead->MaxTempNumber; + } + else if (Symbol->Type == SYMBOL_VARIABLE_COUNT_TYPE) + { + UINT64 VariableCount = Symbol->Value; + for (UINT64 j = 0; j < VariableCount; j++) + { + Symbol = CodeBuffer->Head + i + j + 1; + if ((Symbol->Type & 0x7fffffff) == SYMBOL_LOCAL_ID_TYPE) + { + Symbol->Type = SYMBOL_TEMP_TYPE | (Symbol->Type & 0xffffffff00000000); + Symbol->Value += UserDefinedFunctionHead->MaxTempNumber; + } + else if ((Symbol->Type & 0x7fffffff) == SYMBOL_REFERENCE_LOCAL_ID_TYPE) + { + Symbol->Type = SYMBOL_REFERENCE_LOCAL_ID_TYPE | (Symbol->Type & 0xffffffff00000000); + Symbol->Value += UserDefinedFunctionHead->MaxTempNumber; + } + else if ((Symbol->Type & 0x7fffffff) == SYMBOL_DEREFERENCE_LOCAL_ID_TYPE) + { + Symbol->Type = SYMBOL_DEREFERENCE_LOCAL_ID_TYPE | (Symbol->Type & 0xffffffff00000000); + Symbol->Value += UserDefinedFunctionHead->MaxTempNumber; + } + } + i += VariableCount; + } + } + + // + // set memory size for stack buffer + // + Symbol = CodeBuffer->Head + 1; + Symbol->Value = CurrentUserDefinedFunction->MaxTempNumber + CurrentUserDefinedFunction->LocalVariableNumber; } CodeBuffer->Message = ErrorMessage; @@ -476,8 +645,44 @@ ScriptEngineParse(char * str) if (MatchedStack) RemoveTokenList(MatchedStack); - if (UserDefinedFunctions) - RemoveSymbolBuffer(UserDefinedFunctions); + if (UserDefinedFunctionHead) + { + PUSER_DEFINED_FUNCTION_NODE Node = UserDefinedFunctionHead; + while (Node) + { + if (Node->Name) + free(Node->Name); + + if (Node->IdTable) + RemoveTokenList((PSCRIPT_ENGINE_TOKEN_LIST)Node->IdTable); + + if (Node->FunctionParameterIdTable) + RemoveTokenList((PSCRIPT_ENGINE_TOKEN_LIST)Node->FunctionParameterIdTable); + + if (Node->TempMap) + free(Node->TempMap); + + PUSER_DEFINED_FUNCTION_NODE Temp = Node; + Node = Node->NextNode; + free(Temp); + } + UserDefinedFunctionHead = 0; + } + + if (IncludeHead) + { + PINCLUDE_NODE Node = IncludeHead; + while (Node) + { + if (Node->FilePath) + free(Node->FilePath); + + PINCLUDE_NODE Temp = Node; + Node = Node->NextNode; + free(Temp); + } + IncludeHead = 0; + } if (CurrentIn) RemoveToken(&CurrentIn); @@ -485,13 +690,9 @@ ScriptEngineParse(char * str) if (TopToken) RemoveToken(&TopToken); - if (FunctionParameterIdTable) - { - RemoveTokenList(FunctionParameterIdTable); - FunctionParameterIdTable = NewTokenList(); - } + free(ScriptSource); - return CodeBuffer; + return (PVOID)CodeBuffer; } /** @@ -501,27 +702,29 @@ ScriptEngineParse(char * str) * @param CodeBuffer * @param Operator * @param Error + * @param ScriptSource the script source string + * @return VOID */ void -CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_BUFFER CodeBuffer, PTOKEN Operator, PSCRIPT_ENGINE_ERROR_TYPE Error) +CodeGen(PSCRIPT_ENGINE_TOKEN_LIST MatchedStack, PSYMBOL_BUFFER CodeBuffer, PSCRIPT_ENGINE_TOKEN Operator, PSCRIPT_ENGINE_ERROR_TYPE Error, char ** ScriptSource) { - PTOKEN Op0 = NULL; - PTOKEN Op1 = NULL; - PTOKEN Op2 = NULL; - PTOKEN Temp = NULL; + PSCRIPT_ENGINE_TOKEN Op0 = NULL; + PSCRIPT_ENGINE_TOKEN Op1 = NULL; + PSCRIPT_ENGINE_TOKEN Op2 = NULL; + PSCRIPT_ENGINE_TOKEN Temp = NULL; - PSYMBOL OperatorSymbol = NULL; - PSYMBOL Op0Symbol = NULL; - PSYMBOL Op1Symbol = NULL; - PSYMBOL Op2Symbol = NULL; - PSYMBOL TempSymbol = NULL; - VARIABLE_TYPE * VariableType = NULL; + PSYMBOL OperatorSymbol = NULL; + PSYMBOL Op0Symbol = NULL; + PSYMBOL Op1Symbol = NULL; + PSYMBOL Op2Symbol = NULL; + PSYMBOL TempSymbol = NULL; + VARIABLE_TYPE * VariableType = NULL; + VARIABLE_TYPE * PointerVariableType = NULL; // // It is in user-defined function if CurrentFunctionSymbol is not null // - static PSYMBOL CurrentFunctionSymbol = NULL; - OperatorSymbol = ToSymbol(Operator, Error); + OperatorSymbol = ToSymbol(Operator, Error); #ifdef _SCRIPT_ENGINE_CODEGEN_DBG_EN // @@ -536,30 +739,78 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B printf("\n"); printf("Code Buffer:\n"); - PrintSymbolBuffer(CodeBuffer); + PrintSymbolBuffer((PVOID)CodeBuffer); printf(".\n.\n.\n\n"); #endif while (TRUE) { - if (IsVariableType(Operator)) + if (!strcmp(Operator->Value, "@INCLUDE")) { - PTOKEN PToken = CopyToken(Operator); - PToken->Type = INPUT_VARIABLE_TYPE; - Push(MatchedStack, PToken); + char * IncludeFilePath; + char FullPath[MAX_PATH_LEN]; + char * IncludeFileBuffer; + BOOLEAN IncludedPath = FALSE; + + Temp = Pop(MatchedStack); + IncludeFilePath = Temp->Value; + + ResolveIncludePath(IncludeFilePath, FullPath); + + if (!FileExists(FullPath)) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + break; + } + + if (!ParseIncludeFile(FullPath, &IncludeFileBuffer)) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + break; + } + + if (!IncludeHead) + { + IncludeHead = calloc(sizeof(INCLUDE_NODE), 1); + IncludeHead->FilePath = PlatformStrDup(FullPath); + } + else + { + PINCLUDE_NODE Node, PrevNode = NULL; + + for (Node = IncludeHead; Node; PrevNode = Node, Node = Node->NextNode) + { + if (!strcmp(Node->FilePath, FullPath)) + { + IncludedPath = TRUE; + break; + } + } + + if (!IncludedPath && PrevNode) + { + PrevNode->NextNode = calloc(sizeof(INCLUDE_NODE), 1); + PrevNode->NextNode->FilePath = PlatformStrDup(FullPath); + } + } + + if (!IncludedPath) + { + *ScriptSource = InsertStrNew(*ScriptSource, InputIdx, IncludeFileBuffer); + } } + else if (!strcmp(Operator->Value, "@START_OF_USER_DEFINED_FUNCTION")) { Op0 = Pop(MatchedStack); VariableType = HandleType(MatchedStack); - if (VariableType == VARIABLE_TYPE_UNKNOWN) + if (VariableType->Kind == TY_UNKNOWN) { *Error = SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE; break; } - UINT64 CurrentPointer = CodeBuffer->Pointer; // // Add jmp instruction to Code Buffer // @@ -579,178 +830,280 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B PushSymbol(CodeBuffer, JumpAddressSymbol); RemoveSymbol(&JumpAddressSymbol); - PushSymbol(UserDefinedFunctions, NewFunctionSymbol(Op0->Value, VariableType)); - CurrentFunctionSymbol = NewFunctionSymbol(Op0->Value, VariableType); - PushSymbol(CodeBuffer, CurrentFunctionSymbol); + PUSER_DEFINED_FUNCTION_NODE Node = UserDefinedFunctionHead; + while (Node->NextNode) + { + Node = Node->NextNode; + } + Node->NextNode = malloc(sizeof(USER_DEFINED_FUNCTION_NODE)); + PlatformZeroMemory(Node->NextNode, sizeof(USER_DEFINED_FUNCTION_NODE)); + CurrentUserDefinedFunction = Node->NextNode; - PushSymbol(CodeBuffer, OperatorSymbol); + CurrentUserDefinedFunction->Name = PlatformStrDup(Op0->Value); + CurrentUserDefinedFunction->Address = CodeBuffer->Pointer; // CurrentPointer + CurrentUserDefinedFunction->VariableType = (long long unsigned)VariableType; + CurrentUserDefinedFunction->IdTable = (unsigned long long)NewTokenList(); + CurrentUserDefinedFunction->FunctionParameterIdTable = (unsigned long long)NewTokenList(); + CurrentUserDefinedFunction->TempMap = calloc(MAX_TEMP_COUNT, 1); - PSYMBOL StackTempNumberSymbol = NewSymbol(); - StackTempNumberSymbol->Type = SYMBOL_NUM_TYPE; - StackTempNumberSymbol->Value = 0xffffffffffffffff; - PushSymbol(CodeBuffer, StackTempNumberSymbol); - RemoveSymbol(&StackTempNumberSymbol); + // + // push stack base index + // + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + TempSymbol->Value = FUNC_PUSH; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_STACK_BASE_INDEX_TYPE; + TempSymbol->Value = 0; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + // + // move stack index to stack base index + // + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + TempSymbol->Value = FUNC_MOV; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_STACK_INDEX_TYPE; + TempSymbol->Value = 0; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_STACK_BASE_INDEX_TYPE; + TempSymbol->Value = 0; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + // + // add stack index + // + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + TempSymbol->Value = FUNC_ADD; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_NUM_TYPE; + TempSymbol->Value = 0xffffffffffffffff; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_STACK_INDEX_TYPE; + TempSymbol->Value = 0; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_STACK_INDEX_TYPE; + TempSymbol->Value = 0; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); } else if (!strcmp(Operator->Value, "@FUNCTION_PARAMETER")) { Op0 = Pop(MatchedStack); VariableType = HandleType(MatchedStack); - if (VariableType == VARIABLE_TYPE_UNKNOWN) + if (VariableType->Kind == TY_UNKNOWN) { *Error = SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE; break; } - Op0Symbol = NewSymbol(); - free((void *)Op0Symbol->Value); - Op0Symbol->Value = NewFunctionParameterIdentifier(Op0); - SetType(&Op0Symbol->Type, SYMBOL_FUNCTION_PARAMETER_ID_TYPE); - - PushSymbol(UserDefinedFunctions, Op0Symbol); + NewFunctionParameterIdentifier(Op0); + CurrentUserDefinedFunction->ParameterNumber++; } else if (!strcmp(Operator->Value, "@END_OF_USER_DEFINED_FUNCTION")) { - PushSymbol(CodeBuffer, OperatorSymbol); UINT64 CurrentPointer = CodeBuffer->Pointer; PSYMBOL Symbol = NULL; - BOOL Found = FALSE; - unsigned int i = 0; - // for loop not able to begin from CodeBuffer->Pointer to 0 because of string and wstring's size - for (; i < CodeBuffer->Pointer;) + if (!CurrentUserDefinedFunction) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + break; + } + + // + // change local id to stack temp + // + for (UINT64 i = CurrentUserDefinedFunction->Address; i < CurrentPointer; i++) { Symbol = CodeBuffer->Head + i; + if (Symbol->Type == SYMBOL_LOCAL_ID_TYPE) + { + Symbol->Type = SYMBOL_TEMP_TYPE; + Symbol->Value += CurrentUserDefinedFunction->MaxTempNumber; + } - if (Symbol->Type == SYMBOL_USER_DEFINED_FUNCTION_TYPE && !strcmp((const char *)CurrentFunctionSymbol->Value, (const char *)Symbol->Value)) + else if (Symbol->Type == SYMBOL_VARIABLE_COUNT_TYPE) { - Found = TRUE; - break; + UINT64 VariableCount = Symbol->Value; + for (UINT64 j = 0; j < VariableCount; j++) + { + Symbol = CodeBuffer->Head + i + j + 1; + if ((Symbol->Type & 0x7fffffff) == SYMBOL_LOCAL_ID_TYPE) + { + Symbol->Type = SYMBOL_TEMP_TYPE | (Symbol->Type & 0xffffffff00000000); + Symbol->Value += CurrentUserDefinedFunction->MaxTempNumber; + } + } + i += VariableCount; } - else if (Symbol->Type == SYMBOL_STRING_TYPE || Symbol->Type == SYMBOL_WSTRING_TYPE) - { - int temp = GetSymbolHeapSize(Symbol); - i += temp; - } - else + } + + // + // set memory size for stack buffer + // + Symbol = CodeBuffer->Head + CurrentUserDefinedFunction->Address + 6; + Symbol->Value = CurrentUserDefinedFunction->MaxTempNumber + CurrentUserDefinedFunction->LocalVariableNumber; + + // + // modify jump address + // + for (UINT64 i = CurrentUserDefinedFunction->Address; i < CurrentPointer; i++) + { + Symbol = CodeBuffer->Head + i; + if (Symbol->Type == SYMBOL_SEMANTIC_RULE_TYPE && Symbol->Value == FUNC_JMP && (CodeBuffer->Head + i + 1)->Value == 0xfffffffffffffff0) { + (CodeBuffer->Head + i + 1)->Value = CurrentPointer; i++; } } - if (!Found) - { - *Error = SCRIPT_ENGINE_ERROR_SYNTAX; - break; - } + // + // move stack base index to stack index + // + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + TempSymbol->Value = FUNC_MOV; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_STACK_BASE_INDEX_TYPE; + TempSymbol->Value = 0; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); + + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_STACK_INDEX_TYPE; + TempSymbol->Value = 0; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); // - // skip executing user-defined function first time + // pop stack base index // - Symbol = CodeBuffer->Head + i - 1; - Symbol->Value = CurrentPointer; + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + TempSymbol->Value = FUNC_POP; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); - long long unsigned StackTempNumber = 0; - for (int j = i; j < CurrentPointer; j++) - { - Symbol = CodeBuffer->Head + j; - if (Symbol->Type == SYMBOL_STACK_TEMP_TYPE && (Symbol->Value + 1) > StackTempNumber) - { - StackTempNumber = Symbol->Value + 1; - } - } + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_STACK_BASE_INDEX_TYPE; + TempSymbol->Value = 0; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); - Symbol = CodeBuffer->Head + i + 2; - Symbol->Value = StackTempNumber; + TempSymbol = NewSymbol(); + TempSymbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + TempSymbol->Value = FUNC_RET; + PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); - CurrentFunctionSymbol = NULL; + Symbol = CodeBuffer->Head + CurrentUserDefinedFunction->Address - 1; + Symbol->Value = CodeBuffer->Pointer; + + CurrentUserDefinedFunction = UserDefinedFunctionHead; } else if (!strcmp(Operator->Value, "@RETURN_OF_USER_DEFINED_FUNCTION_WITHOUT_VALUE")) { - if (!CurrentFunctionSymbol) + if (!CurrentUserDefinedFunction) { *Error = SCRIPT_ENGINE_ERROR_SYNTAX; break; } - if (CurrentFunctionSymbol->VariableType != (unsigned long long)VARIABLE_TYPE_VOID) + if (((VARIABLE_TYPE *)CurrentUserDefinedFunction->VariableType)->Kind != TY_VOID) { *Error = SCRIPT_ENGINE_ERROR_NON_VOID_FUNCTION_NOT_RETURNING_VALUE; break; } - PushSymbol(CodeBuffer, OperatorSymbol); + + // + // Jump to ret code + // + PSYMBOL Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_JMP; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = 0xfffffffffffffff0; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); } else if (!strcmp(Operator->Value, "@RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE")) { - if (!CurrentFunctionSymbol) + if (!CurrentUserDefinedFunction) { *Error = SCRIPT_ENGINE_ERROR_SYNTAX; break; } - if (CurrentFunctionSymbol->VariableType == (unsigned long long)VARIABLE_TYPE_VOID) + if (((VARIABLE_TYPE *)CurrentUserDefinedFunction->VariableType)->Kind == TY_VOID) { *Error = SCRIPT_ENGINE_ERROR_VOID_FUNCTION_RETURNING_VALUE; break; } - PushSymbol(CodeBuffer, OperatorSymbol); + // + // Store return value + // + PSYMBOL Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MOV; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); Op0 = Pop(MatchedStack); Op0Symbol = ToSymbol(Op0, Error); PushSymbol(CodeBuffer, Op0Symbol); FreeTemp(Op0); - if (*Error != SCRIPT_ENGINE_ERROR_FREE) - { - break; - } - } - - else if (!strcmp(Operator->Value, "@CALL_USER_DEFINED_FUNCTION")) - { - PSYMBOL Symbol = NULL; - unsigned int i = 0; - PTOKEN FunctionToken = Top(MatchedStack); - BOOL Found = FALSE; + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_RETURN_VALUE_TYPE; + Symbol->Value = 0; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); // - // find function's address + // Jump to ret code // - for (; i < CodeBuffer->Pointer;) - { - Symbol = CodeBuffer->Head + i; + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_JMP; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); - if (Symbol->Type == SYMBOL_USER_DEFINED_FUNCTION_TYPE && !strcmp((const char *)FunctionToken->Value, (const char *)Symbol->Value)) - { - Found = TRUE; - break; - } - else if (Symbol->Type == SYMBOL_STRING_TYPE || Symbol->Type == SYMBOL_WSTRING_TYPE) - { - int temp = GetSymbolHeapSize(Symbol); - i += temp; - } - else - { - i++; - } - } + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = 0xfffffffffffffff0; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); - if (!Found) - { - *Error = SCRIPT_ENGINE_ERROR_UNDEFINED_FUNCTION; - break; - } - - FunctionToken->Type = FUNCTION_TYPE; - PushSymbol(CodeBuffer, OperatorSymbol); - } - else if (!strcmp(Operator->Value, "@CALL_USER_DEFINED_FUNCTION_PARAMETER")) - { - // will rewrite here to input variable's type - PushSymbol(CodeBuffer, OperatorSymbol); - - Op0Symbol = ToSymbol(Top(MatchedStack), Error); - PushSymbol(CodeBuffer, Op0Symbol); if (*Error != SCRIPT_ENGINE_ERROR_FREE) { break; @@ -758,110 +1111,86 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B } else if (!strcmp(Operator->Value, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE") || !strcmp(Operator->Value, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE")) { - PSYMBOL Symbol = NULL; - unsigned int i = 0; - int TargetFunctionVariableNum = 0; - int VariableNum = 0; - PTOKEN FunctionToken = NULL; - BOOL Found = FALSE; - PTOKEN ReturnValueToken = NULL; + PSYMBOL Symbol = NULL; + PSYMBOL TempSymbol = NULL; + int VariableNum = 0; + PSCRIPT_ENGINE_TOKEN FunctionToken = NULL; while (MatchedStack->Pointer > 0) { FunctionToken = Pop(MatchedStack); - if (FunctionToken->Type == FUNCTION_TYPE) + if (FunctionToken->Type == FUNCTION_ID) { break; } else { VariableNum++; - // RemoveToken(&FunctionToken); + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_PUSH; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); + + Symbol = ToSymbol(FunctionToken, Error); + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); + RemoveToken(&FunctionToken); } } - // - // find function's address - // - for (; i < CodeBuffer->Pointer;) - { - Symbol = CodeBuffer->Head + i; + PUSER_DEFINED_FUNCTION_NODE Node = GetUserDefinedFunctionNode(FunctionToken); - if (Symbol->Type == SYMBOL_USER_DEFINED_FUNCTION_TYPE && !strcmp((const char *)FunctionToken->Value, (const char *)Symbol->Value)) - { - Found = TRUE; - break; - } - else if (Symbol->Type == SYMBOL_STRING_TYPE || Symbol->Type == SYMBOL_WSTRING_TYPE) - { - int temp = GetSymbolHeapSize(Symbol); - i += temp; - } - else - { - i++; - } - } - - if (!Found) + if (!Node) { *Error = SCRIPT_ENGINE_ERROR_UNDEFINED_FUNCTION; break; } - // will rewrite here - for (unsigned int j = 0; j < UserDefinedFunctions->Pointer; j++) - { - Symbol = UserDefinedFunctions->Head + j; - if (Symbol->Type == SYMBOL_USER_DEFINED_FUNCTION_TYPE && !strcmp((const char *)FunctionToken->Value, (const char *)Symbol->Value)) - { - j++; - Symbol = UserDefinedFunctions->Head + j; - while (Symbol->Type != SYMBOL_USER_DEFINED_FUNCTION_TYPE && j < UserDefinedFunctions->Pointer) - { - TargetFunctionVariableNum++; - j++; - Symbol = UserDefinedFunctions->Head + j; - } - goto ExitLoop; - } - } - - ExitLoop: - - if (VariableNum != TargetFunctionVariableNum) + if (VariableNum != Node->ParameterNumber) { *Error = SCRIPT_ENGINE_ERROR_SYNTAX; break; } - // - // Add call user-defined function instruction - // - PushSymbol(CodeBuffer, OperatorSymbol); + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_CALL; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); - // - // Add function's address - // - PSYMBOL JumpAddressSymbol = NewSymbol(); - JumpAddressSymbol->Type = SYMBOL_NUM_TYPE; - JumpAddressSymbol->Value = i; - PushSymbol(CodeBuffer, JumpAddressSymbol); - RemoveSymbol(&JumpAddressSymbol); + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = Node->Address; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); - // - // Add return address - // - JumpAddressSymbol = NewSymbol(); - JumpAddressSymbol->Type = SYMBOL_RETURN_ADDRESS_TYPE; - JumpAddressSymbol->Value = CodeBuffer->Pointer + 1; - PushSymbol(CodeBuffer, JumpAddressSymbol); - RemoveSymbol(&JumpAddressSymbol); + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_SUB; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = Node->ParameterNumber; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_STACK_INDEX_TYPE; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_STACK_INDEX_TYPE; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); if (!strcmp(Operator->Value, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE")) { - if (FunctionToken->Type == (TOKEN_TYPE)VARIABLE_TYPE_VOID) + if (((VARIABLE_TYPE *)Node->VariableType)->Kind == TY_VOID) { *Error = SCRIPT_ENGINE_ERROR_VOID_FUNCTION_RETURNING_VALUE; break; @@ -870,17 +1199,24 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Add return variable symbol // - Temp = NewTemp(Error, CurrentFunctionSymbol); + Temp = NewTemp(Error); Push(MatchedStack, Temp); - PSYMBOL Symbol = NewSymbol(); - Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; - Symbol->Value = FUNC_MOV_RETURN_VALUE; + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MOV; + PushSymbol(CodeBuffer, Symbol); + RemoveSymbol(&Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_RETURN_VALUE_TYPE; + Symbol->Value = 0; PushSymbol(CodeBuffer, Symbol); RemoveSymbol(&Symbol); TempSymbol = ToSymbol(Temp, Error); PushSymbol(CodeBuffer, TempSymbol); + RemoveSymbol(&TempSymbol); if (*Error != SCRIPT_ENGINE_ERROR_FREE) { @@ -890,6 +1226,260 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B RemoveToken(&FunctionToken); } + else if (!strcmp(Operator->Value, "@MULTIPLE_ASSIGNMENT")) + { + int Op1Capacity = 8; + int Op1Count = 0; + PSCRIPT_ENGINE_TOKEN * Op1Array = (PSCRIPT_ENGINE_TOKEN *)malloc(sizeof(PSCRIPT_ENGINE_TOKEN) * Op1Capacity); + PSYMBOL Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MOV; + + Op0 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + + for (int i = MatchedStack->Pointer; i > 0; i--) + { + Op1 = Top(MatchedStack); + + if (Op1Count >= Op1Capacity) + { + Op1Capacity *= 2; + Op1Array = (PSCRIPT_ENGINE_TOKEN *)realloc(Op1Array, sizeof(PSCRIPT_ENGINE_TOKEN) * Op1Capacity); + } + Op1Array[Op1Count++] = Op1; + + if (Op1->Type == TEMP || Op1->Type == HEX || Op1->Type == OCTAL || Op1->Type == BINARY || Op1->Type == PSEUDO_REGISTER) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + Pop(MatchedStack); + break; + } + else if (Op1->Type == GLOBAL_UNRESOLVED_ID) + { + PushSymbol(CodeBuffer, Symbol); + PushSymbol(CodeBuffer, Op0Symbol); + + Op1Symbol = NewSymbol(); + free((void *)Op1Symbol->Value); + Op1Symbol->Value = NewGlobalIdentifier(Op1); + SetType(&Op1Symbol->Type, SYMBOL_GLOBAL_ID_TYPE); + Pop(MatchedStack); + PushSymbol(CodeBuffer, Op1Symbol); + } + else if (Op1->Type == LOCAL_UNRESOLVED_ID) + { + PushSymbol(CodeBuffer, Symbol); + PushSymbol(CodeBuffer, Op0Symbol); + + Op1Symbol = NewSymbol(); + free((void *)Op1Symbol->Value); + Op1Symbol->Value = NewLocalIdentifier(Op1, 8); + SetType(&Op1Symbol->Type, SYMBOL_LOCAL_ID_TYPE); + Pop(MatchedStack); + PushSymbol(CodeBuffer, Op1Symbol); + RemoveSymbol(&Op1Symbol); + } + else if (Op1->Type == LOCAL_ID || Op1->Type == GLOBAL_ID || Op1->Type == FUNCTION_PARAMETER_ID || Op1->Type == REGISTER) + { + PushSymbol(CodeBuffer, Symbol); + PushSymbol(CodeBuffer, Op0Symbol); + + Op1Symbol = ToSymbol(Op1, Error); + PushSymbol(CodeBuffer, Op1Symbol); + Pop(MatchedStack); + RemoveSymbol(&Op1Symbol); + } + else + { + break; + } + } + + RemoveSymbol(&Symbol); + Op1 = 0; + + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + FreeTemp(Op0); + break; + } + + if (MatchedStack->Pointer > 0) + { + if (Top(MatchedStack)->Type == SCRIPT_VARIABLE_TYPE) + { + VariableType = HandleType(MatchedStack); + + if (VariableType->Kind == TY_UNKNOWN) + { + *Error = SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE; + break; + } + + for (int i = 0; i < Op1Count; i++) + { + Op1 = Op1Array[i]; + if (Op1->Type == LOCAL_UNRESOLVED_ID || Op1->Type == LOCAL_ID) + { + SetLocalIdentifierVariableType(Op1, VariableType); + } + else if (Op1->Type == GLOBAL_UNRESOLVED_ID || Op1->Type == GLOBAL_ID) + { + SetGlobalIdentifierVariableType(Op1, VariableType); + } + } + + Op1 = 0; + } + } + + // + // Free the operand if it is a temp value + // + FreeTemp(Op0); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + + free(Op1Array); + } + else if (!strcmp(Operator->Value, "@ARRAY_INDEX_READ") || !strcmp(Operator->Value, "@ARRAY_INDEX_WRITE")) + { + int ArrayCapacity = 8; + int TokenCount = 0; + PSCRIPT_ENGINE_TOKEN * TokenArray = (PSCRIPT_ENGINE_TOKEN *)malloc(sizeof(PSCRIPT_ENGINE_TOKEN) * ArrayCapacity); + PSCRIPT_ENGINE_TOKEN IdToken; + PSYMBOL IdSymbol; + int ElementOffset = 0; + PSYMBOL Symbol; + PSCRIPT_ENGINE_TOKEN OffsetToken; + PSYMBOL OffsetSymbol; + + while (MatchedStack->Pointer) + { + if (TokenCount >= ArrayCapacity) + { + TokenCount *= 2; + TokenArray = (PSCRIPT_ENGINE_TOKEN *)realloc(TokenArray, sizeof(PSCRIPT_ENGINE_TOKEN) * ArrayCapacity); + } + + Temp = Top(MatchedStack); + if (!strcmp(Top(MatchedStack)->Value, "@ARRAY_DIM_NUMBER")) + { + Pop(MatchedStack); + TokenArray[TokenCount] = Pop(MatchedStack); + TokenCount++; + } + else + { + break; + } + } + + IdToken = Pop(MatchedStack); + IdSymbol = ToSymbol(IdToken, Error); + + if (IdToken->Type == LOCAL_UNRESOLVED_ID) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + break; + } + + for (int i = 0; i < TokenCount / 2; i++) + { + PSCRIPT_ENGINE_TOKEN tmp = TokenArray[i]; + TokenArray[i] = TokenArray[TokenCount - i - 1]; + TokenArray[TokenCount - i - 1] = tmp; + } + + VariableType = (VARIABLE_TYPE *)IdToken->VariableType; + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + OffsetToken = NewTemp(Error); + OffsetSymbol = ToSymbol(OffsetToken, Error); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MOV; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = 0; + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, OffsetSymbol); + + for (int i = 0; i < TokenCount; i++) + { + if (!VariableType->Base) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + break; + } + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MUL; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = VariableType->Base->Size; + PushSymbol(CodeBuffer, Symbol); + + Symbol = ToSymbol(TokenArray[i], Error); + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, TempSymbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_ADD; + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, TempSymbol); + PushSymbol(CodeBuffer, OffsetSymbol); + PushSymbol(CodeBuffer, OffsetSymbol); + + VariableType = VariableType->Base; + } + + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_ADD; + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, IdSymbol); + PushSymbol(CodeBuffer, OffsetSymbol); + PushSymbol(CodeBuffer, OffsetSymbol); + + if (!strcmp(Operator->Value, "@ARRAY_INDEX_READ")) + { + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_POI; + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, OffsetSymbol); + PushSymbol(CodeBuffer, OffsetSymbol); + } + else if (!strcmp(Operator->Value, "@ARRAY_INDEX_WRITE")) + { + OffsetToken->Type = DEFERENCE_TEMP; + } + + Push(MatchedStack, OffsetToken); + + FreeTemp(Temp); + } else if (!strcmp(Operator->Value, "@MOV")) { PushSymbol(CodeBuffer, OperatorSymbol); @@ -908,7 +1498,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B { Op1Symbol = NewSymbol(); free((void *)Op1Symbol->Value); - Op1Symbol->Value = NewLocalIdentifier(Op1); + Op1Symbol->Value = NewLocalIdentifier(Op1, 8); SetType(&Op1Symbol->Type, SYMBOL_LOCAL_ID_TYPE); } else @@ -918,17 +1508,40 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B if (MatchedStack->Pointer > 0) { - if (Top(MatchedStack)->Type == INPUT_VARIABLE_TYPE) + if (!strcmp(Top(MatchedStack)->Value, "@DECLARE_POINTER_TYPE") || Top(MatchedStack)->Type == SCRIPT_VARIABLE_TYPE) { + if (!strcmp(Top(MatchedStack)->Value, "@DECLARE_POINTER_TYPE")) + { + PointerVariableType = calloc(1, sizeof(VARIABLE_TYPE)); + PointerVariableType->Kind = TY_PTR; + PointerVariableType->Size = 8; + PointerVariableType->Align = 8; + PointerVariableType->IsUnsigned = TRUE; + Pop(MatchedStack); + } + VariableType = HandleType(MatchedStack); - if (VariableType == VARIABLE_TYPE_UNKNOWN) + if (VariableType->Kind == TY_UNKNOWN) { *Error = SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE; break; } - Op1Symbol->VariableType = (unsigned long long)VariableType; + if (PointerVariableType) + { + PointerVariableType->Base = VariableType; + VariableType = PointerVariableType; + } + + if (Op1->Type == LOCAL_UNRESOLVED_ID || Op1->Type == LOCAL_ID) + { + SetLocalIdentifierVariableType(Op1, VariableType); + } + else if (Op1->Type == GLOBAL_UNRESOLVED_ID || Op1->Type == GLOBAL_ID) + { + SetGlobalIdentifierVariableType(Op1, VariableType); + } } } @@ -945,6 +1558,310 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B break; } } + else if (!strcmp(Operator->Value, "@DECLARE_POINTER_TYPE")) + { + Push(MatchedStack, CopyToken(Operator)); + } + else if (!strcmp(Operator->Value, "@ARRAY_DIM_NUMBER") || !strcmp(Operator->Value, "@ARRAY_LEFT_BRACKET") || !strcmp(Operator->Value, "@ARRAY_L_VALUE")) + { + Push(MatchedStack, CopyToken(Operator)); + } + else if (!strcmp(Operator->Value, "@DEREFERENCE")) + { + PSYMBOL Symbol; + + Op0 = Pop(MatchedStack); + Op1 = Pop(MatchedStack); + + if (Op1->Type == LOCAL_UNRESOLVED_ID) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + break; + } + + if (((VARIABLE_TYPE *)Op1->VariableType)->Size == 4) + { + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_ED; + + Op0Symbol = ToSymbol(Op0, Error); + Op1Symbol = ToSymbol(Op1, Error); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + + PushSymbol(CodeBuffer, Symbol); + PushSymbol(CodeBuffer, Op0Symbol); + PushSymbol(CodeBuffer, Op1Symbol); + PushSymbol(CodeBuffer, TempSymbol); + FreeTemp(Temp); + } + else if (((VARIABLE_TYPE *)Op1->VariableType)->Size == 8) + { + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_EQ; + + Op0Symbol = ToSymbol(Op0, Error); + Op1Symbol = ToSymbol(Op1, Error); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + + PushSymbol(CodeBuffer, Symbol); + PushSymbol(CodeBuffer, Op0Symbol); + PushSymbol(CodeBuffer, Op1Symbol); + PushSymbol(CodeBuffer, TempSymbol); + FreeTemp(Temp); + } + + else if (((VARIABLE_TYPE *)Op1->VariableType)->Size == 1) + { + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_EB; + + Op0Symbol = ToSymbol(Op0, Error); + Op1Symbol = ToSymbol(Op1, Error); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + + PushSymbol(CodeBuffer, Symbol); + PushSymbol(CodeBuffer, Op0Symbol); + PushSymbol(CodeBuffer, Op1Symbol); + PushSymbol(CodeBuffer, TempSymbol); + FreeTemp(Temp); + } + } + else if (!strcmp(Operator->Value, "@ARRAY_DECLARITION")) + { + int TokenCapacity = 8; + int TokenCount = 0; + PSCRIPT_ENGINE_TOKEN * TokenArray = (PSCRIPT_ENGINE_TOKEN *)malloc(sizeof(PSCRIPT_ENGINE_TOKEN) * TokenCapacity); + PSCRIPT_ENGINE_TOKEN IdToken = NULL; + PSYMBOL IdSymbol = NewSymbol(); + ; + VARIABLE_TYPE * VariableType2 = NULL; + int Last_ARRAY_DIM_NUMBER_Idx = 0; + int ArrayElementCount = 0; + PSYMBOL Symbol = NULL; + int BaseTypeSize = 0; + + for (int i = MatchedStack->Pointer; i > 0; i--) + { + Temp = Pop(MatchedStack); + if (!strcmp(Temp->Value, "@ARRAY_L_VALUE")) + { + break; + } + + if (TokenCount >= TokenCapacity) + { + TokenCapacity *= 2; + TokenArray = (PSCRIPT_ENGINE_TOKEN *)realloc(TokenArray, sizeof(PSCRIPT_ENGINE_TOKEN) * TokenCapacity); + } + TokenArray[TokenCount++] = Temp; + } + + for (SIZE_T i = 0; i < TokenCount / 2; i++) + { + PSCRIPT_ENGINE_TOKEN tmp = TokenArray[i]; + TokenArray[i] = TokenArray[TokenCount - i - 1]; + TokenArray[TokenCount - i - 1] = tmp; + } + + IdToken = Pop(MatchedStack); + + if (MatchedStack->Pointer > 0) + { + if (Top(MatchedStack)->Type == SCRIPT_VARIABLE_TYPE) + { + VariableType = HandleType(MatchedStack); + + if (VariableType->Kind == TY_UNKNOWN) + { + *Error = SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE; + break; + } + } + } + + if (!VariableType) + { + VariableType = VARIABLE_TYPE_LONG; + } + + BaseTypeSize = VariableType->Size; + + for (int i = TokenCount - 1; i >= 0; i--) + { + if (!strcmp(TokenArray[i]->Value, "@ARRAY_DIM_NUMBER")) + { + Last_ARRAY_DIM_NUMBER_Idx = i; + break; + } + } + + for (int i = Last_ARRAY_DIM_NUMBER_Idx; i >= 0; i--) + { + if (!strcmp(TokenArray[i]->Value, "@ARRAY_DIM_NUMBER")) + { + VariableType2 = calloc(1, sizeof(VARIABLE_TYPE)); + VariableType2->Kind = TY_ARRAY; + VariableType2->Size = VariableType->Size * atoi(TokenArray[i - 1]->Value); + VariableType2->Align = VariableType->Align; + VariableType2->Base = VariableType; + VariableType2->ArrayLen = atoi(TokenArray[i - 1]->Value); + VariableType = VariableType2; + i--; + } + } + + if (IdToken->Type == LOCAL_UNRESOLVED_ID) + { + IdSymbol->Value = NewLocalIdentifier(IdToken, VariableType->Size); + SetType(&IdSymbol->Type, SYMBOL_REFERENCE_LOCAL_ID_TYPE); + SetLocalIdentifierVariableType(IdToken, VariableType); + } + + for (int i = Last_ARRAY_DIM_NUMBER_Idx + 1; i < TokenCount; i++) + { + if (TokenArray[i]->Type != SEMANTIC_RULE) + { + if ((ArrayElementCount * BaseTypeSize) > VariableType->Size) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + break; + } + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MUL; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = BaseTypeSize; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = ArrayElementCount; + PushSymbol(CodeBuffer, Symbol); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + PushSymbol(CodeBuffer, TempSymbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_ADD; + + PushSymbol(CodeBuffer, Symbol); + PushSymbol(CodeBuffer, IdSymbol); + PushSymbol(CodeBuffer, TempSymbol); + PushSymbol(CodeBuffer, TempSymbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + + if (BaseTypeSize == 4) + { + Symbol->Value = FUNC_ED; + } + else if (BaseTypeSize == 8) + { + Symbol->Value = FUNC_EQ; + } + else if (BaseTypeSize == 1) + { + Symbol->Value = FUNC_EB; + } + + PushSymbol(CodeBuffer, Symbol); + + Symbol = ToSymbol(TokenArray[i], Error); + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, TempSymbol); + + PushSymbol(CodeBuffer, TempSymbol); + + FreeTemp(Temp); + + ArrayElementCount++; + } + } + + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + + while ((ArrayElementCount * BaseTypeSize) < VariableType->Size) + { + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MUL; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = BaseTypeSize; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = ArrayElementCount; + PushSymbol(CodeBuffer, Symbol); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + PushSymbol(CodeBuffer, TempSymbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_ADD; + + PushSymbol(CodeBuffer, Symbol); + PushSymbol(CodeBuffer, IdSymbol); + PushSymbol(CodeBuffer, TempSymbol); + PushSymbol(CodeBuffer, TempSymbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + + if (BaseTypeSize == 4) + { + Symbol->Value = FUNC_ED; + } + else if (BaseTypeSize == 8) + { + Symbol->Value = FUNC_EQ; + } + else if (BaseTypeSize == 1) + { + Symbol->Value = FUNC_EB; + } + + PushSymbol(CodeBuffer, Symbol); + + Symbol = Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = 0; + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, TempSymbol); + + PushSymbol(CodeBuffer, TempSymbol); + + FreeTemp(Temp); + + ArrayElementCount++; + } + } else if (IsType2Func(Operator)) { PushSymbol(CodeBuffer, OperatorSymbol); @@ -960,10 +1877,11 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B else if (IsType1Func(Operator)) { PushSymbol(CodeBuffer, OperatorSymbol); - Op0 = Pop(MatchedStack); - Op0Symbol = ToSymbol(Op0, Error); + Op0 = Pop(MatchedStack); + VariableType = (VARIABLE_TYPE *)Op0->VariableType; + Op0Symbol = ToSymbol(Op0, Error); - Temp = NewTemp(Error, CurrentFunctionSymbol); + Temp = NewTemp(Error); Push(MatchedStack, Temp); TempSymbol = ToSymbol(Temp, Error); @@ -999,7 +1917,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B OperandCount++; if (*Error != SCRIPT_ENGINE_ERROR_FREE) { - RemoveSymbolBuffer(TempStack); + RemoveSymbolBuffer((PVOID)TempStack); break; } } @@ -1026,7 +1944,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B RemoveSymbol(&OperandCountSymbol); if (*Error != SCRIPT_ENGINE_ERROR_FREE) { - RemoveSymbolBuffer(TempStack); + RemoveSymbolBuffer((PVOID)TempStack); break; } @@ -1041,7 +1959,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B } PSYMBOL FirstArg = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(FirstArgPointer * sizeof(SYMBOL))); - RemoveSymbolBuffer(TempStack); + RemoveSymbolBuffer((PVOID)TempStack); UINT32 i = 0; char * Str = Format; @@ -1103,6 +2021,21 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B { PushSymbol(CodeBuffer, OperatorSymbol); } + else if (IsType16Func(Operator)) + { + PushSymbol(CodeBuffer, OperatorSymbol); + + Temp = NewTemp(Error); + Push(MatchedStack, Temp); + TempSymbol = ToSymbol(Temp, Error); + + PushSymbol(CodeBuffer, TempSymbol); + + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + } else if (!strcmp(Operator->Value, "@IGNORE_LVALUE")) { Op0 = Pop(MatchedStack); @@ -1123,7 +2056,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B break; } - Temp = NewTemp(Error, CurrentFunctionSymbol); + Temp = NewTemp(Error); Push(MatchedStack, Temp); TempSymbol = ToSymbol(Temp, Error); PushSymbol(CodeBuffer, TempSymbol); @@ -1171,7 +2104,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B PushSymbol(CodeBuffer, Op1Symbol); PushSymbol(CodeBuffer, Op2Symbol); - Temp = NewTemp(Error, CurrentFunctionSymbol); + Temp = NewTemp(Error); Push(MatchedStack, Temp); TempSymbol = ToSymbol(Temp, Error); PushSymbol(CodeBuffer, TempSymbol); @@ -1214,58 +2147,477 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B FreeTemp(Op1); FreeTemp(Op2); } + else if (IsAssignmentOperator(Operator)) + { + BOOL Handled = FALSE; + Op1 = TopIndexed(MatchedStack, 1); + + if (((VARIABLE_TYPE *)Op1->VariableType)->Kind == TY_PTR) + { + if (!strcmp(Operator->Value, "@ADD_ASSIGNMENT")) + { + PSYMBOL Symbol = NULL; + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MUL; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = ((VARIABLE_TYPE *)Op1->VariableType)->Base->Size; + PushSymbol(CodeBuffer, Symbol); + + Op0 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + PushSymbol(CodeBuffer, Op0Symbol); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + PushSymbol(CodeBuffer, TempSymbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_ADD; + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, TempSymbol); + + Op1 = Pop(MatchedStack); + Op1Symbol = ToSymbol(Op1, Error); + PushSymbol(CodeBuffer, Op1Symbol); + PushSymbol(CodeBuffer, Op1Symbol); + + FreeTemp(Op0); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + } + else if (!strcmp(Operator->Value, "@SUB_ASSIGNMENT")) + { + PSYMBOL Symbol = NULL; + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MUL; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = ((VARIABLE_TYPE *)Op1->VariableType)->Base->Size; + PushSymbol(CodeBuffer, Symbol); + + Op0 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + PushSymbol(CodeBuffer, Op0Symbol); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + PushSymbol(CodeBuffer, TempSymbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_SUB; + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, TempSymbol); + + Op1 = Pop(MatchedStack); + Op1Symbol = ToSymbol(Op1, Error); + PushSymbol(CodeBuffer, Op1Symbol); + PushSymbol(CodeBuffer, Op1Symbol); + + FreeTemp(Op0); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + } + else + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + Op0 = Pop(MatchedStack); + Op1 = Pop(MatchedStack); + } + Handled = TRUE; + } + + if (!Handled) + { + PushSymbol(CodeBuffer, OperatorSymbol); + Op0 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + + Op1 = Pop(MatchedStack); + Op1Symbol = ToSymbol(Op1, Error); + + PushSymbol(CodeBuffer, Op0Symbol); + PushSymbol(CodeBuffer, Op1Symbol); + PushSymbol(CodeBuffer, Op1Symbol); + + // + // Free the operand if it is a temp value + // + FreeTemp(Op0); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + } + } else if (IsTwoOperandOperator(Operator)) { - PushSymbol(CodeBuffer, OperatorSymbol); - Op0 = Pop(MatchedStack); - Op0Symbol = ToSymbol(Op0, Error); + BOOL Handled = FALSE; + Op0 = TopIndexed(MatchedStack, 0); + Op1 = TopIndexed(MatchedStack, 1); - Op1 = Pop(MatchedStack); - Op1Symbol = ToSymbol(Op1, Error); - - Temp = NewTemp(Error, CurrentFunctionSymbol); - Push(MatchedStack, Temp); - TempSymbol = ToSymbol(Temp, Error); - - PushSymbol(CodeBuffer, Op0Symbol); - PushSymbol(CodeBuffer, Op1Symbol); - PushSymbol(CodeBuffer, TempSymbol); - - // - // Free the operand if it is a temp value - // - FreeTemp(Op0); - FreeTemp(Op1); - if (*Error != SCRIPT_ENGINE_ERROR_FREE) + if (!strcmp(Operator->Value, "@ADD") || !strcmp(Operator->Value, "@SUB")) { - break; + if (((VARIABLE_TYPE *)Op0->VariableType)->Kind == TY_PTR && ((VARIABLE_TYPE *)Op1->VariableType)->Kind == TY_PTR) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + Op0 = Pop(MatchedStack); + Op1 = Pop(MatchedStack); + Handled = TRUE; + } + else if (((VARIABLE_TYPE *)Op0->VariableType)->Kind == TY_PTR && ((VARIABLE_TYPE *)Op1->VariableType)->Kind != TY_PTR) + { + if (!strcmp(Operator->Value, "@SUB")) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + Op0 = Pop(MatchedStack); + Op1 = Pop(MatchedStack); + } + else + { + PSYMBOL Symbol = NULL; + + Op0 = Pop(MatchedStack); + Op1 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + Op1Symbol = ToSymbol(Op1, Error); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MUL; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = ((VARIABLE_TYPE *)Op0->VariableType)->Base->Size; + PushSymbol(CodeBuffer, Symbol); + + Op1Symbol = ToSymbol(Op1, Error); + PushSymbol(CodeBuffer, Op1Symbol); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + PushSymbol(CodeBuffer, TempSymbol); + + PushSymbol(CodeBuffer, OperatorSymbol); + Op0Symbol = ToSymbol(Op0, Error); + PushSymbol(CodeBuffer, Op0Symbol); + PushSymbol(CodeBuffer, TempSymbol); + PushSymbol(CodeBuffer, TempSymbol); + + Push(MatchedStack, Temp); + + // + // Free the operand if it is a temp value + // + FreeTemp(Op0); + FreeTemp(Op1); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + } + Handled = TRUE; + } + else if (((VARIABLE_TYPE *)Op0->VariableType)->Kind != TY_PTR && ((VARIABLE_TYPE *)Op1->VariableType)->Kind == TY_PTR) + { + PSYMBOL Symbol = NULL; + + Op0 = Pop(MatchedStack); + Op1 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + Op1Symbol = ToSymbol(Op1, Error); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MUL; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = ((VARIABLE_TYPE *)Op1->VariableType)->Base->Size; + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, Op0Symbol); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + PushSymbol(CodeBuffer, TempSymbol); + + PushSymbol(CodeBuffer, OperatorSymbol); + PushSymbol(CodeBuffer, TempSymbol); + PushSymbol(CodeBuffer, Op1Symbol); + PushSymbol(CodeBuffer, TempSymbol); + + Push(MatchedStack, Temp); + + // + // Free the operand if it is a temp value + // + FreeTemp(Op0); + FreeTemp(Op1); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + + Handled = TRUE; + } + + else if (((VARIABLE_TYPE *)Op0->VariableType)->Kind == TY_ARRAY && ((VARIABLE_TYPE *)Op1->VariableType)->Kind == TY_ARRAY) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + Op0 = Pop(MatchedStack); + Op1 = Pop(MatchedStack); + Handled = TRUE; + } + else if (((VARIABLE_TYPE *)Op0->VariableType)->Kind == TY_ARRAY && ((VARIABLE_TYPE *)Op1->VariableType)->Kind != TY_ARRAY) + { + if (!strcmp(Operator->Value, "@SUB")) + { + *Error = SCRIPT_ENGINE_ERROR_SYNTAX; + Op0 = Pop(MatchedStack); + Op1 = Pop(MatchedStack); + } + else + { + PSYMBOL Symbol = NULL; + int VariableBaseSize = 0; + VariableType = (VARIABLE_TYPE *)Op0->VariableType; + while (VariableType->Base) + { + VariableType = VariableType->Base; + } + VariableBaseSize = VariableType->Size; + + Op0 = Pop(MatchedStack); + Op1 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + Op1Symbol = ToSymbol(Op1, Error); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MUL; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = VariableBaseSize; + PushSymbol(CodeBuffer, Symbol); + + Op1Symbol = ToSymbol(Op1, Error); + PushSymbol(CodeBuffer, Op1Symbol); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + PushSymbol(CodeBuffer, TempSymbol); + + PushSymbol(CodeBuffer, OperatorSymbol); + Op0Symbol = ToSymbol(Op0, Error); + PushSymbol(CodeBuffer, Op0Symbol); + PushSymbol(CodeBuffer, TempSymbol); + PushSymbol(CodeBuffer, TempSymbol); + + Push(MatchedStack, Temp); + + // + // Free the operand if it is a temp value + // + FreeTemp(Op0); + FreeTemp(Op1); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + } + Handled = TRUE; + } + else if (((VARIABLE_TYPE *)Op0->VariableType)->Kind != TY_ARRAY && ((VARIABLE_TYPE *)Op1->VariableType)->Kind == TY_ARRAY) + { + PSYMBOL Symbol = NULL; + int VariableBaseSize = 0; + VariableType = (VARIABLE_TYPE *)Op1->VariableType; + while (VariableType->Base) + { + VariableType = VariableType->Base; + } + VariableBaseSize = VariableType->Size; + + Op0 = Pop(MatchedStack); + Op1 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + Op1Symbol = ToSymbol(Op1, Error); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_MUL; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = VariableBaseSize; + PushSymbol(CodeBuffer, Symbol); + + PushSymbol(CodeBuffer, Op0Symbol); + + Temp = NewTemp(Error); + TempSymbol = ToSymbol(Temp, Error); + PushSymbol(CodeBuffer, TempSymbol); + + PushSymbol(CodeBuffer, OperatorSymbol); + PushSymbol(CodeBuffer, TempSymbol); + PushSymbol(CodeBuffer, Op1Symbol); + PushSymbol(CodeBuffer, TempSymbol); + + Push(MatchedStack, Temp); + + // + // Free the operand if it is a temp value + // + FreeTemp(Op0); + FreeTemp(Op1); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + + Handled = TRUE; + } + } + + if (!Handled) + { + PushSymbol(CodeBuffer, OperatorSymbol); + Op0 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + + Op1 = Pop(MatchedStack); + Op1Symbol = ToSymbol(Op1, Error); + + Temp = NewTemp(Error); + Temp->VariableType = (VARIABLE_TYPE *)GetCommonVariableType((VARIABLE_TYPE *)Op0->VariableType, (VARIABLE_TYPE *)Op1->VariableType); + Push(MatchedStack, Temp); + TempSymbol = ToSymbol(Temp, Error); + + PushSymbol(CodeBuffer, Op0Symbol); + PushSymbol(CodeBuffer, Op1Symbol); + PushSymbol(CodeBuffer, TempSymbol); + + // + // Free the operand if it is a temp value + // + FreeTemp(Op0); + FreeTemp(Op1); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } } } else if (IsOneOperandOperator(Operator)) { - PushSymbol(CodeBuffer, OperatorSymbol); - Op0 = Pop(MatchedStack); - Op0Symbol = ToSymbol(Op0, Error); + BOOL Handled = FALSE; + Op0 = Top(MatchedStack); - PushSymbol(CodeBuffer, Op0Symbol); - - // - // Free the operand if it is a temp value - // - FreeTemp(Op0); - if (*Error != SCRIPT_ENGINE_ERROR_FREE) + if (((VARIABLE_TYPE *)Op0->VariableType)->Kind == TY_PTR) { - break; + if (!strcmp(Operator->Value, "@INC")) + { + PSYMBOL Symbol = NULL; + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_ADD; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = ((VARIABLE_TYPE *)Op0->VariableType)->Base->Size; + PushSymbol(CodeBuffer, Symbol); + + Op0 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + PushSymbol(CodeBuffer, Op0Symbol); + PushSymbol(CodeBuffer, Op0Symbol); + + FreeTemp(Op0); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + Handled = TRUE; + } + + else if (!strcmp(Operator->Value, "@DEC")) + { + PSYMBOL Symbol = NULL; + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE; + Symbol->Value = FUNC_SUB; + PushSymbol(CodeBuffer, Symbol); + + Symbol = NewSymbol(); + Symbol->Type = SYMBOL_NUM_TYPE; + Symbol->Value = ((VARIABLE_TYPE *)Op0->VariableType)->Base->Size; + PushSymbol(CodeBuffer, Symbol); + + Op0 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + PushSymbol(CodeBuffer, Op0Symbol); + PushSymbol(CodeBuffer, Op0Symbol); + + FreeTemp(Op0); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + Handled = TRUE; + } + } + + if (!Handled) + { + PushSymbol(CodeBuffer, OperatorSymbol); + Op0 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + + PushSymbol(CodeBuffer, Op0Symbol); + + // + // Free the operand if it is a temp value + // + FreeTemp(Op0); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } } } else if (!strcmp(Operator->Value, "@VARGSTART")) { - PTOKEN OperatorCopy = CopyToken(Operator); + PSCRIPT_ENGINE_TOKEN OperatorCopy = CopyToken(Operator); Push(MatchedStack, OperatorCopy); } else if (!strcmp(Operator->Value, "@START_OF_IF")) { - PTOKEN OperatorCopy = CopyToken(Operator); + PSCRIPT_ENGINE_TOKEN OperatorCopy = CopyToken(Operator); Push(MatchedStack, OperatorCopy); } else if (!strcmp(Operator->Value, "@JZ")) @@ -1286,7 +2638,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B char str[20] = {0}; sprintf(str, "%llu", (UINT64)CodeBuffer->Pointer); - PTOKEN CurrentAddressToken = NewToken(DECIMAL, str); + PSCRIPT_ENGINE_TOKEN CurrentAddressToken = NewToken(DECIMAL, str); Push(MatchedStack, CurrentAddressToken); FreeTemp(Op0); @@ -1300,11 +2652,11 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Set JZ jump address // - UINT64 CurrentPointer = CodeBuffer->Pointer; - PTOKEN JumpSemanticAddressToken = Pop(MatchedStack); - UINT64 JumpSemanticAddress = DecimalToInt(JumpSemanticAddressToken->Value); - PSYMBOL JumpAddressSymbol = (PSYMBOL)(CodeBuffer->Head + JumpSemanticAddress - 2); - JumpAddressSymbol->Value = CurrentPointer + 2; + UINT64 CurrentPointer = CodeBuffer->Pointer; + PSCRIPT_ENGINE_TOKEN JumpSemanticAddressToken = Pop(MatchedStack); + UINT64 JumpSemanticAddress = DecimalToInt(JumpSemanticAddressToken->Value); + PSYMBOL JumpAddressSymbol = (PSYMBOL)(CodeBuffer->Head + JumpSemanticAddress - 2); + JumpAddressSymbol->Value = CurrentPointer + 2; RemoveToken(&JumpSemanticAddressToken); // @@ -1330,14 +2682,14 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // char str[20] = {0}; sprintf(str, "%llu", CurrentPointer); - PTOKEN CurrentAddressToken = NewToken(DECIMAL, str); + PSCRIPT_ENGINE_TOKEN CurrentAddressToken = NewToken(DECIMAL, str); Push(MatchedStack, CurrentAddressToken); } else if (!strcmp(Operator->Value, "@END_OF_IF")) { - UINT64 CurrentPointer = CodeBuffer->Pointer; - PTOKEN JumpSemanticAddressToken = Pop(MatchedStack); - PSYMBOL JumpAddressSymbol; + UINT64 CurrentPointer = CodeBuffer->Pointer; + PSCRIPT_ENGINE_TOKEN JumpSemanticAddressToken = Pop(MatchedStack); + PSYMBOL JumpAddressSymbol; while (strcmp(JumpSemanticAddressToken->Value, "@START_OF_IF")) { UINT64 JumpSemanticAddress = DecimalToInt(JumpSemanticAddressToken->Value); @@ -1354,18 +2706,18 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Push @START_OF_WHILE token into matched stack // - PTOKEN OperatorCopy = CopyToken(Operator); + PSCRIPT_ENGINE_TOKEN OperatorCopy = CopyToken(Operator); Push(MatchedStack, OperatorCopy); char str[20] = {0}; sprintf(str, "%llu", (UINT64)CodeBuffer->Pointer); - PTOKEN CurrentAddressToken = NewToken(DECIMAL, str); + PSCRIPT_ENGINE_TOKEN CurrentAddressToken = NewToken(DECIMAL, str); Push(MatchedStack, CurrentAddressToken); } else if (!strcmp(Operator->Value, "@START_OF_WHILE_COMMANDS")) { - UINT64 CurrentPointer = CodeBuffer->Pointer; - PTOKEN JzToken = NewToken(SEMANTIC_RULE, "@JZ"); + UINT64 CurrentPointer = CodeBuffer->Pointer; + PSCRIPT_ENGINE_TOKEN JzToken = NewToken(SEMANTIC_RULE, "@JZ"); RemoveSymbol(&OperatorSymbol); OperatorSymbol = ToSymbol(JzToken, Error); @@ -1378,11 +2730,11 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B Op0 = Pop(MatchedStack); Op0Symbol = ToSymbol(Op0, Error); - PTOKEN StartOfWhileToken = Pop(MatchedStack); + PSCRIPT_ENGINE_TOKEN StartOfWhileToken = Pop(MatchedStack); char str[20]; sprintf(str, "%llu", CurrentPointer + 1); - PTOKEN CurrentAddressToken = NewToken(DECIMAL, str); + PSCRIPT_ENGINE_TOKEN CurrentAddressToken = NewToken(DECIMAL, str); Push(MatchedStack, CurrentAddressToken); Push(MatchedStack, StartOfWhileToken); @@ -1413,9 +2765,9 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Add jmp address to Code buffer // - PTOKEN JumpAddressToken = Pop(MatchedStack); - UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value); - PSYMBOL JumpAddressSymbol = ToSymbol(JumpAddressToken, Error); + PSCRIPT_ENGINE_TOKEN JumpAddressToken = Pop(MatchedStack); + UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value); + PSYMBOL JumpAddressSymbol = ToSymbol(JumpAddressToken, Error); PushSymbol(CodeBuffer, JumpAddressSymbol); RemoveSymbol(&JumpAddressSymbol); @@ -1450,12 +2802,12 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Push @START_OF_DO_WHILE token into matched stack // - PTOKEN OperatorCopy = CopyToken(Operator); + PSCRIPT_ENGINE_TOKEN OperatorCopy = CopyToken(Operator); Push(MatchedStack, OperatorCopy); char str[20]; sprintf(str, "%llu", (UINT64)CodeBuffer->Pointer); - PTOKEN CurrentAddressToken = NewToken(DECIMAL, str); + PSCRIPT_ENGINE_TOKEN CurrentAddressToken = NewToken(DECIMAL, str); Push(MatchedStack, CurrentAddressToken); } else if (!strcmp(Operator->Value, "@END_OF_DO_WHILE")) @@ -1478,8 +2830,8 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Add jmp address to Code buffer // - PTOKEN JumpAddressToken = Pop(MatchedStack); - UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value); + PSCRIPT_ENGINE_TOKEN JumpAddressToken = Pop(MatchedStack); + UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value); PSYMBOL JumpAddressSymbol = ToSymbol(JumpAddressToken, Error); @@ -1512,7 +2864,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B JumpAddress = DecimalToInt(JumpAddressToken->Value); #ifdef _SCRIPT_ENGINE_LL1_DBG_EN - printf("Jz Jump Address = %d\n", JumpAddress); + printf("Jz Jump Address = %lld\n", JumpAddress); #endif JumpAddressSymbol = (PSYMBOL)(CodeBuffer->Head + JumpAddress); JumpAddressSymbol->Value = CurrentPointer; @@ -1525,7 +2877,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Push @START_OF_FOR token into matched stack // - PTOKEN OperatorCopy = CopyToken(Operator); + PSCRIPT_ENGINE_TOKEN OperatorCopy = CopyToken(Operator); Push(MatchedStack, OperatorCopy); // @@ -1533,7 +2885,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // char str[20] = {0}; sprintf(str, "%llu", (UINT64)CodeBuffer->Pointer); - PTOKEN CurrentAddressToken = NewToken(DECIMAL, str); + PSCRIPT_ENGINE_TOKEN CurrentAddressToken = NewToken(DECIMAL, str); Push(MatchedStack, CurrentAddressToken); } else if (!strcmp(Operator->Value, "@FOR_INC_DEC")) @@ -1596,14 +2948,14 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Pop start_of_for address // - PTOKEN StartOfForAddressToken = Pop(MatchedStack); + PSCRIPT_ENGINE_TOKEN StartOfForAddressToken = Pop(MatchedStack); // // Push current pointer into matched stack // char str[20] = {0}; sprintf(str, "%llu", (UINT64)CodeBuffer->Pointer); - PTOKEN CurrentAddressToken = NewToken(DECIMAL, str); + PSCRIPT_ENGINE_TOKEN CurrentAddressToken = NewToken(DECIMAL, str); Push(MatchedStack, CurrentAddressToken); // @@ -1629,8 +2981,8 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Add jmp address to Code buffer // - PTOKEN JumpAddressToken = Pop(MatchedStack); - UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value); + PSCRIPT_ENGINE_TOKEN JumpAddressToken = Pop(MatchedStack); + UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value); PSYMBOL JumpAddressSymbol = ToSymbol(JumpAddressToken, Error); @@ -1657,13 +3009,13 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // char str[20] = {0}; sprintf(str, "%llu", JumpAddress - 4); - PTOKEN JzAddressToken = NewToken(DECIMAL, str); + PSCRIPT_ENGINE_TOKEN JzAddressToken = NewToken(DECIMAL, str); Push(MatchedStack, JzAddressToken); // // Push @INC_DEC token to matched stack // - PTOKEN IncDecToken = NewToken(SEMANTIC_RULE, "@INC_DEC"); + PSCRIPT_ENGINE_TOKEN IncDecToken = NewToken(SEMANTIC_RULE, "@INC_DEC"); Push(MatchedStack, IncDecToken); // @@ -1689,8 +3041,8 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Add jmp address to Code buffer // - PTOKEN JumpAddressToken = Pop(MatchedStack); - UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value); + PSCRIPT_ENGINE_TOKEN JumpAddressToken = Pop(MatchedStack); + UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value); PSYMBOL JumpAddressSymbol = ToSymbol(JumpAddressToken, Error); @@ -1736,8 +3088,8 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // Pop Objects from stack while reaching @START_OF_* // - PTOKEN_LIST TempStack = NewTokenList(); - PTOKEN TempToken; + PSCRIPT_ENGINE_TOKEN_LIST TempStack = NewTokenList(); + PSCRIPT_ENGINE_TOKEN TempToken; do { TempToken = Pop(MatchedStack); @@ -1758,7 +3110,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B UINT64 CurrentPointer = CodeBuffer->Pointer + 1; char str[20]; sprintf(str, "%llu", CurrentPointer); - PTOKEN CurrentAddressToken = NewToken(DECIMAL, str); + PSCRIPT_ENGINE_TOKEN CurrentAddressToken = NewToken(DECIMAL, str); Push(MatchedStack, CurrentAddressToken); // @@ -1813,8 +3165,8 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B // // Pop Objects from stack while reaching @INC_DEC // - PTOKEN_LIST TempStack = NewTokenList(); - PTOKEN TempToken; + PSCRIPT_ENGINE_TOKEN_LIST TempStack = NewTokenList(); + PSCRIPT_ENGINE_TOKEN TempToken; do { TempToken = Pop(MatchedStack); @@ -1878,7 +3230,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B Op0 = Pop(MatchedStack); Op0Symbol = ToSymbol(Op0, Error); - Temp = NewTemp(Error, CurrentFunctionSymbol); + Temp = NewTemp(Error); Push(MatchedStack, Temp); TempSymbol = ToSymbol(Temp, Error); @@ -1907,7 +3259,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B break; } - Temp = NewTemp(Error, CurrentFunctionSymbol); + Temp = NewTemp(Error); Push(MatchedStack, Temp); TempSymbol = ToSymbol(Temp, Error); PushSymbol(CodeBuffer, TempSymbol); @@ -1927,25 +3279,24 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B Op1 = Pop(MatchedStack); Op1Symbol = ToSymbol(Op1, Error); - PTOKEN Op2 = Pop(MatchedStack); - PSYMBOL Op2Symbol = ToSymbol(Op2, Error); + Op2 = Pop(MatchedStack); + Op2Symbol = ToSymbol(Op2, Error); PushSymbol(CodeBuffer, Op0Symbol); PushSymbol(CodeBuffer, Op1Symbol); PushSymbol(CodeBuffer, Op2Symbol); - Temp = NewTemp(Error, CurrentFunctionSymbol); + Temp = NewTemp(Error); Push(MatchedStack, Temp); TempSymbol = ToSymbol(Temp, Error); PushSymbol(CodeBuffer, TempSymbol); - FreeTemp(Op2); - // // Free the operand if it is a temp value // FreeTemp(Op0); FreeTemp(Op1); + FreeTemp(Op2); if (*Error != SCRIPT_ENGINE_ERROR_FREE) { break; @@ -1957,7 +3308,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B Op0 = Pop(MatchedStack); Op0Symbol = ToSymbol(Op0, Error); - Temp = NewTemp(Error, CurrentFunctionSymbol); + Temp = NewTemp(Error); Push(MatchedStack, Temp); TempSymbol = ToSymbol(Temp, Error); @@ -1986,7 +3337,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B break; } - Temp = NewTemp(Error, CurrentFunctionSymbol); + Temp = NewTemp(Error); Push(MatchedStack, Temp); TempSymbol = ToSymbol(Temp, Error); PushSymbol(CodeBuffer, TempSymbol); @@ -1997,6 +3348,39 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B FreeTemp(Op0); FreeTemp(Op1); } + + else if (IsType15Func(Operator)) + { + PushSymbol(CodeBuffer, OperatorSymbol); + Op0 = Pop(MatchedStack); + Op0Symbol = ToSymbol(Op0, Error); + + Op1 = Pop(MatchedStack); + Op1Symbol = ToSymbol(Op1, Error); + + Op2 = Pop(MatchedStack); + Op2Symbol = ToSymbol(Op2, Error); + + PushSymbol(CodeBuffer, Op0Symbol); + PushSymbol(CodeBuffer, Op1Symbol); + PushSymbol(CodeBuffer, Op2Symbol); + + Temp = NewTemp(Error); + Push(MatchedStack, Temp); + TempSymbol = ToSymbol(Temp, Error); + PushSymbol(CodeBuffer, TempSymbol); + + // + // Free the operand if it is a temp value + // + FreeTemp(Op0); + FreeTemp(Op1); + FreeTemp(Op2); + if (*Error != SCRIPT_ENGINE_ERROR_FREE) + { + break; + } + } else { *Error = SCRIPT_ENGINE_ERROR_UNHANDLED_SEMANTIC_RULE; @@ -2013,7 +3397,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B printf("\n"); printf("Code Buffer:\n"); - PrintSymbolBuffer(CodeBuffer); + PrintSymbolBuffer((PVOID)CodeBuffer); printf("------------------------------------------\n\n"); #endif @@ -2052,7 +3436,7 @@ CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_B * @return UINT64 */ UINT64 -BooleanExpressionExtractEnd(char * str, BOOL * WaitForWaitStatementBooleanExpression, PTOKEN CurrentIn) +BooleanExpressionExtractEnd(char * str, BOOL * WaitForWaitStatementBooleanExpression, PSCRIPT_ENGINE_TOKEN CurrentIn) { UINT64 BooleanExpressionSize = 0; if (*WaitForWaitStatementBooleanExpression) @@ -2105,17 +3489,16 @@ BooleanExpressionExtractEnd(char * str, BOOL * WaitForWaitStatementBooleanExpres void ScriptEngineBooleanExpresssionParse( UINT64 BooleanExpressionSize, - PTOKEN FirstToken, - PTOKEN_LIST MatchedStack, - PSYMBOL_BUFFER UserDefinedFunctions, + PSCRIPT_ENGINE_TOKEN FirstToken, + PSCRIPT_ENGINE_TOKEN_LIST MatchedStack, PSYMBOL_BUFFER CodeBuffer, char * str, char * c, PSCRIPT_ENGINE_ERROR_TYPE Error) { - PTOKEN_LIST Stack = NewTokenList(); + PSCRIPT_ENGINE_TOKEN_LIST Stack = NewTokenList(); - PTOKEN State = NewToken(STATE_ID, "0"); + PSCRIPT_ENGINE_TOKEN State = NewToken(STATE_ID, "0"); Push(Stack, State); #ifdef _SCRIPT_ENGINE_LALR_DBG_EN @@ -2131,15 +3514,15 @@ ScriptEngineBooleanExpresssionParse( // // End of File Token // - PTOKEN EndToken = NewToken(END_OF_STACK, "$"); + PSCRIPT_ENGINE_TOKEN EndToken = NewToken(END_OF_STACK, "$"); - PTOKEN CurrentIn = CopyToken(FirstToken); + PSCRIPT_ENGINE_TOKEN CurrentIn = CopyToken(FirstToken); - PTOKEN TopToken = NULL; - PTOKEN Lhs = NULL; - PTOKEN Temp = NULL; - PTOKEN Operand = NULL; - PTOKEN SemanticRule = NULL; + PSCRIPT_ENGINE_TOKEN TopToken = NULL; + PSCRIPT_ENGINE_TOKEN Lhs = NULL; + PSCRIPT_ENGINE_TOKEN Temp = NULL; + PSCRIPT_ENGINE_TOKEN Operand = NULL; + PSCRIPT_ENGINE_TOKEN SemanticRule = NULL; int Action = INVALID; int StateId = 0; @@ -2147,7 +3530,7 @@ ScriptEngineBooleanExpresssionParse( int InputPointer = 0; int RhsSize = 0; unsigned int InputIdxTemp; - char Ctemp; + CHAR CTemp; while (1) { @@ -2192,13 +3575,13 @@ ScriptEngineBooleanExpresssionParse( Push(Stack, State); InputIdxTemp = InputIdx; - Ctemp = *c; + CTemp = *c; CurrentIn = Scan(str, c); if (InputIdx - 1 > BooleanExpressionSize) { InputIdx = InputIdxTemp; - *c = Ctemp; + *c = CTemp; RemoveToken(&CurrentIn); @@ -2208,9 +3591,9 @@ ScriptEngineBooleanExpresssionParse( else if (Action < 0) // Reduce { StateId = -Action; - Lhs = (PTOKEN)&LalrLhs[StateId - 1]; + Lhs = (PSCRIPT_ENGINE_TOKEN)&LalrLhs[StateId - 1]; RhsSize = LalrGetRhsSize(StateId - 1); - SemanticRule = (PTOKEN)&LalrSemanticRules[StateId - 1]; + SemanticRule = (PSCRIPT_ENGINE_TOKEN)&LalrSemanticRules[StateId - 1]; for (int i = 0; i < 2 * RhsSize; i++) { @@ -2239,7 +3622,7 @@ ScriptEngineBooleanExpresssionParse( } else { - CodeGen(MatchedStack, UserDefinedFunctions, CodeBuffer, SemanticRule, Error); + CodeGen(MatchedStack, CodeBuffer, SemanticRule, Error, &str); if (*Error != SCRIPT_ENGINE_ERROR_FREE) { break; @@ -2252,7 +3635,7 @@ ScriptEngineBooleanExpresssionParse( Goto = LalrGotoTable[StateId][LalrGetNonTerminalId(Lhs)]; - PTOKEN LhsCopy = CopyToken(Lhs); + PSCRIPT_ENGINE_TOKEN LhsCopy = CopyToken(Lhs); char buffer[20] = {0}; sprintf(buffer, "%d", Goto); @@ -2293,10 +3676,9 @@ NewSymbol(void) return NULL; } - Symbol->Value = 0; - Symbol->Len = 0; - Symbol->Type = 0; - Symbol->VariableType = 0; + Symbol->Value = 0; + Symbol->Len = 0; + Symbol->Type = 0; return Symbol; } @@ -2307,10 +3689,10 @@ NewSymbol(void) * @return PSYMBOL */ PSYMBOL -NewStringSymbol(PTOKEN Token) +NewStringSymbol(PSCRIPT_ENGINE_TOKEN Token) { PSYMBOL Symbol; - int BufferSize = (3 * sizeof(unsigned long long) + Token->Len) / sizeof(SYMBOL) + 1; + int BufferSize = (SIZE_SYMBOL_WITHOUT_LEN + Token->Len) / sizeof(SYMBOL) + 1; Symbol = (PSYMBOL)calloc(sizeof(SYMBOL), BufferSize); if (Symbol == NULL) @@ -2323,8 +3705,7 @@ NewStringSymbol(PTOKEN Token) memcpy(&Symbol->Value, Token->Value, Token->Len); SetType(&Symbol->Type, SYMBOL_STRING_TYPE); - Symbol->Len = Token->Len; - Symbol->VariableType = 0; + Symbol->Len = Token->Len; return Symbol; } @@ -2335,10 +3716,10 @@ NewStringSymbol(PTOKEN Token) * @return PSYMBOL */ PSYMBOL -NewWstringSymbol(PTOKEN Token) +NewWstringSymbol(PSCRIPT_ENGINE_TOKEN Token) { PSYMBOL Symbol; - int BufferSize = (3 * sizeof(unsigned long long) + Token->Len) / sizeof(SYMBOL) + 1; + int BufferSize = (SIZE_SYMBOL_WITHOUT_LEN + Token->Len) / sizeof(SYMBOL) + 1; Symbol = (PSYMBOL)malloc(BufferSize * sizeof(SYMBOL)); if (Symbol == NULL) @@ -2351,47 +3732,7 @@ NewWstringSymbol(PTOKEN Token) memcpy(&Symbol->Value, Token->Value, Token->Len); SetType(&Symbol->Type, SYMBOL_WSTRING_TYPE); - Symbol->Len = Token->Len; - Symbol->VariableType = 0; - return Symbol; -} - -/** - * @brief - * - * @return PSYMBOL - */ -PSYMBOL -NewFunctionSymbol(char * FunctionName, VARIABLE_TYPE * VariableType) -{ - int Length = (int)strlen(FunctionName); - PSYMBOL Symbol = NewSymbol(); - Symbol = (PSYMBOL)malloc(sizeof(SYMBOL)); - - if (Symbol == NULL) - { - // - // There was an error allocating buffer - // - free(Symbol); - return NULL; - } - - Symbol->Value = (unsigned long long)calloc(Length + 1, sizeof(char)); - - if (Symbol->Value == 0ull) - { - // - // There was an error allocating buffer - // - free(Symbol); - return NULL; - } - - memcpy((void *)Symbol->Value, FunctionName, Length); - Symbol->Len = Length; - Symbol->Type = SYMBOL_USER_DEFINED_FUNCTION_TYPE; - Symbol->VariableType = (long long unsigned)VariableType; + Symbol->Len = Token->Len; return Symbol; } @@ -2410,7 +3751,7 @@ NewFunctionSymbol(char * FunctionName, VARIABLE_TYPE * VariableType) unsigned int GetSymbolHeapSize(PSYMBOL Symbol) { - int Temp = (3 * sizeof(unsigned long long) + (int)Symbol->Len) / sizeof(SYMBOL) + 1; + int Temp = (SIZE_SYMBOL_WITHOUT_LEN + (int)Symbol->Len) / sizeof(SYMBOL) + 1; return Temp; } @@ -2430,18 +3771,36 @@ RemoveSymbol(PSYMBOL * Symbol) /** * @brief Prints symbol * - * @param Symbol + * @param PVOID */ void -PrintSymbol(PSYMBOL Symbol) +PrintSymbol(PVOID Symbol) { - if (Symbol->Type == SYMBOL_STRING_TYPE) + PSYMBOL Sym = (PSYMBOL)Symbol; + + if (Sym->Type & 0xffffffff00000000) { - printf("Type:%llx, Value:0x%p\n", Symbol->Type, &Symbol->Value); + printf("Type = @VARGSTART\n"); + return; + } + + printf("Type = %s, ", SymbolTypeNames[Sym->Type]); + + if (Sym->Type == SYMBOL_SEMANTIC_RULE_TYPE) + { + printf("Value = %s\n", FunctionNames[Sym->Value]); + } + else if (Sym->Type == SYMBOL_STRING_TYPE) + { + printf("Value = %s\n", (char *)&Sym->Value); + } + else if (Sym->Type == SYMBOL_WSTRING_TYPE) + { + printf("Value = %ls\n", (wchar_t *)&Sym->Value); } else { - printf("Type:%llx, Value:0x%llx\n", Symbol->Type, Symbol->Value); + printf("Value = %lld\n", Sym->Value); } } @@ -2453,7 +3812,7 @@ PrintSymbol(PSYMBOL Symbol) * @return PSYMBOL */ PSYMBOL -ToSymbol(PTOKEN Token, PSCRIPT_ENGINE_ERROR_TYPE Error) +ToSymbol(PSCRIPT_ENGINE_TOKEN Token, PSCRIPT_ENGINE_ERROR_TYPE Error) { PSYMBOL Symbol = NewSymbol(); switch (Token->Type) @@ -2464,9 +3823,20 @@ ToSymbol(PTOKEN Token, PSCRIPT_ENGINE_ERROR_TYPE Error) return Symbol; case LOCAL_ID: + { Symbol->Value = GetLocalIdentifierVal(Token); - SetType(&Symbol->Type, SYMBOL_LOCAL_ID_TYPE); + + if (((VARIABLE_TYPE *)Token->VariableType)->Kind == TY_ARRAY) + { + SetType(&Symbol->Type, SYMBOL_REFERENCE_LOCAL_ID_TYPE); + } + else + { + SetType(&Symbol->Type, SYMBOL_LOCAL_ID_TYPE); + } + return Symbol; + } case DECIMAL: Symbol->Value = DecimalToInt(Token->Value); @@ -2504,13 +3874,18 @@ ToSymbol(PTOKEN Token, PSCRIPT_ENGINE_ERROR_TYPE Error) return Symbol; case TEMP: - Symbol->Value = DecimalToInt(Token->Value); - SetType(&Symbol->Type, SYMBOL_TEMP_TYPE); - return Symbol; - case STACK_TEMP: Symbol->Value = DecimalToInt(Token->Value); - SetType(&Symbol->Type, SYMBOL_STACK_TEMP_TYPE); + + if (((VARIABLE_TYPE *)Token->VariableType)->Kind == TY_ARRAY) + { + SetType(&Symbol->Type, SYMBOL_REFERENCE_TEMP_TYPE); + } + else + { + SetType(&Symbol->Type, SYMBOL_TEMP_TYPE); + } + return Symbol; case STRING: @@ -2526,6 +3901,11 @@ ToSymbol(PTOKEN Token, PSCRIPT_ENGINE_ERROR_TYPE Error) SetType(&Symbol->Type, SYMBOL_FUNCTION_PARAMETER_ID_TYPE); return Symbol; + case DEFERENCE_TEMP: + Symbol->Value = DecimalToInt(Token->Value); + SetType(&Symbol->Type, SYMBOL_DEREFERENCE_TEMP_TYPE); + return Symbol; + default: *Error = SCRIPT_ENGINE_ERROR_UNRESOLVED_VARIABLE; Symbol->Type = INVALID; @@ -2566,11 +3946,13 @@ NewSymbolBuffer(void) * @param SymbolBuffer */ void -RemoveSymbolBuffer(PSYMBOL_BUFFER SymbolBuffer) +RemoveSymbolBuffer(PVOID SymbolBuffer) { - free(SymbolBuffer->Message); - free(SymbolBuffer->Head); - free(SymbolBuffer); + PSYMBOL_BUFFER SymBuf = (PSYMBOL_BUFFER)SymbolBuffer; + + free(SymBuf->Message); + free(SymBuf->Head); + free(SymBuf); } /** @@ -2698,19 +4080,20 @@ PushSymbol(PSYMBOL_BUFFER SymbolBuffer, const PSYMBOL Symbol) * @param SymbolBuffer */ void -PrintSymbolBuffer(const PSYMBOL_BUFFER SymbolBuffer) +PrintSymbolBuffer(const PVOID SymbolBuffer) { - PSYMBOL Symbol; - for (unsigned int i = 0; i < SymbolBuffer->Pointer;) + PSYMBOL_BUFFER SymBuff = (PSYMBOL_BUFFER)SymbolBuffer; + PSYMBOL Symbol; + printf("CodeBuffer:\n"); + for (unsigned int i = 0; i < SymBuff->Pointer;) { - Symbol = SymbolBuffer->Head + i; - - printf("%8x:", i); - PrintSymbol(Symbol); + Symbol = SymBuff->Head + i; + printf("Address = %d, ", i); + PrintSymbol((PVOID)Symbol); if (Symbol->Type == SYMBOL_STRING_TYPE || Symbol->Type == SYMBOL_WSTRING_TYPE) { - int temp = GetSymbolHeapSize(Symbol); - i += temp; + INT Temp = GetSymbolHeapSize(Symbol); + i += Temp; } else { @@ -2728,6 +4111,9 @@ PrintSymbolBuffer(const PSYMBOL_BUFFER SymbolBuffer) unsigned long long int RegisterToInt(char * str) { + // + // Check for register names + // for (int i = 0; i < REGISTER_MAP_LIST_LENGTH; i++) { if (!strcmp(str, RegisterMapList[i].Name)) @@ -2735,6 +4121,85 @@ RegisterToInt(char * str) return RegisterMapList[i].Type; } } + + // + // Check for hwdbg register names + // Check if the registers start with '@hw_portX' or '@hw_pinX' + // + if (g_HwdbgInstanceInfoIsValid) + { + const char * Ptr; + UINT32 Num = 0; + + // + // Check for "hw_pin" + // + if (strncmp(str, "hw_pin", 6) == 0) + { + Ptr = str + 6; + if (*Ptr == '\0') + { + return INVALID; // No number present + } + while (*Ptr) + { + if (!isdigit((unsigned char)*Ptr)) + { + return INVALID; // Not a valid decimal number + } + Ptr++; + } + Num = atoi(str + 6); + + // + // port numbers start after the latest pin number + // + if (Num >= g_HwdbgInstanceInfo.numberOfPins) + { + return INVALID; // Invalid "hw_pinX" + } + else + { + return Num; // Valid "hw_pinX" + } + } + + // + // Check for "hw_port" + // + if (strncmp(str, "hw_port", 7) == 0) + { + Ptr = str + 7; + if (*Ptr == '\0') + { + return INVALID; // No number present + } + while (*Ptr) + { + if (!isdigit((unsigned char)*Ptr)) + { + return INVALID; // Not a valid decimal number + } + + Ptr++; + } + + Num = atoi(str + 7); + + if (Num >= g_HwdbgInstanceInfo.numberOfPorts) + { + return INVALID; // Invalid "hw_portX" + } + else + { + return Num + g_HwdbgInstanceInfo.numberOfPins; // Valid "hw_portX" + } + } + } + + // + // Not a valid register name + // return INVALID; } @@ -2894,12 +4359,12 @@ HandleError(PSCRIPT_ENGINE_ERROR_TYPE Error, char * str) * @return int */ int -GetGlobalIdentifierVal(PTOKEN Token) +GetGlobalIdentifierVal(PSCRIPT_ENGINE_TOKEN Token) { - PTOKEN CurrentToken; - for (uintptr_t i = 0; i < IdTable->Pointer; i++) + PSCRIPT_ENGINE_TOKEN CurrentToken; + for (uintptr_t i = 0; i < GlobalIdTable->Pointer; i++) { - CurrentToken = *(IdTable->Head + i); + CurrentToken = *(GlobalIdTable->Head + i); if (!strcmp(Token->Value, CurrentToken->Value)) { return (int)i; @@ -2915,15 +4380,15 @@ GetGlobalIdentifierVal(PTOKEN Token) * @return int */ int -GetLocalIdentifierVal(PTOKEN Token) +GetLocalIdentifierVal(PSCRIPT_ENGINE_TOKEN Token) { - PTOKEN CurrentToken; - for (uintptr_t i = 0; i < IdTable->Pointer; i++) + PSCRIPT_ENGINE_TOKEN CurrentToken; + for (uintptr_t i = 0; i < ((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->IdTable)->Pointer; i++) { - CurrentToken = *(IdTable->Head + i); + CurrentToken = *(((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->IdTable)->Head + i); if (!strcmp(Token->Value, CurrentToken->Value)) { - return (int)i; + return (int)CurrentToken->VariableMemoryIdx; } } return -1; @@ -2936,11 +4401,50 @@ GetLocalIdentifierVal(PTOKEN Token) * @return int */ int -NewGlobalIdentifier(PTOKEN Token) +NewGlobalIdentifier(PSCRIPT_ENGINE_TOKEN Token) { - PTOKEN CopiedToken = CopyToken(Token); - IdTable = Push(IdTable, CopiedToken); - return IdTable->Pointer - 1; + PSCRIPT_ENGINE_TOKEN CopiedToken = CopyToken(Token); + GlobalIdTable = Push(GlobalIdTable, CopiedToken); + return GlobalIdTable->Pointer - 1; +} + +/** + * @brief + * + * @param Token + */ +VOID +SetGlobalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token, VARIABLE_TYPE * VariableType) +{ + PSCRIPT_ENGINE_TOKEN CurrentToken; + for (uintptr_t i = 0; i < GlobalIdTable->Pointer; i++) + { + CurrentToken = *(GlobalIdTable->Head + i); + if (!strcmp(Token->Value, CurrentToken->Value)) + { + CurrentToken->VariableType = (VARIABLE_TYPE *)VariableType; + } + } +} + +/** + * @brief + * + * @param Token + */ +VARIABLE_TYPE * +GetGlobalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token) +{ + PSCRIPT_ENGINE_TOKEN CurrentToken; + for (uintptr_t i = 0; i < GlobalIdTable->Pointer; i++) + { + CurrentToken = *(GlobalIdTable->Head + i); + if (!strcmp(Token->Value, CurrentToken->Value)) + { + return CurrentToken->VariableType; + } + } + return 0; } /** @@ -2949,41 +4453,84 @@ NewGlobalIdentifier(PTOKEN Token) * @param Token * @return int */ -int -NewLocalIdentifier(PTOKEN Token) +unsigned long long +NewLocalIdentifier(PSCRIPT_ENGINE_TOKEN Token, unsigned int VariableSize) { - PTOKEN CopiedToken = CopyToken(Token); - IdTable = Push(IdTable, CopiedToken); - return IdTable->Pointer - 1; + PSCRIPT_ENGINE_TOKEN CopiedToken = CopyToken(Token); + unsigned int VariableNumber = ((VariableSize + 8 - 1) & ~(8 - 1)) / 8; + CopiedToken->VariableMemoryIdx = CurrentUserDefinedFunction->LocalVariableNumber; + CurrentUserDefinedFunction->LocalVariableNumber += VariableNumber; + Push(((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->IdTable), CopiedToken); + return CopiedToken->VariableMemoryIdx; } /** * @brief * * @param Token - * @return int */ -int -NewFunctionParameterIdentifier(PTOKEN Token) +VOID +SetLocalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token, VARIABLE_TYPE * VariableType) { - PTOKEN CopiedToken = CopyToken(Token); - FunctionParameterIdTable = Push(FunctionParameterIdTable, CopiedToken); - return FunctionParameterIdTable->Pointer - 1; -} - -/** - * @brief - * - * @param Token - * @return int - */ -int -GetFunctionParameterIdentifier(PTOKEN Token) -{ - PTOKEN CurrentToken; - for (uintptr_t i = 0; i < FunctionParameterIdTable->Pointer; i++) + PSCRIPT_ENGINE_TOKEN CurrentToken; + for (uintptr_t i = 0; i < ((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->IdTable)->Pointer; i++) { - CurrentToken = *(FunctionParameterIdTable->Head + i); + CurrentToken = *(((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->IdTable)->Head + i); + if (!strcmp(Token->Value, CurrentToken->Value)) + { + CurrentToken->VariableType = VariableType; + } + } +} + +/** + * @brief + * + * @param Token + * @return VARIABLE_TYPE* + */ +VARIABLE_TYPE * +GetLocalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token) +{ + PSCRIPT_ENGINE_TOKEN CurrentToken; + for (uintptr_t i = 0; i < ((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->IdTable)->Pointer; i++) + { + CurrentToken = *(((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->IdTable)->Head + i); + if (!strcmp(Token->Value, CurrentToken->Value)) + { + return CurrentToken->VariableType; + } + } + return 0; +} + +/** + * @brief + * + * @param Token + * @return int + */ +int +NewFunctionParameterIdentifier(PSCRIPT_ENGINE_TOKEN Token) +{ + PSCRIPT_ENGINE_TOKEN CopiedToken = CopyToken(Token); + Push(((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->FunctionParameterIdTable), CopiedToken); + return ((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->FunctionParameterIdTable)->Pointer - 1; +} + +/** + * @brief + * + * @param Token + * @return int + */ +int +GetFunctionParameterIdentifier(PSCRIPT_ENGINE_TOKEN Token) +{ + PSCRIPT_ENGINE_TOKEN CurrentToken; + for (uintptr_t i = 0; i < ((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->FunctionParameterIdTable)->Pointer; i++) + { + CurrentToken = *(((PSCRIPT_ENGINE_TOKEN_LIST)CurrentUserDefinedFunction->FunctionParameterIdTable)->Head + i); if (!strcmp(Token->Value, CurrentToken->Value)) { return (int)i; @@ -2992,6 +4539,28 @@ GetFunctionParameterIdentifier(PTOKEN Token) return -1; } +/** + * @brief + * + * @param Token + * @return PUSER_DEFINED_FUNCTION_NODE + */ +PUSER_DEFINED_FUNCTION_NODE +GetUserDefinedFunctionNode(PSCRIPT_ENGINE_TOKEN Token) +{ + PUSER_DEFINED_FUNCTION_NODE Node = UserDefinedFunctionHead; + while (Node) + { + if (!strcmp((const char *)Token->Value, Node->Name)) + { + return Node; + break; + } + Node = Node->NextNode; + } + return 0; +} + /** * @brief Returns the size of Right Hand Side (RHS) of a rule * @@ -3020,7 +4589,7 @@ LalrGetRhsSize(int RuleId) * @return BOOL */ BOOL -LalrIsOperandType(PTOKEN Token) +LalrIsOperandType(PSCRIPT_ENGINE_TOKEN Token) { if (Token->Type == GLOBAL_ID) { @@ -3042,6 +4611,10 @@ LalrIsOperandType(PTOKEN Token) { return TRUE; } + else if (Token->Type == FUNCTION_ID) + { + return TRUE; + } else if (Token->Type == DECIMAL) { return TRUE; @@ -3081,13 +4654,218 @@ LalrIsOperandType(PTOKEN Token) return FALSE; } -PSYMBOL_BUFFER -GetStackBuffer() +/** + * @brief Set hwdbg instance info for the script engine + * + * @param InstancInfo + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineSetHwdbgInstanceInfo(HWDBG_INSTANCE_INFORMATION * InstancInfo) { - PSYMBOL_BUFFER StackBuffer = NewSymbolBuffer(); - for (int i = 0; i < 128; i++) - { - PushSymbol(StackBuffer, NewSymbol()); - } - return StackBuffer; + // + // Copy the instance info into the global variable + // + memcpy(&g_HwdbgInstanceInfo, InstancInfo, sizeof(HWDBG_INSTANCE_INFORMATION)); + + // + // Indicate that the instance info is valid + // + g_HwdbgInstanceInfoIsValid = TRUE; + + return TRUE; +} + +/** + * @brief Script Engine get number of operands + * + * @param FuncType + * @param NumberOfGetOperands + * @param NumberOfSetOperands + * @param BOOLEAN Whether the function is defined or not + */ +BOOLEAN +FuncGetNumberOfOperands(UINT64 FuncType, UINT32 * NumberOfGetOperands, UINT32 * NumberOfSetOperands) +{ + BOOLEAN Result = FALSE; + + switch (FuncType) + { + case FUNC_INC: + + *NumberOfGetOperands = 1; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_DEC: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_OR: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_XOR: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_AND: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_ASL: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_ADD: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_SUB: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_MUL: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_DIV: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_MOD: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_GT: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_LT: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_EGT: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_ELT: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_EQUAL: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_NEQ: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + case FUNC_JMP: + + *NumberOfGetOperands = 1; + *NumberOfSetOperands = 0; + Result = TRUE; + + break; + + case FUNC_JZ: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 0; + Result = TRUE; + + break; + + case FUNC_JNZ: + + *NumberOfGetOperands = 2; + *NumberOfSetOperands = 0; + Result = TRUE; + + break; + + case FUNC_MOV: + + *NumberOfGetOperands = 1; + *NumberOfSetOperands = 1; + Result = TRUE; + + break; + + default: + // + // Not defined + // + Result = FALSE; + break; + } + + return Result; } diff --git a/hyperdbg/script-engine/code/script_include.c b/hyperdbg/script-engine/code/script_include.c new file mode 100644 index 00000000..f24d57ef --- /dev/null +++ b/hyperdbg/script-engine/code/script_include.c @@ -0,0 +1,199 @@ +/** + * @file script_include.c + * @author M.H. Gholamrezaei (mh@hyperdbg.org) + * + * @brief Include file path resolution and parsing routines + * @details + * @version 0.1 + * @date 2020-10-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" +#include "script_include.h" + +/** + * @brief Trims leading whitespace from a string in-place + * + * @param Str the string to left-trim + * @return VOID + */ +static VOID +Ltrim(char * Str) +{ + char * P = Str; + + while (*P && isspace((unsigned char)*P)) + P++; + + if (P != Str) + memmove(Str, P, strlen(P) + 1); +} + +/** + * @brief Trims trailing whitespace from a string in-place + * + * @param Str the string to right-trim + * @return VOID + */ +static VOID +Rtrim(char * Str) +{ + char * End = Str + strlen(Str); + + while (End > Str && isspace((unsigned char)End[-1])) + End--; + + *End = '\0'; +} + +/** + * @brief Trims leading and trailing whitespace from a string in-place + * + * @param Str the string to trim + * @return VOID + */ +static VOID +Trim(char * Str) +{ + Ltrim(Str); + Rtrim(Str); +} + +/** + * @brief Inserts a string into another string at a given index + * + * @param Str the original string (will be reallocated) + * @param InputIdx the index at which to insert + * @param Buf the string to insert + * @return char * the new string, or the original on allocation failure + */ +char * +InsertStrNew(char * Str, int InputIdx, const char * Buf) +{ + SIZE_T LenStr = strlen(Str); + SIZE_T LenBuf = strlen(Buf); + + if (InputIdx < 0 || (SIZE_T)InputIdx > LenStr) + return Str; + + char * NewStr = (char *)realloc(Str, LenStr + LenBuf + 1); + if (!NewStr) + return Str; + + memmove(NewStr + InputIdx + LenBuf, + NewStr + InputIdx, + LenStr - InputIdx + 1); + + memcpy(NewStr + InputIdx, Buf, LenBuf); + + return NewStr; +} + +/** + * @brief Checks whether a file path is absolute + * + * @param Path the file path to check + * @return BOOLEAN TRUE if the path is absolute, FALSE otherwise + */ +BOOLEAN +IsAbsolutePath(const char * Path) +{ + if (!Path || !Path[0]) + return FALSE; + + if (strlen(Path) >= 3 && + ((Path[1] == ':' && (Path[2] == '\\' || Path[2] == '/')))) + return TRUE; + + return FALSE; +} + +/** + * @brief Resolves an include file path to a full absolute path + * + * @param IncludeFilePath the include file path (relative or absolute) + * @param OutPath the buffer to receive the resolved path + * @return VOID + */ +VOID +ResolveIncludePath(const char * IncludeFilePath, char * OutPath) +{ + if (IsAbsolutePath(IncludeFilePath)) + { + strncpy(OutPath, IncludeFilePath, MAX_PATH_LEN - 1); + OutPath[MAX_PATH_LEN - 1] = '\0'; + return; + } + + CHAR ExeDir[MAX_PATH_LEN]; + GetModuleFileNameA(NULL, ExeDir, MAX_PATH_LEN); + + char * P = strrchr(ExeDir, '\\'); + if (P) + *P = '\0'; + + snprintf( + OutPath, + MAX_PATH_LEN, + "%s\\%s", + ExeDir, + IncludeFilePath); +} + +/** + * @brief Checks whether a file exists at the given path + * + * @param Path the file path to check + * @return BOOLEAN TRUE if the file exists, FALSE otherwise + */ +BOOLEAN +FileExists(const char * Path) +{ + DWORD Attr = GetFileAttributesA(Path); + + if (Attr == INVALID_FILE_ATTRIBUTES) + return FALSE; + + if (Attr & FILE_ATTRIBUTE_DIRECTORY) + return FALSE; + + return TRUE; +} + +/** + * @brief Reads and parses an include file into a buffer + * + * @param IncludeFile the path to the include file + * @param Buffer pointer to receive the allocated file content buffer + * @return BOOLEAN TRUE if the file was parsed successfully, FALSE otherwise + */ +BOOLEAN +ParseIncludeFile(char * IncludeFile, char ** Buffer) +{ + FILE * Fp = fopen(IncludeFile, "r"); + fseek(Fp, 0, SEEK_END); + LONG Size = ftell(Fp); + rewind(Fp); + *Buffer = calloc(Size + 1, 1); + fread(*Buffer, 1, Size, Fp); + (*Buffer)[Size] = '\0'; + Trim(*Buffer); + SIZE_T Len = strlen(*Buffer); + if ((*Buffer)[0] == '?' && + (*Buffer)[1] == ' ' && + (*Buffer)[2] == '{' && + (*Buffer)[Len - 1] == '}') + { + memmove( + *Buffer, + *Buffer + 3, + Len - 3 + 1); + + (*Buffer)[strlen(*Buffer) - 1] = '\0'; + + return TRUE; + } + return FALSE; +} diff --git a/hyperdbg/script-engine/code/type.c b/hyperdbg/script-engine/code/type.c index a087ded8..b0719061 100644 --- a/hyperdbg/script-engine/code/type.c +++ b/hyperdbg/script-engine/code/type.c @@ -1,3 +1,15 @@ +/** + * @file type.c + * @author M.H. Gholamrezaei (mh@hyperdbg.org) + * + * @brief Routines for handling variable types + * @details + * @version 0.1 + * @date 2020-10-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ #include "pch.h" VARIABLE_TYPE * VARIABLE_TYPE_UNKNOWN = &(VARIABLE_TYPE) {TY_UNKNOWN}; @@ -20,12 +32,13 @@ VARIABLE_TYPE * VARIABLE_TYPE_DOUBLE = &(VARIABLE_TYPE) {TY_DOUBLE, 8, 8}; VARIABLE_TYPE * VARIABLE_TYPE_LDOUBLE = &(VARIABLE_TYPE) {TY_LDOUBLE, 16, 16}; /** - * @brief Return a variable type + * @brief Return a variable type based on the token stack * - * @param str + * @param PtokenStack the token stack containing type tokens + * @return VARIABLE_TYPE * pointer to the resolved variable type */ VARIABLE_TYPE * -HandleType(PTOKEN_LIST PtokenStack) +HandleType(PSCRIPT_ENGINE_TOKEN_LIST PtokenStack) { enum { @@ -42,55 +55,55 @@ HandleType(PTOKEN_LIST PtokenStack) ENUM_UNSIGNED = 1 << 18, }; - VARIABLE_TYPE * Result = VARIABLE_TYPE_UNKNOWN; - int Counter = 0; - PTOKEN TopToken = NULL; + VARIABLE_TYPE * Result = VARIABLE_TYPE_UNKNOWN; + int Counter = 0; + PSCRIPT_ENGINE_TOKEN TopToken = NULL; while (PtokenStack->Pointer > 0) { TopToken = Pop(PtokenStack); - if (TopToken->Type != INPUT_VARIABLE_TYPE) + if (TopToken->Type != SCRIPT_VARIABLE_TYPE) { Push(PtokenStack, TopToken); break; } - if (!strcmp(TopToken->Value, "@VOID")) + if (!strcmp(TopToken->Value, "void")) { Counter += ENUM_VOID; } - else if (!strcmp(TopToken->Value, "@BOOL")) + else if (!strcmp(TopToken->Value, "bool")) { Counter += ENUM_BOOL; } - else if (!strcmp(TopToken->Value, "@CHAR")) + else if (!strcmp(TopToken->Value, "char")) { Counter += ENUM_CHAR; } - else if (!strcmp(TopToken->Value, "@SHORT")) + else if (!strcmp(TopToken->Value, "short")) { Counter += ENUM_SHORT; } - else if (!strcmp(TopToken->Value, "@INT")) + else if (!strcmp(TopToken->Value, "int")) { Counter += ENUM_INT; } - else if (!strcmp(TopToken->Value, "@LONG")) + else if (!strcmp(TopToken->Value, "long")) { Counter += ENUM_LONG; } - else if (!strcmp(TopToken->Value, "@FLOAT")) + else if (!strcmp(TopToken->Value, "float")) { Counter += ENUM_FLOAT; } - else if (!strcmp(TopToken->Value, "@DOUBLE")) + else if (!strcmp(TopToken->Value, "double")) { Counter += ENUM_DOUBLE; } - else if (!strcmp(TopToken->Value, "@SIGNED")) + else if (!strcmp(TopToken->Value, "signed")) { Counter |= ENUM_SIGNED; } - else if (!strcmp(TopToken->Value, "@UNSIGNED")) + else if (!strcmp(TopToken->Value, "unsigned")) { Counter |= ENUM_UNSIGNED; } @@ -162,4 +175,27 @@ HandleType(PTOKEN_LIST PtokenStack) } } return Result; -} \ No newline at end of file +} + +/** + * @brief Returns the common variable type between two types + * + * @param Ty1 the first variable type + * @param Ty2 the second variable type + * @return VARIABLE_TYPE * pointer to the common variable type + */ +VARIABLE_TYPE * +GetCommonVariableType(VARIABLE_TYPE * Ty1, VARIABLE_TYPE * Ty2) +{ + // if (Ty1->Kind == TY_ARRAY) + //{ + // return Ty1; + // } + + // if (Ty2->Kind == TY_ARRAY) + //{ + // return Ty2; + // } + + return VARIABLE_TYPE_LONG; +} diff --git a/hyperdbg/script-engine/header/common.h b/hyperdbg/script-engine/header/common.h index f555e997..c3431088 100644 --- a/hyperdbg/script-engine/header/common.h +++ b/hyperdbg/script-engine/header/common.h @@ -33,7 +33,7 @@ initial size of symbol buffer /** * @brief enumerates possible types for token */ -typedef enum TOKEN_TYPE +typedef enum _SCRIPT_ENGINE_TOKEN_TYPE { LOCAL_ID, LOCAL_UNRESOLVED_ID, @@ -57,113 +57,117 @@ typedef enum TOKEN_TYPE TEMP, STRING, WSTRING, - INPUT_VARIABLE_TYPE, - HANDLED_VARIABLE_TYPE, - FUNCTION_TYPE, + FUNCTION_ID, FUNCTION_PARAMETER_ID, - STACK_TEMP, + SCRIPT_VARIABLE_TYPE, + DEFERENCE_TEMP, UNKNOWN -} TOKEN_TYPE; +} SCRIPT_ENGINE_TOKEN_TYPE; /** * @brief read tokens from input stored in this structure */ -typedef struct _TOKEN +typedef struct _SCRIPT_ENGINE_TOKEN { - TOKEN_TYPE Type; - char * Value; - unsigned int Len; - unsigned int MaxLen; -} TOKEN, *PTOKEN; + SCRIPT_ENGINE_TOKEN_TYPE Type; + char * Value; + unsigned int Len; + unsigned int MaxLen; + VARIABLE_TYPE * VariableType; + unsigned long long VariableMemoryIdx; +} SCRIPT_ENGINE_TOKEN, *PSCRIPT_ENGINE_TOKEN; /** * @brief this structure is a dynamic container of TOKENS */ -typedef struct _TOKEN_LIST +typedef struct _SCRIPT_ENGINE_TOKEN_LIST { - PTOKEN * Head; - unsigned int Pointer; - unsigned int Size; -} TOKEN_LIST, *PTOKEN_LIST; + PSCRIPT_ENGINE_TOKEN * Head; + unsigned int Pointer; + unsigned int Size; +} SCRIPT_ENGINE_TOKEN_LIST, *PSCRIPT_ENGINE_TOKEN_LIST; //////////////////////////////////////////////////// // PTOKEN related functions // //////////////////////////////////////////////////// -PTOKEN +PSCRIPT_ENGINE_TOKEN NewUnknownToken(void); -PTOKEN -NewToken(TOKEN_TYPE Type, char * Value); +PSCRIPT_ENGINE_TOKEN +NewToken(SCRIPT_ENGINE_TOKEN_TYPE Type, char * Value); -void -RemoveToken(PTOKEN * Token); +VOID +RemoveToken(PSCRIPT_ENGINE_TOKEN * Token); -void -PrintToken(PTOKEN Token); +VOID +PrintToken(PSCRIPT_ENGINE_TOKEN Token); -void -AppendByte(PTOKEN Token, char c); +VOID +AppendByte(PSCRIPT_ENGINE_TOKEN Token, CHAR c); -void -AppendWchar(PTOKEN Token, wchar_t c); +VOID +AppendWchar(PSCRIPT_ENGINE_TOKEN Token, wchar_t c); -PTOKEN -CopyToken(PTOKEN Token); +PSCRIPT_ENGINE_TOKEN +CopyToken(PSCRIPT_ENGINE_TOKEN Token); -PTOKEN -NewTemp(PSCRIPT_ENGINE_ERROR_TYPE, PSYMBOL); +PSCRIPT_ENGINE_TOKEN +NewTemp(PSCRIPT_ENGINE_ERROR_TYPE); -PTOKEN -NewStackTemp(PSCRIPT_ENGINE_ERROR_TYPE); +VOID +FreeTemp(PSCRIPT_ENGINE_TOKEN Temp); -void -FreeTemp(PTOKEN Temp); +VARIABLE_TYPE * +HandleType(PSCRIPT_ENGINE_TOKEN_LIST PtokenStack); -void -CleanTempList(void); +VARIABLE_TYPE * +GetCommonVariableType(VARIABLE_TYPE * Ty1, VARIABLE_TYPE * Ty2); //////////////////////////////////////////////////// -// TOKEN_LIST related functions // +// SCRIPT_ENGINE_TOKEN_LIST related functions // //////////////////////////////////////////////////// -PTOKEN_LIST +PSCRIPT_ENGINE_TOKEN_LIST NewTokenList(void); -void -RemoveTokenList(PTOKEN_LIST TokenList); +VOID +RemoveTokenList(PSCRIPT_ENGINE_TOKEN_LIST TokenList); -void -PrintTokenList(PTOKEN_LIST TokenList); +VOID +PrintTokenList(PSCRIPT_ENGINE_TOKEN_LIST TokenList); -PTOKEN_LIST -Push(PTOKEN_LIST TokenList, PTOKEN Token); +PSCRIPT_ENGINE_TOKEN_LIST +Push(PSCRIPT_ENGINE_TOKEN_LIST TokenList, PSCRIPT_ENGINE_TOKEN Token); -PTOKEN -Pop(PTOKEN_LIST TokenList); +PSCRIPT_ENGINE_TOKEN +Pop(PSCRIPT_ENGINE_TOKEN_LIST TokenList); -PTOKEN -Top(PTOKEN_LIST TokenList); +PSCRIPT_ENGINE_TOKEN +Top(PSCRIPT_ENGINE_TOKEN_LIST TokenList); + +PSCRIPT_ENGINE_TOKEN +TopIndexed(PSCRIPT_ENGINE_TOKEN_LIST TokenList, int Index); char -IsNoneTerminal(PTOKEN Token); +IsNoneTerminal(PSCRIPT_ENGINE_TOKEN Token); char -IsSemanticRule(PTOKEN Token); +IsSemanticRule(PSCRIPT_ENGINE_TOKEN Token); char -IsEqual(const PTOKEN Token1, const PTOKEN Token2); +IsEqual(const PSCRIPT_ENGINE_TOKEN Token1, const PSCRIPT_ENGINE_TOKEN Token2); int -GetNonTerminalId(PTOKEN Token); +GetNonTerminalId(PSCRIPT_ENGINE_TOKEN Token); int -GetTerminalId(PTOKEN Token); +GetTerminalId(PSCRIPT_ENGINE_TOKEN Token); int -LalrGetNonTerminalId(PTOKEN Token); +LalrGetNonTerminalId(PSCRIPT_ENGINE_TOKEN Token); int -LalrGetTerminalId(PTOKEN Token); +LalrGetTerminalId(PSCRIPT_ENGINE_TOKEN Token); //////////////////////////////////////////////////// // Util Functions // @@ -178,13 +182,16 @@ IsDecimal(char c); char IsLetter(char c); +char +IsUnderscore(char c); + char IsBinary(char c); char IsOctal(char c); -void +VOID SetType(unsigned long long * Val, unsigned char Type); unsigned long long @@ -202,7 +209,7 @@ OctalToInt(char * str); unsigned long long BinaryToInt(char * str); -void +VOID RotateLeftStringOnce(char * str); //////////////////////////////////////////////////// @@ -210,51 +217,83 @@ RotateLeftStringOnce(char * str); //////////////////////////////////////////////////// char -IsType1Func(PTOKEN Operator); +IsType1Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType2Func(PTOKEN Operator); +IsType2Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType4Func(PTOKEN Operator); +IsType4Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType5Func(PTOKEN Operator); +IsType5Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType6Func(PTOKEN Operator); +IsType6Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType7Func(PTOKEN Operator); +IsType7Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType8Func(PTOKEN Operator); +IsType8Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType9Func(PTOKEN Operator); +IsType9Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType10Func(PTOKEN Operator); +IsType10Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType11Func(PTOKEN Operator); +IsType11Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType12Func(PTOKEN Operator); +IsType12Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType13Func(PTOKEN Operator); +IsType13Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsType14Func(PTOKEN Operator); +IsType14Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsTwoOperandOperator(PTOKEN Operator); +IsType15Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsOneOperandOperator(PTOKEN Operator); +IsType16Func(PSCRIPT_ENGINE_TOKEN Operator); char -IsVariableType(PTOKEN Operator); +IsAssignmentOperator(PSCRIPT_ENGINE_TOKEN Operator); + +char +IsTwoOperandOperator(PSCRIPT_ENGINE_TOKEN Operator); + +char +IsOneOperandOperator(PSCRIPT_ENGINE_TOKEN Operator); + +/** + * @brief User-defined function linked list node + */ +typedef struct _USER_DEFINED_FUNCTION_NODE +{ + char * Name; + long long unsigned Address; + long long unsigned VariableType; + long long unsigned ParameterNumber; + long long unsigned MaxTempNumber; + long long unsigned LocalVariableNumber; + long long unsigned IdTable; + long long unsigned FunctionParameterIdTable; + char * TempMap; + struct _USER_DEFINED_FUNCTION_NODE * NextNode; +} USER_DEFINED_FUNCTION_NODE, *PUSER_DEFINED_FUNCTION_NODE; + +/** + * @brief Include file linked list node + */ +typedef struct _INCLUDE_NODE +{ + char * FilePath; + struct _INCLUDE_NODE * NextNode; +} INCLUDE_NODE, *PINCLUDE_NODE; #endif // !COMMON_H diff --git a/hyperdbg/script-engine/header/globals.h b/hyperdbg/script-engine/header/globals.h index 3c69d1e2..d8855032 100644 --- a/hyperdbg/script-engine/header/globals.h +++ b/hyperdbg/script-engine/header/globals.h @@ -12,9 +12,25 @@ #pragma once #ifndef GLOBALS_H -# define GLOABLS_H +# define GLOBALS_H # define MAX_TEMP_COUNT 128 -extern char TempMap[MAX_TEMP_COUNT]; -extern char StackTempMap[MAX_TEMP_COUNT]; #endif // !GLOBALS_H + +/** + * @brief Instance information of the current hwdbg debuggee + * + */ +extern HWDBG_INSTANCE_INFORMATION g_HwdbgInstanceInfo; + +/** + * @brief Shows whether the instance info is valid (received) or not + * + */ +extern BOOLEAN g_HwdbgInstanceInfoIsValid; + +/** + * @brief Message handler function + * + */ +extern PVOID g_MessageHandler; diff --git a/hyperdbg/script-engine/header/hardware.h b/hyperdbg/script-engine/header/hardware.h new file mode 100644 index 00000000..e478d575 --- /dev/null +++ b/hyperdbg/script-engine/header/hardware.h @@ -0,0 +1,20 @@ +/** + * @file hardware.h + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Headers for hardware (chip debugger) related functions + * @details + * @version 0.11 + * @date 2024-09-25 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +// +// Some of the functions are exported at HyperDbgScriptImports.h +// diff --git a/hyperdbg/script-engine/header/parse-table.h b/hyperdbg/script-engine/header/parse-table.h index 81c0710a..eb7a0242 100644 --- a/hyperdbg/script-engine/header/parse-table.h +++ b/hyperdbg/script-engine/header/parse-table.h @@ -1,33 +1,36 @@ #pragma once #ifndef PARSE_TABLE_H #define PARSE_TABLE_H -#define RULES_COUNT 202 -#define TERMINAL_COUNT 101 -#define NONETERMINAL_COUNT 49 +#define RULES_COUNT 284 +#define TERMINAL_COUNT 128 +#define NONETERMINAL_COUNT 63 #define START_VARIABLE "S" #define MAX_RHS_LEN 15 -#define KEYWORD_LIST_LENGTH 89 -#define OPERATORS_ONE_OPERAND_LIST_LENGTH 4 +#define KEYWORD_LIST_LENGTH 121 +#define OPERATORS_ONE_OPERAND_LIST_LENGTH 3 #define OPERATORS_TWO_OPERAND_LIST_LENGTH 16 #define REGISTER_MAP_LIST_LENGTH 120 -#define PSEUDO_REGISTER_MAP_LIST_LENGTH 14 -#define SEMANTIC_RULES_MAP_LIST_LENGTH 137 +#define PSEUDO_REGISTER_MAP_LIST_LENGTH 16 +#define SCRIPT_VARIABLE_TYPE_LIST_LENGTH 10 +#define ASSIGNMENT_OPERATOR_LIST_LENGTH 10 +#define SEMANTIC_RULES_MAP_LIST_LENGTH 166 #define THREEOPFUNC1_LENGTH 1 -#define THREEOPFUNC2_LENGTH 2 -#define TWOOPFUNC1_LENGTH 5 +#define THREEOPFUNC2_LENGTH 3 +#define TWOOPFUNC1_LENGTH 8 #define TWOOPFUNC2_LENGTH 2 -#define ONEOPFUNC1_LENGTH 18 -#define ONEOPFUNC2_LENGTH 9 +#define ONEOPFUNC1_LENGTH 26 +#define ONEOPFUNC2_LENGTH 10 #define ONEOPFUNC3_LENGTH 1 #define TWOOPFUNC3_LENGTH 1 -#define THREEOPFUNC3_LENGTH 1 +#define THREEOPFUNC3_LENGTH 2 +#define THREEOPFUNC4_LENGTH 1 #define ONEOPFUNC4_LENGTH 1 #define TWOOPFUNC4_LENGTH 1 #define ZEROOPFUNC1_LENGTH 7 +#define ZEROOPFUNC2_LENGTH 7 #define VARARGFUNC1_LENGTH 1 -#define VARIABLETYPE_LENGTH 10 -extern const struct _TOKEN Lhs[RULES_COUNT]; -extern const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]; +extern const struct _SCRIPT_ENGINE_TOKEN Lhs[RULES_COUNT]; +extern const struct _SCRIPT_ENGINE_TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]; extern const unsigned int RhsSize[RULES_COUNT]; extern const char* NoneTerminalMap[NONETERMINAL_COUNT]; extern const char* TerminalMap[TERMINAL_COUNT]; @@ -35,6 +38,7 @@ extern const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT]; extern const char* KeywordList[]; extern const char* OperatorsTwoOperandList[]; extern const char* OperatorsOneOperandList[]; +extern const char* AssignmentOperatorList[]; extern const char* ThreeOpFunc1[]; extern const char* ThreeOpFunc2[]; extern const char* TwoOpFunc1[]; @@ -44,27 +48,29 @@ extern const char* OneOpFunc2[]; extern const char* OneOpFunc3[]; extern const char* TwoOpFunc3[]; extern const char* ThreeOpFunc3[]; +extern const char* ThreeOpFunc4[]; extern const char* OneOpFunc4[]; extern const char* TwoOpFunc4[]; extern const char* ZeroOpFunc1[]; +extern const char* ZeroOpFunc2[]; extern const char* VarArgFunc1[]; -extern const char* VARIABLETYPE[]; extern const SYMBOL_MAP SemanticRulesMapList[]; extern const SYMBOL_MAP RegisterMapList[]; extern const SYMBOL_MAP PseudoRegisterMapList[]; +extern const char* ScriptVariableTypeList[]; -#define LALR_RULES_COUNT 85 -#define LALR_TERMINAL_COUNT 63 -#define LALR_NONTERMINAL_COUNT 19 +#define LALR_RULES_COUNT 117 +#define LALR_TERMINAL_COUNT 86 +#define LALR_NONTERMINAL_COUNT 26 #define LALR_MAX_RHS_LEN 9 -#define LALR_STATE_COUNT 226 -extern const struct _TOKEN LalrLhs[RULES_COUNT]; -extern const struct _TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN]; +#define LALR_STATE_COUNT 332 +extern const struct _SCRIPT_ENGINE_TOKEN LalrLhs[RULES_COUNT]; +extern const struct _SCRIPT_ENGINE_TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN]; extern const unsigned int LalrRhsSize[RULES_COUNT]; extern const char* LalrNoneTerminalMap[NONETERMINAL_COUNT]; extern const char* LalrTerminalMap[TERMINAL_COUNT]; extern const int LalrGotoTable[LALR_STATE_COUNT][LALR_NONTERMINAL_COUNT]; extern const int LalrActionTable[LALR_STATE_COUNT][LALR_TERMINAL_COUNT]; -extern const struct _TOKEN LalrSemanticRules[RULES_COUNT]; +extern const struct _SCRIPT_ENGINE_TOKEN LalrSemanticRules[RULES_COUNT]; #endif diff --git a/hyperdbg/script-engine/header/pch.h b/hyperdbg/script-engine/header/pch.h new file mode 100644 index 00000000..e51ebe45 --- /dev/null +++ b/hyperdbg/script-engine/header/pch.h @@ -0,0 +1,65 @@ +/** + * @file pch.h + * @author M.H. Gholamrezaei (mh@hyperdbg.org) + * + * @details Pre-compiled headers + * @version 0.1 + * @date 2020-10-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +// +// Scope definitions +// +#define HYPERDBG_SCRIPT_ENGINE + +// +// Environment headers +// +#include "platform/general/header/Environment.h" + +// +// Exclude rarely-used stuff from Windows headers +// +#define WIN32_LEAN_AND_MEAN + +// +// Windows Header Files +// +#ifdef _WIN32 +# include +#endif + +#include +#include + +#include +#include +#include +#include + +#include "SDK/HyperDbgSdk.h" +#include "SDK/imports/user/HyperDbgSymImports.h" +#include "SDK/headers/HardwareDebugger.h" +#include "type.h" +#include "script_include.h" +#include "common.h" +#include "scanner.h" +#include "globals.h" +#include "../include/SDK/headers/ScriptEngineCommonDefinitions.h" +#include "script-engine.h" +#include "parse-table.h" +#include "hardware.h" + +// +// Platform-specific library calls +// +#include "platform/user/header/platform-lib-calls.h" + +// +// Import/export definitions +// +#include "SDK/imports/user/HyperDbgScriptImports.h" diff --git a/hyperdbg/script-engine/header/scanner.h b/hyperdbg/script-engine/header/scanner.h index 7605a264..20c9589b 100644 --- a/hyperdbg/script-engine/header/scanner.h +++ b/hyperdbg/script-engine/header/scanner.h @@ -15,43 +15,47 @@ # define SCANNER_H /** - * @brief lookup table for storing Ids + * @brief lookup table for storing global Ids */ -PTOKEN_LIST IdTable; +extern PSCRIPT_ENGINE_TOKEN_LIST GlobalIdTable; /** * @brief */ -PTOKEN_LIST FunctionParameterIdTable; +extern PUSER_DEFINED_FUNCTION_NODE UserDefinedFunctionHead; + +extern PUSER_DEFINED_FUNCTION_NODE CurrentUserDefinedFunction; + +extern PINCLUDE_NODE IncludeHead; /** * @brief number of read characters from input */ -unsigned int InputIdx; +extern unsigned int InputIdx; /** * @brief number of current reading line */ -unsigned int CurrentLine; +extern unsigned int CurrentLine; /* * @brief current line start position */ -unsigned int CurrentLineIdx; +extern unsigned int CurrentLineIdx; /* * @brief current PTOKEN start position */ -unsigned int CurrentTokenIdx; +extern unsigned int CurrentTokenIdx; //////////////////////////////////////////////////// // Interfacing functions // //////////////////////////////////////////////////// -PTOKEN +PSCRIPT_ENGINE_TOKEN GetToken(char * c, char * str); -PTOKEN +PSCRIPT_ENGINE_TOKEN Scan(char * str, char * c); char @@ -65,4 +69,7 @@ IsId(char * str); char IsRegister(char * str); + +char +IsVariableType(char * str); #endif // !SCANNER_H diff --git a/hyperdbg/script-engine/header/script-engine.h b/hyperdbg/script-engine/header/script-engine.h index 119d76fc..2fa1996c 100644 --- a/hyperdbg/script-engine/header/script-engine.h +++ b/hyperdbg/script-engine/header/script-engine.h @@ -16,67 +16,18 @@ #ifndef SCRIPT_ENGINE_H # define SCRIPT_ENGINE_H -// -// *** export pdb wrapper as script engine function *** -// -__declspec(dllexport) UINT64 - ScriptEngineConvertNameToAddress(const char * FunctionOrVariableName, PBOOLEAN WasFound); -__declspec(dllexport) UINT32 - ScriptEngineLoadFileSymbol(UINT64 BaseAddress, const char * PdbFileName, const char * CustomModuleName); -__declspec(dllexport) UINT32 - ScriptEngineUnloadAllSymbols(); -__declspec(dllexport) UINT32 - ScriptEngineUnloadModuleSymbol(char * ModuleName); -__declspec(dllexport) UINT32 - ScriptEngineSearchSymbolForMask(const char * SearchMask); -__declspec(dllexport) BOOLEAN - ScriptEngineGetFieldOffset(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset); -__declspec(dllexport) BOOLEAN - ScriptEngineGetDataTypeSize(CHAR * TypeName, UINT64 * TypeSize); -__declspec(dllexport) BOOLEAN - ScriptEngineCreateSymbolTableForDisassembler(void * CallbackFunction); -__declspec(dllexport) BOOLEAN - ScriptEngineConvertFileToPdbPath(const char * LocalFilePath, char * ResultPath); -__declspec(dllexport) BOOLEAN - ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetails(const char * LocalFilePath, char * PdbFilePath, char * GuidAndAgeDetails, BOOLEAN Is32BitModule); -__declspec(dllexport) BOOLEAN - ScriptEngineSymbolInitLoad(PVOID BufferToStoreDetails, UINT32 StoredLength, BOOLEAN DownloadIfAvailable, const char * SymbolPath, BOOLEAN IsSilentLoad); -__declspec(dllexport) BOOLEAN - ScriptEngineShowDataBasedOnSymbolTypes(const char * TypeName, UINT64 Address, BOOLEAN IsStruct, PVOID BufferAddress, const char * AdditionalParameters); -__declspec(dllexport) VOID - ScriptEngineSymbolAbortLoading(); -__declspec(dllexport) VOID - ScriptEngineSetTextMessageCallback(PVOID Handler); -typedef enum _SCRIPT_ENGINE_ERROR_TYPE -{ - SCRIPT_ENGINE_ERROR_FREE, - SCRIPT_ENGINE_ERROR_SYNTAX, - SCRIPT_ENGINE_ERROR_UNKNOWN_TOKEN, - SCRIPT_ENGINE_ERROR_UNRESOLVED_VARIABLE, - SCRIPT_ENGINE_ERROR_UNHANDLED_SEMANTIC_RULE, - SCRIPT_ENGINE_ERROR_TEMP_LIST_FULL, - SCRIPT_ENGINE_ERROR_UNDEFINED_FUNCTION, - SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE, - SCRIPT_ENGINE_ERROR_VOID_FUNCTION_RETURNING_VALUE, - SCRIPT_ENGINE_ERROR_NON_VOID_FUNCTION_NOT_RETURNING_VALUE -} SCRIPT_ENGINE_ERROR_TYPE, - *PSCRIPT_ENGINE_ERROR_TYPE; +VOID +ShowMessages(const char * Fmt, ...); PSYMBOL NewSymbol(void); PSYMBOL -NewStringSymbol(PTOKEN Token); +NewStringSymbol(PSCRIPT_ENGINE_TOKEN Token); PSYMBOL -NewWstringSymbol(PTOKEN Token); - -PSYMBOL -NewFunctionSymbol(char * FunctionName, VARIABLE_TYPE * VariableType); - -PSYMBOL -NewVariableSymbol(char * VariableName, VARIABLE_TYPE * VariableType); +NewWstringSymbol(PSCRIPT_ENGINE_TOKEN Token); unsigned int GetSymbolHeapSize(PSYMBOL Symbol); @@ -84,40 +35,36 @@ GetSymbolHeapSize(PSYMBOL Symbol); void RemoveSymbol(PSYMBOL * Symbol); -__declspec(dllexport) void PrintSymbol(PSYMBOL Symbol); - PSYMBOL_BUFFER NewSymbolBuffer(void); -__declspec(dllexport) void RemoveSymbolBuffer(PSYMBOL_BUFFER SymbolBuffer); - PSYMBOL_BUFFER PushSymbol(PSYMBOL_BUFFER SymbolBuffer, const PSYMBOL Symbol); -__declspec(dllexport) void PrintSymbolBuffer(const PSYMBOL_BUFFER SymbolBuffer); - PSYMBOL -ToSymbol(PTOKEN PTOKEN, PSCRIPT_ENGINE_ERROR_TYPE Error); - -__declspec(dllexport) PSYMBOL_BUFFER ScriptEngineParse(char * str); -__declspec(dllexport) PSYMBOL_BUFFER GetStackBuffer(); +ToSymbol(PSCRIPT_ENGINE_TOKEN PTOKEN, PSCRIPT_ENGINE_ERROR_TYPE Error); void ScriptEngineBooleanExpresssionParse( UINT64 BooleanExpressionSize, - PTOKEN FirstToken, - PTOKEN_LIST MatchedStack, - PSYMBOL_BUFFER UserDefinedFunctions, + PSCRIPT_ENGINE_TOKEN FirstToken, + PSCRIPT_ENGINE_TOKEN_LIST MatchedStack, PSYMBOL_BUFFER CodeBuffer, char * str, char * c, PSCRIPT_ENGINE_ERROR_TYPE Error); UINT64 -BooleanExpressionExtractEnd(char * str, BOOL * WaitForWaitStatementBooleanExpression, PTOKEN CurrentIn); +BooleanExpressionExtractEnd(char * str, BOOL * WaitForWaitStatementBooleanExpression, PSCRIPT_ENGINE_TOKEN CurrentIn); void -CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_BUFFER CodeBuffer, PTOKEN Operator, PSCRIPT_ENGINE_ERROR_TYPE Error); +CodeGen( + PSCRIPT_ENGINE_TOKEN_LIST MatchedStack, + PSYMBOL_BUFFER CodeBuffer, + PSCRIPT_ENGINE_TOKEN Operator, + PSCRIPT_ENGINE_ERROR_TYPE Error, + char** ScriptSource + ); unsigned long long int RegisterToInt(char * str); @@ -132,26 +79,45 @@ char * HandleError(PSCRIPT_ENGINE_ERROR_TYPE Error, char * str); int -GetGlobalIdentifierVal(PTOKEN PTOKEN); +NewGlobalIdentifier(PSCRIPT_ENGINE_TOKEN PTOKEN); int -GetLocalIdentifierVal(PTOKEN PTOKEN); +GetGlobalIdentifierVal(PSCRIPT_ENGINE_TOKEN PTOKEN); + +VOID +SetGlobalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token, VARIABLE_TYPE * VariableType); + +VARIABLE_TYPE * +GetGlobalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token); + +unsigned long long +NewLocalIdentifier(PSCRIPT_ENGINE_TOKEN PTOKEN, unsigned int VariableSize); int -NewGlobalIdentifier(PTOKEN PTOKEN); +GetLocalIdentifierVal(PSCRIPT_ENGINE_TOKEN PTOKEN); + +VOID +SetLocalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token, VARIABLE_TYPE * VariableType); + +VARIABLE_TYPE * +GetLocalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token); int -NewLocalIdentifier(PTOKEN PTOKEN); +NewFunctionParameterIdentifier(PSCRIPT_ENGINE_TOKEN Token); + +int +GetFunctionParameterIdentifier(PSCRIPT_ENGINE_TOKEN Token); int LalrGetRhsSize(int RuleId); BOOL -LalrIsOperandType(PTOKEN PTOKEN); +LalrIsOperandType(PSCRIPT_ENGINE_TOKEN PTOKEN); -int -NewFunctionParameterIdentifier(PTOKEN Token); +PUSER_DEFINED_FUNCTION_NODE +GetUserDefinedFunctionNode(PSCRIPT_ENGINE_TOKEN Token); + +BOOLEAN +FuncGetNumberOfOperands(UINT64 FuncType, UINT32 * NumberOfGetOperands, UINT32 * NumberOfSetOperands); -int -GetFunctionParameterIdentifier(PTOKEN Token); #endif diff --git a/hyperdbg/script-engine/header/script_include.h b/hyperdbg/script-engine/header/script_include.h new file mode 100644 index 00000000..be451166 --- /dev/null +++ b/hyperdbg/script-engine/header/script_include.h @@ -0,0 +1,27 @@ +/** + * @file script_include.h + * @author M.H. Gholamrezaei (mh@hyperdbg.org) + * + * @brief Include file resolver declarations + * @details + * @version 0.1 + * @date 2020-10-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +#define MAX_PATH_LEN 1024 + +VOID +ResolveIncludePath(const char * IncludeFilePath, char * OutPath); + +BOOLEAN +FileExists(const char * Path); + +BOOLEAN +ParseIncludeFile(char * IncludeFile, char ** Buffer); + +char * +InsertStrNew(char * Str, int InputIdx, const char * Buf); diff --git a/hyperdbg/script-engine/header/type.h b/hyperdbg/script-engine/header/type.h index 98289513..02cfdca7 100644 --- a/hyperdbg/script-engine/header/type.h +++ b/hyperdbg/script-engine/header/type.h @@ -1,9 +1,21 @@ +/** + * @file type.h + * @author M.H. Gholamrezaei (mh@hyperdbg.org) + * + * @brief Variable type definitions for the script engine + * @details + * @version 0.1 + * @date 2020-10-22 + * + * @copyright This project is released under the GNU Public License v3. + * + */ #pragma once #ifndef TYPE_H # define TYPE_H -typedef enum +typedef enum _VARIABLE_TYPE_KIND { TY_UNKNOWN, TY_VOID, @@ -24,13 +36,15 @@ typedef enum TY_UNION, } VARIABLE_TYPE_KIND; -typedef struct VARIABLE_TYPE +typedef struct _VARIABLE_TYPE { - VARIABLE_TYPE_KIND Kind; - int Size; // sizeof() value - int Align; // alignment - BOOLEAN IsUnsigned; -} VARIABLE_TYPE; + VARIABLE_TYPE_KIND Kind; + int Size; // sizeof() value + int Align; // alignment + BOOLEAN IsUnsigned; + struct _VARIABLE_TYPE * Base; + int ArrayLen; +} VARIABLE_TYPE, *PVARIABLE_TYPE; extern VARIABLE_TYPE * VARIABLE_TYPE_UNKNOWN; @@ -51,6 +65,19 @@ extern VARIABLE_TYPE * VARIABLE_TYPE_FLOAT; extern VARIABLE_TYPE * VARIABLE_TYPE_DOUBLE; extern VARIABLE_TYPE * VARIABLE_TYPE_LDOUBLE; -VARIABLE_TYPE * -HandleType(PTOKEN_LIST PtokenStack); -#endif \ No newline at end of file +typedef enum _SCRIPT_ENGINE_ERROR_TYPE +{ + SCRIPT_ENGINE_ERROR_FREE, + SCRIPT_ENGINE_ERROR_SYNTAX, + SCRIPT_ENGINE_ERROR_UNKNOWN_TOKEN, + SCRIPT_ENGINE_ERROR_UNRESOLVED_VARIABLE, + SCRIPT_ENGINE_ERROR_UNHANDLED_SEMANTIC_RULE, + SCRIPT_ENGINE_ERROR_TEMP_LIST_FULL, + SCRIPT_ENGINE_ERROR_UNDEFINED_FUNCTION, + SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE, + SCRIPT_ENGINE_ERROR_VOID_FUNCTION_RETURNING_VALUE, + SCRIPT_ENGINE_ERROR_NON_VOID_FUNCTION_NOT_RETURNING_VALUE +} SCRIPT_ENGINE_ERROR_TYPE, + *PSCRIPT_ENGINE_ERROR_TYPE; + +#endif diff --git a/hyperdbg/script-engine/input.txt b/hyperdbg/script-engine/input.txt deleted file mode 100644 index a171613e..00000000 --- a/hyperdbg/script-engine/input.txt +++ /dev/null @@ -1,29 +0,0 @@ - - -x1 = poi(poi((poi(($proc&neg(1000`0000))+10)^poi(poi(poi(poi(poi(poi(poi(poi($prcb+18)+220)+648)+8)-240)+2a0)))^neg(0n6708588087252463955)^($proc&neg(100000)))-8)-1080); -//test= poi(2); -//a2= poi((01)+ 2 * 3) * poi(2); // Binary -//test=dw(@rcx+($proc|3+poi(poi(@rax)))); -/* - //test=dq(@rcx) - //test=$proc+@rdx - //ad1= b2;A - //a3 = $rsc34; - //a2= 0y0101`1010`1; // Binary - //a10 = 0n34331; // - Decimal - //a10 = 0o770; // Octal - //test=poi(@rax+a0); - //test1=str(poi($proc+10));mytest=str(poi($proc+10));test3=str(poi($proc+10)); - //test=dw(NtCreateFile+10) - //test=dw(NtCreateFile+@rcx+($proc|3+poi(poi(@rax)))) - // - // - //$proc = 0xfffff801`42600000 - // - // - //csc=0y101010`010101*934; - //tsc = 10.032; - // - //test = 343 -*/ \ No newline at end of file diff --git a/hyperdbg/script-engine/modules/script-engine-test b/hyperdbg/script-engine/modules/script-engine-test deleted file mode 160000 index 0b101310..00000000 --- a/hyperdbg/script-engine/modules/script-engine-test +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0b1013105ff1c2b0b4925b964b012ed6bef10b27 diff --git a/hyperdbg/script-engine/pch.h b/hyperdbg/script-engine/pch.h deleted file mode 100644 index 66276290..00000000 --- a/hyperdbg/script-engine/pch.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @file pch.h - * @author M.H. Gholamrezaei (mh@hyperdbg.org) - * - * @details Pre-compiled headers - * @version 0.1 - * @date 2020-10-22 - * - * @copyright This project is released under the GNU Public License v3. - * - */ -#pragma once - -// -// Exclude rarely-used stuff from Windows headers -// -#define WIN32_LEAN_AND_MEAN - -// -// Windows Header Files -// -#include -#include -#include -#include -#include - -#include "SDK/Imports/HyperDbgSymImports.h" -#include "common.h" -#include "scanner.h" -#include "globals.h" -#include "..\script-eval\header\ScriptEngineCommonDefinitions.h" -#include "script-engine.h" -#include "parse-table.h" -#include "type.h" diff --git a/hyperdbg/script-engine/python/Boolean_Expression_Grammar.txt b/hyperdbg/script-engine/python/Boolean_Expression_Grammar.txt index 6706bfa0..66a2dd16 100644 --- a/hyperdbg/script-engine/python/Boolean_Expression_Grammar.txt +++ b/hyperdbg/script-engine/python/Boolean_Expression_Grammar.txt @@ -1,8 +1,11 @@ +# ZeroOpFunc2 no input and returns a number +.ZeroOpFunc2->rdtsc rdtscp lbr_save lbr_dump lbr_print lbr_restore lbr_check + # OneOpFunc1 input is a number and returns a number. -.OneOpFunc1->poi db dd dw dq neg hi low not check_address strlen wcslen disassemble_len disassemble_len32 disassemble_len64 interlocked_increment interlocked_decrement reference physical_to_virtual virtual_to_physical +.OneOpFunc1->poi db dd dw dq neg hi low not check_address strlen wcslen disassemble_len disassemble_len32 disassemble_len64 interlocked_increment interlocked_decrement reference physical_to_virtual virtual_to_physical poi_pa hi_pa low_pa db_pa dd_pa dw_pa dq_pa lbr_restore_by_filter # TwoOpFunc1 inputs are two numbers and returns a number. -.TwoOpFunc1->ed eb eq interlocked_exchange interlocked_exchange_add wcscmp +.TwoOpFunc1->ed eb eq interlocked_exchange interlocked_exchange_add wcscmp eb_pa ed_pa eq_pa # ThreeOpFunc1 inputs are three numbers and returns a number. .ThreeOpFunc1->interlocked_compare_exchange @@ -14,7 +17,7 @@ .TwoOpFunc3->strcmp # ThreeOpFunc3 the first two inputs are numbers or strings and the third input is a number and returns a number. -.ThreeOpFunc3->memcmp +.ThreeOpFunc3->memcmp strncmp # OneOpFunc4 input is a number or a wstring and returns a number. .OneOpFunc4->wcslen @@ -22,6 +25,9 @@ # TwoOpFunc4 the two inputs are numbers or wstrings and returns a number. .TwoOpFunc4->wcscmp +# ThreeOpFunc4 the first two inputs are numbers or wstrings and the third input is a number and returns a number. +.ThreeOpFunc4->wcsncmp + .OperatorsOneOperand->inc dec reference dereference S->BE @@ -79,7 +85,7 @@ E10->* E12 @POI E10->& E12 @REFERENCE - +E12->.ZeroOpFunc2 ( ) @.ZeroOpFunc2 E12->.OneOpFunc1 ( EXP ) @.OneOpFunc1 E12->.TwoOpFunc1 ( EXP , EXP ) @.TwoOpFunc2 E12->.ThreeOpFunc1 ( EXP , EXP , EXP ) @.ThreeOpFunc1 @@ -88,6 +94,7 @@ E12->.TwoOpFunc3 ( StringNumber , StringNumber ) @.TwoOpFunc3 E12->.ThreeOpFunc3 ( StringNumber , StringNumber , EXP ) @.ThreeOpFunc3 E12->.OneOpFunc4 ( WstringNumber ) @.OneOpFunc4 E12->.TwoOpFunc4 ( WstringNumber , WstringNumber ) @.TwoOpFunc4 +E12->.ThreeOpFunc4 ( WstringNumber , WstringNumber , EXP ) @.ThreeOpFunc4 E12->( BE ) @@ -95,7 +102,11 @@ E12->( BE ) E12->_register @PUSH E12->_global_id @PUSH E12->_local_id @PUSH -E12->_function_parameter_id @PUSH +E12->_function_parameter_id @PUSH + +E12->ARRAY1 + + # numbers E12->_hex @PUSH @@ -105,6 +116,14 @@ E12->_binary @PUSH E12->_pseudo_register @PUSH +E12->E13 ( VA2 ) @END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE +E13->_function_id @PUSH + +VA2->eps +VA2->EXP VA3 +VA3->, EXP VA3 +VA3->eps + STRING->_string @PUSH WSTRING->_wstring @PUSH @@ -112,4 +131,11 @@ StringNumber->EXP StringNumber->STRING WstringNumber->EXP -WstringNumber->WSTRING \ No newline at end of file +WstringNumber->WSTRING + + +ARRAY1->ARRAY2 ARRAY3 ARRAY4 @ARRAY_INDEX_READ +ARRAY2->_local_id @PUSH +ARRAY3->[ EXP ] @ARRAY_DIM_NUMBER +ARRAY4->ARRAY3 ARRAY4 +ARRAY4->eps diff --git a/hyperdbg/script-engine/python/Grammar.txt b/hyperdbg/script-engine/python/Grammar.txt index a7bfbf11..d08c90c9 100644 --- a/hyperdbg/script-engine/python/Grammar.txt +++ b/hyperdbg/script-engine/python/Grammar.txt @@ -2,19 +2,19 @@ .ThreeOpFunc1->interlocked_compare_exchange # ThreeOpFunc2 inputs are three numbers and returns no value. -.ThreeOpFunc2->event_inject_error_code memcpy +.ThreeOpFunc2->event_inject_error_code memcpy memcpy_pa # TwoOpFunc1 inputs are two numbers and returns a number. -.TwoOpFunc1->ed eb eq interlocked_exchange interlocked_exchange_add +.TwoOpFunc1->ed eb eq interlocked_exchange interlocked_exchange_add eb_pa ed_pa eq_pa # TwoOpFunc2 inputs are two numbers and returns no value .TwoOpFunc2->spinlock_lock_custom_wait event_inject # OneOpFunc1 input is a number and returns a number. -.OneOpFunc1->poi db dd dw dq neg hi low not check_address disassemble_len disassemble_len32 disassemble_len64 interlocked_increment interlocked_decrement reference physical_to_virtual virtual_to_physical +.OneOpFunc1->poi db dd dw dq neg hi low not check_address disassemble_len disassemble_len32 disassemble_len64 interlocked_increment interlocked_decrement reference physical_to_virtual virtual_to_physical poi_pa hi_pa low_pa db_pa dd_pa dw_pa dq_pa lbr_restore_by_filter # OneOpFunc2 input is a number. -.OneOpFunc2->print formats event_enable event_disable event_clear test_statement spinlock_lock spinlock_unlock event_sc +.OneOpFunc2->print formats event_enable event_disable event_clear test_statement spinlock_lock spinlock_unlock event_sc microsleep # OneOpFunc3 input is a number or a string and returns a number. .OneOpFunc3->strlen @@ -23,26 +23,35 @@ .TwoOpFunc3->strcmp # ThreeOpFunc3 the first two inputs are numbers or strings and the third input is a number and returns a number. -.ThreeOpFunc3->memcmp +.ThreeOpFunc3->memcmp strncmp + +# ThreeOpFunc4 the first two inputs are numbers or wstrings and the third input is a number and returns a number. +.ThreeOpFunc4->wcsncmp # OneOpFunc4 input is a number or a wstring and returns a number. .OneOpFunc4->wcslen + # TwoOpFunc4 the two inputs are numbers or wstrings and returns a number. .TwoOpFunc4->wcscmp -.ZeroOpFunc1->pause flush event_trace_step event_trace_step_in event_trace_step_out event_trace_instrumentation_step event_trace_instrumentation_step_in +.ZeroOpFunc1->pause flush event_trace_step event_trace_step_in event_trace_step_out event_trace_instrumentation_step event_trace_instrumentation_step_in + +# ZeroOpFunc2 no input and returns a number +.ZeroOpFunc2->rdtsc rdtscp lbr_save lbr_dump lbr_print lbr_restore lbr_check .VarArgFunc1->printf -.OperatorsTwoOperand->or xor and asr asl add sub mul div mod gt lt egt elt equal neq -.OperatorsOneOperand->inc dec reference dereference +.OperatorsTwoOperand->or xor and asr asl add sub mul div mod gt lt egt elt equal neq +.OperatorsOneOperand->inc dec reference -.SemantiRules->start_of_if jmp jz jnz jmp_to_end_and_jzcompleted end_of_if start_of_while end_of_while vargstart mov start_of_do_while start_of_do_while_commands end_of_do_while start_of_for for_inc_dec start_of_for_ommands end_of_if ignore_lvalue end_of_user_defined_function return_of_user_defined_function_with_value return_of_user_defined_function_without_value call_user_defined_function_parameter end_of_calling_user_defined_function_without_returning_value end_of_calling_user_defined_function_with_returning_value call_user_defined_function start_of_user_defined_function mov_return_value +.AssignmentOperator->add_assignment sub_assignment mul_assignment div_assignment mod_assignment asl_assignment asr_assignment and_assignment xor_assignment or_assignment + +.SemantiRules->jmp jz jnz mov start_of_do_while start_of_do_while_commands end_of_do_while start_of_for for_inc_dec start_of_for_ommands end_of_if ignore_lvalue push pop call ret .Registers->rax eax ax ah al rcx ecx cx ch cl rdx edx dx dh dl rbx ebx bx bh bl rsp esp sp spl rbp ebp bp bpl rsi esi si sil rdi edi di dil r8 r8d r8w r8h r8l r9 r9d r9w r9h r9l r10 r10d r10w r10h r10l r11 r11d r11w r11h r11l r12 r12d r12w r12h r12l r13 r13d r13w r13h r13l r14 r14d r14w r14h r14l r15 r15d r15w r15h r15l ds es fs gs cs ss rflags eflags flags cf pf af zf sf tf if df of iopl nt rf vm ac vif vip id rip eip ip idtr ldtr gdtr tr cr0 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr6 dr7 -.PseudoRegisters->pid tid pname core proc thread peb teb ip buffer context event_tag event_id event_stage +.PseudoRegisters->pid tid pname core proc thread peb teb ip buffer context event_tag event_id event_stage date time S->STATEMENT S S->{ STATEMENT S } @@ -52,11 +61,14 @@ STATEMENT->IF_STATEMENT STATEMENT->WHILE_STATEMENT STATEMENT->DO_WHILE_STATEMENT STATEMENT->FOR_STATEMENT -STATEMENT->L_VALUE L_VALUE2 +STATEMENT->ASSIGNMENT_STATEMENT ; +STATEMENT->@PUSH _function_id ( VA2 ) @END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE ; STATEMENT->CALL_FUNC_STATEMENT ; STATEMENT->break @BREAK ; STATEMENT->continue @CONTINUE ; STATEMENT->VARIABLE_TYPE3 +STATEMENT->#include STRING @INCLUDE ; + S2->STATEMENT2 S2 S2->{ STATEMENT2 S2 } @@ -66,24 +78,49 @@ STATEMENT2->IF_STATEMENT STATEMENT2->WHILE_STATEMENT STATEMENT2->DO_WHILE_STATEMENT STATEMENT2->FOR_STATEMENT -STATEMENT2->L_VALUE L_VALUE2 +STATEMENT2->ASSIGNMENT_STATEMENT ; +STATEMENT2->@PUSH _function_id ( VA2 ) @END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE ; STATEMENT2->CALL_FUNC_STATEMENT ; STATEMENT2->break @BREAK ; STATEMENT2->continue @CONTINUE ; -STATEMENT2->VARIABLE_TYPE1 VARIABLE_TYPE2 L_VALUE = EXPRESSION @MOV ; +STATEMENT2->VARIABLE_TYPE1 VARIABLE_TYPE2 L_VALUE = EXPRESSION MULTIPLE_ASSIGNMENT ; STATEMENT2->return RETURN ; + RETURN->eps @RETURN_OF_USER_DEFINED_FUNCTION_WITHOUT_VALUE RETURN->EXPRESSION @RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE -# name started with a dot is a list of fun, wii rewrite here -.VARIABLETYPE->void bool char short int long unsigned signed float double -VARIABLE_TYPE1->@PUSH .VARIABLETYPE +.ScriptVariableType->void bool char short int long unsigned signed float double +VARIABLE_TYPE1->@PUSH _script_variable_type -VARIABLE_TYPE2->VARIABLE_TYPE1 +VARIABLE_TYPE2->VARIABLE_TYPE1 VARIABLE_TYPE2 +VARIABLE_TYPE2->* @DECLARE_POINTER_TYPE VARIABLE_TYPE2->eps VARIABLE_TYPE3->VARIABLE_TYPE1 VARIABLE_TYPE2 L_VALUE VARIABLE_TYPE4 -VARIABLE_TYPE4->= EXPRESSION @MOV ; +VARIABLE_TYPE4->= EXPRESSION MULTIPLE_ASSIGNMENT ; + +VARIABLE_TYPE4->@ARRAY_L_VALUE ARRAY_DIMS = ARRAY_INIT @ARRAY_DECLARITION ; + +ARRAY_DIMS->[ CONST_NUMBER @ARRAY_DIM_NUMBER ] ARRAY_DIMS2 +ARRAY_DIMS2->ARRAY_DIMS +ARRAY_DIMS2->eps + +ARRAY_INIT->{ INIT_LIST } @ARRAY_LEFT_BRACKET + +INIT_LIST->INIT_ITEM INIT_LIST_TAIL + +INIT_ITEM->ARRAY_INIT +INIT_ITEM->EXPRESSION + +INIT_LIST_TAIL->, INIT_LIST_CONT +INIT_LIST_TAIL->eps + +INIT_LIST_CONT->INIT_ITEM INIT_LIST_TAIL +INIT_LIST_CONT->eps + + + + # define function VARIABLE_TYPE4->@START_OF_USER_DEFINED_FUNCTION ( VARIABLE_TYPE5 ) { S2 @END_OF_USER_DEFINED_FUNCTION } @@ -93,20 +130,41 @@ VARIABLE_TYPE5->VARIABLE_TYPE1 VARIABLE_TYPE2 L_VALUE @FUNCTION_PARAMETER VARIAB VARIABLE_TYPE6->, VARIABLE_TYPE1 VARIABLE_TYPE2 L_VALUE @FUNCTION_PARAMETER VARIABLE_TYPE6 VARIABLE_TYPE6->eps -# L_VALUE2 is to decide whether is assignment or call user-defined function -L_VALUE2->ASSIGNMENT_STATEMENT' ; -L_VALUE2->@CALL_USER_DEFINED_FUNCTION ( CALL_USER_DEFINED_FUNCTION_PARAMETER ) @END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE ; -CALL_USER_DEFINED_FUNCTION_PARAMETER->eps -CALL_USER_DEFINED_FUNCTION_PARAMETER->EXPRESSION @CALL_USER_DEFINED_FUNCTION_PARAMETER CALL_USER_DEFINED_FUNCTION_PARAMETER2 -CALL_USER_DEFINED_FUNCTION_PARAMETER2->, EXPRESSION @CALL_USER_DEFINED_FUNCTION_PARAMETER CALL_USER_DEFINED_FUNCTION_PARAMETER2 -CALL_USER_DEFINED_FUNCTION_PARAMETER2->eps +ASSIGNMENT_STATEMENT->* L_VALUE = EXPRESSION @DEREFERENCE + +ASSIGNMENT_STATEMENT->L_VALUE ARRAY_DIMS_WRITE_OPT ASSIGNMENT_STATEMENT' + +ARRAY_DIMS_WRITE_OPT->ARRAY_DIMS_WRITE +ARRAY_DIMS_WRITE_OPT->eps + +ARRAY_DIMS_WRITE->[ EXPRESSION @ARRAY_DIM_NUMBER ] ARRAY_DIMS_WRITE2 +ARRAY_DIMS_WRITE2->ARRAY_DIMS_WRITE +ARRAY_DIMS_WRITE2->eps @ARRAY_INDEX_WRITE + + ASSIGNMENT_STATEMENT'->++ @INC ASSIGNMENT_STATEMENT'->-- @DEC -ASSIGNMENT_STATEMENT'->= EXPRESSION @MOV +ASSIGNMENT_STATEMENT'->= EXPRESSION MULTIPLE_ASSIGNMENT +ASSIGNMENT_STATEMENT'->+= EXPRESSION @ADD_ASSIGNMENT +ASSIGNMENT_STATEMENT'->-= EXPRESSION @SUB_ASSIGNMENT +ASSIGNMENT_STATEMENT'->*= EXPRESSION @MUL_ASSIGNMENT +ASSIGNMENT_STATEMENT'->/= EXPRESSION @DIV_ASSIGNMENT +ASSIGNMENT_STATEMENT'->%= EXPRESSION @MOD_ASSIGNMENT +ASSIGNMENT_STATEMENT'-><<= EXPRESSION @ASL_ASSIGNMENT +ASSIGNMENT_STATEMENT'->>>= EXPRESSION @ASR_ASSIGNMENT +ASSIGNMENT_STATEMENT'->&= EXPRESSION @AND_ASSIGNMENT +ASSIGNMENT_STATEMENT'->^= EXPRESSION @XOR_ASSIGNMENT +ASSIGNMENT_STATEMENT'->|= EXPRESSION @OR_ASSIGNMENT + + + + + CALL_FUNC_STATEMENT->.OneOpFunc2 ( EXPRESSION @.OneOpFunc2 ) CALL_FUNC_STATEMENT->.VarArgFunc1 ( STRING @VARGSTART VA @.VarArgFunc1 ) CALL_FUNC_STATEMENT->.ZeroOpFunc1 ( @.ZeroOpFunc1 ) +CALL_FUNC_STATEMENT->.ZeroOpFunc2 ( @.ZeroOpFunc2 ) @IGNORE_LVALUE CALL_FUNC_STATEMENT->.TwoOpFunc2 ( EXPRESSION , EXPRESSION @.TwoOpFunc2 ) CALL_FUNC_STATEMENT->.OneOpFunc1 ( EXPRESSION @.OneOpFunc1 ) @IGNORE_LVALUE CALL_FUNC_STATEMENT->.TwoOpFunc1 ( EXPRESSION , EXPRESSION @.TwoOpFunc1 ) @IGNORE_LVALUE @@ -117,6 +175,7 @@ CALL_FUNC_STATEMENT->.ThreeOpFunc3 ( StringNumber , StringNumber , EXPRESSION @. CALL_FUNC_STATEMENT->.OneOpFunc4 ( WstringNumber @.OneOpFunc4 ) @IGNORE_LVALUE CALL_FUNC_STATEMENT->.TwoOpFunc4 ( WstringNumber , WstringNumber @.TwoOpFunc4 ) @IGNORE_LVALUE CALL_FUNC_STATEMENT->.ThreeOpFunc2 ( EXPRESSION , EXPRESSION , EXPRESSION @.ThreeOpFunc2 ) +CALL_FUNC_STATEMENT->.ThreeOpFunc4 ( WstringNumber , WstringNumber , EXPRESSION @.ThreeOpFunc4 ) @IGNORE_LVALUE VA->, EXPRESSION VA VA->eps @@ -135,21 +194,35 @@ WHILE_STATEMENT->while @START_OF_WHILE ( BOOLEAN_EXPRESSION ) @START_OF_WHILE_CO DO_WHILE_STATEMENT->do @START_OF_DO_WHILE { S2 } while ( BOOLEAN_EXPRESSION ) @END_OF_DO_WHILE ; FOR_STATEMENT->for ( SIMPLE_ASSIGNMENT ; @START_OF_FOR BOOLEAN_EXPRESSION ; @FOR_INC_DEC INC_DEC ) { @START_OF_FOR_COMMANDS S2 @END_OF_FOR } -SIMPLE_ASSIGNMENT->VARIABLE_TYPE1 VARIABLE_TYPE2 L_VALUE = EXPRESSION @MOV SIMPLE_ASSIGNMENT' -SIMPLE_ASSIGNMENT->L_VALUE = EXPRESSION @MOV SIMPLE_ASSIGNMENT' +SIMPLE_ASSIGNMENT->VARIABLE_TYPE1 VARIABLE_TYPE2 L_VALUE = EXPRESSION MULTIPLE_ASSIGNMENT +SIMPLE_ASSIGNMENT->L_VALUE = EXPRESSION MULTIPLE_ASSIGNMENT SIMPLE_ASSIGNMENT->eps -SIMPLE_ASSIGNMENT'->eps INC_DEC->L_VALUE INC_DEC' INC_DEC'->++ @INC INC_DEC'->-- @DEC -INC_DEC'->= EXPRESSION @MOV SIMPLE_ASSIGNMENT' - +INC_DEC'->= EXPRESSION MULTIPLE_ASSIGNMENT +INC_DEC'->+= EXPRESSION @ADD_ASSIGNMENT +INC_DEC'->-= EXPRESSION @SUB_ASSIGNMENT +INC_DEC'->*= EXPRESSION @MUL_ASSIGNMENT +INC_DEC'->/= EXPRESSION @DIV_ASSIGNMENT +INC_DEC'->%= EXPRESSION @MOD_ASSIGNMENT +INC_DEC'-><<= EXPRESSION @ASL_ASSIGNMENT +INC_DEC'->>>= EXPRESSION @ASR_ASSIGNMENT +INC_DEC'->&= EXPRESSION @AND_ASSIGNMENT +INC_DEC'->^= EXPRESSION @XOR_ASSIGNMENT +INC_DEC'->|= EXPRESSION @OR_ASSIGNMENT INC_DEC'->eps BOOLEAN_EXPRESSION->eps +MULTIPLE_ASSIGNMENT->eps @MOV +MULTIPLE_ASSIGNMENT->= EXPRESSION MULTIPLE_ASSIGNMENT2 +MULTIPLE_ASSIGNMENT2->= EXPRESSION MULTIPLE_ASSIGNMENT2 +MULTIPLE_ASSIGNMENT2->eps @MULTIPLE_ASSIGNMENT + + EXPRESSION->E1 E0' E0'->| E1 @OR E0' @@ -184,8 +257,7 @@ E5'->eps - - +E12->.ZeroOpFunc2 ( @.ZeroOpFunc2 ) E12->.OneOpFunc1 ( EXPRESSION @.OneOpFunc1 ) E12->.TwoOpFunc1 ( EXPRESSION , EXPRESSION @.TwoOpFunc1 ) E12->.ThreeOpFunc1 ( EXPRESSION , EXPRESSION , EXPRESSION @.ThreeOpFunc1 ) @@ -194,22 +266,32 @@ E12->.TwoOpFunc3 ( StringNumber , StringNumber @.TwoOpFunc3 ) E12->.ThreeOpFunc3 ( StringNumber , StringNumber , EXPRESSION @.ThreeOpFunc3 ) E12->.OneOpFunc4 ( WstringNumber @.OneOpFunc4 ) E12->.TwoOpFunc4 ( WstringNumber , WstringNumber @.TwoOpFunc4 ) +E12->.ThreeOpFunc4 ( WstringNumber , WstringNumber , EXPRESSION @.ThreeOpFunc4 ) E12->( EXPRESSION ) +E12->L_VALUE ARRAY_DIMS_READ_OPT +E12->@PUSH _function_id ( VA2 ) @END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE + +ARRAY_DIMS_READ_OPT->ARRAY_DIMS_READ +ARRAY_DIMS_READ_OPT->eps + +ARRAY_DIMS_READ->[ EXPRESSION @ARRAY_DIM_NUMBER ] ARRAY_DIMS_READ2 +ARRAY_DIMS_READ2->ARRAY_DIMS_READ +ARRAY_DIMS_READ2->eps @ARRAY_INDEX_READ + + -E12->L_VALUE E13 -E13->eps -E13->@CALL_USER_DEFINED_FUNCTION ( CALL_USER_DEFINED_FUNCTION_PARAMETER ) @END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE # numbers -E12->@PUSH _hex -E12->@PUSH _decimal -E12->@PUSH _octal -E12->@PUSH _binary +CONST_NUMBER->@PUSH _hex +CONST_NUMBER->@PUSH _decimal +CONST_NUMBER->@PUSH _octal +CONST_NUMBER->@PUSH _binary +E12->CONST_NUMBER E12->@PUSH _pseudo_register @@ -227,7 +309,12 @@ L_VALUE->@PUSH _local_id L_VALUE->@PUSH _register L_VALUE->@PUSH _function_parameter_id +VA2->eps +VA2->EXPRESSION VA3 +VA3->, EXPRESSION VA3 +VA3->eps + StringNumber->EXPRESSION StringNumber->STRING WstringNumber->EXPRESSION -WstringNumber->WSTRING +WstringNumber->WSTRING \ No newline at end of file diff --git a/hyperdbg/script-engine/python/generator.py b/hyperdbg/script-engine/python/generator.py index 1ec9125f..78b98e2c 100644 --- a/hyperdbg/script-engine/python/generator.py +++ b/hyperdbg/script-engine/python/generator.py @@ -1,3 +1,19 @@ +""" + * @file generator.py + * @author M.H. Gholamrezei (mh@hyperdbg.org) + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief Script engine LL(1) Parse table generator + * @details This program reads grammar from Greammar.txt file + * placed in the same directory of the program + * and creates parse_table.h and parse_table.c which is + * used by the parser of script engine. + * @version 0.1 + * @date 2020-10-24 + * + * @copyright This project is released under the GNU Public License v3. + + """ + from ll1_parser import * from lalr1_parser import * @@ -5,8 +21,9 @@ class Generator(): def __init__(self): self.SourceFile = open("..\\code\\parse-table.c", "w") self.HeaderFile = open("..\\header\\parse-table.h", "w") - self.CommonHeaderFile = open("..\\..\\script-eval\\header\\ScriptEngineCommonDefinitions.h", "w") - self.ll1 = LL1Parser(self.SourceFile, self.HeaderFile, self.CommonHeaderFile) + self.CommonHeaderFile = open("..\\..\\include\\SDK\\Headers\\ScriptEngineCommonDefinitions.h", "w") + self.CommonHeaderFileScala = open("..\\..\\..\\hwdbg\\src\\main\\scala\\hwdbg\\script\\script_definitions.scala", "w") + self.ll1 = LL1Parser(self.SourceFile, self.HeaderFile, self.CommonHeaderFile, self.CommonHeaderFileScala) self.lalr = LALR1Parser(self.SourceFile, self.HeaderFile) def Run(self): @@ -34,27 +51,94 @@ class Generator(): def WriteCommonHeader(self): + + # + # Write scala headers + # + self.CommonHeaderFileScala.write("""package hwdbg.script + +import chisel3._ +import chisel3.util._ + +/** + * @brief + * The structure of HWDBG_SHORT_SYMBOL used in script engine of HyperDbg + */ +class HwdbgShortSymbol( + scriptVariableLength: Int +) extends Bundle { + + // + // Ensure that the script variable length is at least 8 bits or 1 byte + // + require( + scriptVariableLength >= 8, + f"err, the minimum script variable length is 8 bits (1 byte)." + ) + + val Type = UInt(scriptVariableLength.W) // long long unsigned is 64 bits but it can be dynamic + val Value = UInt(scriptVariableLength.W) // long long unsigned is 64 bits but it can be dynamic +} + +/** + * @brief + * Constant values for the script engine + */ +object ScriptConstants { + val SYMBOL_MEM_VALID_CHECK_MASK = 1 << 31 + val INVALID = 0x80000000 + val LALR_ACCEPT = 0x7fffffff +} + +/** + * @brief + * Constant type values for the script engine + */ +object ScriptConstantTypes { + object ScriptDataTypes extends ChiselEnum { + val symbolUndefined, symbolGlobalIdType, symbolLocalIdType, symbolNumType, symbolRegisterType, symbolPseudoRegType, symbolSemanticRuleType, symbolTempType, symbolStringType, symbolVariableCountType, symbolInvalid, symbolWstringType, symbolFunctionParameterIdType, symbolReturnAddressType, symbolFunctionParameterType, symbolStackIndexType, symbolStackBaseIndexType, symbolReturnValueType = Value + } +} + +""") + # + # Write C/C++ headers + # self.CommonHeaderFile.write( """#pragma once #ifndef SCRIPT_ENGINE_COMMON_DEFINITIONS_H #define SCRIPT_ENGINE_COMMON_DEFINITIONS_H -typedef struct SYMBOL { - long long unsigned Type; + +typedef struct SYMBOL +{ + long long unsigned Type; long long unsigned Len; - long long unsigned VariableType; - long long unsigned Value; -} SYMBOL, * PSYMBOL; + long long unsigned Value; + +} SYMBOL, *PSYMBOL; + +#define SIZE_SYMBOL_WITHOUT_LEN sizeof(long long unsigned) * 2 + +typedef struct HWDBG_SHORT_SYMBOL +{ + long long unsigned Type; + long long unsigned Value; + +} HWDBG_SHORT_SYMBOL, *PHWDBG_SHORT_SYMBOL; + typedef struct SYMBOL_BUFFER { - PSYMBOL Head; - unsigned int Pointer; - unsigned int Size; - char* Message; + PSYMBOL Head; + unsigned int Pointer; + unsigned int Size; + char* Message; } SYMBOL_BUFFER, * PSYMBOL_BUFFER; + typedef struct SYMBOL_MAP { char* Name; long long unsigned Type; } SYMBOL_MAP, * PSYMBOL_MAP; + typedef struct ACTION_BUFFER { long long unsigned Tag; long long unsigned CurrentAction; @@ -63,24 +147,55 @@ typedef struct ACTION_BUFFER { char CallingStage; } ACTION_BUFFER, *PACTION_BUFFER; - -#define SYMBOL_GLOBAL_ID_TYPE 0 -#define SYMBOL_LOCAL_ID_TYPE 1 -#define SYMBOL_NUM_TYPE 2 -#define SYMBOL_REGISTER_TYPE 3 -#define SYMBOL_PSEUDO_REG_TYPE 4 -#define SYMBOL_SEMANTIC_RULE_TYPE 5 -#define SYMBOL_TEMP_TYPE 6 -#define SYMBOL_STRING_TYPE 7 -#define SYMBOL_VARIABLE_COUNT_TYPE 8 -#define SYMBOL_MEM_VALID_CHECK_MASK (1 << 31) -#define SYMBOL_INVALID 9 -#define SYMBOL_WSTRING_TYPE 10 -#define SYMBOL_USER_DEFINED_FUNCTION_TYPE 11 +#define SYMBOL_UNDEFINED 0 +#define SYMBOL_GLOBAL_ID_TYPE 1 +#define SYMBOL_LOCAL_ID_TYPE 2 +#define SYMBOL_NUM_TYPE 3 +#define SYMBOL_REGISTER_TYPE 4 +#define SYMBOL_PSEUDO_REG_TYPE 5 +#define SYMBOL_SEMANTIC_RULE_TYPE 6 +#define SYMBOL_TEMP_TYPE 7 +#define SYMBOL_STRING_TYPE 8 +#define SYMBOL_VARIABLE_COUNT_TYPE 9 +#define SYMBOL_INVALID 10 +#define SYMBOL_WSTRING_TYPE 11 #define SYMBOL_FUNCTION_PARAMETER_ID_TYPE 12 #define SYMBOL_RETURN_ADDRESS_TYPE 13 -#define SYMBOL_STACK_TEMP_TYPE 14 -#define SYMBOL_FUNCTION_PARAMETER_TYPE 15 +#define SYMBOL_FUNCTION_PARAMETER_TYPE 14 +#define SYMBOL_STACK_INDEX_TYPE 15 +#define SYMBOL_STACK_BASE_INDEX_TYPE 16 +#define SYMBOL_RETURN_VALUE_TYPE 17 +#define SYMBOL_REFERENCE_LOCAL_ID_TYPE 18 +#define SYMBOL_REFERENCE_TEMP_TYPE 19 +#define SYMBOL_DEREFERENCE_LOCAL_ID_TYPE 20 +#define SYMBOL_DEREFERENCE_TEMP_TYPE 21 + +static const char *const SymbolTypeNames[] = { +"SYMBOL_UNDEFINED", +"SYMBOL_GLOBAL_ID_TYPE", +"SYMBOL_LOCAL_ID_TYPE", +"SYMBOL_NUM_TYPE", +"SYMBOL_REGISTER_TYPE", +"SYMBOL_PSEUDO_REG_TYPE", +"SYMBOL_SEMANTIC_RULE_TYPE", +"SYMBOL_TEMP_TYPE", +"SYMBOL_STRING_TYPE", +"SYMBOL_VARIABLE_COUNT_TYPE", +"SYMBOL_INVALID", +"SYMBOL_WSTRING_TYPE", +"SYMBOL_FUNCTION_PARAMETER_ID_TYPE", +"SYMBOL_RETURN_ADDRESS_TYPE", +"SYMBOL_FUNCTION_PARAMETER_TYPE", +"SYMBOL_STACK_INDEX_TYPE", +"SYMBOL_STACK_BASE_INDEX_TYPE", +"SYMBOL_RETURN_VALUE_TYPE", +"SYMBOL_REFERENCE_LOCAL_ID_TYPE", +"SYMBOL_REFERENCE_TEMP_TYPE", +"SYMBOL_DEREFERENCE_LOCAL_ID_TYPE", +"SYMBOL_DEREFERENCE_TEMP_TYPE" +}; + +#define SYMBOL_MEM_VALID_CHECK_MASK (1 << 31) #define INVALID 0x80000000 #define LALR_ACCEPT 0x7fffffff diff --git a/hyperdbg/script-engine/python/lalr1_parser.py b/hyperdbg/script-engine/python/lalr1_parser.py index f380403f..74745376 100644 --- a/hyperdbg/script-engine/python/lalr1_parser.py +++ b/hyperdbg/script-engine/python/lalr1_parser.py @@ -44,7 +44,7 @@ class LALR1Parser: # maximum of "Right Hand Side(Rhs)" length self.MAXIMUM_RHS_LEN = 0 - self.SPECIAL_TOKENS = ['%', '+', '++', '-', '--', "*", "/", "=", "==", "!=", ",", ";", "(", ")", "{", "}", "|", "||", ">>", ">=", "<<", "<=", "&", "&&", "^"] + self.SPECIAL_TOKENS = ['%', '+', '++', '-', '--', "*", "/", "=", "==", "!=", ",", ";", "(", ")", "{", "}", "|", "||", ">>", ">=", "<<", "<=", "&", "&&", "^", "[", "]"] @@ -94,8 +94,8 @@ class LALR1Parser: def WriteLhsList(self): - self.SourceFile.write("const struct _TOKEN LalrLhs[RULES_COUNT]= \n{\n") - self.HeaderFile.write("extern const struct _TOKEN LalrLhs[RULES_COUNT];\n") + self.SourceFile.write("const struct _SCRIPT_ENGINE_TOKEN LalrLhs[RULES_COUNT]= \n{\n") + self.HeaderFile.write("extern const struct _SCRIPT_ENGINE_TOKEN LalrLhs[RULES_COUNT];\n") Counter = 0 for Lhs in self.LhsList: if Counter == len(self.LhsList)-1: @@ -106,8 +106,8 @@ class LALR1Parser: self.SourceFile.write("};\n") def WriteRhsList(self): - self.SourceFile.write("const struct _TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN]= \n{\n") - self.HeaderFile.write("extern const struct _TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN];\n") + self.SourceFile.write("const struct _SCRIPT_ENGINE_TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN]= \n{\n") + self.HeaderFile.write("extern const struct _SCRIPT_ENGINE_TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN];\n") Counter =0 for Rhs in self.RhsList: self.SourceFile.write("\t{") @@ -168,8 +168,8 @@ class LALR1Parser: def WriteSemanticRules(self): - self.SourceFile.write("const struct _TOKEN LalrSemanticRules[RULES_COUNT]= \n{\n") - self.HeaderFile.write("extern const struct _TOKEN LalrSemanticRules[RULES_COUNT];\n") + self.SourceFile.write("const struct _SCRIPT_ENGINE_TOKEN LalrSemanticRules[RULES_COUNT]= \n{\n") + self.HeaderFile.write("extern const struct _SCRIPT_ENGINE_TOKEN LalrSemanticRules[RULES_COUNT];\n") Counter = 0 for SemanticRule in self.SemanticList: diff --git a/hyperdbg/script-engine/python/ll1_parser.py b/hyperdbg/script-engine/python/ll1_parser.py index 3bb7b9f3..a070f36f 100644 --- a/hyperdbg/script-engine/python/ll1_parser.py +++ b/hyperdbg/script-engine/python/ll1_parser.py @@ -1,6 +1,7 @@ """ * @file ll1_parse_table_generator.py * @author M.H. Gholamrezei (mh@hyperdbg.org) + * @author Sina Karvandi (sina@hyperdbg.org) * @brief Script engine LL(1) Parse table generator * @details This program reads grammar from Greammar.txt file * placed in the same directory of the program @@ -17,7 +18,7 @@ from util import * from lalr1_parser import * class LL1Parser: - def __init__(self, SourceFile, HeaderFile, CommonHeaderFile): + def __init__(self, SourceFile, HeaderFile, CommonHeaderFile, CommonHeaderFileScala): # The file which contains the grammar of the language self.GrammarFile = open("Grammar.txt", "r") @@ -25,6 +26,7 @@ class LL1Parser: self.SourceFile = SourceFile self.HeaderFile = HeaderFile self.CommonHeaderFile = CommonHeaderFile + self.CommonHeaderFileScala = CommonHeaderFileScala # Lists which used for storing the rules: @@ -46,7 +48,8 @@ class LL1Parser: self.MAXIMUM_RHS_LEN = 0 - self.SPECIAL_TOKENS = ['%', '+', '~', '++', '-', '--', "*", "/", "=", "==", "!=", ",", ";", "(", ")", "{", "}", "|", "||", ">>", ">=", "<<", "<=", "&", "&&", "^"] + self.SPECIAL_TOKENS = ['%', '+', '~', '++', '-', '--', "*", "/", "=", "==", "!=", ",", ";", "(", ")", "{", "}", "|", "||", ">>", ">=", "<<", "<=", "&", "&&", "^", + "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", "^=", "|=" , "[", "]"] # INVALID rule indicator self.INVALID = 0x80000000 @@ -56,8 +59,10 @@ class LL1Parser: self.OperatorsOneOperand = [] self.RegistersList = [] self.PseudoRegistersList = [] + self.VariableTypeList = [] self.keywordList = [] self.SemantiRulesList = [] + self.AssignmentOperator = [] # Dictionaries used for storing first and follow sets @@ -110,7 +115,9 @@ class LL1Parser: self.HeaderFile.write("#define OPERATORS_TWO_OPERAND_LIST_LENGTH " + str(len(self.OperatorsTwoOperand)) + "\n") self.HeaderFile.write("#define REGISTER_MAP_LIST_LENGTH " + str(len(self.RegistersList))+ "\n") self.HeaderFile.write("#define PSEUDO_REGISTER_MAP_LIST_LENGTH " + str(len(self.PseudoRegistersList))+ "\n") - self.HeaderFile.write("#define SEMANTIC_RULES_MAP_LIST_LENGTH " + str(len(self.keywordList) + len(self.OperatorsOneOperand) + len(self.OperatorsTwoOperand) + len(self.SemantiRulesList))+ "\n") + self.HeaderFile.write("#define SCRIPT_VARIABLE_TYPE_LIST_LENGTH " + str(len(self.VariableTypeList))+ "\n") + self.HeaderFile.write("#define ASSIGNMENT_OPERATOR_LIST_LENGTH " + str(len(self.AssignmentOperator)) + "\n") + self.HeaderFile.write("#define SEMANTIC_RULES_MAP_LIST_LENGTH " + str(len(self.keywordList) + len(self.OperatorsOneOperand) + len(self.OperatorsTwoOperand) + len(self.SemantiRulesList) + len(self.AssignmentOperator))+ "\n") for Key in self.FunctionsDict: self.HeaderFile.write("#define "+ Key[1:].upper() + "_LENGTH "+ str(len(self.FunctionsDict[Key]))+"\n") @@ -148,7 +155,7 @@ class LL1Parser: self.WriteSemanticMaps() self.WriteRegisterMaps() self.WritePseudoRegMaps() - + self.WriteVariableTypeList() # Closes Grammar Input File self.GrammarFile.close() @@ -175,7 +182,7 @@ class LL1Parser: # Push start variable into stack Stack.append(self.Start) - # Assign top variale an invalid value + # Assign top variable an invalid value Top = "" # Read input @@ -346,7 +353,7 @@ class LL1Parser: if L[0][1:] == "OperatorsTwoOperand": self.OperatorsTwoOperand += Elements continue - if L[0][1:] == "OperatorsOneOperand": + elif L[0][1:] == "OperatorsOneOperand": self.OperatorsOneOperand += Elements continue elif L[0][1:] == "SemantiRules": @@ -358,6 +365,12 @@ class LL1Parser: elif L[0][1:] == "PseudoRegisters": self.PseudoRegistersList += Elements continue + elif L[0][1:] == "ScriptVariableType": + self.VariableTypeList += Elements + continue + elif L[0][1:] == "AssignmentOperator": + self.AssignmentOperator += Elements + continue self.FunctionsDict[L[0]] = Elements continue @@ -423,24 +436,56 @@ class LL1Parser: def WriteSemanticMaps(self): - - Counter = 0 + + self.CommonHeaderFileScala.write("object ScriptEvalFunc {\n object ScriptOperators extends ChiselEnum {\n val ") + + Counter = 0 + CheckForDuplicateList = [] + + self.CommonHeaderFile.write("#define " + "FUNC_UNDEFINED " + str(Counter) + "\n") + self.CommonHeaderFileScala.write("sFunc" + "Undefined") + Counter += 1 + for X in self.OperatorsOneOperand: - self.CommonHeaderFile.write("#ifndef FUNC_" + X.upper() + "\n#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n#endif // !FUNC_" + X.upper() + "\n\n") - Counter += 1 + + if X not in CheckForDuplicateList: + self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n") + self.CommonHeaderFileScala.write(", sFunc" + X.capitalize()) + + CheckForDuplicateList.append(X) + Counter += 1 for X in self.OperatorsTwoOperand: - self.CommonHeaderFile.write("#ifndef FUNC_" + X.upper() + "\n#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n#endif // !FUNC_" + X.upper() + "\n\n") - Counter += 1 + + if X not in CheckForDuplicateList: + self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n") + self.CommonHeaderFileScala.write(", sFunc" + X.capitalize()) + CheckForDuplicateList.append(X) + Counter += 1 for X in self.SemantiRulesList: - self.CommonHeaderFile.write("#ifndef FUNC_" + X.upper() + "\n#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n#endif // !FUNC_" + X.upper() + "\n\n") - Counter += 1 - + + if X not in CheckForDuplicateList: + self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n") + self.CommonHeaderFileScala.write(", sFunc" + X.capitalize()) + CheckForDuplicateList.append(X) + Counter += 1 + for X in self.keywordList: - self.CommonHeaderFile.write("#ifndef FUNC_" + X.upper() + "\n#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n#endif // !FUNC_" + X.upper() + "\n\n") - Counter += 1 - + + if X not in CheckForDuplicateList: + self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n") + + # + # Check if it's the last item + # + self.CommonHeaderFileScala.write(", sFunc" + X.capitalize() + "") + + CheckForDuplicateList.append(X) + Counter += 1 + + + self.CommonHeaderFileScala.write(" = Value\n }\n} ") self.SourceFile.write("const SYMBOL_MAP SemanticRulesMapList[]= {\n") @@ -458,13 +503,39 @@ class LL1Parser: for X in self.keywordList: self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n") - + for X in self.AssignmentOperator: + self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper().replace("_ASSIGNMENT", "") + "},\n") self.SourceFile.write("};\n") + CheckForDuplicateList = [] + self.CommonHeaderFile.write("\nstatic const char *const FunctionNames[] = {") + self.CommonHeaderFile.write("\n\"FUNC_UNDEFINED\""+ ",\n") + for X in self.OperatorsOneOperand: + if X not in CheckForDuplicateList: + self.CommonHeaderFile.write("\"" + "FUNC_" + X.upper() + "\"" + ",\n") + CheckForDuplicateList.append(X) + + for X in self.OperatorsTwoOperand: + if X not in CheckForDuplicateList: + self.CommonHeaderFile.write("\"" + "FUNC_" + X.upper() + "\"" + ",\n") + CheckForDuplicateList.append(X) + + for X in self.SemantiRulesList: + if X not in CheckForDuplicateList: + self.CommonHeaderFile.write("\"" + "FUNC_" + X.upper() + "\"" + ",\n") + CheckForDuplicateList.append(X) + + for X in self.keywordList: + if X not in CheckForDuplicateList: + self.CommonHeaderFile.write("\"" + "FUNC_" + X.upper() + "\"" + ",\n") + CheckForDuplicateList.append(X) + + self.CommonHeaderFile.write("};\n") + def WriteRegisterMaps(self): - self.CommonHeaderFile.write("typedef enum REGS_ENUM {\n") + self.CommonHeaderFile.write("\ntypedef enum REGS_ENUM {\n") Counter = 0 for X in self.RegistersList: if Counter == len(self.RegistersList)-1: @@ -523,6 +594,19 @@ class LL1Parser: Counter +=1 self.SourceFile.write("};\n") + def WriteVariableTypeList(self): + self.SourceFile.write("const char* ScriptVariableTypeList[]= {\n") + self.HeaderFile.write("extern const char* ScriptVariableTypeList[];\n") + + Counter = 0 + for X in self.VariableTypeList: + if Counter == len(self.VariableTypeList)-1: + self.SourceFile.write("\"" + X + "\"" + "\n") + else: + self.SourceFile.write("\"" + X + "\"" + ",\n") + Counter +=1 + self.SourceFile.write("};\n") + def WriteKeywordList(self): self.SourceFile.write("const char* KeywordList[]= {\n") self.HeaderFile.write("extern const char* KeywordList[];\n") @@ -561,6 +645,20 @@ class LL1Parser: Counter +=1 self.SourceFile.write("};\n") + self.SourceFile.write("const char* AssignmentOperatorList[]= {\n") + self.HeaderFile.write("extern const char* AssignmentOperatorList[];\n") + + Counter = 0 + for X in self.AssignmentOperator: + if Counter == len(self.AssignmentOperator)-1: + self.SourceFile.write("\"" + "@"+ X.upper() + "\"" + "\n") + else: + self.SourceFile.write("\"" + "@"+ X.upper() + "\"" + ",\n") + Counter +=1 + self.SourceFile.write("};\n") + + + def WriteMaps(self): for Key in self.FunctionsDict: print(Key) @@ -581,8 +679,8 @@ class LL1Parser: def WriteLhsList(self): - self.SourceFile.write("const struct _TOKEN Lhs[RULES_COUNT]= \n{\n") - self.HeaderFile.write("extern const struct _TOKEN Lhs[RULES_COUNT];\n") + self.SourceFile.write("const struct _SCRIPT_ENGINE_TOKEN Lhs[RULES_COUNT]= \n{\n") + self.HeaderFile.write("extern const struct _SCRIPT_ENGINE_TOKEN Lhs[RULES_COUNT];\n") Counter = 0 for Lhs in self.LhsList: if Counter == len(self.LhsList)-1: @@ -610,8 +708,8 @@ class LL1Parser: def WriteRhsList(self): - self.SourceFile.write("const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= \n{\n") - self.HeaderFile.write("extern const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN];\n") + self.SourceFile.write("const struct _SCRIPT_ENGINE_TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= \n{\n") + self.HeaderFile.write("extern const struct _SCRIPT_ENGINE_TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN];\n") Counter =0 for Rhs in self.RhsList: self.SourceFile.write("\t{") diff --git a/hyperdbg/script-engine/script-engine.vcxproj b/hyperdbg/script-engine/script-engine.vcxproj index 46bbecb5..e6abe194 100644 --- a/hyperdbg/script-engine/script-engine.vcxproj +++ b/hyperdbg/script-engine/script-engine.vcxproj @@ -21,14 +21,14 @@ DynamicLibrary true - v143 + v145 Unicode false DynamicLibrary false - v143 + v145 true Unicode @@ -65,6 +65,7 @@ MultiThreadedDebug $(SolutionDir)\script-engine\header;$(SolutionDir)\include;$(SolutionDir)\script-engine;$(SolutionDir)\script-eval;%(AdditionalIncludeDirectories) true + stdcpp20 Windows @@ -74,8 +75,17 @@ true - - + set "SRC=$(ProjectDir)script" +set "DST=$(TargetDir)script" + +if not exist "%DST%" mkdir "%DST%" + +robocopy "%SRC%" "%DST%" /E /NFL /NDL /NJH /NJS /NP +set "RC=%ERRORLEVEL%" + +if %RC% GEQ 8 exit /b %RC% +exit /b 0 + @@ -91,6 +101,8 @@ MultiThreaded $(SolutionDir)\script-engine\header;$(SolutionDir)\include;$(SolutionDir)\script-engine;$(SolutionDir)\script-eval;%(AdditionalIncludeDirectories) true + stdcpp20 + MaxSpeed Windows @@ -102,30 +114,45 @@ true - - + set "SRC=$(ProjectDir)script" +set "DST=$(TargetDir)script" + +if not exist "%DST%" mkdir "%DST%" + +robocopy "%SRC%" "%DST%" /E /NFL /NDL /NJH /NJS /NP +set "RC=%ERRORLEVEL%" + +if %RC% GEQ 8 exit /b %RC% +exit /b 0 + + + + + - + + + + Create + Create + + - - Create - Create - diff --git a/hyperdbg/script-engine/script-engine.vcxproj.filters b/hyperdbg/script-engine/script-engine.vcxproj.filters index 6f89306c..c41bb19a 100644 --- a/hyperdbg/script-engine/script-engine.vcxproj.filters +++ b/hyperdbg/script-engine/script-engine.vcxproj.filters @@ -9,11 +9,14 @@ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx + + {53ae7bcb-e612-4a1a-89db-de1e77f2d730} + + + {45bab125-0b6b-4791-bb0e-eace92a93baa} + - - header - header @@ -32,11 +35,20 @@ header + + header + + + header + + + header + + + header\platform + - - code - code @@ -55,5 +67,17 @@ code + + code + + + code + + + code + + + code\platform + \ No newline at end of file diff --git a/hyperdbg/script-engine/script/fibonacci.ds b/hyperdbg/script-engine/script/fibonacci.ds new file mode 100644 index 00000000..d9b19a27 --- /dev/null +++ b/hyperdbg/script-engine/script/fibonacci.ds @@ -0,0 +1,12 @@ +? { + + int myfibonacci(int var1) { + if (var1 == 0) { + return 0; + } + if (var1 == 1) { + return 1; + } + return myfibonacci(var1 - 1) + myfibonacci(var1 - 2); + } +} diff --git a/hyperdbg/script-engine/script/test.ds b/hyperdbg/script-engine/script/test.ds new file mode 100644 index 00000000..49dd1325 --- /dev/null +++ b/hyperdbg/script-engine/script/test.ds @@ -0,0 +1,8 @@ +? { + void my_func(int var, int var2) { + printf("var = %d, var2 = %d\n", var, var2); + return; + printf("this statement is never shown!\n"); + } + +} diff --git a/hyperdbg/script-eval/code/Functions.c b/hyperdbg/script-eval/code/Functions.c index fa2b0715..17b0fc0e 100644 --- a/hyperdbg/script-eval/code/Functions.c +++ b/hyperdbg/script-eval/code/Functions.c @@ -26,15 +26,11 @@ extern BOOLEAN g_CurrentExprEvalResultHasError; // *** Definitions *** // UINT64 -GetValue(PGUEST_REGS GuestRegs, - PACTION_BUFFER ActionBuffer, - SCRIPT_ENGINE_VARIABLES_LIST * VariablesList, - PSYMBOL Symbol, - BOOLEAN ReturnReference, - SYMBOL_BUFFER * StackBuffer, - int * StackIndx, - int * StackBaseIndx, - int * StackTempBaseIndx); +GetValue(PGUEST_REGS GuestRegs, + PACTION_BUFFER ActionBuffer, + PSCRIPT_ENGINE_GENERAL_REGISTERS ScriptGeneralRegisters, + PSYMBOL Symbol, + BOOLEAN ReturnReference); // // *** Functions *** @@ -157,6 +153,132 @@ ScriptEngineFunctionEb(UINT64 Address, BYTE Value, BOOL * HasError) return TRUE; } +/** + * @brief Implementation of eq function (Physical Memory) + * + * @param Address + * @param Value + * @param HasError + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineFunctionEqPa(UINT64 Address, QWORD Value, BOOL * HasError) +{ + UNREFERENCED_PARAMETER(HasError); + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + if (!CheckAddressPhysical(Address)) + { + // + // Instead of indicating an error, just return false + // to assign it as a return result to a variable + // + // *HasError = TRUE; + + return FALSE; + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE + +#ifdef SCRIPT_ENGINE_USER_MODE + + ShowMessages("err, using physical address functions (eq_pa) is not possible in user-mode\n"); + return FALSE; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + MemoryMapperWriteMemorySafeByPhysicalAddress(Address, (UINT64)&Value, sizeof(QWORD)); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return TRUE; +} + +/** + * @brief Implementation of ed function (Physical Memory) + * + * @param Address + * @param Value + * @param HasError + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineFunctionEdPa(UINT64 Address, DWORD Value, BOOL * HasError) +{ + UNREFERENCED_PARAMETER(HasError); + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + if (!CheckAddressPhysical(Address)) + { + // + // Instead of indicating an error, just return false + // to assign it as a return result to a variable + // + // *HasError = TRUE; + + return FALSE; + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE + +#ifdef SCRIPT_ENGINE_USER_MODE + + ShowMessages("err, using physical address functions (ed_pa) is not possible in user-mode\n"); + return FALSE; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + MemoryMapperWriteMemorySafeByPhysicalAddress(Address, (UINT64)&Value, sizeof(DWORD)); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return TRUE; +} + +/** + * @brief Implementation of eb function (Physical Memory) + * + * @param Address + * @param Value + * @param HasError + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineFunctionEbPa(UINT64 Address, BYTE Value, BOOL * HasError) +{ + UNREFERENCED_PARAMETER(HasError); + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + if (!CheckAddressPhysical(Address)) + { + // + // Instead of indicating an error, just return false + // to assign it as a return result to a variable + // + // *HasError = TRUE; + + return FALSE; + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE + +#ifdef SCRIPT_ENGINE_USER_MODE + + ShowMessages("err, using physical address functions (eb_pa) is not possible in user-mode\n"); + return FALSE; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + MemoryMapperWriteMemorySafeByPhysicalAddress(Address, (UINT64)&Value, sizeof(BYTE)); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return TRUE; +} + /** * @brief Check whether the address is valid or not * @@ -203,6 +325,17 @@ ScriptEngineFunctionMemcpy(UINT64 Destination, UINT64 Source, UINT32 Num, BOOL * UINT64 PrevReadLen = 0; BYTE MovingBuffer[DebuggerScriptEngineMemcpyMovingBufferSize] = {0}; + // + // Reject zero-length copies: a Num of 0 would pass address-range + // validation vacuously (checking 0 bytes at any mapped page succeeds), + // which could be abused as a kernel address-mapping oracle. + // + if (Num == 0) + { + *HasError = TRUE; + return; + } + #ifdef SCRIPT_ENGINE_USER_MODE // @@ -307,6 +440,108 @@ ScriptEngineFunctionMemcpy(UINT64 Destination, UINT64 Source, UINT32 Num, BOOL * #endif // SCRIPT_ENGINE_KERNEL_MODE } +/** + * @brief A VMX-compatible equivalent of memcpy function in C for physical memory + * + * @param Destination + * @param Source + * @param Num + * @param HasError + * @return VOID + */ +VOID +ScriptEngineFunctionMemcpyPa(UINT64 Destination, UINT64 Source, UINT32 Num, BOOL * HasError) +{ + UINT64 PrevReadLen = 0; + BYTE MovingBuffer[DebuggerScriptEngineMemcpyMovingBufferSize] = {0}; + +#ifdef SCRIPT_ENGINE_USER_MODE + + // + // Show an error message in user-mode + // + ShowMessages("err, using physical address functions (memcpy_pa) is not possible in user-mode\n"); + return; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + // + // Check the destination address (physical) + // + if (!CheckAddressPhysical(Destination)) + { + *HasError = TRUE; + return; + } + + // + // Check the source address (physical) + // + if (!CheckAddressPhysical(Source)) + { + *HasError = TRUE; + return; + } + + // + // Address is valid, perform the memcpy in kernel-mode (VMX-root mode) + // + while (Num > 0) + { + // + // Check the target buffer size + // + if (Num > DebuggerScriptEngineMemcpyMovingBufferSize) + { + // + // *** The size of read buffer is greater to maximum the moving buffer size *** + // + + // + // Read memory into the buffer + // + MemoryMapperReadMemorySafeByPhysicalAddress(Source + PrevReadLen, (UINT64)MovingBuffer, DebuggerScriptEngineMemcpyMovingBufferSize); + + // + // Write the moving buffer into the target buffer + // + MemoryMapperWriteMemorySafeByPhysicalAddress(Destination + PrevReadLen, (UINT64)MovingBuffer, DebuggerScriptEngineMemcpyMovingBufferSize); + + // + // Computing the bytes that we read + // + PrevReadLen += DebuggerScriptEngineMemcpyMovingBufferSize; + Num -= DebuggerScriptEngineMemcpyMovingBufferSize; + } + else + { + // + // *** The size of read buffer is lower than or equal to the moving buffer size *** + // + + // + // Read memory into the buffer + // + MemoryMapperReadMemorySafeByPhysicalAddress(Source + PrevReadLen, (UINT64)MovingBuffer, Num); + + // + // Write the moving buffer into the target buffer + // + MemoryMapperWriteMemorySafeByPhysicalAddress(Destination + PrevReadLen, (UINT64)MovingBuffer, Num); + + // + // Computing the bytes that we gonna read + // + PrevReadLen += Num; + Num = 0; // or Num -= Num; + } + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE +} + // // Convert virtual address to physical address // @@ -373,7 +608,7 @@ ScriptEngineFunctionPrint(UINT64 Tag, BOOLEAN ImmediateMessagePassing, UINT64 Va // Prepare a buffer to bypass allocating a huge stack space for logging // char TempBuffer[20] = {0}; - UINT32 TempBufferLen = sprintf(TempBuffer, "%llx", Value); + UINT32 TempBufferLen = sprintf(TempBuffer, "%llx\n", Value); LogSimpleWithTag((UINT32)Tag, ImmediateMessagePassing, TempBuffer, TempBufferLen + 1); @@ -557,6 +792,68 @@ ScriptEngineFunctionWcslen(const wchar_t * Address) return Result; } +#ifdef SCRIPT_ENGINE_USER_MODE +VOID +UserModeMicroSleep(UINT64 Us) +{ + LARGE_INTEGER Start, End, Frequency; + PlatformQueryPerformanceFrequency(&Frequency); + + LONGLONG TickPerUs = Frequency.QuadPart / 1000000; + LONGLONG Ticks = TickPerUs * Us; + + PlatformQueryPerformanceCounter(&Start); + + while (TRUE) + { + PlatformQueryPerformanceCounter(&End); + + if (End.QuadPart - Start.QuadPart > Ticks) + { + break; + } + } +} +#endif // SCRIPT_ENGINE_USER_MODE + +/** + * @brief Implementation of microsleep function + * + * @param Us delay in micro second + */ +VOID +ScriptEngineFunctionMicroSleep(UINT64 Us) +{ +#ifdef SCRIPT_ENGINE_USER_MODE + UserModeMicroSleep(Us); +#endif + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + VmFuncVmxCompatibleMicroSleep(Us); +#endif +} + +/** + * @brief Implementation of rdtsc function + * + */ +UINT64 +ScriptEngineFunctionRdtsc() +{ + return CpuReadTsc(); +} + +/** + * @brief Implementation of rdtscp function + * + */ +UINT64 +ScriptEngineFunctionRdtscp() +{ + UINT32 Aux; + return CpuReadTscp(&Aux); +} + /** * @brief Implementation of interlocked_exchange function * @@ -582,7 +879,7 @@ ScriptEngineFunctionInterlockedExchange(long long volatile * Target, #endif // SCRIPT_ENGINE_KERNEL_MODE - Result = InterlockedExchange64(Target, Value); + Result = CpuInterlockedExchange64(Target, Value); return Result; } @@ -612,7 +909,7 @@ ScriptEngineFunctionInterlockedExchangeAdd(long long volatile * Addend, #endif // SCRIPT_ENGINE_KERNEL_MODE - Result = InterlockedExchangeAdd64(Addend, Value); + Result = CpuInterlockedExchangeAdd64(Addend, Value); return Result; } @@ -640,7 +937,7 @@ ScriptEngineFunctionInterlockedIncrement(long long volatile * Addend, #endif // SCRIPT_ENGINE_KERNEL_MODE - Result = InterlockedIncrement64(Addend); + Result = CpuInterlockedIncrement64(Addend); return Result; } @@ -668,7 +965,7 @@ ScriptEngineFunctionInterlockedDecrement(long long volatile * Addend, #endif // SCRIPT_ENGINE_KERNEL_MODE - Result = InterlockedDecrement64(Addend); + Result = CpuInterlockedDecrement64(Addend); return Result; } @@ -701,7 +998,7 @@ ScriptEngineFunctionInterlockedCompareExchange( #endif // SCRIPT_ENGINE_KERNEL_MODE - Result = InterlockedCompareExchange64(Destination, ExChange, Comperand); + Result = CpuInterlockedCompareExchange64(Destination, ExChange, Comperand); return Result; } @@ -939,6 +1236,10 @@ ScriptEngineFunctionFormats(UINT64 Tag, BOOLEAN ImmediateMessagePassing, UINT64 { KdSendFormatsFunctionResult(Value); } + else if (g_UserDebuggerState) + { + UdSendFormatsFunctionResult(Value); + } else { // @@ -1037,7 +1338,7 @@ ApplyFormatSpecifier(const CHAR * CurrentSpecifier, CHAR * FinalBuffer, PUINT32 *CurrentProcessedPositionFromStartOfFormat = *CurrentProcessedPositionFromStartOfFormat + (UINT32)strlen(CurrentSpecifier); - sprintf(TempBuffer, CurrentSpecifier, Val); + PlatformSprintf(TempBuffer, sizeof(TempBuffer), CurrentSpecifier, Val); TempBufferLen = (UINT32)strlen(TempBuffer); // @@ -1172,8 +1473,8 @@ ApplyStringFormatSpecifier(const CHAR * CurrentSpecifier, CHAR * FinalBuffer, PU // // Zero the buffers // - RtlZeroMemory(WstrBuffer, sizeof(WstrBuffer)); - RtlZeroMemory(AsciiBuffer, sizeof(AsciiBuffer)); + PlatformZeroMemory(WstrBuffer, sizeof(WstrBuffer)); + PlatformZeroMemory(AsciiBuffer, sizeof(AsciiBuffer)); // // Check for the last block @@ -1257,7 +1558,7 @@ ApplyStringFormatSpecifier(const CHAR * CurrentSpecifier, CHAR * FinalBuffer, PU * * @param GuestRegs * @param ActionDetail - * @param VariablesList + * @param ScriptGeneralRegisters * @param Tag * @param ImmediateMessagePassing * @param Format @@ -1267,19 +1568,15 @@ ApplyStringFormatSpecifier(const CHAR * CurrentSpecifier, CHAR * FinalBuffer, PU * @return VOID */ VOID -ScriptEngineFunctionPrintf(PGUEST_REGS GuestRegs, - ACTION_BUFFER * ActionDetail, - SCRIPT_ENGINE_VARIABLES_LIST * VariablesList, - UINT64 Tag, - BOOLEAN ImmediateMessagePassing, - char * Format, - UINT64 ArgCount, - PSYMBOL FirstArg, - BOOLEAN * HasError, - SYMBOL_BUFFER * StackBuffer, - int * StackIndx, - int * StackBaseIndx, - int * StackTempBaseIndx) +ScriptEngineFunctionPrintf(PGUEST_REGS GuestRegs, + ACTION_BUFFER * ActionDetail, + SCRIPT_ENGINE_GENERAL_REGISTERS * ScriptGeneralRegisters, + UINT64 Tag, + BOOLEAN ImmediateMessagePassing, + char * Format, + UINT64 ArgCount, + PSYMBOL FirstArg, + BOOLEAN * HasError) { // // *** The printf function *** @@ -1312,14 +1609,11 @@ ScriptEngineFunctionPrintf(PGUEST_REGS GuestRegs, memcpy(&TempSymbol, Symbol, sizeof(SYMBOL)); TempSymbol.Type &= 0x7fffffff; - Val = GetValue(GuestRegs, ActionDetail, VariablesList, &TempSymbol, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + Val = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, &TempSymbol, FALSE); CHAR PercentageChar = Format[Position]; - /* - printf("position = %d is %c%c \n", Position, PercentageChar, - IndicatorChar1); - */ + // printf("position = %d is %c%c \n", Position, PercentageChar, IndicatorChar1); if (CurrentProcessedPositionFromStartOfFormat != Position) { @@ -1572,6 +1866,7 @@ ScriptEngineFunctionEventInjectErrorCode(UINT32 InterruptionType, UINT32 Vector, * * @param Address1 * @param Address2 + * * @return UINT64 */ UINT64 @@ -1589,11 +1884,36 @@ ScriptEngineFunctionStrcmp(const char * Address1, const char * Address2) return Result; } +/** + * @brief Implementation of strcmp function + * + * @param Address1 + * @param Address2 + * @param Num + * + * @return UINT64 + */ +UINT64 +ScriptEngineFunctionStrncmp(const char * Address1, const char * Address2, size_t Num) +{ + UINT64 Result = 0; +#ifdef SCRIPT_ENGINE_USER_MODE + Result = strncmp(Address1, Address2, Num); +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + Result = VmFuncVmxCompatibleStrncmp(Address1, Address2, Num); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return Result; +} + /** * @brief Implementation of wcscmp function * * @param Address1 * @param Address2 + * * @return UINT64 */ UINT64 @@ -1611,6 +1931,30 @@ ScriptEngineFunctionWcscmp(const wchar_t * Address1, const wchar_t * Address2) return Result; } +/** + * @brief Implementation of wcsncmp function + * + * @param Address1 + * @param Address2 + * @param Num + * + * @return UINT64 + */ +UINT64 +ScriptEngineFunctionWcsncmp(const wchar_t * Address1, const wchar_t * Address2, size_t Num) +{ + UINT64 Result = 0; +#ifdef SCRIPT_ENGINE_USER_MODE + Result = wcsncmp(Address1, Address2, Num); +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + Result = VmFuncVmxCompatibleWcsncmp(Address1, Address2, Num); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return Result; +} + /** * @brief Implementation of memcmp function * @@ -1672,12 +2016,116 @@ ScriptEngineFunctionEventTraceStepIn() #ifdef SCRIPT_ENGINE_KERNEL_MODE - ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL); - // // Call instrumentation step in // - TracingPerformRegularStepInInstruction(&g_DbgState[CurrentCore]); + TracingPerformRegularStepInInstruction(); + +#endif // SCRIPT_ENGINE_KERNEL_MODE +} + +/** + * @brief Implementation of lbr_save function + * + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineFunctionLbrSave() +{ +#ifdef SCRIPT_ENGINE_USER_MODE + ShowMessages("err, it's not possible to call lbr_save function in the user-mode\n"); + return FALSE; +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + // + // Depending if we are in VMX-root then a VMCALL is issued by default instead, otherwise the VMCALL is ignored + // + return HyperTraceLbrSave(NULL); + +#endif // SCRIPT_ENGINE_KERNEL_MODE +} + +/** + * @brief Implementation of lbr_print function + * + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineFunctionLbrPrint() +{ +#ifdef SCRIPT_ENGINE_USER_MODE + ShowMessages("err, it's not possible to call lbr_print function in the user-mode\n"); + return FALSE; +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + // + // Depending if we are in VMX-root then a VMCALL is issued by default instead, otherwise the VMCALL is ignored + // + return HyperTraceLbrPrint(NULL); + +#endif // SCRIPT_ENGINE_KERNEL_MODE +} + +/** + * @brief Implementation of lbr_check function + * + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineFunctionLbrCheck() +{ +#ifdef SCRIPT_ENGINE_USER_MODE + ShowMessages("err, it's not possible to call lbr_check function in the user-mode\n"); + return FALSE; +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + return HyperTraceLbrCheck(); + +#endif // SCRIPT_ENGINE_KERNEL_MODE +} + +/** + * @brief Implementation of lbr_restore function + * + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineFunctionLbrRestore() +{ +#ifdef SCRIPT_ENGINE_USER_MODE + ShowMessages("err, it's not possible to call lbr_restore function in the user-mode\n"); + return FALSE; +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + return HyperTraceLbrRestore(); + +#endif // SCRIPT_ENGINE_KERNEL_MODE +} + +/** + * @brief Implementation of lbr_restore_by_filter function + * + * @return BOOLEAN + */ +BOOLEAN +ScriptEngineFunctionLbrRestoreByFilter(UINT64 FilterOptions) +{ +#ifdef SCRIPT_ENGINE_USER_MODE + ShowMessages("err, it's not possible to call lbr_restore_by_filter function in the user-mode\n"); + return FALSE; +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + return HyperTraceLbrRestoreByFilter(FilterOptions); #endif // SCRIPT_ENGINE_KERNEL_MODE } diff --git a/hyperdbg/script-eval/code/Keywords.c b/hyperdbg/script-eval/code/Keywords.c index bb641570..cb3a29de 100644 --- a/hyperdbg/script-eval/code/Keywords.c +++ b/hyperdbg/script-eval/code/Keywords.c @@ -16,6 +16,12 @@ // *** Keywords *** // +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// // +// For Virtual Memory // +// // +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** * @brief Implementation of poi keyword * @@ -253,3 +259,268 @@ ScriptEngineKeywordDq(PUINT64 Address, BOOL * HasError) return Result; } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// // +// For Physical Memory // +// // +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Implementation of poi_pa keyword + * + * @param Address + * @param HasError + * @return UINT64 + */ +UINT64 +ScriptEngineKeywordPoiPa(PUINT64 Address, BOOL * HasError) +{ + UINT64 Result = (UINT64)NULL; + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + if (!CheckAddressPhysical((UINT64)Address)) + { + *HasError = TRUE; + + return (UINT64)NULL; + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE + +#ifdef SCRIPT_ENGINE_USER_MODE + + ShowMessages("err, using physical address keywords (poi_pa) is not possible in user-mode\n"); + return (UINT64)NULL; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + MemoryMapperReadMemorySafeByPhysicalAddress((UINT64)Address, (UINT64)&Result, sizeof(UINT64)); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return Result; +} + +/** + * @brief Implementation of hi keyword + * + * @param Address + * @param HasError + * @return WORD + */ +WORD +ScriptEngineKeywordHiPa(PUINT64 Address, BOOL * HasError) +{ + QWORD Result = NULL64_ZERO; + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + if (!CheckAddressPhysical((UINT64)Address)) + { + *HasError = TRUE; + + return NULL64_ZERO; + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE + +#ifdef SCRIPT_ENGINE_USER_MODE + + ShowMessages("err, using physical address keywords (hi_pa) is not possible in user-mode\n"); + return (WORD)NULL; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + MemoryMapperReadMemorySafeByPhysicalAddress((UINT64)Address, (UINT64)&Result, sizeof(UINT64)); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return HIWORD(Result); +} + +/** + * @brief Implementation of low keyword + * + * @param Address + * @param HasError + * @return WORD + */ +WORD +ScriptEngineKeywordLowPa(PUINT64 Address, BOOL * HasError) +{ + QWORD Result = NULL64_ZERO; + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + if (!CheckAddressPhysical((UINT64)Address)) + { + *HasError = TRUE; + + return NULL64_ZERO; + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE + +#ifdef SCRIPT_ENGINE_USER_MODE + + ShowMessages("err, using physical address keywords (low_pa) is not possible in user-mode\n"); + return (WORD)NULL; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + MemoryMapperReadMemorySafeByPhysicalAddress((UINT64)Address, (UINT64)&Result, sizeof(UINT64)); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return LOWORD(Result); +} + +/** + * @brief Implementation of db keyword + * + * @param Address + * @param HasError + * @return BYTE + */ +BYTE +ScriptEngineKeywordDbPa(PUINT64 Address, BOOL * HasError) +{ + BYTE Result = NULL_ZERO; + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + if (!CheckAddressPhysical((UINT64)Address)) + { + *HasError = TRUE; + + return NULL_ZERO; + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE + +#ifdef SCRIPT_ENGINE_USER_MODE + + ShowMessages("err, using physical address keywords (db_pa) is not possible in user-mode\n"); + return (BYTE)NULL; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + MemoryMapperReadMemorySafeByPhysicalAddress((UINT64)Address, (UINT64)&Result, sizeof(BYTE)); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return Result; +} + +/** + * @brief Implementation of dd keyword + * + * @param Address + * @param HasError + * @return DWORD + */ +DWORD +ScriptEngineKeywordDdPa(PUINT64 Address, BOOL * HasError) +{ + DWORD Result = NULL_ZERO; + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + if (!CheckAddressPhysical((UINT64)Address)) + { + *HasError = TRUE; + + return NULL_ZERO; + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE + +#ifdef SCRIPT_ENGINE_USER_MODE + + ShowMessages("err, using physical address keywords (dd_pa) is not possible in user-mode\n"); + return (DWORD)NULL; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + MemoryMapperReadMemorySafeByPhysicalAddress((UINT64)Address, (UINT64)&Result, sizeof(DWORD)); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return Result; +} + +/** + * @brief Implementation of dw keyword + * + * @param Address + * @param HasError + * @return WORD + */ +WORD +ScriptEngineKeywordDwPa(PUINT64 Address, BOOL * HasError) +{ + WORD Result = NULL_ZERO; + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + if (!CheckAddressPhysical((UINT64)Address)) + { + *HasError = TRUE; + + return NULL_ZERO; + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE + +#ifdef SCRIPT_ENGINE_USER_MODE + + ShowMessages("err, using physical address keywords (dw_pa) is not possible in user-mode\n"); + return (WORD)NULL; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + MemoryMapperReadMemorySafeByPhysicalAddress((UINT64)Address, (UINT64)&Result, sizeof(WORD)); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return Result; +} + +/** + * @brief Implementation of dq keyword + * + * @param Address + * @param HasError + * @return QWORD + */ +QWORD +ScriptEngineKeywordDqPa(PUINT64 Address, BOOL * HasError) +{ + QWORD Result = (QWORD)NULL; + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + if (!CheckAddressPhysical((UINT64)Address)) + { + *HasError = TRUE; + + return (QWORD)NULL; + } + +#endif // SCRIPT_ENGINE_KERNEL_MODE + +#ifdef SCRIPT_ENGINE_USER_MODE + + ShowMessages("err, using physical address keywords (dq_pa) is not possible in user-mode\n"); + return (QWORD)NULL; + +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + MemoryMapperReadMemorySafeByPhysicalAddress((UINT64)Address, (UINT64)&Result, sizeof(QWORD)); +#endif // SCRIPT_ENGINE_KERNEL_MODE + + return Result; +} diff --git a/hyperdbg/script-eval/code/PseudoRegisters.c b/hyperdbg/script-eval/code/PseudoRegisters.c index 3654892d..493c8a6f 100644 --- a/hyperdbg/script-eval/code/PseudoRegisters.c +++ b/hyperdbg/script-eval/code/PseudoRegisters.c @@ -25,11 +25,11 @@ UINT64 ScriptEnginePseudoRegGetTid() { #ifdef SCRIPT_ENGINE_USER_MODE - return (UINT64)GetCurrentThreadId(); + return (UINT64)PlatformGetCurrentThreadId(); #endif // SCRIPT_ENGINE_USER_MODE #ifdef SCRIPT_ENGINE_KERNEL_MODE - return (UINT64)PsGetCurrentThreadId(); + return (UINT64)PlatformProcessGetCurrentThreadId(); #endif // SCRIPT_ENGINE_KERNEL_MODE } @@ -42,11 +42,11 @@ UINT64 ScriptEnginePseudoRegGetCore() { #ifdef SCRIPT_ENGINE_USER_MODE - return (UINT64)GetCurrentProcessorNumber(); + return (UINT64)PlatformGetCurrentProcessorNumber(); #endif // SCRIPT_ENGINE_USER_MODE #ifdef SCRIPT_ENGINE_KERNEL_MODE - return (UINT64)KeGetCurrentProcessorNumberEx(NULL); + return (UINT64)PlatformCpuGetCurrentProcessorNumber(); #endif // SCRIPT_ENGINE_KERNEL_MODE } @@ -59,11 +59,11 @@ UINT64 ScriptEnginePseudoRegGetPid() { #ifdef SCRIPT_ENGINE_USER_MODE - return (UINT64)GetCurrentProcessId(); + return (UINT64)PlatformGetCurrentProcessId(); #endif // SCRIPT_ENGINE_USER_MODE #ifdef SCRIPT_ENGINE_KERNEL_MODE - return (UINT64)PsGetCurrentProcessId(); + return (UINT64)PlatformProcessGetCurrentProcessId(); #endif // SCRIPT_ENGINE_KERNEL_MODE } @@ -76,43 +76,11 @@ CHAR * ScriptEnginePseudoRegGetPname() { #ifdef SCRIPT_ENGINE_USER_MODE - - HANDLE Handle = OpenProcess( - PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, - FALSE, - GetCurrentProcessId() /* Current process */ - ); - - if (Handle) - { - CHAR CurrentModulePath[MAX_PATH] = {0}; - if (GetModuleFileNameEx(Handle, 0, CurrentModulePath, MAX_PATH)) - { - // - // At this point, buffer contains the full path to the executable - // - CloseHandle(Handle); - return PathFindFileNameA(CurrentModulePath); - } - else - { - // - // error might be shown by GetLastError() - // - CloseHandle(Handle); - return NULL; - } - } - - // - // unable to get handle - // - return NULL; - + return PlatformGetCurrentProcessName(); #endif // SCRIPT_ENGINE_USER_MODE #ifdef SCRIPT_ENGINE_KERNEL_MODE - return CommonGetProcessNameFromProcessControlBlock(PsGetCurrentProcess()); + return CommonGetProcessNameFromProcessControlBlock(PlatformProcessGetCurrentProcess()); #endif // SCRIPT_ENGINE_KERNEL_MODE } @@ -129,7 +97,7 @@ ScriptEnginePseudoRegGetProc() #endif // SCRIPT_ENGINE_USER_MODE #ifdef SCRIPT_ENGINE_KERNEL_MODE - return (UINT64)PsGetCurrentProcess(); + return (UINT64)PlatformProcessGetCurrentProcess(); #endif // SCRIPT_ENGINE_KERNEL_MODE } @@ -146,7 +114,7 @@ ScriptEnginePseudoRegGetThread() #endif // SCRIPT_ENGINE_USER_MODE #ifdef SCRIPT_ENGINE_KERNEL_MODE - return (UINT64)PsGetCurrentThread(); + return (UINT64)PlatformProcessGetCurrentThread(); #endif // SCRIPT_ENGINE_KERNEL_MODE } @@ -159,6 +127,7 @@ UINT64 ScriptEnginePseudoRegGetPeb() { #ifdef SCRIPT_ENGINE_USER_MODE +# ifdef _WIN32 // // Hand-rolled structs ( may cause conflict depending on your dev env ) // @@ -269,6 +238,22 @@ ScriptEnginePseudoRegGetPeb() return (UINT64)PebPtr; +# else // !_WIN32 + + // + // The PEB (Process Environment Block) is a Windows NT-specific structure + // maintained by the kernel for every user-mode process. It holds loader + // data, heap pointers, the image path, and other process-wide state that + // has no direct equivalent in the Linux process model. + // + // TODO: investigate whether a meaningful substitute exists on Linux + // (e.g. /proc/self/maps, dl_iterate_phdr, or a custom auxv walk) + // and implement it here if HyperDbg user-mode on Linux ever needs $peb. + // + return 0; + +# endif // _WIN32 + #endif // SCRIPT_ENGINE_USER_MODE #ifdef SCRIPT_ENGINE_KERNEL_MODE @@ -293,7 +278,7 @@ ScriptEnginePseudoRegGetTeb() #endif // SCRIPT_ENGINE_USER_MODE #ifdef SCRIPT_ENGINE_KERNEL_MODE - return (UINT64)PsGetCurrentThreadTeb(); + return (UINT64)PlatformProcessGetCurrentThreadTeb(); #endif // SCRIPT_ENGINE_KERNEL_MODE } @@ -391,3 +376,45 @@ ScriptEnginePseudoRegGetEventStage(PACTION_BUFFER ActionBuffer) return ActionBuffer->CallingStage; #endif // SCRIPT_ENGINE_KERNEL_MODE } + +/** + * @brief Implementation of time pseudo-register + * + * @return UINT64 + */ +UINT64 +ScriptEnginePseudoRegGetTime() +{ +#ifdef SCRIPT_ENGINE_USER_MODE + return NULL; +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + // + // Get the current core's time + // + return ScriptEngineGetTargetCoreTime(); +#endif // SCRIPT_ENGINE_KERNEL_MODE +} + +/** + * @brief Implementation of date pseudo-register + * + * @return UINT64 + */ +UINT64 +ScriptEnginePseudoRegGetDate() +{ +#ifdef SCRIPT_ENGINE_USER_MODE + return NULL; +#endif // SCRIPT_ENGINE_USER_MODE + +#ifdef SCRIPT_ENGINE_KERNEL_MODE + + // + // Get the current core's date + // + return ScriptEngineGetTargetCoreDate(); +#endif // SCRIPT_ENGINE_KERNEL_MODE +} diff --git a/hyperdbg/script-eval/code/Regs.c b/hyperdbg/script-eval/code/Regs.c index 6abbf082..7734e2cb 100644 --- a/hyperdbg/script-eval/code/Regs.c +++ b/hyperdbg/script-eval/code/Regs.c @@ -12,6 +12,23 @@ */ #include "pch.h" +#if defined(SCRIPT_ENGINE_USER_MODE) && defined(HYPERDBG_LIBHYPERDBG) +extern BOOLEAN g_HwdbgInstanceInfoIsValid; +#endif // defined(SCRIPT_ENGINE_USER_MODE) && defined(HYPERDBG_LIBHYPERDBG) + +/** + * @brief Get the register value for hardware debugging + * + * @param Regs + * @param RegId + * @return UINT64 + */ +UINT64 +GetRegValueHwdbg(UINT64 * Regs, UINT32 RegId) +{ + return Regs[RegId]; +} + /** * @brief Get the register value * @@ -22,6 +39,13 @@ UINT64 GetRegValue(PGUEST_REGS GuestRegs, REGS_ENUM RegId) { +#if defined(SCRIPT_ENGINE_USER_MODE) && defined(HYPERDBG_LIBHYPERDBG) + if (g_HwdbgInstanceInfoIsValid) + { + return GetRegValueHwdbg((UINT64 *)GuestRegs, RegId); + } +#endif // defined(SCRIPT_ENGINE_USER_MODE) && defined(HYPERDBG_LIBHYPERDBG) + switch (RegId) { case REGISTER_RAX: @@ -950,18 +974,37 @@ GetRegValue(PGUEST_REGS GuestRegs, REGS_ENUM RegId) } } +/** + * @brief Set the register value for hardware debugging + * + * @param Regs + * @param RegisterId + * @param Value + * + * @return BOOLEAN + */ +BOOLEAN +SetRegValueHwdbg(UINT64 * Regs, UINT32 RegisterId, UINT64 Value) +{ + Regs[RegisterId] = Value; + return TRUE; +} + /** * @brief Set the register value * * @param GuestRegs - * @param Symbol + * @param RegisterId * @param Value - * @return VOID + * + * @return BOOLEAN */ -VOID -SetRegValue(PGUEST_REGS GuestRegs, PSYMBOL Symbol, UINT64 Value) +BOOLEAN +SetRegValue(PGUEST_REGS GuestRegs, UINT32 RegisterId, UINT64 Value) { - switch (Symbol->Value) + BOOLEAN Result = TRUE; + + switch (RegisterId) { case REGISTER_RAX: GuestRegs->rax = Value; @@ -1969,6 +2012,34 @@ SetRegValue(PGUEST_REGS GuestRegs, PSYMBOL Symbol, UINT64 Value) SetGuestDr7(Value); #endif // SCRIPT_ENGINE_KERNEL_MODE + break; + default: + Result = FALSE; break; } + + return Result; +} + +/** + * @brief Set the register value + * + * @param GuestRegs + * @param Symbol + * @param Value + * @param ActionBuffer + * + * @return BOOLEAN + */ +BOOLEAN +SetRegValueUsingSymbol(PGUEST_REGS GuestRegs, PSYMBOL Symbol, UINT64 Value) +{ +#if defined(SCRIPT_ENGINE_USER_MODE) && defined(HYPERDBG_LIBHYPERDBG) + if (g_HwdbgInstanceInfoIsValid == FALSE) + return SetRegValue(GuestRegs, (UINT32)Symbol->Value, Value); + else + return SetRegValueHwdbg((UINT64 *)GuestRegs, (UINT32)Symbol->Value, Value); +#else + return SetRegValue(GuestRegs, (UINT32)Symbol->Value, Value); +#endif // defined(SCRIPT_ENGINE_USER_MODE) && defined(HYPERDBG_LIBHYPERDBG) } diff --git a/hyperdbg/script-eval/code/ScriptEngineEval.c b/hyperdbg/script-eval/code/ScriptEngineEval.c index c178aad2..e3604f6d 100644 --- a/hyperdbg/script-eval/code/ScriptEngineEval.c +++ b/hyperdbg/script-eval/code/ScriptEngineEval.c @@ -11,7 +11,7 @@ * */ #include "pch.h" -#include "..\script-eval\header\ScriptEngineInternalHeader.h" +#include "../script-eval/header/ScriptEngineInternalHeader.h" /** * @brief Get the Pseudo reg value @@ -61,6 +61,10 @@ GetPseudoRegValue(PSYMBOL Symbol, PACTION_BUFFER ActionBuffer) return ScriptEnginePseudoRegGetEventId(ActionBuffer); case PSEUDO_REGISTER_EVENT_STAGE: return ScriptEnginePseudoRegGetEventStage(ActionBuffer); + case PSEUDO_REGISTER_TIME: + return ScriptEnginePseudoRegGetTime(); + case PSEUDO_REGISTER_DATE: + return ScriptEnginePseudoRegGetDate(); case INVALID: #ifdef SCRIPT_ENGINE_USER_MODE ShowMessages("error in reading regesiter"); @@ -79,41 +83,26 @@ GetPseudoRegValue(PSYMBOL Symbol, PACTION_BUFFER ActionBuffer) * * @param GuestRegs * @param ActionBuffer - * @param VariablesList + * @param ScriptGeneralRegisters * @param Symbol * @param ReturnReference * @return UINT64 */ UINT64 -GetValue(PGUEST_REGS GuestRegs, - PACTION_BUFFER ActionBuffer, - PSCRIPT_ENGINE_VARIABLES_LIST VariablesList, - PSYMBOL Symbol, - BOOLEAN ReturnReference, - SYMBOL_BUFFER * StackBuffer, - int * StackIndx, - int * StackBaseIndx, - int * StackTempBaseIndx) +GetValue(PGUEST_REGS GuestRegs, + PACTION_BUFFER ActionBuffer, + PSCRIPT_ENGINE_GENERAL_REGISTERS ScriptGeneralRegisters, + PSYMBOL Symbol, + BOOLEAN ReturnReference) { -#ifdef SCRIPT_ENGINE_KERNEL_MODE - UNREFERENCED_PARAMETER(StackIndx); -#endif // SCRIPT_ENGINE_KERNEL_MODE - switch (Symbol->Type) { case SYMBOL_GLOBAL_ID_TYPE: if (ReturnReference) - return ((UINT64)(&VariablesList->GlobalVariablesList[Symbol->Value])); + return ((UINT64)(&ScriptGeneralRegisters->GlobalVariablesList[Symbol->Value])); else - return VariablesList->GlobalVariablesList[Symbol->Value]; - - case SYMBOL_LOCAL_ID_TYPE: - - if (ReturnReference) - return ((UINT64)(&VariablesList->LocalVariablesList[Symbol->Value])); - else - return VariablesList->LocalVariablesList[Symbol->Value]; + return ScriptGeneralRegisters->GlobalVariablesList[Symbol->Value]; case SYMBOL_NUM_TYPE: @@ -136,28 +125,45 @@ GetValue(PGUEST_REGS GuestRegs, else return GetPseudoRegValue(Symbol, ActionBuffer); - case SYMBOL_TEMP_TYPE: + case SYMBOL_STACK_INDEX_TYPE: if (ReturnReference) - return ((UINT64)&VariablesList->TempList[Symbol->Value]); + return (UINT64)&ScriptGeneralRegisters->StackIndx; else - return VariablesList->TempList[Symbol->Value]; + return ScriptGeneralRegisters->StackIndx; - case SYMBOL_STACK_TEMP_TYPE: - { - PSYMBOL StackSymbol = NULL; + case SYMBOL_STACK_BASE_INDEX_TYPE: + if (ReturnReference) + return (UINT64)&ScriptGeneralRegisters->StackBaseIndx; + else + return ScriptGeneralRegisters->StackBaseIndx; + + case SYMBOL_RETURN_VALUE_TYPE: + if (ReturnReference) + return (UINT64)&ScriptGeneralRegisters->ReturnValue; + else + return ScriptGeneralRegisters->ReturnValue; + + case SYMBOL_TEMP_TYPE: + + if (ReturnReference) + return (UINT64)&ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackBaseIndx + Symbol->Value]; + else + return ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackBaseIndx + Symbol->Value]; + + case SYMBOL_REFERENCE_TEMP_TYPE: + + return (UINT64)&ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackBaseIndx + Symbol->Value]; + + case SYMBOL_DEREFERENCE_TEMP_TYPE: + + return *(UINT64 *)ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackBaseIndx + Symbol->Value]; - StackSymbol = (PSYMBOL)((unsigned long long)StackBuffer->Head + - (unsigned long long)((*StackTempBaseIndx + Symbol->Value) * sizeof(SYMBOL))); - return StackSymbol->Value; - } case SYMBOL_FUNCTION_PARAMETER_ID_TYPE: - { - PSYMBOL StackSymbol = NULL; - StackSymbol = (PSYMBOL)((unsigned long long)StackBuffer->Head + - (unsigned long long)((*StackBaseIndx + Symbol->Value) * sizeof(SYMBOL))); - return StackSymbol->Value; - } + if (ReturnReference) + return (UINT64)&ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackBaseIndx - 3 - Symbol->Value]; + else + return ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackBaseIndx - 3 - Symbol->Value]; } // @@ -170,56 +176,50 @@ GetValue(PGUEST_REGS GuestRegs, * @brief Set the value * * @param GuestRegs - * @param VariablesList + * @param ScriptGeneralRegisters * @param Symbol * @param Value * @return VOID */ VOID -SetValue(PGUEST_REGS GuestRegs, - SCRIPT_ENGINE_VARIABLES_LIST * VariablesList, - PSYMBOL Symbol, - UINT64 Value, - SYMBOL_BUFFER * StackBuffer, - int * StackIndx, - int * StackBaseIndx, - int * StackTempBaseIndx) +SetValue(PGUEST_REGS GuestRegs, + SCRIPT_ENGINE_GENERAL_REGISTERS * ScriptGeneralRegisters, + PSYMBOL Symbol, + UINT64 Value) { -#ifdef SCRIPT_ENGINE_KERNEL_MODE - UNREFERENCED_PARAMETER(StackIndx); -#endif // SCRIPT_ENGINE_KERNEL_MODE - switch (Symbol->Type) { case SYMBOL_GLOBAL_ID_TYPE: - VariablesList->GlobalVariablesList[Symbol->Value] = Value; - return; - case SYMBOL_LOCAL_ID_TYPE: - VariablesList->LocalVariablesList[Symbol->Value] = Value; - return; - case SYMBOL_TEMP_TYPE: - VariablesList->TempList[Symbol->Value] = Value; + ScriptGeneralRegisters->GlobalVariablesList[Symbol->Value] = Value; return; case SYMBOL_REGISTER_TYPE: - SetRegValue(GuestRegs, Symbol, Value); + SetRegValueUsingSymbol(GuestRegs, Symbol, Value); return; - case SYMBOL_STACK_TEMP_TYPE: - { - PSYMBOL StackSymbol = NULL; - StackSymbol = (PSYMBOL)((unsigned long long)StackBuffer->Head + - (unsigned long long)((*StackTempBaseIndx + Symbol->Value) * sizeof(SYMBOL))); - StackSymbol->Value = Value; + case SYMBOL_STACK_INDEX_TYPE: + ScriptGeneralRegisters->StackIndx = Value; return; - } + + case SYMBOL_STACK_BASE_INDEX_TYPE: + ScriptGeneralRegisters->StackBaseIndx = Value; + return; + + case SYMBOL_RETURN_VALUE_TYPE: + ScriptGeneralRegisters->ReturnValue = Value; + return; + + case SYMBOL_TEMP_TYPE: + ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackBaseIndx + Symbol->Value] = Value; + return; + + case SYMBOL_DEREFERENCE_TEMP_TYPE: + *(UINT64 *)ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackBaseIndx + Symbol->Value] = Value; + return; + case SYMBOL_FUNCTION_PARAMETER_ID_TYPE: - { - PSYMBOL StackSymbol = (PSYMBOL)((unsigned long long)StackBuffer->Head + - (unsigned long long)((*StackBaseIndx + Symbol->Value) * sizeof(SYMBOL))); - StackSymbol->Value = Value; + ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackBaseIndx - 3 - Symbol->Value] = Value; return; } - } } /** @@ -255,6 +255,27 @@ ScriptEngineGetOperatorName(PSYMBOL OperatorSymbol, CHAR * BufferForName) case FUNC_LOW: memcpy(BufferForName, "low", 3); break; + case FUNC_POI_PA: + memcpy(BufferForName, "poi_pa", 6); + break; + case FUNC_DB_PA: + memcpy(BufferForName, "db_pa", 5); + break; + case FUNC_DD_PA: + memcpy(BufferForName, "dd_pa", 5); + break; + case FUNC_DW_PA: + memcpy(BufferForName, "dw_pa", 5); + break; + case FUNC_DQ_PA: + memcpy(BufferForName, "dq_pa", 5); + break; + case FUNC_HI_PA: + memcpy(BufferForName, "hi_pa", 5); + break; + case FUNC_LOW_PA: + memcpy(BufferForName, "low_pa", 6); + break; default: memcpy(BufferForName, "error", 5); break; @@ -266,23 +287,19 @@ ScriptEngineGetOperatorName(PSYMBOL OperatorSymbol, CHAR * BufferForName) * * @param GuestRegs General purpose registers * @param ActionDetail Detail of the specific action - * @param VariablesList List of core specific (and global) variable holders + * @param ScriptGeneralRegisters of core specific (and global) variable holders * @param CodeBuffer The script buffer to be executed * @param Indx Script Buffer index * @param ErrorOperator Error in operator * @return BOOL */ BOOL -ScriptEngineExecute(PGUEST_REGS GuestRegs, - ACTION_BUFFER * ActionDetail, - SCRIPT_ENGINE_VARIABLES_LIST * VariablesList, - SYMBOL_BUFFER * CodeBuffer, - UINT64 * Indx, - SYMBOL_BUFFER * StackBuffer, - int * StackIndx, - int * StackBaseIndx, - int * StackTempBaseIndx, - SYMBOL * ErrorOperator) +ScriptEngineExecute(PGUEST_REGS GuestRegs, + ACTION_BUFFER * ActionDetail, + PSCRIPT_ENGINE_GENERAL_REGISTERS ScriptGeneralRegisters, + SYMBOL_BUFFER * CodeBuffer, + UINT64 * Indx, + SYMBOL * ErrorOperator) { PSYMBOL Operator; PSYMBOL Src0; @@ -297,9 +314,6 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, UINT64 DesVal; BOOL HasError = FALSE; - static int StackIndxTemp = NULL_ZERO; - static unsigned long long ReturnValue = NULL64_ZERO; - Operator = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -325,7 +339,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -333,7 +347,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -342,7 +356,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionEd(SrcVal1, (DWORD)SrcVal0, &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -354,7 +368,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -362,7 +376,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -371,7 +385,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionEb(SrcVal1, (BYTE)SrcVal0, &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -382,7 +396,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -390,7 +404,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -399,7 +413,93 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionEq(SrcVal1, SrcVal0, &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_ED_PA: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + SrcVal1 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionEdPa(SrcVal1, (DWORD)SrcVal0, &HasError); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_EB_PA: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + SrcVal1 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionEbPa(SrcVal1, (BYTE)SrcVal0, &HasError); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_EQ_PA: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + SrcVal1 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionEqPa(SrcVal1, SrcVal0, &HasError); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -411,7 +511,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -419,7 +519,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -427,7 +527,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionInterlockedExchange((volatile long long *)SrcVal1, SrcVal0, &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -439,7 +539,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -447,7 +547,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -456,7 +556,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionInterlockedExchangeAdd((volatile long long *)SrcVal1, SrcVal0, &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -468,14 +568,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Src2 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -483,7 +583,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal2 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src2, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -491,7 +591,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionInterlockedCompareExchange((volatile long long *)SrcVal2, SrcVal1, SrcVal0, &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -503,14 +603,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Src2 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -518,7 +618,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal2 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src2, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -536,14 +636,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Src2 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -551,16 +651,41 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal2 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src2, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); - - Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + - (unsigned long long)(*Indx * sizeof(SYMBOL))); - *Indx = *Indx + 1; + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE); ScriptEngineFunctionMemcpy(SrcVal2, SrcVal1, (UINT32)SrcVal0, &HasError); break; + case FUNC_MEMCPY_PA: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + SrcVal1 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); + + Src2 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + SrcVal2 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE); + + ScriptEngineFunctionMemcpyPa(SrcVal2, SrcVal1, (UINT32)SrcVal0, &HasError); + + break; + case FUNC_SPINLOCK_LOCK_CUSTOM_WAIT: Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -569,7 +694,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -577,7 +702,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); ScriptEngineFunctionSpinlockLockCustomWait((volatile long *)SrcVal1, (UINT32)SrcVal0, &HasError); @@ -591,7 +716,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -599,7 +724,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); ScriptEngineFunctionEventInject((UINT32)SrcVal1, (UINT32)SrcVal0, &HasError); @@ -609,6 +734,75 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, ScriptEngineFunctionPause(ActionDetail, GuestRegs); + + break; + + case FUNC_LBR_CHECK: + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionLbrCheck(); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_LBR_SAVE: + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionLbrSave(); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_LBR_PRINT: + case FUNC_LBR_DUMP: + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionLbrPrint(); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_LBR_RESTORE: + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionLbrRestore(); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_LBR_RESTORE_BY_FILTER: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionLbrRestoreByFilter((unsigned long long)SrcVal0); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + break; case FUNC_FLUSH: @@ -646,7 +840,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -664,7 +858,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -672,7 +866,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -681,7 +875,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 | SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -692,13 +886,13 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); DesVal = SrcVal0 + 1; Des = Src0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -709,13 +903,13 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); DesVal = SrcVal0 - 1; Des = Src0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -726,7 +920,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -734,7 +928,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -742,7 +936,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 ^ SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -753,14 +947,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -768,7 +962,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 & SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -779,14 +973,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -794,7 +988,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 >> SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -805,7 +999,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -813,7 +1007,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -822,7 +1016,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 << SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -833,14 +1027,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -848,7 +1042,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 + SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -860,7 +1054,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -868,7 +1062,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -876,7 +1070,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 - SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -887,14 +1081,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -902,7 +1096,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 * SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -913,14 +1107,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -935,7 +1129,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 / SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -946,14 +1140,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -967,7 +1161,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 % SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -978,14 +1172,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -993,7 +1187,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = (INT64)SrcVal1 > (INT64)SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1004,14 +1198,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1019,7 +1213,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = (INT64)SrcVal1 < (INT64)SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1030,14 +1224,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1045,7 +1239,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = (INT64)SrcVal1 >= (INT64)SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1056,14 +1250,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1072,7 +1266,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = (INT64)SrcVal1 <= (INT64)SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1083,7 +1277,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1091,7 +1285,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1099,7 +1293,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 == SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1111,7 +1305,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1119,7 +1313,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1127,7 +1321,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal1 != SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1138,16 +1332,16 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; - DesVal = ScriptEngineKeywordPoi((PUINT64)GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx), + DesVal = ScriptEngineKeywordPoi((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1158,15 +1352,15 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; - DesVal = ScriptEngineKeywordDb((PUINT64)GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx), + DesVal = ScriptEngineKeywordDb((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1177,16 +1371,16 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; - DesVal = ScriptEngineKeywordDd((PUINT64)GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx), + DesVal = ScriptEngineKeywordDd((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1198,16 +1392,16 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; - DesVal = ScriptEngineKeywordDw((PUINT64)GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx), + DesVal = ScriptEngineKeywordDw((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1218,16 +1412,116 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; - DesVal = ScriptEngineKeywordDq((PUINT64)GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx), + DesVal = ScriptEngineKeywordDq((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_POI_PA: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + DesVal = ScriptEngineKeywordPoiPa((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), + &HasError); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_DB_PA: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + DesVal = ScriptEngineKeywordDbPa((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), + &HasError); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_DD_PA: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + DesVal = ScriptEngineKeywordDdPa((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), + &HasError); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_DW_PA: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + DesVal = ScriptEngineKeywordDwPa((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), + &HasError); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_DQ_PA: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + DesVal = ScriptEngineKeywordDqPa((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), + &HasError); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1238,7 +1532,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1247,7 +1541,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ~SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1261,7 +1555,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, // // It's reference, we need an address // - SrcVal0 = GetValue(GuestRegs, ActionDetail, VariablesList, Src0, TRUE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SrcVal0 = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, TRUE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1269,7 +1563,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1280,15 +1574,15 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; - DesVal = ScriptEngineFunctionPhysicalToVirtual(GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx)); + DesVal = ScriptEngineFunctionPhysicalToVirtual(GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE)); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1299,15 +1593,15 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; - DesVal = ScriptEngineFunctionVirtualToPhysical(GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx)); + DesVal = ScriptEngineFunctionVirtualToPhysical(GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE)); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1318,7 +1612,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1329,7 +1623,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, else DesVal = 0; // FALSE - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1342,14 +1636,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, if (Src0->Type == SYMBOL_STRING_TYPE) { *Indx = - *Indx + ((3 * sizeof(unsigned long long) + Src0->Len) / + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src0->Len) / sizeof(SYMBOL)); SrcVal0 = (UINT64)&Src0->Value; } else { SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); } Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -1358,7 +1652,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionStrlen((const char *)SrcVal0); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1370,7 +1664,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1378,7 +1672,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionDisassembleLen((PVOID)SrcVal0, FALSE); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1389,7 +1683,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1397,7 +1691,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionDisassembleLen((PVOID)SrcVal0, TRUE); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1410,14 +1704,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, if (Src0->Type == SYMBOL_WSTRING_TYPE) { *Indx = - *Indx + ((3 * sizeof(unsigned long long) + Src0->Len) / + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src0->Len) / sizeof(SYMBOL)); SrcVal0 = (UINT64)&Src0->Value; } else { SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); } Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -1426,10 +1720,44 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionWcslen((const wchar_t *)SrcVal0); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; + case FUNC_MICROSLEEP: + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + ScriptEngineFunctionMicroSleep(SrcVal0); + break; + + case FUNC_RDTSC: + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionRdtsc(); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_RDTSCP: + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionRdtscp(); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + break; + case FUNC_INTERLOCKED_INCREMENT: Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -1437,7 +1765,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1446,7 +1774,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionInterlockedIncrement((volatile long long *)SrcVal0, &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1457,7 +1785,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1465,7 +1793,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionInterlockedDecrement((volatile long long *)SrcVal0, &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1477,7 +1805,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1485,7 +1813,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = -(INT64)SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1496,15 +1824,15 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; - DesVal = ScriptEngineKeywordHi((PUINT64)GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx), + DesVal = ScriptEngineKeywordHi((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1516,16 +1844,16 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; - DesVal = ScriptEngineKeywordLow((PUINT64)GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx), + DesVal = ScriptEngineKeywordLow((PUINT64)GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE), &HasError); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1536,7 +1864,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1544,7 +1872,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = SrcVal0; - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1556,7 +1884,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); // // Call the target function @@ -1571,7 +1899,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); // // Call the target function @@ -1587,7 +1915,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); // // Call the target function @@ -1601,7 +1929,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); // // Call the target function @@ -1616,7 +1944,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); ScriptEngineFunctionEventEnable(SrcVal0); @@ -1628,7 +1956,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); ScriptEngineFunctionEventDisable(SrcVal0); @@ -1640,7 +1968,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); ScriptEngineFunctionEventClear(SrcVal0); @@ -1652,7 +1980,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); // // Call the target function @@ -1670,14 +1998,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); if (SrcVal1 == 0) *Indx = SrcVal0; @@ -1691,14 +2019,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); if (SrcVal1 != 0) *Indx = SrcVal0; @@ -1711,175 +2039,58 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); *Indx = SrcVal0; break; - case FUNC_CALL_USER_DEFINED_FUNCTION: - StackIndxTemp = *StackIndx; - break; - case FUNC_CALL_USER_DEFINED_FUNCTION_PARAMETER: - - // - // push parameter variable into stack - // + case FUNC_PUSH: Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; + SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); - Src1 = (PSYMBOL)((unsigned long long)StackBuffer->Head + - (unsigned long long)(*StackIndx * sizeof(SYMBOL))); - *StackIndx = *StackIndx + 1; - Src1->Len = 0; - Src1->Type = SYMBOL_FUNCTION_PARAMETER_TYPE; - Src1->VariableType = 0; - Src1->Value = SrcVal0; + ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackIndx] = SrcVal0; + ScriptGeneralRegisters->StackIndx++; break; - case FUNC_END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE: - case FUNC_END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE: - { - // - // - // - Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + - (unsigned long long)(*Indx * sizeof(SYMBOL))); - *Indx = *Indx + 1; - UINT64 FunctionAddress = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + case FUNC_POP: + ScriptGeneralRegisters->StackIndx--; - // - // push return address symbol into stack - // - Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + - (unsigned long long)(*Indx * sizeof(SYMBOL))); - *Indx = *Indx + 1; - Src1 = (PSYMBOL)((unsigned long long)StackBuffer->Head + - (unsigned long long)(*StackIndx * sizeof(SYMBOL))); - *StackIndx = *StackIndx + 1; - Src1->Len = Src0->Len; - Src1->Type = Src0->Type; - Src1->Value = Src0->Value; - Src1->VariableType = Src0->VariableType; + SrcVal0 = ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackIndx]; - *StackTempBaseIndx = *StackIndx; - *StackBaseIndx = 0; - - *StackBaseIndx = StackIndxTemp; - - // jump to function - *Indx = FunctionAddress + 1; - } - - break; - - case FUNC_START_OF_USER_DEFINED_FUNCTION: - Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + - (unsigned long long)(*Indx * sizeof(SYMBOL))); - *Indx = *Indx + 1; - - SrcVal0 = GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); - *StackIndx = (UINT32)(*StackIndx + SrcVal0); - - break; - - case FUNC_MOV_RETURN_VALUE: Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); *Indx = *Indx + 1; - SetValue(GuestRegs, VariablesList, Des, ReturnValue, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, SrcVal0); + break; - case FUNC_END_OF_USER_DEFINED_FUNCTION: - case FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITHOUT_VALUE: - // check - case FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE: - { - if (Operator->Value == FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE) - { - Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + - (unsigned long long)(*Indx * sizeof(SYMBOL))); - *Indx = *Indx + 1; - ReturnValue = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); - } + case FUNC_CALL: + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); - // - // pop return address - // - UINT64 ReturnAddress = 0; + *Indx = *Indx + 1; - Src0 = (PSYMBOL)((unsigned long long)StackBuffer->Head + - (unsigned long long)((*StackTempBaseIndx - 1) * sizeof(SYMBOL))); + ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackIndx] = *Indx; - if (Src0->Type == SYMBOL_RETURN_ADDRESS_TYPE) - { - ReturnAddress = Src0->Value; - } - else - { - // error - } + ScriptGeneralRegisters->StackIndx++; - *StackIndx = *StackBaseIndx; + *Indx = SrcVal0; + break; - // update StackBaseIndx and StackTempBaseIndx + case FUNC_RET: - if (*StackIndx == 0) - { - *StackTempBaseIndx = 0; - *StackBaseIndx = 0; - } - else - { - int i = *StackIndx; - PSYMBOL StackSymbol = NULL; - - *StackTempBaseIndx = 0; - *StackBaseIndx = 0; - for (; i > 0; i--) - { - StackSymbol = (PSYMBOL)((unsigned long long)StackBuffer->Head + - (unsigned long long)((i - 1) * sizeof(SYMBOL))); - if (StackSymbol->Type == SYMBOL_RETURN_ADDRESS_TYPE) - { - *StackTempBaseIndx = i; - *StackBaseIndx = *StackTempBaseIndx - 1; - break; - } - } - - for (i = *StackTempBaseIndx - 2; i >= 0; i--) - { - StackSymbol = (PSYMBOL)((unsigned long long)StackBuffer->Head + - (unsigned long long)((i) * sizeof(SYMBOL))); - if (StackSymbol->Type == SYMBOL_FUNCTION_PARAMETER_TYPE) - { - continue; - } - else - { - *StackBaseIndx = i + 1; - break; - } - } - - if (i == -1) - { - *StackBaseIndx = 0; - } - } - - *Indx = ReturnAddress; - } - - break; + ScriptGeneralRegisters->StackIndx--; + *Indx = ScriptGeneralRegisters->StackBuffer[ScriptGeneralRegisters->StackIndx]; + break; case FUNC_STRCMP: Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -1890,14 +2101,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, if (Src0->Type == SYMBOL_STRING_TYPE) { *Indx = - *Indx + ((3 * sizeof(unsigned long long) + Src0->Len) / + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src0->Len) / sizeof(SYMBOL)); SrcVal0 = (UINT64)&Src0->Value; } else { SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); } Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -1908,14 +2119,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, if (Src1->Type == SYMBOL_STRING_TYPE) { *Indx = - *Indx + ((3 * sizeof(unsigned long long) + Src1->Len) / + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src1->Len) / sizeof(SYMBOL)); SrcVal1 = (UINT64)&Src1->Value; } else { SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); } Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -1925,7 +2136,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionStrcmp((const char *)SrcVal1, (const char *)SrcVal0); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1939,14 +2150,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, if (Src0->Type == SYMBOL_WSTRING_TYPE) { *Indx = - *Indx + ((3 * sizeof(unsigned long long) + Src0->Len) / + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src0->Len) / sizeof(SYMBOL)); SrcVal0 = (UINT64)&Src0->Value; } else { SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); } Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -1957,14 +2168,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, if (Src1->Type == SYMBOL_WSTRING_TYPE) { *Indx = - *Indx + ((3 * sizeof(unsigned long long) + Src1->Len) / + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src1->Len) / sizeof(SYMBOL)); SrcVal1 = (UINT64)&Src1->Value; } else { SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); } Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -1974,7 +2185,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionWcscmp((const wchar_t *)SrcVal1, (const wchar_t *)SrcVal0); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -1986,7 +2197,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, *Indx = *Indx + 1; SrcVal0 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src0, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + (unsigned long long)(*Indx * sizeof(SYMBOL))); @@ -1996,14 +2207,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, if (Src1->Type == SYMBOL_STRING_TYPE) { *Indx = - *Indx + ((3 * sizeof(unsigned long long) + Src1->Len) / + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src1->Len) / sizeof(SYMBOL)); SrcVal1 = (UINT64)&Src1->Value; } else { SrcVal1 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src1, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); } Src2 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -2014,14 +2225,14 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, if (Src2->Type == SYMBOL_STRING_TYPE) { *Indx = - *Indx + ((3 * sizeof(unsigned long long) + Src2->Len) / + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src2->Len) / sizeof(SYMBOL)); SrcVal2 = (UINT64)&Src2->Value; } else { SrcVal2 = - GetValue(GuestRegs, ActionDetail, VariablesList, Src2, FALSE, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE); } Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -2031,7 +2242,121 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, DesVal = ScriptEngineFunctionMemcmp((const char *)SrcVal2, (const char *)SrcVal1, SrcVal0); - SetValue(GuestRegs, VariablesList, Des, DesVal, StackBuffer, StackIndx, StackBaseIndx, StackTempBaseIndx); + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_STRNCMP: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + if (Src1->Type == SYMBOL_STRING_TYPE) + { + *Indx = + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src1->Len) / + sizeof(SYMBOL)); + SrcVal1 = (UINT64)&Src1->Value; + } + else + { + SrcVal1 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); + } + + Src2 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + if (Src2->Type == SYMBOL_STRING_TYPE) + { + *Indx = + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src2->Len) / + sizeof(SYMBOL)); + SrcVal2 = (UINT64)&Src2->Value; + } + else + { + SrcVal2 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE); + } + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionStrncmp((const char *)SrcVal2, (const char *)SrcVal1, SrcVal0); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); + + break; + + case FUNC_WCSNCMP: + + Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + SrcVal0 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE); + + Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + if (Src1->Type == SYMBOL_WSTRING_TYPE) + { + *Indx = + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src1->Len) / + sizeof(SYMBOL)); + SrcVal1 = (UINT64)&Src1->Value; + } + else + { + SrcVal1 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE); + } + + Src2 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + if (Src2->Type == SYMBOL_WSTRING_TYPE) + { + *Indx = + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src2->Len) / + sizeof(SYMBOL)); + SrcVal2 = (UINT64)&Src2->Value; + } + else + { + SrcVal2 = + GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE); + } + + Des = (PSYMBOL)((unsigned long long)CodeBuffer->Head + + (unsigned long long)(*Indx * sizeof(SYMBOL))); + + *Indx = *Indx + 1; + + DesVal = ScriptEngineFunctionWcsncmp((const wchar_t *)SrcVal2, (const wchar_t *)SrcVal1, SrcVal0); + + SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal); break; @@ -2046,7 +2371,7 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, // *Indx = - *Indx + ((3 * sizeof(unsigned long long) + Src0->Len) / + *Indx + ((SIZE_SYMBOL_WITHOUT_LEN + Src0->Len) / sizeof(SYMBOL)); Src1 = (PSYMBOL)((unsigned long long)CodeBuffer->Head + @@ -2067,17 +2392,13 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs, ScriptEngineFunctionPrintf( GuestRegs, ActionDetail, - VariablesList, + ScriptGeneralRegisters, ActionDetail->Tag, ActionDetail->ImmediatelySendTheResults, (char *)&Src0->Value, Src1->Value, Src2, - (BOOLEAN *)&HasError, - StackBuffer, - StackIndx, - StackBaseIndx, - StackTempBaseIndx); + (BOOLEAN *)&HasError); break; } diff --git a/hyperdbg/script-eval/header/ScriptEngineCommonDefinitions.h b/hyperdbg/script-eval/header/ScriptEngineCommonDefinitions.h deleted file mode 100644 index aa818c3b..00000000 --- a/hyperdbg/script-eval/header/ScriptEngineCommonDefinitions.h +++ /dev/null @@ -1,757 +0,0 @@ -#pragma once -#ifndef SCRIPT_ENGINE_COMMON_DEFINITIONS_H -#define SCRIPT_ENGINE_COMMON_DEFINITIONS_H -typedef struct SYMBOL { - long long unsigned Type; - long long unsigned Len; - long long unsigned VariableType; - long long unsigned Value; -} SYMBOL, * PSYMBOL; -typedef struct SYMBOL_BUFFER { - PSYMBOL Head; - unsigned int Pointer; - unsigned int Size; - char* Message; -} SYMBOL_BUFFER, * PSYMBOL_BUFFER; -typedef struct SYMBOL_MAP -{ - char* Name; - long long unsigned Type; -} SYMBOL_MAP, * PSYMBOL_MAP; -typedef struct ACTION_BUFFER { - long long unsigned Tag; - long long unsigned CurrentAction; - char ImmediatelySendTheResults; - long long unsigned Context; - char CallingStage; -} ACTION_BUFFER, *PACTION_BUFFER; - - -#define SYMBOL_GLOBAL_ID_TYPE 0 -#define SYMBOL_LOCAL_ID_TYPE 1 -#define SYMBOL_NUM_TYPE 2 -#define SYMBOL_REGISTER_TYPE 3 -#define SYMBOL_PSEUDO_REG_TYPE 4 -#define SYMBOL_SEMANTIC_RULE_TYPE 5 -#define SYMBOL_TEMP_TYPE 6 -#define SYMBOL_STRING_TYPE 7 -#define SYMBOL_VARIABLE_COUNT_TYPE 8 -#define SYMBOL_MEM_VALID_CHECK_MASK (1 << 31) -#define SYMBOL_INVALID 9 -#define SYMBOL_WSTRING_TYPE 10 -#define SYMBOL_USER_DEFINED_FUNCTION_TYPE 11 -#define SYMBOL_FUNCTION_PARAMETER_ID_TYPE 12 -#define SYMBOL_RETURN_ADDRESS_TYPE 13 -#define SYMBOL_STACK_TEMP_TYPE 14 -#define SYMBOL_FUNCTION_PARAMETER_TYPE 15 -#define INVALID 0x80000000 -#define LALR_ACCEPT 0x7fffffff - - - -#ifndef FUNC_INC -#define FUNC_INC 0 -#endif // !FUNC_INC - -#ifndef FUNC_DEC -#define FUNC_DEC 1 -#endif // !FUNC_DEC - -#ifndef FUNC_REFERENCE -#define FUNC_REFERENCE 2 -#endif // !FUNC_REFERENCE - -#ifndef FUNC_DEREFERENCE -#define FUNC_DEREFERENCE 3 -#endif // !FUNC_DEREFERENCE - -#ifndef FUNC_OR -#define FUNC_OR 4 -#endif // !FUNC_OR - -#ifndef FUNC_XOR -#define FUNC_XOR 5 -#endif // !FUNC_XOR - -#ifndef FUNC_AND -#define FUNC_AND 6 -#endif // !FUNC_AND - -#ifndef FUNC_ASR -#define FUNC_ASR 7 -#endif // !FUNC_ASR - -#ifndef FUNC_ASL -#define FUNC_ASL 8 -#endif // !FUNC_ASL - -#ifndef FUNC_ADD -#define FUNC_ADD 9 -#endif // !FUNC_ADD - -#ifndef FUNC_SUB -#define FUNC_SUB 10 -#endif // !FUNC_SUB - -#ifndef FUNC_MUL -#define FUNC_MUL 11 -#endif // !FUNC_MUL - -#ifndef FUNC_DIV -#define FUNC_DIV 12 -#endif // !FUNC_DIV - -#ifndef FUNC_MOD -#define FUNC_MOD 13 -#endif // !FUNC_MOD - -#ifndef FUNC_GT -#define FUNC_GT 14 -#endif // !FUNC_GT - -#ifndef FUNC_LT -#define FUNC_LT 15 -#endif // !FUNC_LT - -#ifndef FUNC_EGT -#define FUNC_EGT 16 -#endif // !FUNC_EGT - -#ifndef FUNC_ELT -#define FUNC_ELT 17 -#endif // !FUNC_ELT - -#ifndef FUNC_EQUAL -#define FUNC_EQUAL 18 -#endif // !FUNC_EQUAL - -#ifndef FUNC_NEQ -#define FUNC_NEQ 19 -#endif // !FUNC_NEQ - -#ifndef FUNC_START_OF_IF -#define FUNC_START_OF_IF 20 -#endif // !FUNC_START_OF_IF - -#ifndef FUNC_JMP -#define FUNC_JMP 21 -#endif // !FUNC_JMP - -#ifndef FUNC_JZ -#define FUNC_JZ 22 -#endif // !FUNC_JZ - -#ifndef FUNC_JNZ -#define FUNC_JNZ 23 -#endif // !FUNC_JNZ - -#ifndef FUNC_JMP_TO_END_AND_JZCOMPLETED -#define FUNC_JMP_TO_END_AND_JZCOMPLETED 24 -#endif // !FUNC_JMP_TO_END_AND_JZCOMPLETED - -#ifndef FUNC_END_OF_IF -#define FUNC_END_OF_IF 25 -#endif // !FUNC_END_OF_IF - -#ifndef FUNC_START_OF_WHILE -#define FUNC_START_OF_WHILE 26 -#endif // !FUNC_START_OF_WHILE - -#ifndef FUNC_END_OF_WHILE -#define FUNC_END_OF_WHILE 27 -#endif // !FUNC_END_OF_WHILE - -#ifndef FUNC_VARGSTART -#define FUNC_VARGSTART 28 -#endif // !FUNC_VARGSTART - -#ifndef FUNC_MOV -#define FUNC_MOV 29 -#endif // !FUNC_MOV - -#ifndef FUNC_START_OF_DO_WHILE -#define FUNC_START_OF_DO_WHILE 30 -#endif // !FUNC_START_OF_DO_WHILE - -#ifndef FUNC_ -#define FUNC_ 31 -#endif // !FUNC_ - -#ifndef FUNC_START_OF_DO_WHILE_COMMANDS -#define FUNC_START_OF_DO_WHILE_COMMANDS 32 -#endif // !FUNC_START_OF_DO_WHILE_COMMANDS - -#ifndef FUNC_END_OF_DO_WHILE -#define FUNC_END_OF_DO_WHILE 33 -#endif // !FUNC_END_OF_DO_WHILE - -#ifndef FUNC_START_OF_FOR -#define FUNC_START_OF_FOR 34 -#endif // !FUNC_START_OF_FOR - -#ifndef FUNC_FOR_INC_DEC -#define FUNC_FOR_INC_DEC 35 -#endif // !FUNC_FOR_INC_DEC - -#ifndef FUNC_START_OF_FOR_OMMANDS -#define FUNC_START_OF_FOR_OMMANDS 36 -#endif // !FUNC_START_OF_FOR_OMMANDS - -#ifndef FUNC_END_OF_IF -#define FUNC_END_OF_IF 37 -#endif // !FUNC_END_OF_IF - -#ifndef FUNC_IGNORE_LVALUE -#define FUNC_IGNORE_LVALUE 38 -#endif // !FUNC_IGNORE_LVALUE - -#ifndef FUNC_END_OF_USER_DEFINED_FUNCTION -#define FUNC_END_OF_USER_DEFINED_FUNCTION 39 -#endif // !FUNC_END_OF_USER_DEFINED_FUNCTION - -#ifndef FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE -#define FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE 40 -#endif // !FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE - -#ifndef FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITHOUT_VALUE -#define FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITHOUT_VALUE 41 -#endif // !FUNC_RETURN_OF_USER_DEFINED_FUNCTION_WITHOUT_VALUE - -#ifndef FUNC_CALL_USER_DEFINED_FUNCTION_PARAMETER -#define FUNC_CALL_USER_DEFINED_FUNCTION_PARAMETER 42 -#endif // !FUNC_CALL_USER_DEFINED_FUNCTION_PARAMETER - -#ifndef FUNC_END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE -#define FUNC_END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE 43 -#endif // !FUNC_END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE - -#ifndef FUNC_END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE -#define FUNC_END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE 44 -#endif // !FUNC_END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE - -#ifndef FUNC_CALL_USER_DEFINED_FUNCTION -#define FUNC_CALL_USER_DEFINED_FUNCTION 45 -#endif // !FUNC_CALL_USER_DEFINED_FUNCTION - -#ifndef FUNC_START_OF_USER_DEFINED_FUNCTION -#define FUNC_START_OF_USER_DEFINED_FUNCTION 46 -#endif // !FUNC_START_OF_USER_DEFINED_FUNCTION - -#ifndef FUNC_MOV_RETURN_VALUE -#define FUNC_MOV_RETURN_VALUE 47 -#endif // !FUNC_MOV_RETURN_VALUE - -#ifndef FUNC_VOID -#define FUNC_VOID 48 -#endif // !FUNC_VOID - -#ifndef FUNC_BOOL -#define FUNC_BOOL 49 -#endif // !FUNC_BOOL - -#ifndef FUNC_CHAR -#define FUNC_CHAR 50 -#endif // !FUNC_CHAR - -#ifndef FUNC_SHORT -#define FUNC_SHORT 51 -#endif // !FUNC_SHORT - -#ifndef FUNC_INT -#define FUNC_INT 52 -#endif // !FUNC_INT - -#ifndef FUNC_LONG -#define FUNC_LONG 53 -#endif // !FUNC_LONG - -#ifndef FUNC_UNSIGNED -#define FUNC_UNSIGNED 54 -#endif // !FUNC_UNSIGNED - -#ifndef FUNC_SIGNED -#define FUNC_SIGNED 55 -#endif // !FUNC_SIGNED - -#ifndef FUNC_FLOAT -#define FUNC_FLOAT 56 -#endif // !FUNC_FLOAT - -#ifndef FUNC_DOUBLE -#define FUNC_DOUBLE 57 -#endif // !FUNC_DOUBLE - -#ifndef FUNC_PRINT -#define FUNC_PRINT 58 -#endif // !FUNC_PRINT - -#ifndef FUNC_FORMATS -#define FUNC_FORMATS 59 -#endif // !FUNC_FORMATS - -#ifndef FUNC_EVENT_ENABLE -#define FUNC_EVENT_ENABLE 60 -#endif // !FUNC_EVENT_ENABLE - -#ifndef FUNC_EVENT_DISABLE -#define FUNC_EVENT_DISABLE 61 -#endif // !FUNC_EVENT_DISABLE - -#ifndef FUNC_EVENT_CLEAR -#define FUNC_EVENT_CLEAR 62 -#endif // !FUNC_EVENT_CLEAR - -#ifndef FUNC_TEST_STATEMENT -#define FUNC_TEST_STATEMENT 63 -#endif // !FUNC_TEST_STATEMENT - -#ifndef FUNC_SPINLOCK_LOCK -#define FUNC_SPINLOCK_LOCK 64 -#endif // !FUNC_SPINLOCK_LOCK - -#ifndef FUNC_SPINLOCK_UNLOCK -#define FUNC_SPINLOCK_UNLOCK 65 -#endif // !FUNC_SPINLOCK_UNLOCK - -#ifndef FUNC_EVENT_SC -#define FUNC_EVENT_SC 66 -#endif // !FUNC_EVENT_SC - -#ifndef FUNC_PRINTF -#define FUNC_PRINTF 67 -#endif // !FUNC_PRINTF - -#ifndef FUNC_PAUSE -#define FUNC_PAUSE 68 -#endif // !FUNC_PAUSE - -#ifndef FUNC_FLUSH -#define FUNC_FLUSH 69 -#endif // !FUNC_FLUSH - -#ifndef FUNC_EVENT_TRACE_STEP -#define FUNC_EVENT_TRACE_STEP 70 -#endif // !FUNC_EVENT_TRACE_STEP - -#ifndef FUNC_EVENT_TRACE_STEP_IN -#define FUNC_EVENT_TRACE_STEP_IN 71 -#endif // !FUNC_EVENT_TRACE_STEP_IN - -#ifndef FUNC_EVENT_TRACE_STEP_OUT -#define FUNC_EVENT_TRACE_STEP_OUT 72 -#endif // !FUNC_EVENT_TRACE_STEP_OUT - -#ifndef FUNC_EVENT_TRACE_INSTRUMENTATION_STEP -#define FUNC_EVENT_TRACE_INSTRUMENTATION_STEP 73 -#endif // !FUNC_EVENT_TRACE_INSTRUMENTATION_STEP - -#ifndef FUNC_EVENT_TRACE_INSTRUMENTATION_STEP_IN -#define FUNC_EVENT_TRACE_INSTRUMENTATION_STEP_IN 74 -#endif // !FUNC_EVENT_TRACE_INSTRUMENTATION_STEP_IN - -#ifndef FUNC_SPINLOCK_LOCK_CUSTOM_WAIT -#define FUNC_SPINLOCK_LOCK_CUSTOM_WAIT 75 -#endif // !FUNC_SPINLOCK_LOCK_CUSTOM_WAIT - -#ifndef FUNC_EVENT_INJECT -#define FUNC_EVENT_INJECT 76 -#endif // !FUNC_EVENT_INJECT - -#ifndef FUNC_POI -#define FUNC_POI 77 -#endif // !FUNC_POI - -#ifndef FUNC_DB -#define FUNC_DB 78 -#endif // !FUNC_DB - -#ifndef FUNC_DD -#define FUNC_DD 79 -#endif // !FUNC_DD - -#ifndef FUNC_DW -#define FUNC_DW 80 -#endif // !FUNC_DW - -#ifndef FUNC_DQ -#define FUNC_DQ 81 -#endif // !FUNC_DQ - -#ifndef FUNC_NEG -#define FUNC_NEG 82 -#endif // !FUNC_NEG - -#ifndef FUNC_HI -#define FUNC_HI 83 -#endif // !FUNC_HI - -#ifndef FUNC_LOW -#define FUNC_LOW 84 -#endif // !FUNC_LOW - -#ifndef FUNC_NOT -#define FUNC_NOT 85 -#endif // !FUNC_NOT - -#ifndef FUNC_CHECK_ADDRESS -#define FUNC_CHECK_ADDRESS 86 -#endif // !FUNC_CHECK_ADDRESS - -#ifndef FUNC_DISASSEMBLE_LEN -#define FUNC_DISASSEMBLE_LEN 87 -#endif // !FUNC_DISASSEMBLE_LEN - -#ifndef FUNC_DISASSEMBLE_LEN32 -#define FUNC_DISASSEMBLE_LEN32 88 -#endif // !FUNC_DISASSEMBLE_LEN32 - -#ifndef FUNC_DISASSEMBLE_LEN64 -#define FUNC_DISASSEMBLE_LEN64 89 -#endif // !FUNC_DISASSEMBLE_LEN64 - -#ifndef FUNC_INTERLOCKED_INCREMENT -#define FUNC_INTERLOCKED_INCREMENT 90 -#endif // !FUNC_INTERLOCKED_INCREMENT - -#ifndef FUNC_INTERLOCKED_DECREMENT -#define FUNC_INTERLOCKED_DECREMENT 91 -#endif // !FUNC_INTERLOCKED_DECREMENT - -#ifndef FUNC_REFERENCE -#define FUNC_REFERENCE 92 -#endif // !FUNC_REFERENCE - -#ifndef FUNC_PHYSICAL_TO_VIRTUAL -#define FUNC_PHYSICAL_TO_VIRTUAL 93 -#endif // !FUNC_PHYSICAL_TO_VIRTUAL - -#ifndef FUNC_VIRTUAL_TO_PHYSICAL -#define FUNC_VIRTUAL_TO_PHYSICAL 94 -#endif // !FUNC_VIRTUAL_TO_PHYSICAL - -#ifndef FUNC_ED -#define FUNC_ED 95 -#endif // !FUNC_ED - -#ifndef FUNC_EB -#define FUNC_EB 96 -#endif // !FUNC_EB - -#ifndef FUNC_EQ -#define FUNC_EQ 97 -#endif // !FUNC_EQ - -#ifndef FUNC_INTERLOCKED_EXCHANGE -#define FUNC_INTERLOCKED_EXCHANGE 98 -#endif // !FUNC_INTERLOCKED_EXCHANGE - -#ifndef FUNC_INTERLOCKED_EXCHANGE_ADD -#define FUNC_INTERLOCKED_EXCHANGE_ADD 99 -#endif // !FUNC_INTERLOCKED_EXCHANGE_ADD - -#ifndef FUNC_INTERLOCKED_COMPARE_EXCHANGE -#define FUNC_INTERLOCKED_COMPARE_EXCHANGE 100 -#endif // !FUNC_INTERLOCKED_COMPARE_EXCHANGE - -#ifndef FUNC_STRLEN -#define FUNC_STRLEN 101 -#endif // !FUNC_STRLEN - -#ifndef FUNC_STRCMP -#define FUNC_STRCMP 102 -#endif // !FUNC_STRCMP - -#ifndef FUNC_MEMCMP -#define FUNC_MEMCMP 103 -#endif // !FUNC_MEMCMP - -#ifndef FUNC_WCSLEN -#define FUNC_WCSLEN 104 -#endif // !FUNC_WCSLEN - -#ifndef FUNC_WCSCMP -#define FUNC_WCSCMP 105 -#endif // !FUNC_WCSCMP - -#ifndef FUNC_EVENT_INJECT_ERROR_CODE -#define FUNC_EVENT_INJECT_ERROR_CODE 106 -#endif // !FUNC_EVENT_INJECT_ERROR_CODE - -#ifndef FUNC_MEMCPY -#define FUNC_MEMCPY 107 -#endif // !FUNC_MEMCPY - -#ifndef FUNC_POI -#define FUNC_POI 108 -#endif // !FUNC_POI - -#ifndef FUNC_DB -#define FUNC_DB 109 -#endif // !FUNC_DB - -#ifndef FUNC_DD -#define FUNC_DD 110 -#endif // !FUNC_DD - -#ifndef FUNC_DW -#define FUNC_DW 111 -#endif // !FUNC_DW - -#ifndef FUNC_DQ -#define FUNC_DQ 112 -#endif // !FUNC_DQ - -#ifndef FUNC_NEG -#define FUNC_NEG 113 -#endif // !FUNC_NEG - -#ifndef FUNC_HI -#define FUNC_HI 114 -#endif // !FUNC_HI - -#ifndef FUNC_LOW -#define FUNC_LOW 115 -#endif // !FUNC_LOW - -#ifndef FUNC_NOT -#define FUNC_NOT 116 -#endif // !FUNC_NOT - -#ifndef FUNC_CHECK_ADDRESS -#define FUNC_CHECK_ADDRESS 117 -#endif // !FUNC_CHECK_ADDRESS - -#ifndef FUNC_DISASSEMBLE_LEN -#define FUNC_DISASSEMBLE_LEN 118 -#endif // !FUNC_DISASSEMBLE_LEN - -#ifndef FUNC_DISASSEMBLE_LEN32 -#define FUNC_DISASSEMBLE_LEN32 119 -#endif // !FUNC_DISASSEMBLE_LEN32 - -#ifndef FUNC_DISASSEMBLE_LEN64 -#define FUNC_DISASSEMBLE_LEN64 120 -#endif // !FUNC_DISASSEMBLE_LEN64 - -#ifndef FUNC_INTERLOCKED_INCREMENT -#define FUNC_INTERLOCKED_INCREMENT 121 -#endif // !FUNC_INTERLOCKED_INCREMENT - -#ifndef FUNC_INTERLOCKED_DECREMENT -#define FUNC_INTERLOCKED_DECREMENT 122 -#endif // !FUNC_INTERLOCKED_DECREMENT - -#ifndef FUNC_REFERENCE -#define FUNC_REFERENCE 123 -#endif // !FUNC_REFERENCE - -#ifndef FUNC_PHYSICAL_TO_VIRTUAL -#define FUNC_PHYSICAL_TO_VIRTUAL 124 -#endif // !FUNC_PHYSICAL_TO_VIRTUAL - -#ifndef FUNC_VIRTUAL_TO_PHYSICAL -#define FUNC_VIRTUAL_TO_PHYSICAL 125 -#endif // !FUNC_VIRTUAL_TO_PHYSICAL - -#ifndef FUNC_ED -#define FUNC_ED 126 -#endif // !FUNC_ED - -#ifndef FUNC_EB -#define FUNC_EB 127 -#endif // !FUNC_EB - -#ifndef FUNC_EQ -#define FUNC_EQ 128 -#endif // !FUNC_EQ - -#ifndef FUNC_INTERLOCKED_EXCHANGE -#define FUNC_INTERLOCKED_EXCHANGE 129 -#endif // !FUNC_INTERLOCKED_EXCHANGE - -#ifndef FUNC_INTERLOCKED_EXCHANGE_ADD -#define FUNC_INTERLOCKED_EXCHANGE_ADD 130 -#endif // !FUNC_INTERLOCKED_EXCHANGE_ADD - -#ifndef FUNC_INTERLOCKED_COMPARE_EXCHANGE -#define FUNC_INTERLOCKED_COMPARE_EXCHANGE 131 -#endif // !FUNC_INTERLOCKED_COMPARE_EXCHANGE - -#ifndef FUNC_STRLEN -#define FUNC_STRLEN 132 -#endif // !FUNC_STRLEN - -#ifndef FUNC_STRCMP -#define FUNC_STRCMP 133 -#endif // !FUNC_STRCMP - -#ifndef FUNC_MEMCMP -#define FUNC_MEMCMP 134 -#endif // !FUNC_MEMCMP - -#ifndef FUNC_WCSLEN -#define FUNC_WCSLEN 135 -#endif // !FUNC_WCSLEN - -#ifndef FUNC_WCSCMP -#define FUNC_WCSCMP 136 -#endif // !FUNC_WCSCMP - -typedef enum REGS_ENUM { - REGISTER_RAX = 0, - REGISTER_EAX = 1, - REGISTER_AX = 2, - REGISTER_AH = 3, - REGISTER_AL = 4, - REGISTER_RCX = 5, - REGISTER_ECX = 6, - REGISTER_CX = 7, - REGISTER_CH = 8, - REGISTER_CL = 9, - REGISTER_RDX = 10, - REGISTER_EDX = 11, - REGISTER_DX = 12, - REGISTER_DH = 13, - REGISTER_DL = 14, - REGISTER_RBX = 15, - REGISTER_EBX = 16, - REGISTER_BX = 17, - REGISTER_BH = 18, - REGISTER_BL = 19, - REGISTER_RSP = 20, - REGISTER_ESP = 21, - REGISTER_SP = 22, - REGISTER_SPL = 23, - REGISTER_RBP = 24, - REGISTER_EBP = 25, - REGISTER_BP = 26, - REGISTER_BPL = 27, - REGISTER_RSI = 28, - REGISTER_ESI = 29, - REGISTER_SI = 30, - REGISTER_SIL = 31, - REGISTER_RDI = 32, - REGISTER_EDI = 33, - REGISTER_DI = 34, - REGISTER_DIL = 35, - REGISTER_R8 = 36, - REGISTER_R8D = 37, - REGISTER_R8W = 38, - REGISTER_R8H = 39, - REGISTER_R8L = 40, - REGISTER_R9 = 41, - REGISTER_R9D = 42, - REGISTER_R9W = 43, - REGISTER_R9H = 44, - REGISTER_R9L = 45, - REGISTER_R10 = 46, - REGISTER_R10D = 47, - REGISTER_R10W = 48, - REGISTER_R10H = 49, - REGISTER_R10L = 50, - REGISTER_R11 = 51, - REGISTER_R11D = 52, - REGISTER_R11W = 53, - REGISTER_R11H = 54, - REGISTER_R11L = 55, - REGISTER_R12 = 56, - REGISTER_R12D = 57, - REGISTER_R12W = 58, - REGISTER_R12H = 59, - REGISTER_R12L = 60, - REGISTER_R13 = 61, - REGISTER_R13D = 62, - REGISTER_R13W = 63, - REGISTER_R13H = 64, - REGISTER_R13L = 65, - REGISTER_R14 = 66, - REGISTER_R14D = 67, - REGISTER_R14W = 68, - REGISTER_R14H = 69, - REGISTER_R14L = 70, - REGISTER_R15 = 71, - REGISTER_R15D = 72, - REGISTER_R15W = 73, - REGISTER_R15H = 74, - REGISTER_R15L = 75, - REGISTER_DS = 76, - REGISTER_ES = 77, - REGISTER_FS = 78, - REGISTER_GS = 79, - REGISTER_CS = 80, - REGISTER_SS = 81, - REGISTER_RFLAGS = 82, - REGISTER_EFLAGS = 83, - REGISTER_FLAGS = 84, - REGISTER_CF = 85, - REGISTER_PF = 86, - REGISTER_AF = 87, - REGISTER_ZF = 88, - REGISTER_SF = 89, - REGISTER_TF = 90, - REGISTER_IF = 91, - REGISTER_DF = 92, - REGISTER_OF = 93, - REGISTER_IOPL = 94, - REGISTER_NT = 95, - REGISTER_RF = 96, - REGISTER_VM = 97, - REGISTER_AC = 98, - REGISTER_VIF = 99, - REGISTER_VIP = 100, - REGISTER_ID = 101, - REGISTER_RIP = 102, - REGISTER_EIP = 103, - REGISTER_IP = 104, - REGISTER_IDTR = 105, - REGISTER_LDTR = 106, - REGISTER_GDTR = 107, - REGISTER_TR = 108, - REGISTER_CR0 = 109, - REGISTER_CR2 = 110, - REGISTER_CR3 = 111, - REGISTER_CR4 = 112, - REGISTER_CR8 = 113, - REGISTER_DR0 = 114, - REGISTER_DR1 = 115, - REGISTER_DR2 = 116, - REGISTER_DR3 = 117, - REGISTER_DR6 = 118, - REGISTER_DR7 = 119 - -} REGS_ENUM; - -static const char *const RegistersNames[] = { -"rax", "eax", "ax", "ah", "al", "rcx", "ecx", "cx", -"ch", "cl", "rdx", "edx", "dx", "dh", "dl", "rbx", -"ebx", "bx", "bh", "bl", "rsp", "esp", "sp", "spl", -"rbp", "ebp", "bp", "bpl", "rsi", "esi", "si", "sil", -"rdi", "edi", "di", "dil", "r8", "r8d", "r8w", "r8h", -"r8l", "r9", "r9d", "r9w", "r9h", "r9l", "r10", "r10d", -"r10w", "r10h", "r10l", "r11", "r11d", "r11w", "r11h", "r11l", -"r12", "r12d", "r12w", "r12h", "r12l", "r13", "r13d", "r13w", -"r13h", "r13l", "r14", "r14d", "r14w", "r14h", "r14l", "r15", -"r15d", "r15w", "r15h", "r15l", "ds", "es", "fs", "gs", -"cs", "ss", "rflags", "eflags", "flags", "cf", "pf", "af", -"zf", "sf", "tf", "if", "df", "of", "iopl", "nt", -"rf", "vm", "ac", "vif", "vip", "id", "rip", "eip", -"ip", "idtr", "ldtr", "gdtr", "tr", "cr0", "cr2", "cr3", -"cr4", "cr8", "dr0", "dr1", "dr2", "dr3", "dr6", "dr7" -}; - -#define PSEUDO_REGISTER_PID 0 -#define PSEUDO_REGISTER_TID 1 -#define PSEUDO_REGISTER_PNAME 2 -#define PSEUDO_REGISTER_CORE 3 -#define PSEUDO_REGISTER_PROC 4 -#define PSEUDO_REGISTER_THREAD 5 -#define PSEUDO_REGISTER_PEB 6 -#define PSEUDO_REGISTER_TEB 7 -#define PSEUDO_REGISTER_IP 8 -#define PSEUDO_REGISTER_BUFFER 9 -#define PSEUDO_REGISTER_CONTEXT 10 -#define PSEUDO_REGISTER_EVENT_TAG 11 -#define PSEUDO_REGISTER_EVENT_ID 12 -#define PSEUDO_REGISTER_EVENT_STAGE 13 - -#endif diff --git a/hyperdbg/script-eval/header/ScriptEngineHeader.h b/hyperdbg/script-eval/header/ScriptEngineHeader.h index 9e48ba23..9f6ad5cb 100644 --- a/hyperdbg/script-eval/header/ScriptEngineHeader.h +++ b/hyperdbg/script-eval/header/ScriptEngineHeader.h @@ -11,23 +11,33 @@ */ #pragma once -BOOL -ScriptEngineExecute(PGUEST_REGS GuestRegs, - ACTION_BUFFER * ActionDetail, - SCRIPT_ENGINE_VARIABLES_LIST * VariablesList, - SYMBOL_BUFFER * CodeBuffer, - UINT64 * Indx, - SYMBOL_BUFFER * StackBuffer, - int * StackIndx, - int * StackBaseIndx, - int * StackTempBaseIndx, - SYMBOL * ErrorOperator); +////////////////////////////////////////////////// +// Registers // +////////////////////////////////////////////////// + +BOOLEAN +SetRegValue(PGUEST_REGS GuestRegs, UINT32 RegisterId, UINT64 Value); UINT64 GetRegValue(PGUEST_REGS GuestRegs, REGS_ENUM RegId); -VOID -ScriptEngineGetOperatorName(PSYMBOL OperatorSymbol, CHAR * BufferForName); +BOOLEAN +SetRegValueHwdbg(UINT64 * Regs, UINT32 RegisterId, UINT64 Value); + +UINT64 +GetRegValueHwdbg(UINT64 * Regs, UINT32 RegId); + +////////////////////////////////////////////////// +// Functions // +////////////////////////////////////////////////// + +BOOL +ScriptEngineExecute(PGUEST_REGS GuestRegs, + ACTION_BUFFER * ActionDetail, + PSCRIPT_ENGINE_GENERAL_REGISTERS ScriptGeneralRegisters, + SYMBOL_BUFFER * CodeBuffer, + UINT64 * Indx, + SYMBOL * ErrorOperator); VOID ScriptEngineGetOperatorName(PSYMBOL OperatorSymbol, CHAR * BufferForName); diff --git a/hyperdbg/script-eval/header/ScriptEngineInternalHeader.h b/hyperdbg/script-eval/header/ScriptEngineInternalHeader.h index 1580c233..4fa7e15f 100644 --- a/hyperdbg/script-eval/header/ScriptEngineInternalHeader.h +++ b/hyperdbg/script-eval/header/ScriptEngineInternalHeader.h @@ -16,14 +16,11 @@ // Registers // ////////////////////////////////////////////////// -VOID -SetRegValue(PGUEST_REGS GuestRegs, PSYMBOL Symbol, UINT64 Value); - -UINT64 -GetRegValue(PGUEST_REGS GuestRegs, REGS_ENUM RegId); +BOOLEAN +SetRegValueUsingSymbol(PGUEST_REGS GuestRegs, PSYMBOL Symbol, UINT64 Value); ////////////////////////////////////////////////// -// Pseudo-registers // +// Pseudo-registers // ////////////////////////////////////////////////// UINT64 @@ -65,10 +62,20 @@ ScriptEnginePseudoRegGetEventId(PACTION_BUFFER ActionBuffer); UINT64 ScriptEnginePseudoRegGetEventStage(PACTION_BUFFER ActionBuffer); +UINT64 +ScriptEnginePseudoRegGetTime(); + +UINT64 +ScriptEnginePseudoRegGetDate(); + ////////////////////////////////////////////////// // Keywords // ////////////////////////////////////////////////// +// +// For Virtual Memory +// + UINT64 ScriptEngineKeywordPoi(PUINT64 Address, BOOL * HasError); @@ -90,6 +97,31 @@ ScriptEngineKeywordDw(PUINT64 Address, BOOL * HasError); QWORD ScriptEngineKeywordDq(PUINT64 Address, BOOL * HasError); +// +// For Physical Memory +// + +UINT64 +ScriptEngineKeywordPoiPa(PUINT64 Address, BOOL * HasError); + +WORD +ScriptEngineKeywordHiPa(PUINT64 Address, BOOL * HasError); + +WORD +ScriptEngineKeywordLowPa(PUINT64 Address, BOOL * HasError); + +BYTE +ScriptEngineKeywordDbPa(PUINT64 Address, BOOL * HasError); + +DWORD +ScriptEngineKeywordDdPa(PUINT64 Address, BOOL * HasError); + +WORD +ScriptEngineKeywordDwPa(PUINT64 Address, BOOL * HasError); + +QWORD +ScriptEngineKeywordDqPa(PUINT64 Address, BOOL * HasError); + ////////////////////////////////////////////////// // Functions // ////////////////////////////////////////////////// @@ -103,17 +135,23 @@ ScriptEngineFunctionEd(UINT64 Address, DWORD Value, BOOL * HasError); BOOLEAN ScriptEngineFunctionEb(UINT64 Address, BYTE Value, BOOL * HasError); +BOOLEAN +ScriptEngineFunctionEqPa(UINT64 Address, QWORD Value, BOOL * HasError); + +BOOLEAN +ScriptEngineFunctionEdPa(UINT64 Address, DWORD Value, BOOL * HasError); + +BOOLEAN +ScriptEngineFunctionEbPa(UINT64 Address, BYTE Value, BOOL * HasError); + BOOLEAN ScriptEngineFunctionCheckAddress(UINT64 Address, UINT32 Length); VOID ScriptEngineFunctionMemcpy(UINT64 Destination, UINT64 Source, UINT32 Num, BOOL * HasError); -UINT64 -ScriptEngineFunctionVirtualToPhysical(UINT64 Address); - -UINT64 -ScriptEngineFunctionPhysicalToVirtual(UINT64 Address); +VOID +ScriptEngineFunctionMemcpyPa(UINT64 Destination, UINT64 Source, UINT32 Num, BOOL * HasError); VOID ScriptEngineFunctionPrint(UINT64 Tag, BOOLEAN ImmediateMessagePassing, UINT64 Value); @@ -130,6 +168,12 @@ ScriptEngineFunctionSpinlockUnlock(volatile LONG * Lock, BOOL * HasError); VOID ScriptEngineFunctionSpinlockLockCustomWait(volatile long * Lock, unsigned MaxWait, BOOL * HasError); +UINT64 +ScriptEngineFunctionVirtualToPhysical(UINT64 Address); + +UINT64 +ScriptEngineFunctionPhysicalToVirtual(UINT64 Address); + UINT64 ScriptEngineFunctionStrlen(const char * Address); @@ -139,6 +183,15 @@ ScriptEngineFunctionDisassembleLen(PVOID Address, BOOLEAN Is32Bit); UINT64 ScriptEngineFunctionWcslen(const wchar_t * Address); +VOID +ScriptEngineFunctionMicroSleep(UINT64 Us); + +UINT64 +ScriptEngineFunctionRdtsc(); + +UINT64 +ScriptEngineFunctionRdtscp(); + long long ScriptEngineFunctionInterlockedExchange(long long volatile * Target, long long Value, @@ -188,19 +241,15 @@ VOID ScriptEngineFunctionFormats(UINT64 Tag, BOOLEAN ImmediateMessagePassing, UINT64 Value); VOID -ScriptEngineFunctionPrintf(PGUEST_REGS GuestRegs, - ACTION_BUFFER * ActionDetail, - SCRIPT_ENGINE_VARIABLES_LIST * VariablesList, - UINT64 Tag, - BOOLEAN ImmediateMessagePassing, - char * Format, - UINT64 ArgCount, - PSYMBOL FirstArg, - BOOLEAN * HasError, - SYMBOL_BUFFER * StackBuffer, - int * StackIndx, - int * StackBaseIndx, - int * StackTempBaseIndx); +ScriptEngineFunctionPrintf(PGUEST_REGS GuestRegs, + ACTION_BUFFER * ActionDetail, + SCRIPT_ENGINE_GENERAL_REGISTERS * ScriptGeneralRegisters, + UINT64 Tag, + BOOLEAN ImmediateMessagePassing, + char * Format, + UINT64 ArgCount, + PSYMBOL FirstArg, + BOOLEAN * HasError); VOID ScriptEngineFunctionEventInject(UINT32 InterruptionType, UINT32 Vector, BOOL * HasError); @@ -214,11 +263,32 @@ ScriptEngineFunctionEventTraceInstrumentationStep(); VOID ScriptEngineFunctionEventTraceStepIn(); +BOOLEAN +ScriptEngineFunctionLbrSave(); + +BOOLEAN +ScriptEngineFunctionLbrPrint(); + +BOOLEAN +ScriptEngineFunctionLbrCheck(); + +BOOLEAN +ScriptEngineFunctionLbrRestore(); + +BOOLEAN +ScriptEngineFunctionLbrRestoreByFilter(UINT64 FilterOptions); + UINT64 ScriptEngineFunctionStrcmp(const char * Address1, const char * Address2); +UINT64 +ScriptEngineFunctionStrncmp(const char * Address1, const char * Address2, size_t Num); + UINT64 ScriptEngineFunctionWcscmp(const wchar_t * Address1, const wchar_t * Address2); +UINT64 +ScriptEngineFunctionWcsncmp(const wchar_t * Address1, const wchar_t * Address2, size_t Num); + UINT64 ScriptEngineFunctionMemcmp(const char * Address1, const char * Address2, size_t Count); diff --git a/hyperdbg/symbol-parser/CMakeLists.txt b/hyperdbg/symbol-parser/CMakeLists.txt new file mode 100644 index 00000000..1d19d43c --- /dev/null +++ b/hyperdbg/symbol-parser/CMakeLists.txt @@ -0,0 +1,17 @@ +# Code generated by Visual Studio kit, DO NOT EDIT. +set(SourceFiles + "code/casting.cpp" + "code/common-utils.cpp" + "code/symbol-parser.cpp" + "pch.cpp" + "../include/platform/user/header/Environment.h" + "header/common-utils.h" + "header/symbol-parser.h" + "pch.h" +) +include_directories( + "../include" + "../dependencies" + "." +) +add_library(symbol-parser SHARED ${SourceFiles}) diff --git a/hyperdbg/symbol-parser/code/codeview-rsds.cpp b/hyperdbg/symbol-parser/code/codeview-rsds.cpp new file mode 100644 index 00000000..0acc20d5 --- /dev/null +++ b/hyperdbg/symbol-parser/code/codeview-rsds.cpp @@ -0,0 +1,559 @@ +/** + * @file codeview-rsds.cpp + * @author jtaw5649 + * @brief Bounded in-memory CodeView RSDS parser + * @details + * @version 0.19 + * @date 2026-06-02 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +/** + * @brief Helper function to check if the specified offset and length are within the bounds of the image size + * + * @param ImageSize The size of the image in bytes + * @param Offset The offset to check + * @param Length The length to check + * + * @return BOOLEAN TRUE if the offset and length are within bounds, FALSE otherwise + */ +static BOOLEAN +SymRsdsHasRange(SIZE_T ImageSize, SIZE_T Offset, SIZE_T Length) +{ + return Offset <= ImageSize && Length <= ImageSize - Offset; +} + +/** + * @brief Helper function to safely add two SIZE_T values and check for overflow + * + * @param Left The first value to add + * @param Right The second value to add + * @param Result An output pointer to receive the result of the addition if successful + * + * @return BOOLEAN TRUE if the addition was successful without overflow, FALSE otherwise + */ +static BOOLEAN +SymRsdsAddSize(SIZE_T Left, SIZE_T Right, SIZE_T * Result) +{ + if (Result == NULL || Right > (SIZE_T)-1 - Left) + { + return FALSE; + } + + *Result = Left + Right; + return TRUE; +} + +/** + * @brief Helper function to clear the output parameters for the PDB file name, GUID, and age + * + * @param PdbFileName An optional output buffer for the PDB file name. If not NULL, it will be set to an empty string + * @param PdbFileNameSize The size of the PDB file name buffer in bytes. Must be greater than 0 if PdbFileName is not NULL + * @param Guid An optional output pointer for the GUID. If not NULL, it will be zeroed out + * @param Age An optional output pointer for the age. If not NULL, it will be set to 0 + * + * @return VOID + */ +static VOID +SymRsdsClearOutputs(CHAR * PdbFileName, SIZE_T PdbFileNameSize, GUID * Guid, DWORD * Age) +{ + if (PdbFileName != NULL && PdbFileNameSize != 0) + { + PdbFileName[0] = '\0'; + } + + if (Guid != NULL) + { + ZeroMemory(Guid, sizeof(*Guid)); + } + + if (Age != NULL) + { + *Age = 0; + } +} + +/** + * @brief Helper function to get a pointer to a specified offset and length within the image, while checking bounds + * + * @param ImageBase The base address of the image in memory + * @param ImageSize The size of the image in bytes + * @param Offset The offset to get a pointer to + * @param Length The length of the range to check for validity + * @param Pointer An output pointer to receive the pointer to the specified offset if valid + * + * @return BOOLEAN TRUE if the pointer was successfully obtained and is within bounds, FALSE otherwise + */ +static BOOLEAN +SymRsdsGetPointerAtOffset(const BYTE * ImageBase, SIZE_T ImageSize, SIZE_T Offset, SIZE_T Length, const BYTE ** Pointer) +{ + if (ImageBase == NULL || Pointer == NULL || !SymRsdsHasRange(ImageSize, Offset, Length)) + { + return FALSE; + } + + *Pointer = ImageBase + Offset; + return TRUE; +} + +/** + * @brief Helper function to extract the SizeOfHeaders field from the optional header, handling both 32-bit and 64-bit formats + * + * @param OptionalHeader A pointer to the optional header data in memory + * @param Is32Bit A boolean indicating whether the optional header is in 32-bit format (true) or 64-bit format (false) + * + * @return DWORD The value of the SizeOfHeaders field from the optional header + */ +static DWORD +SymRsdsGetSizeOfHeaders(const BYTE * OptionalHeader, BOOLEAN Is32Bit) +{ + if (Is32Bit) + { + return ((const IMAGE_OPTIONAL_HEADER32 *)OptionalHeader)->SizeOfHeaders; + } + + return ((const IMAGE_OPTIONAL_HEADER64 *)OptionalHeader)->SizeOfHeaders; +} + +/** + * @brief Helper function to extract the IMAGE_DATA_DIRECTORY entry for the debug directory from the optional header, handling both 32-bit and 64-bit formats + * + * @param OptionalHeader A pointer to the optional header data in memory + * @param Is32Bit A boolean indicating whether the optional header is in 32-bit format (true) or 64-bit format (false) + * + * @return IMAGE_DATA_DIRECTORY The IMAGE_DATA_DIRECTORY entry for the debug directory from the optional header + */ +static IMAGE_DATA_DIRECTORY +SymRsdsGetDebugDataDirectory(const BYTE * OptionalHeader, BOOLEAN Is32Bit) +{ + if (Is32Bit) + { + return ((const IMAGE_OPTIONAL_HEADER32 *)OptionalHeader)->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]; + } + + return ((const IMAGE_OPTIONAL_HEADER64 *)OptionalHeader)->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]; +} + +/** + * @brief Helper function to extract the NumberOfRvaAndSizes field from the optional header, handling both 32-bit and 64-bit formats + * + * @param OptionalHeader A pointer to the optional header data in memory + * @param Is32Bit A boolean indicating whether the optional header is in 32-bit format (true) or 64-bit format (false) + * + * @return DWORD The value of the NumberOfRvaAndSizes field from the optional header + */ +static DWORD +SymRsdsGetNumberOfRvaAndSizes(const BYTE * OptionalHeader, BOOLEAN Is32Bit) +{ + if (Is32Bit) + { + return ((const IMAGE_OPTIONAL_HEADER32 *)OptionalHeader)->NumberOfRvaAndSizes; + } + + return ((const IMAGE_OPTIONAL_HEADER64 *)OptionalHeader)->NumberOfRvaAndSizes; +} + +/** + * @brief Helper function to convert an RVA to a file offset by checking the section headers and bounds of the image + * + * @param ImageBase The base address of the image in memory + * @param ImageSize The size of the image in bytes + * @param FileHeader A pointer to the IMAGE_FILE_HEADER structure from the PE headers + * @param SectionHeaders A pointer to the first IMAGE_SECTION_HEADER in the section header array from the PE headers + * @param SizeOfHeaders The value of the SizeOfHeaders field from the optional header + * @param Rva The RVA to convert to a file offset + * @param Length The length of the range starting at Rva to check for validity + * @param FileOffset An output pointer to receive the calculated file offset if successful + * + * @return BOOLEAN TRUE if the RVA was successfully converted to a file offset and is within bounds, FALSE otherwise + */ +static BOOLEAN +SymRsdsRvaToFileOffset(const BYTE * ImageBase, + SIZE_T ImageSize, + const IMAGE_FILE_HEADER * FileHeader, + const IMAGE_SECTION_HEADER * SectionHeaders, + DWORD SizeOfHeaders, + DWORD Rva, + DWORD Length, + SIZE_T * FileOffset) +{ + if (ImageBase == NULL || FileHeader == NULL || SectionHeaders == NULL || FileOffset == NULL) + { + return FALSE; + } + + SIZE_T HeaderEnd = 0; + + if (SymRsdsAddSize((SIZE_T)Rva, (SIZE_T)Length, &HeaderEnd) && SizeOfHeaders <= ImageSize && Rva < SizeOfHeaders && + HeaderEnd <= SizeOfHeaders && SymRsdsHasRange(ImageSize, (SIZE_T)Rva, (SIZE_T)Length)) + { + *FileOffset = (SIZE_T)Rva; + return TRUE; + } + + for (WORD Index = 0; Index < FileHeader->NumberOfSections; Index++) + { + const IMAGE_SECTION_HEADER * SectionHeader = &SectionHeaders[Index]; + DWORD SectionSpan = max(SectionHeader->Misc.VirtualSize, SectionHeader->SizeOfRawData); + + if (SectionSpan == 0 || Rva < SectionHeader->VirtualAddress) + { + continue; + } + + DWORD Delta = Rva - SectionHeader->VirtualAddress; + if (Delta >= SectionSpan || Length > SectionSpan - Delta) + { + continue; + } + + if (Delta > SectionHeader->SizeOfRawData || Length > SectionHeader->SizeOfRawData - Delta) + { + return FALSE; + } + + SIZE_T RawOffset = 0; + + if (!SymRsdsAddSize((SIZE_T)SectionHeader->PointerToRawData, (SIZE_T)Delta, &RawOffset) || + !SymRsdsHasRange(ImageSize, RawOffset, (SIZE_T)Length)) + { + return FALSE; + } + + *FileOffset = RawOffset; + return TRUE; + } + + return FALSE; +} + +/** + * @brief Helper function to convert an RVA to a loaded image offset by checking the bounds of the image + * + * @param ImageSize The size of the image in bytes + * @param Rva The RVA to convert to a loaded image offset + * @param Length The length of the range starting at Rva to check for validity + * @param LoadedOffset An output pointer to receive the calculated loaded image offset if successful + * + * @return BOOLEAN TRUE if the RVA was successfully converted to a loaded image offset and is within bounds, FALSE otherwise + */ +static BOOLEAN +SymRsdsRvaToLoadedOffset(SIZE_T ImageSize, DWORD Rva, DWORD Length, SIZE_T * LoadedOffset) +{ + if (LoadedOffset == NULL || !SymRsdsHasRange(ImageSize, (SIZE_T)Rva, (SIZE_T)Length)) + { + return FALSE; + } + + *LoadedOffset = (SIZE_T)Rva; + return TRUE; +} + +/** + * @brief Helper function to extract the base name from a file path and copy it to the output buffer, ensuring it fits within the buffer size + * + * @param Path The input file path string + * @param PathLength The length of the input file path string in bytes + * @param PdbFileName The output buffer to receive the base name of the file. Must be at least PdbFileNameSize bytes + * @param PdbFileNameSize The size of the PdbFileName buffer in bytes + * + * @return BOOLEAN TRUE if the base name was successfully extracted and copied to the output buffer, FALSE otherwise (e.g., if inputs are invalid or base name does not fit in buffer) + */ +static BOOLEAN +SymRsdsCopyBasename(const CHAR * Path, SIZE_T PathLength, CHAR * PdbFileName, SIZE_T PdbFileNameSize) +{ + if (Path == NULL || PdbFileName == NULL || PdbFileNameSize == 0) + { + return FALSE; + } + + const CHAR * BaseName = Path; + SIZE_T BaseLength = PathLength; + + for (SIZE_T Index = 0; Index < PathLength; Index++) + { + if (Path[Index] == '\\' || Path[Index] == '/') + { + BaseName = Path + Index + 1; + BaseLength = PathLength - Index - 1; + } + } + + if (BaseLength == 0 || BaseLength >= PdbFileNameSize) + { + return FALSE; + } + + CopyMemory(PdbFileName, BaseName, BaseLength); + PdbFileName[BaseLength] = '\0'; + return TRUE; +} + +/** + * @brief Helper function to parse the RSDS CodeView debug information from the provided data and extract the PDB file name, GUID, and age + * + * @param CodeViewData A pointer to the CodeView debug information data in memory + * @param CodeViewSize The size of the CodeView debug information data in bytes + * @param PdbFileName An output buffer to receive the base name of the PDB file extracted from the CodeView data. Must be at least PdbFileNameSize bytes + * @param PdbFileNameSize The size of the PdbFileName buffer in bytes + * @param Guid An output pointer to receive the GUID extracted from the CodeView data + * @param Age An output pointer to receive the age extracted from the CodeView data + * + * @return BOOLEAN TRUE if the CodeView data was successfully parsed and information was extracted, FALSE otherwise (e.g., if data is invalid or does not contain valid RSDS information) + */ +static BOOLEAN +SymRsdsTryParseCodeView(const BYTE * CodeViewData, + DWORD CodeViewSize, + CHAR * PdbFileName, + SIZE_T PdbFileNameSize, + GUID * Guid, + DWORD * Age) +{ + static constexpr DWORD RsdsSignature = 0x53445352; + static constexpr DWORD RsdsHeaderSize = sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD); + + if (CodeViewData == NULL || CodeViewSize < RsdsHeaderSize || *(const DWORD *)CodeViewData != RsdsSignature) + { + return FALSE; + } + + const CHAR * Path = (const CHAR *)(CodeViewData + RsdsHeaderSize); + SIZE_T PathLimit = (SIZE_T)CodeViewSize - RsdsHeaderSize; + SIZE_T PathLength = 0; + + while (PathLength < PathLimit && Path[PathLength] != '\0') + { + PathLength++; + } + + if (PathLength == PathLimit) + { + return FALSE; + } + + if (!SymRsdsCopyBasename(Path, PathLength, PdbFileName, PdbFileNameSize)) + { + return FALSE; + } + + CopyMemory(Guid, CodeViewData + sizeof(DWORD), sizeof(*Guid)); + CopyMemory(Age, CodeViewData + sizeof(DWORD) + sizeof(GUID), sizeof(*Age)); + return TRUE; +} + +/** + * @brief Internal helper function to extract CodeView RSDS information from a PE image in memory, with options for loaded layout parsing + * + * @param ImageBase The base address of the PE image in memory + * @param ImageSize The size of the PE image in bytes + * @param PdbFileName An output buffer to receive the base name of the PDB file extracted from the CodeView data. Must be at least PdbFileNameSize bytes + * @param PdbFileNameSize The size of the PdbFileName buffer in bytes + * @param Guid An output pointer to receive the GUID extracted from the CodeView data + * @param Age An output pointer to receive the age extracted from the CodeView data + * @param LoadedLayout A boolean indicating whether to parse the image as if it is loaded in memory (true) or as a file on disk (false), which affects how RVAs are interpreted + * + * @return BOOLEAN TRUE if the CodeView RSDS information was successfully extracted, FALSE otherwise (e.g., if image is invalid or does not contain valid RSDS information) + */ +static BOOLEAN +SymExtractCodeViewRsdsInfoFromPeImageInternal(const BYTE * ImageBase, + SIZE_T ImageSize, + CHAR * PdbFileName, + SIZE_T PdbFileNameSize, + GUID * Guid, + DWORD * Age, + BOOLEAN LoadedLayout) +{ + SymRsdsClearOutputs(PdbFileName, PdbFileNameSize, Guid, Age); + + if (ImageBase == NULL || PdbFileName == NULL || PdbFileNameSize == 0 || Guid == NULL || Age == NULL) + { + return FALSE; + } + + if (!SymRsdsHasRange(ImageSize, 0, sizeof(IMAGE_DOS_HEADER))) + { + return FALSE; + } + + const IMAGE_DOS_HEADER * DosHeader = (const IMAGE_DOS_HEADER *)ImageBase; + if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE || DosHeader->e_lfanew < 0) + { + return FALSE; + } + + SIZE_T NtHeaderOffset = (SIZE_T)DosHeader->e_lfanew; + if (!SymRsdsHasRange(ImageSize, NtHeaderOffset, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))) + { + return FALSE; + } + + const BYTE * NtHeaders = ImageBase + NtHeaderOffset; + if (*(const DWORD *)NtHeaders != IMAGE_NT_SIGNATURE) + { + return FALSE; + } + + const IMAGE_FILE_HEADER * FileHeader = (const IMAGE_FILE_HEADER *)(NtHeaders + sizeof(DWORD)); + SIZE_T OptionalHeaderOffset = NtHeaderOffset + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER); + + if (FileHeader->SizeOfOptionalHeader < sizeof(WORD) || + !SymRsdsHasRange(ImageSize, OptionalHeaderOffset, FileHeader->SizeOfOptionalHeader)) + { + return FALSE; + } + + const BYTE * OptionalHeader = ImageBase + OptionalHeaderOffset; + WORD OptionalHeaderMagic = *(const WORD *)OptionalHeader; + BOOLEAN Is32Bit = FALSE; + SIZE_T MinimumOptionalHeaderSize = 0; + + if (OptionalHeaderMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + Is32Bit = TRUE; + MinimumOptionalHeaderSize = sizeof(IMAGE_OPTIONAL_HEADER32); + } + else if (OptionalHeaderMagic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + MinimumOptionalHeaderSize = sizeof(IMAGE_OPTIONAL_HEADER64); + } + else + { + return FALSE; + } + + if (FileHeader->SizeOfOptionalHeader < MinimumOptionalHeaderSize) + { + return FALSE; + } + + SIZE_T SectionTableOffset = OptionalHeaderOffset + FileHeader->SizeOfOptionalHeader; + SIZE_T SectionTableSize = (SIZE_T)FileHeader->NumberOfSections * sizeof(IMAGE_SECTION_HEADER); + + if (!LoadedLayout && FileHeader->NumberOfSections != 0 && SectionTableSize / sizeof(IMAGE_SECTION_HEADER) != FileHeader->NumberOfSections) + { + return FALSE; + } + + if (!LoadedLayout && !SymRsdsHasRange(ImageSize, SectionTableOffset, SectionTableSize)) + { + return FALSE; + } + + if (SymRsdsGetNumberOfRvaAndSizes(OptionalHeader, Is32Bit) <= IMAGE_DIRECTORY_ENTRY_DEBUG) + { + return FALSE; + } + + IMAGE_DATA_DIRECTORY DebugDirectory = SymRsdsGetDebugDataDirectory(OptionalHeader, Is32Bit); + if (DebugDirectory.VirtualAddress == 0 || DebugDirectory.Size < sizeof(IMAGE_DEBUG_DIRECTORY) || + DebugDirectory.Size % sizeof(IMAGE_DEBUG_DIRECTORY) != 0) + { + return FALSE; + } + + const IMAGE_SECTION_HEADER * SectionHeaders = LoadedLayout ? NULL : (const IMAGE_SECTION_HEADER *)(ImageBase + SectionTableOffset); + SIZE_T DebugOffset = 0; + + if (LoadedLayout) + { + if (!SymRsdsRvaToLoadedOffset(ImageSize, DebugDirectory.VirtualAddress, DebugDirectory.Size, &DebugOffset)) + { + return FALSE; + } + } + else if (!SymRsdsRvaToFileOffset(ImageBase, + ImageSize, + FileHeader, + SectionHeaders, + SymRsdsGetSizeOfHeaders(OptionalHeader, Is32Bit), + DebugDirectory.VirtualAddress, + DebugDirectory.Size, + &DebugOffset)) + { + return FALSE; + } + + const BYTE * DebugBytes = NULL; + if (!SymRsdsGetPointerAtOffset(ImageBase, ImageSize, DebugOffset, DebugDirectory.Size, &DebugBytes)) + { + return FALSE; + } + + DWORD DebugEntryCount = DebugDirectory.Size / sizeof(IMAGE_DEBUG_DIRECTORY); + for (DWORD Index = 0; Index < DebugEntryCount; Index++) + { + const IMAGE_DEBUG_DIRECTORY * DebugEntry = ((const IMAGE_DEBUG_DIRECTORY *)DebugBytes) + Index; + if (DebugEntry->Type != IMAGE_DEBUG_TYPE_CODEVIEW || DebugEntry->SizeOfData < sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD)) + { + continue; + } + + SIZE_T CodeViewOffset = 0; + const BYTE * CodeViewData = NULL; + + BOOLEAN IsCodeViewMapped = LoadedLayout ? SymRsdsRvaToLoadedOffset(ImageSize, DebugEntry->AddressOfRawData, DebugEntry->SizeOfData, &CodeViewOffset) : SymRsdsRvaToFileOffset(ImageBase, ImageSize, FileHeader, SectionHeaders, SymRsdsGetSizeOfHeaders(OptionalHeader, Is32Bit), DebugEntry->AddressOfRawData, DebugEntry->SizeOfData, &CodeViewOffset); + + if (!IsCodeViewMapped || !SymRsdsGetPointerAtOffset(ImageBase, ImageSize, CodeViewOffset, DebugEntry->SizeOfData, &CodeViewData)) + { + continue; + } + + if (SymRsdsTryParseCodeView(CodeViewData, DebugEntry->SizeOfData, PdbFileName, PdbFileNameSize, Guid, Age)) + { + return TRUE; + } + + SymRsdsClearOutputs(PdbFileName, PdbFileNameSize, Guid, Age); + } + + return FALSE; +} + +/** + * @brief Extracts CodeView RSDS information from a PE image in memory, interpreting the image as it would be laid out on disk + * + * @param ImageBase The base address of the PE image in memory + * @param ImageSize The size of the PE image in bytes + * @param PdbFileName An output buffer to receive the base name of the PDB file extracted from the CodeView data. Must be at least PdbFileNameSize bytes + * @param PdbFileNameSize The size of the PdbFileName buffer in bytes + * @param Guid An output pointer to receive the GUID extracted from the CodeView data + * @param Age An output pointer to receive the age extracted from the CodeView data + * + * @return BOOLEAN TRUE if the CodeView RSDS information was successfully extracted, FALSE otherwise (e.g., if image is invalid or does not contain valid RSDS information) + */ +BOOLEAN +SymExtractCodeViewRsdsInfoFromPeImage(const BYTE * ImageBase, + SIZE_T ImageSize, + CHAR * PdbFileName, + SIZE_T PdbFileNameSize, + GUID * Guid, + DWORD * Age) +{ + return SymExtractCodeViewRsdsInfoFromPeImageInternal(ImageBase, ImageSize, PdbFileName, PdbFileNameSize, Guid, Age, FALSE); +} + +/** + * @brief Extracts CodeView RSDS information from a PE image in memory, interpreting the image as it would be laid out in memory when loaded (i.e., using loaded image offsets) + * + * @param ImageBase The base address of the PE image in memory + * @param ImageSize The size of the PE image in bytes + * @param PdbFileName An output buffer to receive the base name of the PDB file extracted from the CodeView data. Must be at least PdbFileNameSize bytes + * @param PdbFileNameSize The size of the PdbFileName buffer in bytes + * @param Guid An output pointer to receive the GUID extracted from the CodeView data + * @param Age An output pointer to receive the age extracted from the CodeView data + * + * @return BOOLEAN TRUE if the CodeView RSDS information was successfully extracted, FALSE otherwise (e.g., if image is invalid or does not contain valid RSDS information) + */ +BOOLEAN +SymExtractCodeViewRsdsInfoFromLoadedPeImage(const BYTE * ImageBase, + SIZE_T ImageSize, + CHAR * PdbFileName, + SIZE_T PdbFileNameSize, + GUID * Guid, + DWORD * Age) +{ + return SymExtractCodeViewRsdsInfoFromPeImageInternal(ImageBase, ImageSize, PdbFileName, PdbFileNameSize, Guid, Age, TRUE); +} diff --git a/hyperdbg/symbol-parser/code/common-utils.cpp b/hyperdbg/symbol-parser/code/common-utils.cpp index c3e7a23a..3b0c2e2e 100644 --- a/hyperdbg/symbol-parser/code/common-utils.cpp +++ b/hyperdbg/symbol-parser/code/common-utils.cpp @@ -53,7 +53,7 @@ IsDirExists(const std::string & DirPath) BOOLEAN CreateDirectoryRecursive(const std::string & Path) { - size_t Pos = 0; + SIZE_T Pos = 0; do { Pos = Path.find_first_of("\\/", Pos + 1); @@ -67,6 +67,79 @@ CreateDirectoryRecursive(const std::string & Path) return FALSE; } +/** + * @brief Split path and arguments and handle strings between quotes + * + * @param Qargs the vector to store the result of split + * @param Command the command string to split + * @return VOID + */ +VOID +SplitPathAndArgs(std::vector & Qargs, const std::string & Command) +{ + int Len = (int)Command.length(); + BOOLEAN Qot = FALSE; + BOOLEAN Sqot = FALSE; + int ArgLen; + + for (int i = 0; i < Len; i++) + { + INT Start = i; + if (Command[i] == '\"') + { + Qot = TRUE; + } + else if (Command[i] == '\'') + Sqot = TRUE; + + if (Qot) + { + i++; + Start++; + while (i < Len && Command[i] != '\"') + i++; + if (i < Len) + Qot = FALSE; + ArgLen = i - Start; + i++; + } + else if (Sqot) + { + i++; + while (i < Len && Command[i] != '\'') + i++; + if (i < Len) + Sqot = FALSE; + ArgLen = i - Start; + i++; + } + else + { + while (i < Len && Command[i] != ' ') + i++; + ArgLen = i - Start; + } + + string Temp = Command.substr(Start, ArgLen); + if (!Temp.empty() && Temp != " ") + { + Qargs.push_back(Temp); + } + } + + /* + for (int i = 0; i < Qargs.size(); i++) + { + std::cout << Qargs[i] << std::endl; + } + + std::cout << Qargs.size(); + + if (Qot || Sqot) + std::cout << "One of the quotes is open\n"; + */ +} + /** * @brief general split command * @@ -77,21 +150,21 @@ CreateDirectoryRecursive(const std::string & Path) const std::vector Split(const std::string & s, const char & c) { - string buff {""}; - vector v; + string Buff {""}; + vector V; for (auto n : s) { if (n != c) - buff += n; - else if (n == c && !buff.empty()) + Buff += n; + else if (n == c && !Buff.empty()) { - v.push_back(buff); - buff.clear(); + V.push_back(Buff); + Buff.clear(); } } - if (!buff.empty()) - v.push_back(buff); + if (!Buff.empty()) + V.push_back(Buff); - return v; + return V; } diff --git a/hyperdbg/symbol-parser/code/pdb-identity.cpp b/hyperdbg/symbol-parser/code/pdb-identity.cpp new file mode 100644 index 00000000..753d120e --- /dev/null +++ b/hyperdbg/symbol-parser/code/pdb-identity.cpp @@ -0,0 +1,330 @@ +/** + * @file pdb-identity.cpp + * @author jtaw5649 + * @brief Internal PDB identity formatting helpers + * @details + * @version 0.19 + * @date 2026-06-02 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +#include "header/codeview-rsds.h" +#include "header/pdb-identity.h" + +/** + * @brief Helper function to clear the output buffer + * + * + * @param Buffer The output buffer pointer to check + * @param BufferSize The size of the output buffer in bytes + * + * @return BOOLEAN TRUE if the buffer is valid for writing, FALSE otherwise + */ +static VOID +SymClearOutputBuffer(CHAR * Buffer, SIZE_T BufferSize) +{ + if (Buffer != NULL && BufferSize != 0) + { + Buffer[0] = '\0'; + } +} + +/** + * @brief Helper function to check if the output buffer is valid for writing + * + * A buffer is considered valid if it is either NULL (indicating the caller does not want that output) or if it has a non-zero size. + * + * @param Buffer The output buffer pointer to check + * @param BufferSize The size of the output buffer in bytes + * + * @return BOOLEAN TRUE if the buffer is valid for writing, FALSE otherwise + */ +static BOOLEAN +SymOutputBufferHasSpace(const CHAR * Buffer, SIZE_T BufferSize) +{ + return Buffer == NULL || BufferSize != 0; +} + +/** + * @brief Helper function to format the PDB identity information into the specified output buffers + * + * The function formats the PDB file name, GUID, and age into a symbol server relative path and a combined GUID-and-age string according to the standard symbol server layout. + * + * @param PdbFile The base name of the PDB file (e.g., "example.pdb") + * @param Guid The GUID associated with the PDB + * @param Age The age associated with the PDB + * @param SymbolServerRelativePath An optional output buffer to receive the formatted symbol server relative path. If not NULL, it must have enough space for the formatted string + * @param SymbolServerRelativePathSize The size of the SymbolServerRelativePath buffer in bytes + * @param GuidAndAgeDetails An optional output buffer to receive the formatted GUID and age details string. If not NULL, it must have enough space for the formatted string + * @param GuidAndAgeDetailsSize The size of the GuidAndAgeDetails buffer in bytes + * + * @return BOOLEAN TRUE if the formatting succeeded and output buffers were filled as requested, FALSE if there was an error (e.g., invalid parameters or insufficient buffer sizes) + */ +BOOLEAN +SymFormatPdbIdentity(const CHAR * PdbFile, + const GUID * Guid, + DWORD Age, + CHAR * SymbolServerRelativePath, + SIZE_T SymbolServerRelativePathSize, + CHAR * GuidAndAgeDetails, + SIZE_T GuidAndAgeDetailsSize) +{ + const CHAR * FormatStrSymbolServerRelativePath = "%s/%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x%x/%s"; + const CHAR * FormatStrGuidAndAgeDetails = "%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x%x"; + + if (PdbFile == NULL || Guid == NULL || (SymbolServerRelativePath == NULL && GuidAndAgeDetails == NULL)) + { + return FALSE; + } + + if (SymbolServerRelativePath != NULL) + { + HRESULT Result = StringCchPrintfA(SymbolServerRelativePath, + SymbolServerRelativePathSize, + FormatStrSymbolServerRelativePath, + PdbFile, + Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7], + Age, + PdbFile); + + if (FAILED(Result)) + { + return FALSE; + } + } + + if (GuidAndAgeDetails != NULL) + { + HRESULT Result = StringCchPrintfA(GuidAndAgeDetails, + GuidAndAgeDetailsSize, + FormatStrGuidAndAgeDetails, + Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7], + Age); + + if (FAILED(Result)) + { + return FALSE; + } + } + + return TRUE; +} + +/** + * @brief Helper function to extract PDB identity information from a PE image using a specified extractor callback, with an optional fallback if extraction fails + * + * @param PeImageBytes A pointer to the bytes of the PE image in memory + * @param PeImageSize The size of the PE image in bytes + * @param SymbolServerRelativePath An optional output buffer to receive the formatted symbol server relative path. If not NULL, it must have enough space for the formatted string + * @param SymbolServerRelativePathSize The size of the SymbolServerRelativePath buffer in bytes + * @param PdbFilePath An optional output buffer to receive the extracted PDB file path. If not NULL, it must have enough space for the file path string + * @param PdbFilePathSize The size of the PdbFilePath buffer in bytes + * @param GuidAndAgeDetails An optional output buffer to receive the formatted GUID and age details string. If not NULL, it must have enough space for the formatted string + * @param GuidAndAgeDetailsSize The size of the GuidAndAgeDetails buffer in bytes + * @param ExtractorCallback A callback function that attempts to extract the PDB file name, GUID, and age from the PE image bytes. It should return TRUE on success and FALSE on failure + * @param FallbackCallback An optional callback function that is invoked if the extractor callback fails. It should attempt to provide the same information as the extractor and return TRUE on success or FALSE on failure + * @param FallbackContext An optional context pointer that is passed to the fallback callback when invoked + * + * @return BOOLEAN TRUE if either extraction method succeeded and output buffers were filled as requested, FALSE if both methods failed or if there was an error with parameters or buffer sizes + */ +static BOOLEAN +SymFormatPdbIdentityFromExtractorOrFallback(const BYTE * PeImageBytes, + SIZE_T PeImageSize, + CHAR * SymbolServerRelativePath, + SIZE_T SymbolServerRelativePathSize, + CHAR * PdbFilePath, + SIZE_T PdbFilePathSize, + CHAR * GuidAndAgeDetails, + SIZE_T GuidAndAgeDetailsSize, + PSYM_PDB_IDENTITY_EXTRACTOR_CALLBACK ExtractorCallback, + PSYM_PDB_IDENTITY_FALLBACK_CALLBACK FallbackCallback, + PVOID FallbackContext) +{ + CHAR PdbFile[MAX_PATH] = {0}; + GUID Guid = {0}; + DWORD Age = 0; + std::vector SymbolServerRelativePathBuffer; + std::vector PdbFilePathBuffer; + std::vector GuidAndAgeDetailsBuffer; + + SymClearOutputBuffer(SymbolServerRelativePath, SymbolServerRelativePathSize); + SymClearOutputBuffer(PdbFilePath, PdbFilePathSize); + SymClearOutputBuffer(GuidAndAgeDetails, GuidAndAgeDetailsSize); + + if (!SymOutputBufferHasSpace(SymbolServerRelativePath, SymbolServerRelativePathSize) || + !SymOutputBufferHasSpace(PdbFilePath, PdbFilePathSize) || + !SymOutputBufferHasSpace(GuidAndAgeDetails, GuidAndAgeDetailsSize)) + { + return FALSE; + } + + if (SymbolServerRelativePath == NULL && PdbFilePath == NULL && GuidAndAgeDetails == NULL) + { + return FALSE; + } + + if (PeImageBytes == NULL || ExtractorCallback == NULL || + !ExtractorCallback(PeImageBytes, PeImageSize, PdbFile, sizeof(PdbFile), &Guid, &Age)) + { + if (FallbackCallback == NULL || !FallbackCallback(FallbackContext, PdbFile, sizeof(PdbFile), &Guid, &Age)) + { + return FALSE; + } + } + + if (SymbolServerRelativePath != NULL) + { + SymbolServerRelativePathBuffer.resize(SymbolServerRelativePathSize); + } + + if (PdbFilePath != NULL) + { + PdbFilePathBuffer.resize(PdbFilePathSize); + + HRESULT Result = StringCchCopyA(PdbFilePathBuffer.data(), PdbFilePathBuffer.size(), PdbFile); + if (FAILED(Result)) + { + return FALSE; + } + } + + if (GuidAndAgeDetails != NULL) + { + GuidAndAgeDetailsBuffer.resize(GuidAndAgeDetailsSize); + } + + if ((SymbolServerRelativePath != NULL || GuidAndAgeDetails != NULL) && + !SymFormatPdbIdentity(PdbFile, + &Guid, + Age, + SymbolServerRelativePath == NULL ? NULL : SymbolServerRelativePathBuffer.data(), + SymbolServerRelativePathBuffer.size(), + GuidAndAgeDetails == NULL ? NULL : GuidAndAgeDetailsBuffer.data(), + GuidAndAgeDetailsBuffer.size())) + { + return FALSE; + } + + if (SymbolServerRelativePath != NULL && + FAILED(StringCchCopyA(SymbolServerRelativePath, SymbolServerRelativePathSize, SymbolServerRelativePathBuffer.data()))) + { + return FALSE; + } + + if (PdbFilePath != NULL && FAILED(StringCchCopyA(PdbFilePath, PdbFilePathSize, PdbFilePathBuffer.data()))) + { + return FALSE; + } + + if (GuidAndAgeDetails != NULL && FAILED(StringCchCopyA(GuidAndAgeDetails, GuidAndAgeDetailsSize, GuidAndAgeDetailsBuffer.data()))) + { + return FALSE; + } + + return TRUE; +} + +/** + * @brief Extracts PDB identity information from a PE image using the specified extractor callback, with an optional fallback if extraction fails + * + * @param PeImageBytes A pointer to the bytes of the PE image in memory + * @param PeImageSize The size of the PE image in bytes + * @param SymbolServerRelativePath An optional output buffer to receive the formatted symbol server relative path. If not NULL, it must have enough space for the formatted string + * @param SymbolServerRelativePathSize The size of the SymbolServerRelativePath buffer in bytes + * @param PdbFilePath An optional output buffer to receive the extracted PDB file path. If not NULL, it must have enough space for the file path string + * @param PdbFilePathSize The size of the PdbFilePath buffer in bytes + * @param GuidAndAgeDetails An optional output buffer to receive the formatted GUID and age details string. If not NULL, it must have enough space for the formatted string + * @param GuidAndAgeDetailsSize The size of the GuidAndAgeDetails buffer in bytes + * @param FallbackCallback An optional callback function that is invoked if the extractor callback fails. It should attempt to provide the same information as the extractor and return TRUE on success or FALSE on failure + * @param FallbackContext An optional context pointer that is passed to the fallback callback when invoked + * + * @return BOOLEAN TRUE if either extraction method succeeded and output buffers were filled as requested, FALSE if both methods failed or if there was an error with parameters or buffer sizes + */ +BOOLEAN +SymFormatPdbIdentityFromPeImageOrFallback(const BYTE * PeImageBytes, + SIZE_T PeImageSize, + CHAR * SymbolServerRelativePath, + SIZE_T SymbolServerRelativePathSize, + CHAR * PdbFilePath, + SIZE_T PdbFilePathSize, + CHAR * GuidAndAgeDetails, + SIZE_T GuidAndAgeDetailsSize, + PSYM_PDB_IDENTITY_FALLBACK_CALLBACK FallbackCallback, + PVOID FallbackContext) +{ + return SymFormatPdbIdentityFromExtractorOrFallback(PeImageBytes, + PeImageSize, + SymbolServerRelativePath, + SymbolServerRelativePathSize, + PdbFilePath, + PdbFilePathSize, + GuidAndAgeDetails, + GuidAndAgeDetailsSize, + SymExtractCodeViewRsdsInfoFromPeImage, + FallbackCallback, + FallbackContext); +} + +/** + * @brief Extracts PDB identity information from a PE image using the specified extractor callback that parses the image as if it is loaded in memory, with an optional fallback if extraction fails + * + * @param PeImageBytes A pointer to the bytes of the PE image in memory + * @param PeImageSize The size of the PE image in bytes + * @param SymbolServerRelativePath An optional output buffer to receive the formatted symbol server relative path. If not NULL, it must have enough space for the formatted string + * @param SymbolServerRelativePathSize The size of the SymbolServerRelativePath buffer in bytes + * @param PdbFilePath An optional output buffer to receive the extracted PDB file path. If not NULL, it must have enough space for the file path string + * @param PdbFilePathSize The size of the PdbFilePath buffer in bytes + * @param GuidAndAgeDetails An optional output buffer to receive the formatted GUID and age details string. If not NULL, it must have enough space for the formatted string + * @param GuidAndAgeDetailsSize The size of the GuidAndAgeDetails buffer in bytes + * @param FallbackCallback An optional callback function that is invoked if the extractor callback fails. It should attempt to provide the same information as the extractor and return TRUE on success or FALSE on failure + * @param FallbackContext An optional context pointer that is passed to the fallback callback when invoked + * + * @return BOOLEAN TRUE if either extraction method succeeded and output buffers were filled as requested, FALSE if both methods failed or if there was an error with parameters or buffer sizes + */ +BOOLEAN +SymFormatPdbIdentityFromLoadedPeImageOrFallback(const BYTE * PeImageBytes, + SIZE_T PeImageSize, + CHAR * SymbolServerRelativePath, + SIZE_T SymbolServerRelativePathSize, + CHAR * PdbFilePath, + SIZE_T PdbFilePathSize, + CHAR * GuidAndAgeDetails, + SIZE_T GuidAndAgeDetailsSize, + PSYM_PDB_IDENTITY_FALLBACK_CALLBACK FallbackCallback, + PVOID FallbackContext) +{ + return SymFormatPdbIdentityFromExtractorOrFallback(PeImageBytes, + PeImageSize, + SymbolServerRelativePath, + SymbolServerRelativePathSize, + PdbFilePath, + PdbFilePathSize, + GuidAndAgeDetails, + GuidAndAgeDetailsSize, + SymExtractCodeViewRsdsInfoFromLoadedPeImage, + FallbackCallback, + FallbackContext); +} diff --git a/hyperdbg/symbol-parser/code/symbol-parser.cpp b/hyperdbg/symbol-parser/code/symbol-parser.cpp index e1e6c2b1..aed38a13 100644 --- a/hyperdbg/symbol-parser/code/symbol-parser.cpp +++ b/hyperdbg/symbol-parser/code/symbol-parser.cpp @@ -12,6 +12,8 @@ */ #include "pch.h" +#include "header/pdb-identity.h" + // // Global Variables // @@ -19,24 +21,117 @@ std::vector g_LoadedModules; BOOLEAN g_IsLoadedModulesInitialized = FALSE; BOOLEAN g_AbortLoadingExecution = FALSE; CHAR * g_CurrentModuleName = NULL; -Callback g_MessageHandler = NULL; +PVOID g_MessageHandler = NULL; SymbolMapCallback g_SymbolMapForDisassembler = NULL; +/** + * @brief Reads the contents of a file into a byte vector + * + * @param LocalFilePath The path to the local file to read + * @param FileBytes An output reference to a vector that will receive the file bytes on success; will be cleared on failure + * + * @return BOOLEAN TRUE if the file was successfully read, FALSE on failure (e.g. file not found, access denied, read error) + */ +static BOOLEAN +SymReadFileBytes(const char * LocalFilePath, std::vector & FileBytes) +{ + FileBytes.clear(); + + if (LocalFilePath == NULL) + { + return FALSE; + } + + HANDLE FileHandle = CreateFileA(LocalFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + LARGE_INTEGER FileSize = {0}; + if (!GetFileSizeEx(FileHandle, &FileSize) || FileSize.QuadPart <= 0 || (ULONGLONG)FileSize.QuadPart > FileBytes.max_size()) + { + CloseHandle(FileHandle); + return FALSE; + } + + FileBytes.resize((SIZE_T)FileSize.QuadPart); + + BYTE * WriteCursor = FileBytes.data(); + SIZE_T Remaining = FileBytes.size(); + while (Remaining != 0) + { + DWORD ChunkSize = Remaining > MAXDWORD ? MAXDWORD : (DWORD)Remaining; + DWORD BytesRead = 0; + + if (!ReadFile(FileHandle, WriteCursor, ChunkSize, &BytesRead, NULL) || BytesRead == 0) + { + CloseHandle(FileHandle); + FileBytes.clear(); + return FALSE; + } + + WriteCursor += BytesRead; + Remaining -= BytesRead; + } + + CloseHandle(FileHandle); + return TRUE; +} + +/** + * @brief Fallback callback function to retrieve PDB file name, GUID, and age information using SymSrvGetFileIndexInfo when the primary extractor fails + * + * @param Context A context pointer that is expected to be a string representing the file path to query with SymSrvGetFileIndexInfo + * @param PdbFile An output buffer to receive the base name of the PDB file extracted from SymSrvGetFileIndexInfo. Must be at least PdbFileSize bytes + * @param PdbFileSize The size of the PdbFile buffer in bytes + * @param Guid An output pointer to receive the GUID extracted from SymSrvGetFileIndexInfo + * @param Age An output pointer to receive the age extracted from SymSrvGetFileIndexInfo + * + * @return BOOLEAN TRUE if the information was successfully retrieved and output buffers were filled as requested, FALSE otherwise (e.g., if Context is invalid or SymSrvGetFileIndexInfo fails) + */ +static BOOLEAN +SymSrvGetFileIndexInfoFallback(PVOID Context, CHAR * PdbFile, SIZE_T PdbFileSize, GUID * Guid, DWORD * Age) +{ + SYMSRV_INDEX_INFO SymInfo = {0}; + SymInfo.sizeofstruct = sizeof(SYMSRV_INDEX_INFO); + + if (Context == NULL || PdbFile == NULL || Guid == NULL || Age == NULL) + { + return FALSE; + } + + if (!SymSrvGetFileIndexInfo((const char *)Context, &SymInfo, 0)) + { + return FALSE; + } + + if (FAILED(StringCchCopyA(PdbFile, PdbFileSize, SymInfo.pdbfile))) + { + return FALSE; + } + + *Guid = SymInfo.guid; + *Age = SymInfo.age; + + return TRUE; +} + /** * @brief Set the function callback that will be called if any message * needs to be shown * - * @param handler Function that handles the messages + * @param Handler Function that handles the messages */ void -SymSetTextMessageCallback(PVOID handler) +SymSetTextMessageCallback(PVOID Handler) { - g_MessageHandler = (Callback)handler; + g_MessageHandler = Handler; // // Set the pdbex's message handler // - pdbex_set_logging_method_export(handler); + pdbex_set_logging_method_export(Handler); } /** @@ -60,22 +155,23 @@ ShowMessages(const char * Fmt, ...) { char TempMessage[COMMUNICATION_BUFFER_SIZE + TCP_END_OF_BUFFER_CHARS_COUNT] = {0}; va_start(ArgList, Fmt); - int sprintfresult = vsprintf_s(TempMessage, Fmt, ArgList); + INT SprintfResult = vsprintf_s(TempMessage, Fmt, ArgList); va_end(ArgList); - if (sprintfresult != -1) + if (SprintfResult != -1) { // // There is another handler // - g_MessageHandler(TempMessage); + ((SendMessageWithParamCallback)g_MessageHandler)(TempMessage); } } } /** * @brief Interpret and find module base, based on module name - * @param SearchMask + * @param SearchMask the search mask to find module + * @param SetModuleNameGlobally whether to set module name globally * * @return PSYMBOL_LOADED_MODULE_DETAILS NULL means error or not found, * otherwise it returns the instance of loaded module based on search mask @@ -86,7 +182,7 @@ SymGetModuleBaseFromSearchMask(const char * SearchMask, BOOLEAN SetModuleNameGlo string Token; char ModuleName[_MAX_FNAME] = {0}; int Index = 0; - char Ch = NULL; + char Ch = '\0'; if (!g_IsLoadedModulesInitialized || SearchMask == NULL) { @@ -208,8 +304,8 @@ SymGetFieldOffsetFromModule(UINT64 Base, WCHAR * TypeName, WCHAR * FieldName, UI // const DWORD SizeOfStruct = sizeof(SYMBOL_INFOW) + ((MAX_SYM_NAME - 1) * sizeof(wchar_t)); - uint8_t SymbolInfoBuffer[SizeOfStruct]; - auto SymbolInfo = PSYMBOL_INFOW(SymbolInfoBuffer); + UINT8 SymbolInfoBuffer[SizeOfStruct]; + auto SymbolInfo = PSYMBOL_INFOW(SymbolInfoBuffer); // // Initialize the fields that need initialization @@ -243,7 +339,7 @@ SymGetFieldOffsetFromModule(UINT64 Base, WCHAR * TypeName, WCHAR * FieldName, UI // // Allocate enough memory to receive the children ids // - auto FindChildrenParamsBacking = std::make_unique( + auto FindChildrenParamsBacking = std::make_unique( sizeof(_TI_FINDCHILDREN_PARAMS) + ((ChildrenCount - 1) * sizeof(ULONG))); auto FindChildrenParams = (_TI_FINDCHILDREN_PARAMS *)FindChildrenParamsBacking.get(); @@ -335,8 +431,8 @@ SymGetDataTypeSizeFromModule(UINT64 Base, WCHAR * TypeName, UINT64 * TypeSize) // const DWORD SizeOfStruct = sizeof(SYMBOL_INFOW) + ((MAX_SYM_NAME - 1) * sizeof(wchar_t)); - uint8_t SymbolInfoBuffer[SizeOfStruct]; - auto SymbolInfo = PSYMBOL_INFOW(SymbolInfoBuffer); + UINT8 SymbolInfoBuffer[SizeOfStruct]; + auto SymbolInfo = PSYMBOL_INFOW(SymbolInfoBuffer); // // Initialize the fields that need initialization @@ -533,7 +629,7 @@ SymLoadFileSymbol(UINT64 BaseAddress, const char * PdbFileName, const char * Cus { DWORD FileSize = 0; int Index = 0; - char Ch = NULL; + char Ch = '\0'; char ModuleName[_MAX_FNAME] = {0}; char AlternateModuleName[_MAX_FNAME] = {0}; PSYMBOL_LOADED_MODULE_DETAILS ModuleDetails = NULL; @@ -795,7 +891,7 @@ SymUnloadAllSymbols() /** * @brief Convert function name to address * - * @param FunctionName + * @param FunctionOrVariableName the name of the function or variable to convert * @param WasFound * * @return UINT64 @@ -831,7 +927,7 @@ SymConvertNameToAddress(const char * FunctionOrVariableName, PBOOLEAN WasFound) // // Check if '!' is present in the function or variable name // - size_t FoundIndex = TempName.find('!'); + SIZE_T FoundIndex = TempName.find('!'); if (FoundIndex != std::string::npos) { ExtractedModuleName = TempName.substr(0, FoundIndex); @@ -981,7 +1077,7 @@ SymGetFieldOffset(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset) // Convert TypeName to wide-char, it's because SymGetTypeInfo supports // wide-char // - const size_t TypeNameSize = strlen(TypeName) + 1; + const SIZE_T TypeNameSize = strlen(TypeName) + 1; WCHAR * TypeNameW = (WCHAR *)malloc(sizeof(wchar_t) * TypeNameSize); if (TypeNameW == NULL) @@ -997,7 +1093,7 @@ SymGetFieldOffset(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset) // Convert FieldName to wide-char, it's because SymGetTypeInfo supports // wide-char // - const size_t FieldNameSize = strlen(FieldName) + 1; + const SIZE_T FieldNameSize = strlen(FieldName) + 1; WCHAR * FieldNameW = (WCHAR *)malloc(sizeof(wchar_t) * FieldNameSize); if (FieldNameW == NULL) @@ -1021,9 +1117,8 @@ SymGetFieldOffset(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset) /** * @brief Get the size of structures from the symbols * - * @param TypeName - * @param FieldName - * @param FieldOffset + * @param TypeName the type (structure) name to query + * @param TypeSize pointer to receive the size of the data type * * @return BOOLEAN Whether the module is found successfully or not */ @@ -1070,7 +1165,7 @@ SymGetDataTypeSize(CHAR * TypeName, UINT64 * TypeSize) // Convert FieldName to wide-char, it's because SymGetTypeInfo supports // wide-char // - const size_t TypeNameSize = strlen(TypeName) + 1; + const SIZE_T TypeNameSize = strlen(TypeName) + 1; WCHAR * TypeNameW = (WCHAR *)malloc(sizeof(wchar_t) * TypeNameSize); if (TypeNameW == NULL) @@ -1284,9 +1379,9 @@ SymGetFileSize(const char * FileName, DWORD & FileSize) // // Open the file // - HANDLE hFile = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + HANDLE HFile = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) + if (HFile == INVALID_HANDLE_VALUE) { ShowMessages("err, unable to open symbol file (%x)\n", GetLastError()); return FALSE; @@ -1295,7 +1390,7 @@ SymGetFileSize(const char * FileName, DWORD & FileSize) // // Obtain the size of the file // - FileSize = GetFileSize(hFile, NULL); + FileSize = GetFileSize(HFile, NULL); if (FileSize == INVALID_FILE_SIZE) { @@ -1309,7 +1404,7 @@ SymGetFileSize(const char * FileName, DWORD & FileSize) // // Close the file // - if (!CloseHandle(hFile)) + if (!CloseHandle(HFile)) { ShowMessages("err, unable to close symbol file (%x)\n", GetLastError()); @@ -1680,58 +1775,39 @@ SymTagStr(ULONG Tag) * * @param LocalFilePath * @param ResultPath + * @param ResultPathSize the size of the result path buffer * * @return BOOLEAN */ BOOLEAN -SymConvertFileToPdbPath(const char * LocalFilePath, char * ResultPath) +SymConvertFileToPdbPath(const char * LocalFilePath, char * ResultPath, SIZE_T ResultPathSize) { - SYMSRV_INDEX_INFO SymInfo = {0}; - const char * FormatStr = - "%s/%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x%x/%s"; - SymInfo.sizeofstruct = sizeof(SYMSRV_INDEX_INFO); + std::vector FileBytes; - BOOL Ret = SymSrvGetFileIndexInfo(LocalFilePath, &SymInfo, 0); - - if (Ret) + if (LocalFilePath == NULL && ResultPath == NULL) { - wsprintfA(ResultPath, - FormatStr, - SymInfo.pdbfile, - SymInfo.guid.Data1, - SymInfo.guid.Data2, - SymInfo.guid.Data3, - SymInfo.guid.Data4[0], - SymInfo.guid.Data4[1], - SymInfo.guid.Data4[2], - SymInfo.guid.Data4[3], - SymInfo.guid.Data4[4], - SymInfo.guid.Data4[5], - SymInfo.guid.Data4[6], - SymInfo.guid.Data4[7], - SymInfo.age, - SymInfo.pdbfile); - - return TRUE; - } - else - { - // - // ShowMessages("err, unable to get symbol information for %s (%x)\n", LocalFilePath, GetLastError()); - // return FALSE; } - // - // By default, return false - // - return FALSE; + SymReadFileBytes(LocalFilePath, FileBytes); + + return SymFormatPdbIdentityFromPeImageOrFallback(FileBytes.empty() ? NULL : FileBytes.data(), + FileBytes.size(), + ResultPath, + ResultPathSize, + NULL, + 0, + NULL, + 0, + SymSrvGetFileIndexInfoFallback, + (PVOID)LocalFilePath); } /** * @brief Convert redirection of 32-bit compatibility path * * @param LocalFilePath + * @param Wow64ConvertedPath the converted path for Wow64 compatibility * * @return VOID */ @@ -1744,17 +1820,17 @@ SymConvertWow64CompatibilityPaths(const char * LocalFilePath, std::string & Wow6 std::transform(FilePath.begin(), FilePath.end(), FilePath.begin(), ::tolower); // Replace "\windows\system32" with "\windows\syswow64" - size_t pos = FilePath.find(":\\windows\\system32"); - if (pos != std::string::npos) + SIZE_T Pos = FilePath.find(":\\windows\\system32"); + if (Pos != std::string::npos) { - FilePath.replace(pos, 18, ":\\windows\\syswow64"); + FilePath.replace(Pos, 18, ":\\windows\\syswow64"); } // Replace "\program files" with "\program files (x86)" - pos = FilePath.find(":\\program files"); - if (pos != std::string::npos) + Pos = FilePath.find(":\\program files"); + if (Pos != std::string::npos) { - FilePath.replace(pos, 15, ":\\program files (x86)"); + FilePath.replace(Pos, 15, ":\\program files (x86)"); } // @@ -1777,13 +1853,9 @@ SymConvertWow64CompatibilityPaths(const char * LocalFilePath, std::string & Wow6 BOOLEAN SymConvertFileToPdbFileAndGuidAndAgeDetails(const char * LocalFilePath, char * PdbFilePath, char * GuidAndAgeDetails, BOOLEAN Is32BitModule) { - SYMSRV_INDEX_INFO SymInfo = {0}; std::string Wow64ConvertedPath; - const char * FormatStrPdbFilePath = "%s"; - const char * ActualLocalFilePath = NULL; - const char * FormatStrPdbFileGuidAndAgeDetails = - "%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x%x"; - SymInfo.sizeofstruct = sizeof(SYMSRV_INDEX_INFO); + std::vector FileBytes; + const char * ActualLocalFilePath = NULL; if (Is32BitModule) { @@ -1798,41 +1870,54 @@ SymConvertFileToPdbFileAndGuidAndAgeDetails(const char * LocalFilePath, char * P // ShowMessages("the final (actual) address is: %s\n", ActualLocalFilePath); - BOOL Ret = SymSrvGetFileIndexInfo(ActualLocalFilePath, &SymInfo, 0); + SymReadFileBytes(ActualLocalFilePath, FileBytes); - if (Ret) + return SymFormatPdbIdentityFromPeImageOrFallback(FileBytes.empty() ? NULL : FileBytes.data(), + FileBytes.size(), + NULL, + 0, + PdbFilePath, + MAX_PATH, + GuidAndAgeDetails, + MAXIMUM_GUID_AND_AGE_SIZE, + SymSrvGetFileIndexInfoFallback, + (PVOID)ActualLocalFilePath); +} + +BOOLEAN +SymConvertLoadedModuleToPdbFileAndGuidAndAgeDetails(const BYTE * LoadedImageBytes, + SIZE_T LoadedImageSize, + const char * LocalFilePath, + char * PdbFilePath, + char * GuidAndAgeDetails, + BOOLEAN Is32BitModule) +{ + std::string Wow64ConvertedPath; + const char * ActualLocalFilePath = NULL; + + if (Is32BitModule) { - wsprintfA(PdbFilePath, FormatStrPdbFilePath, SymInfo.pdbfile); - - wsprintfA(GuidAndAgeDetails, - FormatStrPdbFileGuidAndAgeDetails, - SymInfo.guid.Data1, - SymInfo.guid.Data2, - SymInfo.guid.Data3, - SymInfo.guid.Data4[0], - SymInfo.guid.Data4[1], - SymInfo.guid.Data4[2], - SymInfo.guid.Data4[3], - SymInfo.guid.Data4[4], - SymInfo.guid.Data4[5], - SymInfo.guid.Data4[6], - SymInfo.guid.Data4[7], - SymInfo.age); - - return TRUE; + SymConvertWow64CompatibilityPaths(LocalFilePath, Wow64ConvertedPath); + ActualLocalFilePath = Wow64ConvertedPath.c_str(); + // ShowMessages("local file path: %s | final file path: %s\n", LocalFilePath, ActualLocalFilePath); } else { - // - // ShowMessages("err, unable to get symbol information for %s (%x)\n", ActualLocalFilePath, GetLastError()); - // - return FALSE; + ActualLocalFilePath = LocalFilePath; } - // - // By default, return false - // - return FALSE; + // ShowMessages("the final (actual) address is: %s\n", ActualLocalFilePath); + + return SymFormatPdbIdentityFromLoadedPeImageOrFallback(LoadedImageBytes, + LoadedImageSize, + NULL, + 0, + PdbFilePath, + MAX_PATH, + GuidAndAgeDetails, + MAXIMUM_GUID_AND_AGE_SIZE, + SymSrvGetFileIndexInfoFallback, + (PVOID)ActualLocalFilePath); } /** @@ -1870,7 +1955,7 @@ SymbolInitLoad(PVOID BufferToStoreDetails, // // Split each module and details // - for (size_t i = 0; i < StoredLength / sizeof(MODULE_SYMBOL_DETAIL); i++) + for (SIZE_T i = 0; i < StoredLength / sizeof(MODULE_SYMBOL_DETAIL); i++) { // // Check for abort @@ -2051,13 +2136,12 @@ SymbolInitLoad(PVOID BufferToStoreDetails, /** * @brief download pdb file * - * @param BufferToStoreDetails Pointer to a buffer to store the symbols details - * this buffer will be allocated by this function and needs to be freed by caller - * @param StoredLength The length that stored on the BufferToStoreDetails - * @param SymPath The path of symbols - * @param IsSilentLoad Download without any message + * @param SymName the name of the symbol (pdb file name) + * @param GUID the GUID and age string identifying the symbol version + * @param SymPath the symbol search path + * @param IsSilentLoad download without any message * - * return BOOLEAN + * @return BOOLEAN */ BOOLEAN SymbolPdbDownload(std::string SymName, const std::string & GUID, const std::string & SymPath, BOOLEAN IsSilentLoad) @@ -2113,7 +2197,7 @@ SymbolPdbDownload(std::string SymName, const std::string & GUID, const std::stri * @brief In the case of pressing CTRL+C, it sets a flag * to abort the execution of the 'reload'ing and the 'download'ing * - * return VOID + * @return VOID */ VOID SymbolAbortLoading() @@ -2173,7 +2257,7 @@ SymShowDataBasedOnSymbolTypes(const char * TypeName, // // Split the arguments by space // - SplitedSymPath = Split(AdditionalParametersString, ' '); + SplitPathAndArgs(SplitedSymPath, AdditionalParametersString); // // Allocate buffer to convert it to the char* @@ -2224,7 +2308,7 @@ SymShowDataBasedOnSymbolTypes(const char * TypeName, // // Fill the parameter with char array // - for (size_t i = 3; i < SizeOfArgv; i++) + for (SIZE_T i = 3; i < SizeOfArgv; i++) { ArgvArray[i] = (char *)SplitedSymPath.at(i - 3).c_str(); } diff --git a/hyperdbg/symbol-parser/header/codeview-rsds.h b/hyperdbg/symbol-parser/header/codeview-rsds.h new file mode 100644 index 00000000..3ce6dcb8 --- /dev/null +++ b/hyperdbg/symbol-parser/header/codeview-rsds.h @@ -0,0 +1,28 @@ +/** + * @file codeview-rsds.h + * @author jtaw5649 + * @brief Bounded in-memory CodeView RSDS parser + * @details + * @version 0.19 + * @date 2026-06-02 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +BOOLEAN +SymExtractCodeViewRsdsInfoFromPeImage(const BYTE * ImageBase, + SIZE_T ImageSize, + CHAR * PdbFileName, + SIZE_T PdbFileNameSize, + GUID * Guid, + DWORD * Age); + +BOOLEAN +SymExtractCodeViewRsdsInfoFromLoadedPeImage(const BYTE * ImageBase, + SIZE_T ImageSize, + CHAR * PdbFileName, + SIZE_T PdbFileNameSize, + GUID * Guid, + DWORD * Age); diff --git a/hyperdbg/symbol-parser/header/common-utils.h b/hyperdbg/symbol-parser/header/common-utils.h index c8ecd0f7..fa7fea13 100644 --- a/hyperdbg/symbol-parser/header/common-utils.h +++ b/hyperdbg/symbol-parser/header/common-utils.h @@ -27,3 +27,6 @@ CreateDirectoryRecursive(const std::string & Path); const std::vector Split(const std::string & s, const char & c); + +VOID +SplitPathAndArgs(std::vector & Qargs, const std::string & Command); diff --git a/hyperdbg/symbol-parser/header/pdb-identity.h b/hyperdbg/symbol-parser/header/pdb-identity.h new file mode 100644 index 00000000..d960d8f4 --- /dev/null +++ b/hyperdbg/symbol-parser/header/pdb-identity.h @@ -0,0 +1,59 @@ +/** + * @file pdb-identity.h + * @author jtaw5649 + * @brief Internal PDB identity formatting helpers + * @details + * @version 0.19 + * @date 2026-06-02 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#pragma once + +typedef BOOLEAN (*PSYM_PDB_IDENTITY_FALLBACK_CALLBACK)(PVOID Context, + CHAR * PdbFile, + SIZE_T PdbFileSize, + GUID * Guid, + DWORD * Age); + + +typedef BOOLEAN (*PSYM_PDB_IDENTITY_EXTRACTOR_CALLBACK)(const BYTE * PeImageBytes, + SIZE_T PeImageSize, + CHAR * PdbFile, + SIZE_T PdbFileSize, + GUID * Guid, + DWORD * Age); + +BOOLEAN +SymFormatPdbIdentity(const CHAR * PdbFile, + const GUID * Guid, + DWORD Age, + CHAR * SymbolServerRelativePath, + SIZE_T SymbolServerRelativePathSize, + CHAR * GuidAndAgeDetails, + SIZE_T GuidAndAgeDetailsSize); + +BOOLEAN +SymFormatPdbIdentityFromPeImageOrFallback(const BYTE * PeImageBytes, + SIZE_T PeImageSize, + CHAR * SymbolServerRelativePath, + SIZE_T SymbolServerRelativePathSize, + CHAR * PdbFilePath, + SIZE_T PdbFilePathSize, + CHAR * GuidAndAgeDetails, + SIZE_T GuidAndAgeDetailsSize, + PSYM_PDB_IDENTITY_FALLBACK_CALLBACK FallbackCallback, + PVOID FallbackContext); + +BOOLEAN +SymFormatPdbIdentityFromLoadedPeImageOrFallback(const BYTE * PeImageBytes, + SIZE_T PeImageSize, + CHAR * SymbolServerRelativePath, + SIZE_T SymbolServerRelativePathSize, + CHAR * PdbFilePath, + SIZE_T PdbFilePathSize, + CHAR * GuidAndAgeDetails, + SIZE_T GuidAndAgeDetailsSize, + PSYM_PDB_IDENTITY_FALLBACK_CALLBACK FallbackCallback, + PVOID FallbackContext); diff --git a/hyperdbg/symbol-parser/header/symbol-parser.h b/hyperdbg/symbol-parser/header/symbol-parser.h index f5763f92..bbbc9afd 100644 --- a/hyperdbg/symbol-parser/header/symbol-parser.h +++ b/hyperdbg/symbol-parser/header/symbol-parser.h @@ -43,28 +43,10 @@ extern "C" { // // Imports // -__declspec(dllimport) int pdbex_export(int argc, char ** argv, bool is_struct, void * buffer_address); -__declspec(dllimport) void pdbex_set_logging_method_export(PVOID handler); - -// -// Exports -// -__declspec(dllexport) VOID SymSetTextMessageCallback(PVOID handler); -__declspec(dllexport) VOID SymbolAbortLoading(); -__declspec(dllexport) UINT32 SymLoadFileSymbol(UINT64 BaseAddress, const char * PdbFileName, const char * CustomModuleName); -__declspec(dllexport) UINT32 SymUnloadAllSymbols(); -__declspec(dllexport) UINT32 SymUnloadModuleSymbol(char * ModuleName); -__declspec(dllexport) UINT32 SymSearchSymbolForMask(const char * SearchMask); -__declspec(dllexport) BOOLEAN SymGetFieldOffset(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset); -__declspec(dllexport) BOOLEAN SymGetDataTypeSize(CHAR * TypeName, UINT64 * TypeSize); -__declspec(dllexport) BOOLEAN SymCreateSymbolTableForDisassembler(void * CallbackFunction); -__declspec(dllexport) UINT64 SymConvertNameToAddress(const char * FunctionOrVariableName, PBOOLEAN WasFound); -__declspec(dllexport) BOOLEAN SymConvertFileToPdbPath(const char * LocalFilePath, char * ResultPath); -__declspec(dllexport) BOOLEAN SymConvertFileToPdbFileAndGuidAndAgeDetails(const char * LocalFilePath, char * PdbFilePath, char * GuidAndAgeDetails, BOOLEAN Is32BitModule); -__declspec(dllexport) BOOLEAN SymbolInitLoad(PVOID BufferToStoreDetails, UINT32 StoredLength, BOOLEAN DownloadIfAvailable, const char * SymbolPath, BOOLEAN IsSilentLoad); -__declspec(dllexport) BOOLEAN SymShowDataBasedOnSymbolTypes(const char * TypeName, UINT64 Address, BOOLEAN IsStruct, PVOID BufferAddress, const char * AdditionalParameters); -__declspec(dllexport) BOOLEAN SymQuerySizeof( const char * StructNameOrTypeName, UINT32 * SizeOfField); -__declspec(dllexport) BOOLEAN SymCastingQueryForFiledsAndTypes( const char * StructName, const char * FiledOfStructName, PBOOLEAN IsStructNamePointerOrNot, PBOOLEAN IsFiledOfStructNamePointerOrNot, char ** NewStructOrTypeName, UINT32 * OffsetOfFieldFromTop, UINT32 * SizeOfField); +__declspec(dllimport) int +pdbex_export(int argc, char ** argv, bool is_struct, void * buffer_address); +__declspec(dllimport) void +pdbex_set_logging_method_export(PVOID handler); } ////////////////////////////////////////////////// diff --git a/hyperdbg/symbol-parser/pch.cpp b/hyperdbg/symbol-parser/pch.cpp index 4af69dae..43408d27 100644 --- a/hyperdbg/symbol-parser/pch.cpp +++ b/hyperdbg/symbol-parser/pch.cpp @@ -1,5 +1,5 @@ /** - * @file pch.c + * @file pch.cpp * @author Sina Karvandi (sina@hyperdbg.org) * * @details Pre-compiled headers diff --git a/hyperdbg/symbol-parser/pch.h b/hyperdbg/symbol-parser/pch.h index 57e1a20e..53c113fb 100644 --- a/hyperdbg/symbol-parser/pch.h +++ b/hyperdbg/symbol-parser/pch.h @@ -11,13 +11,25 @@ */ #pragma once +// +// Scope definitions +// +#define HYPERDBG_SYMBOL_PARSER + +using namespace std; + +// +// Environment headers +// +#include "platform/general/header/Environment.h" + #include #include #include #include #include #include - +#include #define _NO_CVCONST_H // for symbol parsing #include @@ -35,12 +47,15 @@ typedef RFLAGS * PRFLAGS; #endif // USE_LIB_IA32 #include "SDK/HyperDbgSdk.h" -#include "SDK/Imports/HyperDbgCtrlImports.h" -#include "Definition.h" -#include "..\symbol-parser\header\common-utils.h" -#include "..\symbol-parser\header\symbol-parser.h" +#include "config/Definition.h" +#include "SDK/imports/user/HyperDbgLibImports.h" +#include "../symbol-parser/header/common-utils.h" +#include "../symbol-parser/header/symbol-parser.h" -using namespace std; +// +// Module imports/exports +// +#include "SDK/imports/user/HyperDbgSymImports.h" // // Needed to link symbol server diff --git a/hyperdbg/symbol-parser/symbol-parser.vcxproj b/hyperdbg/symbol-parser/symbol-parser.vcxproj index ed0ebc30..62dc6ef9 100644 --- a/hyperdbg/symbol-parser/symbol-parser.vcxproj +++ b/hyperdbg/symbol-parser/symbol-parser.vcxproj @@ -21,13 +21,13 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode @@ -64,6 +64,7 @@ pch.h $(SolutionDir)\include;$(SolutionDir)dependencies;$(ProjectDir);%(AdditionalIncludeDirectories) true + stdcpp20 Console @@ -85,6 +86,8 @@ pch.h $(SolutionDir)\include;$(SolutionDir)dependencies;$(ProjectDir);%(AdditionalIncludeDirectories) true + stdcpp20 + MaxSpeed Console @@ -97,7 +100,9 @@ + + Create @@ -105,7 +110,9 @@ + + diff --git a/hyperdbg/symbol-parser/symbol-parser.vcxproj.filters b/hyperdbg/symbol-parser/symbol-parser.vcxproj.filters index 3cf8e830..9c5f7f69 100644 --- a/hyperdbg/symbol-parser/symbol-parser.vcxproj.filters +++ b/hyperdbg/symbol-parser/symbol-parser.vcxproj.filters @@ -9,6 +9,9 @@ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + {7884782a-2386-47f5-aeed-fabdefcc888d} + @@ -20,6 +23,12 @@ code + + code + + + code + code @@ -34,5 +43,11 @@ header + + header + + + header + - \ No newline at end of file + diff --git a/hyperdbg/tests/command-parser/command-parser-failed-testcases.txt b/hyperdbg/tests/command-parser/command-parser-failed-testcases.txt new file mode 100644 index 00000000..e69de29b diff --git a/hyperdbg/tests/command-parser/command-parser-testcases.txt b/hyperdbg/tests/command-parser/command-parser-testcases.txt new file mode 100644 index 00000000..903ff55c --- /dev/null +++ b/hyperdbg/tests/command-parser/command-parser-testcases.txt @@ -0,0 +1,5574 @@ +_____________________________________________________________ +salam khobi 123 456 +---------------------------------- +salam +---------------------------------- +khobi +---------------------------------- +123 +---------------------------------- +456 +_____________________________________________________________ +!monitor 123 1234 script { tesTo salam + +khoobi? + } +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- + tesTo salam + +khoobi? + +_____________________________________________________________ + !monitor rwx 123 1234 script { @rax= @rbx; + +printf("ho"); + } +---------------------------------- +!monitor +---------------------------------- +rwx +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- + @rax= @rbx; + +printf("ho"); + +_____________________________________________________________ + + + + + +!monitor 123 1234 script { tesTo salam + +khoobi? + } +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- + tesTo salam + +khoobi? + +_____________________________________________________________ + help settings +---------------------------------- +help +---------------------------------- +settings +_____________________________________________________________ +help settings +---------------------------------- +help +---------------------------------- +settings +_____________________________________________________________ + !monitor 456 789 script {salam} +---------------------------------- +!monitor +---------------------------------- +456 +---------------------------------- +789 +---------------------------------- +script +---------------------------------- +salam +_____________________________________________________________ + !monitor 123 987 script { salam} +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +987 +---------------------------------- +script +---------------------------------- + salam +_____________________________________________________________ + !monitor 123 1234 script {salam } +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- +salam +_____________________________________________________________ + !monitor 123 1234 script {-} script {salam } +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- +- +---------------------------------- +script +---------------------------------- +salam +_____________________________________________________________ + !monitor 123 1234 script {- + + + + + } script {salam } +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- +- + + + + + +---------------------------------- +script +---------------------------------- +salam +_____________________________________________________________ +!command -flag1 -flag2 input { value1 value2 } +---------------------------------- +!command +---------------------------------- +-flag1 +---------------------------------- +-flag2 +---------------------------------- +input +---------------------------------- + value1 value2 +_____________________________________________________________ +combine {first part} { second part } {third part} +---------------------------------- +combine +---------------------------------- +first part +---------------------------------- + second part +---------------------------------- +third part +_____________________________________________________________ +mix { spaces inside } and {no space} +---------------------------------- +mix +---------------------------------- + spaces inside +---------------------------------- +and +---------------------------------- +no space +_____________________________________________________________ +testcase1 testcase2 { enclosed with spaces } +---------------------------------- +testcase1 +---------------------------------- +testcase2 +---------------------------------- + enclosed with spaces +_____________________________________________________________ +!action -key1=value1 -key2=value2 {payload data} +---------------------------------- +!action +---------------------------------- +-key1=value1 +---------------------------------- +-key2=value2 +---------------------------------- +payload data +_____________________________________________________________ +cmd {first block} subsequent {second block} ending +---------------------------------- +cmd +---------------------------------- +first block +---------------------------------- +subsequent +---------------------------------- +second block +---------------------------------- +ending +_____________________________________________________________ +!start -fast {quick action} -secure {safe mode} +---------------------------------- +!start +---------------------------------- +-fast +---------------------------------- +quick action +---------------------------------- +-secure +---------------------------------- +safe mode +_____________________________________________________________ +simple command with { embedded data } +---------------------------------- +simple +---------------------------------- +command +---------------------------------- +with +---------------------------------- + embedded data +_____________________________________________________________ +cmd1 cmd2 cmd3 {sequential commands} +---------------------------------- +cmd1 +---------------------------------- +cmd2 +---------------------------------- +cmd3 +---------------------------------- +sequential commands +_____________________________________________________________ +!launch -now -force {immediate start} && {verify} +---------------------------------- +!launch +---------------------------------- +-now +---------------------------------- +-force +---------------------------------- +immediate start +---------------------------------- +&& +---------------------------------- +verify +_____________________________________________________________ + +!script launch { @init(); } followed by {execute main;} +---------------------------------- +!script +---------------------------------- +launch +---------------------------------- + @init(); +---------------------------------- +followed +---------------------------------- +by +---------------------------------- +execute main; +_____________________________________________________________ +cmd {simple} {sequence} -option +---------------------------------- +cmd +---------------------------------- +simple +---------------------------------- +sequence +---------------------------------- +-option +_____________________________________________________________ +run -flag1 {data1} -flag2 {data2} -flag3 {data3} +---------------------------------- +run +---------------------------------- +-flag1 +---------------------------------- +data1 +---------------------------------- +-flag2 +---------------------------------- +data2 +---------------------------------- +-flag3 +---------------------------------- +data3 +_____________________________________________________________ +test -x -y -z {set1} and {set2} followed by {set3} +---------------------------------- +test +---------------------------------- +-x +---------------------------------- +-y +---------------------------------- +-z +---------------------------------- +set1 +---------------------------------- +and +---------------------------------- +set2 +---------------------------------- +followed +---------------------------------- +by +---------------------------------- +set3 +_____________________________________________________________ +init {first} then {second} && finally {third} +---------------------------------- +init +---------------------------------- +first +---------------------------------- +then +---------------------------------- +second +---------------------------------- +&& +---------------------------------- +finally +---------------------------------- +third +_____________________________________________________________ +long command with {multiple parts in} {separate blocks} +---------------------------------- +long +---------------------------------- +command +---------------------------------- +with +---------------------------------- +multiple parts in +---------------------------------- +separate blocks +_____________________________________________________________ +simple {standalone block} +---------------------------------- +simple +---------------------------------- +standalone block +_____________________________________________________________ +trigger {script } && -flag {option} final +---------------------------------- +trigger +---------------------------------- +script +---------------------------------- +&& +---------------------------------- +-flag +---------------------------------- +option +---------------------------------- +final +_____________________________________________________________ +initiate --parameters { --data="complex value"; return 0;} and end +---------------------------------- +initiate +---------------------------------- +--parameters +---------------------------------- + --data="complex value"; return 0; +---------------------------------- +and +---------------------------------- +end +_____________________________________________________________ +multi-step {process} && {handle} then {finalize} +---------------------------------- +multi-step +---------------------------------- +process +---------------------------------- +&& +---------------------------------- +handle +---------------------------------- +then +---------------------------------- +finalize +_____________________________________________________________ +cmd -flag1 -flag2 {parameter} {another} part +---------------------------------- +cmd +---------------------------------- +-flag1 +---------------------------------- +-flag2 +---------------------------------- +parameter +---------------------------------- +another +---------------------------------- +part +_____________________________________________________________ +test {unmatched brackets and inputs +---------------------------------- +test +---------------------------------- +unmatched brackets and inputs +_____________________________________________________________ +{no command} just {brackets here} +---------------------------------- +no command +---------------------------------- +just +---------------------------------- +brackets here +_____________________________________________________________ + + !monitor 321 654 script { salam { } } + + +---------------------------------- +!monitor +---------------------------------- +321 +---------------------------------- +654 +---------------------------------- +script +---------------------------------- + salam { } +_____________________________________________________________ + !monitor 123 1234 script {salam { }} +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- +salam { } +_____________________________________________________________ + !monitor 123 1234 script {{}} script {salam } +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- +{} +---------------------------------- +script +---------------------------------- +salam +_____________________________________________________________ +!run multiple {commands here; print("hello") } now +---------------------------------- +!run +---------------------------------- +multiple +---------------------------------- +commands here; print("hello") +---------------------------------- +now +_____________________________________________________________ +execute --option=value --flag {do this} && {do that} +---------------------------------- +execute +---------------------------------- +--option=value +---------------------------------- +--flag +---------------------------------- +do this +---------------------------------- +&& +---------------------------------- +do that +_____________________________________________________________ +test input multiple { nested {token1 token2} token3 } +---------------------------------- +test +---------------------------------- +input +---------------------------------- +multiple +---------------------------------- + nested {token1 token2} token3 +_____________________________________________________________ +!example with-symbols { $var1 = @func(); } @end +---------------------------------- +!example +---------------------------------- +with-symbols +---------------------------------- + $var1 = @func(); +---------------------------------- +@end +_____________________________________________________________ +check {brackets}without spaces {another}one +---------------------------------- +check +---------------------------------- +brackets +---------------------------------- +without +---------------------------------- +spaces +---------------------------------- +another +---------------------------------- +one +_____________________________________________________________ +trigger --conditionA --conditionB sequence {if(A) {exec B;}} +---------------------------------- +trigger +---------------------------------- +--conditionA +---------------------------------- +--conditionB +---------------------------------- +sequence +---------------------------------- +if(A) {exec B;} +_____________________________________________________________ +check -flag { first {nested} block } and another +---------------------------------- +check +---------------------------------- +-flag +---------------------------------- + first {nested} block +---------------------------------- +and +---------------------------------- +another +_____________________________________________________________ + +cmd -opt1 --opt2 {multi-level { nesting } example } +---------------------------------- +cmd +---------------------------------- +-opt1 +---------------------------------- +--opt2 +---------------------------------- +multi-level { nesting } example +_____________________________________________________________ + +prefix {command with {extra} spaces} suffix +---------------------------------- +prefix +---------------------------------- +command with {extra} spaces +---------------------------------- +suffix +_____________________________________________________________ +{edge case} with {close} but {mismatched } +---------------------------------- +edge case +---------------------------------- +with +---------------------------------- +close +---------------------------------- +but +---------------------------------- +mismatched +_____________________________________________________________ + +cmd1 {with spaces }between {tokens} +---------------------------------- +cmd1 +---------------------------------- +with spaces +---------------------------------- +between +---------------------------------- +tokens +_____________________________________________________________ + +execute command --with-options {enclose {inner block} complete} +---------------------------------- +execute +---------------------------------- +command +---------------------------------- +--with-options +---------------------------------- +enclose {inner block} complete +_____________________________________________________________ +combine --flags { group {of {nested} data} here } +---------------------------------- +combine +---------------------------------- +--flags +---------------------------------- + group {of {nested} data} here +_____________________________________________________________ + +launch operation {perform task with details*&^%$#@! } +---------------------------------- +launch +---------------------------------- +operation +---------------------------------- +perform task with details*&^%$#@! +_____________________________________________________________ +{beginning}{middle}{end} as a story +---------------------------------- +beginning +---------------------------------- +middle +---------------------------------- +end +---------------------------------- +as +---------------------------------- +a +---------------------------------- +story +_____________________________________________________________ +process data {with embedded {brackets} and symbols!@# } +---------------------------------- +process +---------------------------------- +data +---------------------------------- +with embedded {brackets} and symbols!@# +_____________________________________________________________ +{part1} {part2} {part3} followed by {part4} +---------------------------------- +part1 +---------------------------------- +part2 +---------------------------------- +part3 +---------------------------------- +followed +---------------------------------- +by +---------------------------------- +part4 +_____________________________________________________________ +trigger function {execute this {with nested} commands} +---------------------------------- +trigger +---------------------------------- +function +---------------------------------- +execute this {with nested} commands +_____________________________________________________________ +{first}{second}{third}{fourth} in order +---------------------------------- +first +---------------------------------- +second +---------------------------------- +third +---------------------------------- +fourth +---------------------------------- +in +---------------------------------- +order +_____________________________________________________________ +invoke action {with parameters and special *&^%$#@! characters} +---------------------------------- +invoke +---------------------------------- +action +---------------------------------- +with parameters and special *&^%$#@! characters +_____________________________________________________________ +{alpha}{beta}{gamma} proceed +---------------------------------- +alpha +---------------------------------- +beta +---------------------------------- +gamma +---------------------------------- +proceed +_____________________________________________________________ +launch command {multiple levels {of nested} structures} +---------------------------------- +launch +---------------------------------- +command +---------------------------------- +multiple levels {of nested} structures +_____________________________________________________________ +{start}{continue}{finish} the process +---------------------------------- +start +---------------------------------- +continue +---------------------------------- +finish +---------------------------------- +the +---------------------------------- +process +_____________________________________________________________ +execute command {execute {inner} logic } finalize +---------------------------------- +execute +---------------------------------- +command +---------------------------------- +execute {inner} logic +---------------------------------- +finalize +_____________________________________________________________ + +run long command {with spaces and symbols!@#$%^&*() } +---------------------------------- +run +---------------------------------- +long +---------------------------------- +command +---------------------------------- +with spaces and symbols!@#$%^&*() +_____________________________________________________________ + +!inject kernel!IoCreateFile script { + +memcpy(" { buffer content @0x%x\n", @rdx); + + +} +---------------------------------- +!inject +---------------------------------- +kernel!IoCreateFile +---------------------------------- +script +---------------------------------- + + +memcpy(" { buffer content @0x%x\n", @rdx); + + + +_____________________________________________________________ +!hook routine!KeWaitForSingleObject script { + +if (condition) { { wait @timeout\n"," @rcx);}} + +} +---------------------------------- +!hook +---------------------------------- +routine!KeWaitForSingleObject +---------------------------------- +script +---------------------------------- + + +if (condition) { { wait @timeout\n"," @rcx);}} + + +_____________________________________________________________ +!trace nt!ZwQuerySystemInformation script { + +DbgPrint(" { { system info: %p\n", @r8); + +} +---------------------------------- +!trace +---------------------------------- +nt!ZwQuerySystemInformation +---------------------------------- +script +---------------------------------- + + +DbgPrint(" { { system info: %p\n", @r8); + + +_____________________________________________________________ +!monitor function!NtOpenProcess script { + +log(" { { process opened: %d\n", @r9); + + +} +---------------------------------- +!monitor +---------------------------------- +function!NtOpenProcess +---------------------------------- +script +---------------------------------- + + +log(" { { process opened: %d\n", @r9); + + + +_____________________________________________________________ +!filter nt!MmMapLockedPagesSpecifyCache script { + +trace(" { { mapping pages @%p\n", @r10); + +} +---------------------------------- +!filter +---------------------------------- +nt!MmMapLockedPagesSpecifyCache +---------------------------------- +script +---------------------------------- + + +trace(" { { mapping pages @%p\n", @r10); + + +_____________________________________________________________ +!watch kernel!ObReferenceObjectByHandle script { + +check(" { { object handle: 0x%x\n","xxx" @r11); + +} +---------------------------------- +!watch +---------------------------------- +kernel!ObReferenceObjectByHandle +---------------------------------- +script +---------------------------------- + + +check(" { { object handle: 0x%x\n","xxx" @r11); + + +_____________________________________________________________ +!watch kernel!ObReferenceObjectByHandle script { }{ + +check(" { { object handle: 0x%x\n", @r11); + +} +---------------------------------- +!watch +---------------------------------- +kernel!ObReferenceObjectByHandle +---------------------------------- +script +---------------------------------- + +---------------------------------- + + +check(" { { object handle: 0x%x\n", @r11); + + +_____________________________________________________________ +!watch kernel!ObReferenceObjectByHandle script { }{ + +check(" } object handle: 0x%x\n", @r11); + +} +---------------------------------- +!watch +---------------------------------- +kernel!ObReferenceObjectByHandle +---------------------------------- +script +---------------------------------- + +---------------------------------- + + +check(" } object handle: 0x%x\n", @r11); + + +_____________________________________________________________ +{block1}{block2}{block3} in sequence +---------------------------------- +block1 +---------------------------------- +block2 +---------------------------------- +block3 +---------------------------------- +in +---------------------------------- +sequence +_____________________________________________________________ + +!epthook nt!ExAllocatePoolWithTag script { + +printf(" { { hi2 ! :%llx\n", @rax); + +} +---------------------------------- +!epthook +---------------------------------- +nt!ExAllocatePoolWithTag +---------------------------------- +script +---------------------------------- + + +printf(" { { hi2 ! :%llx\n", @rax); + + +_____________________________________________________________ + +!epthook nt!ExAllocatePoolWithTag script { + +printf(" { { hi ! :%llx\n", @rax); + +} +---------------------------------- +!epthook +---------------------------------- +nt!ExAllocatePoolWithTag +---------------------------------- +script +---------------------------------- + + +printf(" { { hi ! :%llx\n", @rax); + + +_____________________________________________________________ +command1 /* pre-command comment */ param1 param2 // inline comment +---------------------------------- +command1 +---------------------------------- +param1 +---------------------------------- +param2 +_____________________________________________________________ +/* comment at start */command2 123 /* middle comment */ 456 +---------------------------------- +command2 +---------------------------------- +123 +---------------------------------- +456 +_____________________________________________________________ +command3 789 { inner /* comment */ block } /* outer comment */ final +---------------------------------- +command3 +---------------------------------- +789 +---------------------------------- + inner /* comment */ block +---------------------------------- +final +_____________________________________________________________ +!execute /*start*/ command /*ignored*/ {this part stays // comment inside } next +---------------------------------- +!execute +---------------------------------- +command +---------------------------------- +this part stays // comment inside +---------------------------------- +next +_____________________________________________________________ +// entire line comment +finalCommand 999 /* another comment */ {untouched /* inner */ block} +---------------------------------- +finalCommand +---------------------------------- +999 +---------------------------------- +untouched /* inner */ block +_____________________________________________________________ +/* tricky */!run 1234 script /* inner */ {brackets should {remain}} end // finish +---------------------------------- +!run +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- +brackets should {remain} +---------------------------------- +end +_____________________________________________________________ +// comment at the start +/*!example 5678 script */ /*{preserve this block}*/ result +---------------------------------- +result +_____________________________________________________________ +/**/command4 { content /* inside */ untouched } // comment +---------------------------------- +command4 +---------------------------------- + content /* inside */ untouched +_____________________________________________________________ +/* remove this */ {block /* with comment*/} /* another comment */ +---------------------------------- +block /* with comment*/ +_____________________________________________________________ +simpleCommand /* comment in the middle */ {final //comment inside} // end +---------------------------------- +simpleCommand +---------------------------------- +final //comment inside +_____________________________________________________________ +/* complex */ command {nested {brackets /* and comments */ inside} } end +---------------------------------- +command +---------------------------------- +nested {brackets /* and comments */ inside} +---------------------------------- +end +_____________________________________________________________ +// mixed comments +!action 1 2 3 /*{should be removed}*/ result /*final*/ +---------------------------------- +!action +---------------------------------- +1 +---------------------------------- +2 +---------------------------------- +3 +---------------------------------- +result +_____________________________________________________________ +command5 /* multiple lines +comment */ final // inline comment +---------------------------------- +command5 +---------------------------------- +final +_____________________________________________________________ +/* multiple lines +comment */ command6 { /* inner block */ content } next // final comment +---------------------------------- +command6 +---------------------------------- + /* inner block */ content +---------------------------------- +next +_____________________________________________________________ +/// full line comment +/*!ignore this*/ command7 {keep /* this comment */ block} // end +---------------------------------- +command7 +---------------------------------- +keep /* this comment */ block +_____________________________________________________________ +/* nested comments */ command8{content /* with nested */ parts} // final +---------------------------------- +command8 +---------------------------------- +content /* with nested */ parts +_____________________________________________________________ +_____________________________________________________________ +/* nested comments */ command8{content /* with nested */ parts}com // final +---------------------------------- +command8 +---------------------------------- +content /* with nested */ parts +---------------------------------- +com +_____________________________________________________________ +!operation /*start*/ { inner content } /* middle */final// finish +---------------------------------- +!operation +---------------------------------- + inner content +---------------------------------- +final +_____________________________________________________________ +// ignore everything +/*!skip this*/ /*{and this block}*/result //final +---------------------------------- +result +_____________________________________________________________ +/**/ complexCommand {keep /* special */ part}// ending comment/**/ +---------------------------------- +complexCommand +---------------------------------- +keep /* special */ part +_____________________________________________________________ +// full line comment +cmd1 param1 /*inline comment*/ param2 +---------------------------------- +cmd1 +---------------------------------- +param1 +---------------------------------- +param2 +_____________________________________________________________ +commandA // with a comment +---------------------------------- +commandA +_____________________________________________________________ +/*block comment*/cmd2 { }arg1 arg2 +---------------------------------- +cmd2 +---------------------------------- + +---------------------------------- +arg1 +---------------------------------- +arg2 +_____________________________________________________________ +cmd3 {block with // inline comment} next +---------------------------------- +cmd3 +---------------------------------- +block with // inline comment +---------------------------------- +next +_____________________________________________________________ +// start comment +cmd4 123 /* another comment */ {block} end +---------------------------------- +cmd4 +---------------------------------- +123 +---------------------------------- +block +---------------------------------- +end +_____________________________________________________________ +/*!skip this*/ cmd5 {content remains /* inside comment */} final +---------------------------------- +cmd5 +---------------------------------- +content remains /* inside comment */ +---------------------------------- +final +_____________________________________________________________ +cmd6 param /* ignore this */ {keep this block} +---------------------------------- +cmd6 +---------------------------------- +param +---------------------------------- +keep this block +_____________________________________________________________ +// skip comment +cmd7 /* block */ next +---------------------------------- +cmd7 +---------------------------------- +next +_____________________________________________________________ +/* first comment */cmd8 {preserve this} last +---------------------------------- +cmd8 +---------------------------------- +preserve this +---------------------------------- +last +_____________________________________________________________ + +commandB param /*{don't remove this + + +block}*/ param2 +---------------------------------- +commandB +---------------------------------- +param +---------------------------------- +param2 +_____________________________________________________________ +/*!skip*/ cmd9 param {block with // /* + + +*/ {} {} {} comment} final +---------------------------------- +cmd9 +---------------------------------- +param +---------------------------------- +block with // /* + + +*/ {} {} {} comment +---------------------------------- +final +_____________________________________________________________ +cmd10 param /* + + +/* + + + +middle */ param2 +---------------------------------- +cmd10 +---------------------------------- +param +---------------------------------- +param2 +_____________________________________________________________ +cmd11 {keep /* + special */ block} final +---------------------------------- +cmd11 +---------------------------------- +keep /* + special */ block +---------------------------------- +final +_____________________________________________________________ +// skip line +commandC {block} / * comment */ param +---------------------------------- +commandC +---------------------------------- +block +---------------------------------- +/ +---------------------------------- +* +---------------------------------- +comment +---------------------------------- +*/ +---------------------------------- +param +_____________________________________________________________ +cmd12 {start block} /* comment */ next / / +---------------------------------- +cmd12 +---------------------------------- +start block +---------------------------------- +next +---------------------------------- +/ +---------------------------------- +/ +_____________________________________________________________ +cmd13 /* comment before */ {b + + + + +lock}/*>*?*/last +---------------------------------- +cmd13 +---------------------------------- +b + + + + +lock +---------------------------------- +last +_____________________________________________________________ +commandD param1 /*comment*/ param2 +---------------------------------- +commandD +---------------------------------- +param1 +---------------------------------- +param2 +_____________________________________________________________ +cmd14 {complex /* block */content} final +---------------------------------- +cmd14 +---------------------------------- +complex /* block */content +---------------------------------- +final +_____________________________________________________________ +// full comment +commandE /* remove this */ param1 +---------------------------------- +commandE +---------------------------------- +param1 +_____________________________________________________________ +cmd15 {nested /* comment */ block} result +---------------------------------- +cmd15 +---------------------------------- +nested /* comment */ block +---------------------------------- +result +_____________________________________________________________ +/*!ignore*/ cmd16 param1 {keep /* nested */ content} +---------------------------------- +cmd16 +---------------------------------- +param1 +---------------------------------- +keep /* nested */ content +_____________________________________________________________ +cmd17 param/**/{block with comment // inside} +---------------------------------- +cmd17 +---------------------------------- +param +---------------------------------- +block with comment // inside +_____________________________________________________________ + + +salam // test 123 456 +---------------------------------- +salam +_____________________________________________________________ +!monitor 123 1234 script /*{ tesTo salam + +khoobi? + }*/ +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +_____________________________________________________________ +!monitor 123 1234 script /*{ tesTo salam + +khoobi? + }*/ +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +_____________________________________________________________ +!monitor 123 1234 script /* { tesTo salam + +khoobi? + }*/ test +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- +test +_____________________________________________________________ +/**/!monitor 123 1234 script /* { tesTo salam + +khoobi? + }*/ test +---------------------------------- +!monitor +---------------------------------- +123 +---------------------------------- +1234 +---------------------------------- +script +---------------------------------- +test +_____________________________________________________________ +/*!monitor 123 1234 script /* { tesTo salam + +khoobi? + }*/ test +---------------------------------- +test +_____________________________________________________________ +/**//*!monitor 123 1234 script /* { tesTo salam + +khoobi? + }*/ test2 +---------------------------------- +test2 +_____________________________________________________________ +/**//*!monitor 123 1234 script /* { tesTo salam + +khoobi? + }*/ test3 +---------------------------------- +test3 +_____________________________________________________________ +///**//*!monitor 123 1234 script /* { tesTo salam + +khoobi? + }*/ test3 +---------------------------------- +khoobi? +---------------------------------- +}*/ +---------------------------------- +test3 +_____________________________________________________________ +///**//*!monitor 123 1234 script /* { tesTo salam + +khoobi? + //}*/ test3 +---------------------------------- +khoobi? +_____________________________________________________________ +///**//*!monitor 123 1234 script /* { tesTo salam + +khoobi?//testttt + //}*/ test4 +---------------------------------- +khoobi? +_____________________________________________________________ +///**//*!monitor 123 1234 script /* { tesTo salam + +khoobi?//testttt + //}*/ test3 +---------------------------------- +khoobi? +_____________________________________________________________ +///**//*!monitor 123 1234 script /* { tesTo salam + +khoobi?/*//testttt*/ + //}*/ test3 +---------------------------------- +khoobi? +_____________________________________________________________ +///**//*!monitor 123 1234 script /* { tesTo salam + +khoobi?/**///testttt/**/ + //}*/ test3 +---------------------------------- +khoobi? +_____________________________________________________________ + + +cmd18 /**/{block} next + + +---------------------------------- +cmd18 +---------------------------------- +block +---------------------------------- +next +_____________________________________________________________ +/*!skip*/ commandF {content /* with */ inside} final??/****/ +---------------------------------- +commandF +---------------------------------- +content /* with */ inside +---------------------------------- +final?? +_____________________________________________________________ +cmd19 param {complex block /* with comments */ inside//}/*****/ +---------------------------------- +cmd19 +---------------------------------- +param +---------------------------------- +complex block /* with comments */ inside// +_____________________________________________________________ +cmd20 /* block comment */ {preserve this} last// +---------------------------------- +cmd20 +---------------------------------- +preserve this +---------------------------------- +last +_____________________________________________________________ +commandG /* remove this */ param1//// +---------------------------------- +commandG +---------------------------------- +param1 +_____________________________________________________________ +/*!skip this*/ cmd21 param {block /* with */ comment} final\\// +---------------------------------- +cmd21 +---------------------------------- +param +---------------------------------- +block /* with */ comment +---------------------------------- +final\\ +_____________________________________________________________ +cmd22 param /* comment inside */ {block} last +---------------------------------- +cmd22 +---------------------------------- +param +---------------------------------- +block +---------------------------------- +last +_____________________________________________________________ +/*cmd43*/cmd23{complex block /* with */ content} final +---------------------------------- +cmd23 +---------------------------------- +complex block /* with */ content +---------------------------------- +final +_____________________________________________________________ +/*/*//*/*//*/*//*/*//*/*/cmd24 param1 /* comment inside */ param2 +---------------------------------- +cmd24 +---------------------------------- +param1 +---------------------------------- +param2 +_____________________________________________________________ +cmd25 {keep /* special */ block//} final +---------------------------------- +cmd25 +---------------------------------- +keep /* special */ block// +---------------------------------- +final +_____________________________________________________________ +// full line comment +commandH {preserve this}/* comment */final +---------------------------------- +commandH +---------------------------------- +preserve this +---------------------------------- +final +_____________________________________________________________ +cmd26 param {block with /* inside */ comment} +---------------------------------- +cmd26 +---------------------------------- +param +---------------------------------- +block with /* inside */ comment +_____________________________________________________________ +/*!ignore*/ cmd27 {nested /* block */ comment}{nested /* block */ comment} final +---------------------------------- +cmd27 +---------------------------------- +nested /* block */ comment +---------------------------------- +nested /* block */ comment +---------------------------------- +final +_____________________________________________________________ + + + + +cmd28 + +/* comment before */ + + +{block} next + +---------------------------------- +cmd28 +---------------------------------- +block +---------------------------------- +next +_____________________________________________________________ +/*/*//*/* + + +*/ + + +commandI /* remove this */ param +---------------------------------- +commandI +---------------------------------- +param +_____________________________________________________________ + +cmd29 param {block /* with */ comment} final{ + +} +---------------------------------- +cmd29 +---------------------------------- +param +---------------------------------- +block /* with */ comment +---------------------------------- +final +---------------------------------- + + + +_____________________________________________________________ +/*!skip*/ cmd30 param {content /* inside */ block} last +---------------------------------- +cmd30 +---------------------------------- +param +---------------------------------- +content /* inside */ block +---------------------------------- +last +_____________________________________________________________ +cmd31 {{}} /* comment */ {keep this block} next +---------------------------------- +cmd31 +---------------------------------- +{} +---------------------------------- +keep this block +---------------------------------- +next +_____________________________________________________________ +cmd32 param /////////////////* comment inside */ {block} final +---------------------------------- +cmd32 +---------------------------------- +param +---------------------------------- +_____________________________________________________________ +cmd33 {complex block /* with */ comment}//////////////// result +---------------------------------- +cmd33 +---------------------------------- +complex block /* with */ comment +_____________________________________________________________ + +// full comment +commandJ param1 //* comment inside //*/ param2 +---------------------------------- +commandJ +---------------------------------- +param1 +_____________________________________________________________ +/*!skip + + + + + +*/ cmd34 {nested /* block */ comment}final// +---------------------------------- +cmd34 +---------------------------------- +nested /* block */ comment +---------------------------------- +final +_____________________________________________________________ +cmd35 param {block {{}} comment} last +---------------------------------- +cmd35 +---------------------------------- +param +---------------------------------- +block {{}} comment +---------------------------------- +last +_____________________________________________________________ +cmd36 {keep /* nested */{{ + +}} block} result +---------------------------------- +cmd36 +---------------------------------- +keep /* nested */{{ + +}} block +---------------------------------- +result +_____________________________________________________________ +cmd37 param1 /* comment inside */ param2// +---------------------------------- +cmd37 +---------------------------------- +param1 +---------------------------------- +param2 +_____________________________________________________________ +cmd38 "test /**/" {complex block /* with */ content} final +---------------------------------- +cmd38 +---------------------------------- +test /**/ +---------------------------------- +complex block /* with */ content +---------------------------------- +final +_____________________________________________________________ +/*!ignore*/ commandK {preserve this} final"test" +---------------------------------- +commandK +---------------------------------- +preserve this +---------------------------------- +final +---------------------------------- +test +_____________________________________________________________ +cmd39 param "{block /* with */ comment}" last +---------------------------------- +cmd39 +---------------------------------- +param +---------------------------------- +{block /* with */ comment} +---------------------------------- +last +_____________________________________________________________ +cmd40 /* comment */ {nested block} final " + +test + +" +---------------------------------- +cmd40 +---------------------------------- +nested block +---------------------------------- +final +---------------------------------- + + +test + + +_____________________________________________________________ +// full line comment " test " +commandL param1 /* comment */ param2 +---------------------------------- +commandL +---------------------------------- +param1 +---------------------------------- +param2 +_____________________________________________________________ +""/*!skip*/ cmd41 {keep /* special */ block} final +---------------------------------- + +---------------------------------- +cmd41 +---------------------------------- +keep /* special */ block +---------------------------------- +final +_____________________________________________________________ +cmd42 param {nested block /* with */ comment//"}"} last +---------------------------------- +cmd42 +---------------------------------- +param +---------------------------------- +nested block /* with */ comment//"}" +---------------------------------- +last +_____________________________________________________________ +cmd43 /* comment before */ {blo""ck} next +---------------------------------- +cmd43 +---------------------------------- +blo""ck +---------------------------------- +next +_____________________________________________________________ +commandM "/*" remove /* this */ param1 +---------------------------------- +commandM +---------------------------------- +/* +---------------------------------- +remove +---------------------------------- +param1 +_____________________________________________________________ +/*!skip this*/" test me " cmd44 param {block /* with */ comment} final +---------------------------------- + test me +---------------------------------- +cmd44 +---------------------------------- +param +---------------------------------- +block /* with */ comment +---------------------------------- +final +_____________________________________________________________ +cmd45 param {complex block /* with */ comment} "re sul" t +---------------------------------- +cmd45 +---------------------------------- +param +---------------------------------- +complex block /* with */ comment +---------------------------------- +re sul +---------------------------------- +t +_____________________________________________________________ +cmd46 /* comment inside */ {nested block} final +---------------------------------- +cmd46 +---------------------------------- +nested block +---------------------------------- +final +_____________________________________________________________ +// full comment +commandN/**/"tos t" param1 /* comment inside */ param2 +---------------------------------- +commandN +---------------------------------- +tos t +---------------------------------- +param1 +---------------------------------- +param2 +_____________________________________________________________ +"t est"/*!ignore*/ cmd47 {block /* with nested */ comment} final +---------------------------------- +t est +---------------------------------- +cmd47 +---------------------------------- +block /* with nested */ comment +---------------------------------- +final +_____________________________________________________________ +cmd48 param {block + +/* inside */ comment}"tt tt" next +---------------------------------- +cmd48 +---------------------------------- +param +---------------------------------- +block + +/* inside */ comment +---------------------------------- +tt tt +---------------------------------- +next +_____________________________________________________________ +cmd49 {keep /* special */ block}"" result +---------------------------------- +cmd49 +---------------------------------- +keep /* special */ block +---------------------------------- + +---------------------------------- +result +_____________________________________________________________ + + +" "// + +cmd50 param1 /* comment inside */ param2 +---------------------------------- + +---------------------------------- +cmd50 +---------------------------------- +param1 +---------------------------------- +param2 +_____________________________________________________________ + +cmdZ /*block before*/ paramA {block/*inside*/} "fi nal" +---------------------------------- +cmdZ +---------------------------------- +paramA +---------------------------------- +block/*inside*/ +---------------------------------- +fi nal +_____________________________________________________________ +cmdCurlyBraces "me here" {{shouldStay}} {alsoStay} +---------------------------------- +cmdCurlyBraces +---------------------------------- +me here +---------------------------------- +{shouldStay} +---------------------------------- +alsoStay +_____________________________________________________________ +cmdQuotes "preserve this //comment" {insideQuotes} +---------------------------------- +cmdQuotes +---------------------------------- +preserve this //comment +---------------------------------- +insideQuotes +_____________________________________________________________ +cmdMixed /* mix this */ param /* with that */ {and preserve /* these */}"plus thuis" +---------------------------------- +cmdMixed +---------------------------------- +param +---------------------------------- +and preserve /* these */ +---------------------------------- +plus thuis +_____________________________________________________________ +cmdNest!!ed2 /*{keep this} but //remove*/ param +---------------------------------- +cmdNest!!ed2 +---------------------------------- +param +_____________________________________________________________ +cmdComplex /* outer /* inner outer */ final +---------------------------------- +cmdComplex +---------------------------------- +final +_____________________________________________________________ +cmdSymbols !@#$%^&*()_+\{\}:<>?[];',./ `~ | {test these} +---------------------------------- +cmdSymbols +---------------------------------- +!@#$%^&*()_+{}:<>?[];',./ +---------------------------------- +`~ +---------------------------------- +| +---------------------------------- +test these +_____________________________________________________________ +cmdSpaces excessive spaces here {and within } +---------------------------------- +cmdSpaces +---------------------------------- +excessive +---------------------------------- +spaces +---------------------------------- +here +---------------------------------- +and within +_____________________________________________________________ +cmdSlashSlash //double slash in cmd {preserve +f//this part} +---------------------------------- +cmdSlashSlash +---------------------------------- +f +_____________________________________________________________ +cmdSlashAsterisk /*comment here*/ nextCmd /*and here*/ +---------------------------------- +cmdSlashAsterisk +---------------------------------- +nextCmd +_____________________________________________________________ +cmdSlashCombo // start /* middle */ end +---------------------------------- +cmdSlashCombo +_____________________________________________________________ +cmdEscaped "escaped // slash and quote\"" +---------------------------------- +cmdEscaped +---------------------------------- +escaped // slash and quote" +_____________________________________________________________ +cmdEmbedded/*before*/param/*inline {with special}*/ end +---------------------------------- +cmdEmbeddedparam +---------------------------------- +end +_____________________________________________________________ + +cmdBracketsInside { /*keep {inner} and outer*/ } final +---------------------------------- +cmdBracketsInside +---------------------------------- + /*keep {inner} and outer*/ +---------------------------------- +final +_____________________________________________________________ +cmdHTMLLike /*ignore this*/ {content} +---------------------------------- +cmdHTMLLike +---------------------------------- + +---------------------------------- + +---------------------------------- +content +_____________________________________________________________ +cmdMathSymbols "\"\"" {symbolsInside} +---------------------------------- +cmdMathSymbols +---------------------------------- +"" +---------------------------------- +symbolsInside +_____________________________________________________________ +cmdExclamation !!multiple !exclamations {preserve!} +---------------------------------- +cmdExclamation +---------------------------------- +!!multiple +---------------------------------- +!exclamations +---------------------------------- +preserve! +_____________________________________________________________ +cmdParentheses (param1 param2) {inside ()} +---------------------------------- +cmdParentheses +---------------------------------- +(param1 +---------------------------------- +param2) +---------------------------------- +inside () +_____________________________________________________________ +cmdBrackets [] {preserve [brackets]} +---------------------------------- +cmdBrackets +---------------------------------- +[] +---------------------------------- +preserve [brackets] +_____________________________________________________________ +cmdSpecialSequence /*remove*/ /**/ param //comment +---------------------------------- +cmdSpecialSequence +---------------------------------- +param +_____________________________________________________________ +cmdPercentSign %keep this intact {"100% sure"} +---------------------------------- +cmdPercentSign +---------------------------------- +%keep +---------------------------------- +this +---------------------------------- +intact +---------------------------------- +"100% sure" +_____________________________________________________________ +cmdEscapedQuotes "preserve // comment\"" {\"inside\"} +---------------------------------- +cmdEscapedQuotes +---------------------------------- +preserve // comment" +---------------------------------- +\"inside\" +_____________________________________________________________ +cmdCurlyCombo {keep this} and {also + + + + + + + + + + + + +this} // remove +---------------------------------- +cmdCurlyCombo +---------------------------------- +keep this +---------------------------------- +and +---------------------------------- +also + + + + + + + + + + + + +this +_____________________________________________________________ +cmdQuotesCurly "\"inside quotes\""{keep this}"tse s" +---------------------------------- +cmdQuotesCurly +---------------------------------- +"inside quotes" +---------------------------------- +keep this +---------------------------------- +tse s +_____________________________________________________________ + +cmdPipeSymbol | pipe this | {keep inside} +---------------------------------- +cmdPipeSymbol +---------------------------------- +| +---------------------------------- +pipe +---------------------------------- +this +---------------------------------- +| +---------------------------------- +keep inside +_____________________________________________________________ +cmdAngleBrackets /* comment */ next { void printTime() { + printf("process pid %d \n",$pid); + timePtr = $time; + printf("TIME PTR %x\n", timePtr); + + yearPtr = timePtr - 10; + year = (db(yearPtr+1) << 8) | db(yearPtr); + + monthPtr = timePtr - E; + month = (db(monthPtr+1) << 8) | db(monthPtr); + + dayPtr = timePtr - C; + day = (db(dayPtr+1) << 8) | db(dayPtr); + hourPtr = timePtr - A; + hour = (db(hourPtr+1) << 8) | db(hourPtr); + minPtr = timePtr - 8; + min = (db(minPtr+1) << 8) | db(minPtr); + secPtr = timePtr - 6; + sec = (db(secPtr+1) << 8) | db(secPtr); + msecPtr = timePtr - 4; + msec = (db(msecPtr+1) << 8) | db(msecPtr); + printf("FULL TIME : %d %d %d %d %d %d %d\n", year, month, day, hour, min, sec, msec); + } + printTime(); +} +---------------------------------- +cmdAngleBrackets +---------------------------------- + +---------------------------------- +next +---------------------------------- + void printTime() { + printf("process pid %d \n",$pid); + timePtr = $time; + printf("TIME PTR %x\n", timePtr); + + yearPtr = timePtr - 10; + year = (db(yearPtr+1) << 8) | db(yearPtr); + + monthPtr = timePtr - E; + month = (db(monthPtr+1) << 8) | db(monthPtr); + + dayPtr = timePtr - C; + day = (db(dayPtr+1) << 8) | db(dayPtr); + hourPtr = timePtr - A; + hour = (db(hourPtr+1) << 8) | db(hourPtr); + minPtr = timePtr - 8; + min = (db(minPtr+1) << 8) | db(minPtr); + secPtr = timePtr - 6; + sec = (db(secPtr+1) << 8) | db(secPtr); + msecPtr = timePtr - 4; + msec = (db(msecPtr+1) << 8) | db(msecPtr); + printf("FULL TIME : %d %d %d %d %d %d %d\n", year, month, day, hour, min, sec, msec); + } + printTime(); + +_____________________________________________________________ + +cmdSlashStart "// whole line comment /*and block*/ last" +---------------------------------- +cmdSlashStart +---------------------------------- +// whole line comment /*and block*/ last +_____________________________________________________________ +cmdStarSlash /*entire line*/ {keep /*and this*/ intact} + +{ + void printTime() { + printf("process pid %d \n",$pid); + timePtr = $time; + printf("TIME PTR %x\n", timePtr); + + yearPtr = timePtr - 10; + year = (db(yearPtr+1) << 8) | db(yearPtr); + + monthPtr = timePtr - E; + month = (db(monthPtr+1) << 8) | db(monthPtr); + + dayPtr = timePtr - C; + day = (db(dayPtr+1) << 8) | db(dayPtr); + hourPtr = timePtr - A; + hour = (db(hourPtr+1) << 8) | db(hourPtr); + minPtr = timePtr - 8; + min = (db(minPtr+1) << 8) | db(minPtr); + secPtr = timePtr - 6; + sec = (db(secPtr+1) << 8) | db(secPtr); + msecPtr = timePtr - 4; + msec = (db(msecPtr+1) << 8) | db(msecPtr); + printf("FULL TIME : %d %d %d %d %d %d %d\n", year, month, day, hour, min, sec, msec); + } + printTime(); +} +---------------------------------- +cmdStarSlash +---------------------------------- +keep /*and this*/ intact +---------------------------------- + + void printTime() { + printf("process pid %d \n",$pid); + timePtr = $time; + printf("TIME PTR %x\n", timePtr); + + yearPtr = timePtr - 10; + year = (db(yearPtr+1) << 8) | db(yearPtr); + + monthPtr = timePtr - E; + month = (db(monthPtr+1) << 8) | db(monthPtr); + + dayPtr = timePtr - C; + day = (db(dayPtr+1) << 8) | db(dayPtr); + hourPtr = timePtr - A; + hour = (db(hourPtr+1) << 8) | db(hourPtr); + minPtr = timePtr - 8; + min = (db(minPtr+1) << 8) | db(minPtr); + secPtr = timePtr - 6; + sec = (db(secPtr+1) << 8) | db(secPtr); + msecPtr = timePtr - 4; + msec = (db(msecPtr+1) << 8) | db(msecPtr); + printf("FULL TIME : %d %d %d %d %d %d %d\n", year, month, day, hour, min, sec, msec); + } + printTime(); + +_____________________________________________________________ +cmdMixedQuotesCurly "\"with curly {inside}\" "{preserve this} +---------------------------------- +cmdMixedQuotesCurly +---------------------------------- +"with curly {inside}" +---------------------------------- +preserve this +_____________________________________________________________ +cmdWeirdCharacters{ + void printTime() { + printf("process pid %d \n",$pid); + timePtr = $time; + printf("TIME PTR %x\n", timePtr); + + yearPtr = timePtr - 10; + year = (db(yearPtr+1) << 8) | db(yearPtr); + + monthPtr = timePtr - E; + month = (db(monthPtr+1) << 8) | db(monthPtr); + + dayPtr = timePtr - C; + day = (db(dayPtr+1) << 8) | db(dayPtr); + hourPtr = timePtr - A; + hour = (db(hourPtr+1) << 8) | db(hourPtr); + minPtr = timePtr - 8; + min = (db(minPtr+1) << 8) | db(minPtr); + secPtr = timePtr - 6; + sec = (db(secPtr+1) << 8) | db(secPtr); + msecPtr = timePtr - 4; + msec = (db(msecPtr+1) << 8) | db(msecPtr); + printf("FULL TIME : %d %d %d %d %d %d %d\n", year, month, day, hour, min, sec, msec); + } + printTime(); +}test{symbolsInside} +---------------------------------- +cmdWeirdCharacters +---------------------------------- + + void printTime() { + printf("process pid %d \n",$pid); + timePtr = $time; + printf("TIME PTR %x\n", timePtr); + + yearPtr = timePtr - 10; + year = (db(yearPtr+1) << 8) | db(yearPtr); + + monthPtr = timePtr - E; + month = (db(monthPtr+1) << 8) | db(monthPtr); + + dayPtr = timePtr - C; + day = (db(dayPtr+1) << 8) | db(dayPtr); + hourPtr = timePtr - A; + hour = (db(hourPtr+1) << 8) | db(hourPtr); + minPtr = timePtr - 8; + min = (db(minPtr+1) << 8) | db(minPtr); + secPtr = timePtr - 6; + sec = (db(secPtr+1) << 8) | db(secPtr); + msecPtr = timePtr - 4; + msec = (db(msecPtr+1) << 8) | db(msecPtr); + printf("FULL TIME : %d %d %d %d %d %d %d\n", year, month, day, hour, min, sec, msec); + } + printTime(); + +---------------------------------- +test +---------------------------------- +symbolsInside +_____________________________________________________________ + +cmdNestedQuotes "inside \"quotes" and {outside} +---------------------------------- +cmdNestedQuotes +---------------------------------- +inside "quotes +---------------------------------- +and +---------------------------------- +outside +_____________________________________________________________ +{ +void Sleep(int milliseconds) { + .count = 0; + .delay = milliseconds * 1000; // Convert milliseconds to microseconds + + while (.delay != 0) { + .delay--; + .count = 1000; // This constant can be adjusted based on the clock speed + while (.count != 0) { + .count--; + // Do nothing, just busy-wait + } + } +} + +Sleep(10); +} +---------------------------------- + +void Sleep(int milliseconds) { + .count = 0; + .delay = milliseconds * 1000; // Convert milliseconds to microseconds + + while (.delay != 0) { + .delay--; + .count = 1000; // This constant can be adjusted based on the clock speed + while (.count != 0) { + .count--; + // Do nothing, just busy-wait + } + } +} + +Sleep(10); + +_____________________________________________________________ +cmdStringInside /*comment*/ inside {string {with} braces} +---------------------------------- +cmdStringInside +---------------------------------- +inside +---------------------------------- +string {with} braces +_____________________________________________________________ +cmdHashSymbols #hashtag comment {#preserve this} +---------------------------------- +cmdHashSymbols +---------------------------------- +#hashtag +---------------------------------- +comment +---------------------------------- +#preserve this +_____________________________________________________________ +cmdPercentage %preserve {? { +void Sleep(int milliseconds) { + .count = 0; + .delay = milliseconds * 1000; // Convert milliseconds to microseconds + + while (.delay != 0) { + .delay--; + .count = 1000; // This constant can be adjusted based on the clock speed + while (.count != 0) { + .count--; + // Do nothing, just busy-wait + } + } +} + +Sleep(10); +}} next +---------------------------------- +cmdPercentage +---------------------------------- +%preserve +---------------------------------- +? { +void Sleep(int milliseconds) { + .count = 0; + .delay = milliseconds * 1000; // Convert milliseconds to microseconds + + while (.delay != 0) { + .delay--; + .count = 1000; // This constant can be adjusted based on the clock speed + while (.count != 0) { + .count--; + // Do nothing, just busy-wait + } + } +} + +Sleep(10); +} +---------------------------------- +next +_____________________________________________________________ + + +cmdFunctionLike funcName(param) /*comment*/ {block inside} +---------------------------------- +cmdFunctionLike +---------------------------------- +funcName(param) +---------------------------------- +block inside +_____________________________________________________________ +; j ; semicolon /*comment*/ {preserve;} +---------------------------------- +; +---------------------------------- +j +---------------------------------- +; +---------------------------------- +semicolon +---------------------------------- +preserve; +_____________________________________________________________ +cmdEllipsis ...preserve {these...} and next +---------------------------------- +cmdEllipsis +---------------------------------- +...preserve +---------------------------------- +these... +---------------------------------- +and +---------------------------------- +next +_____________________________________________________________ +cmdGreaterLess > greater < less {inside > < here} +---------------------------------- +cmdGreaterLess +---------------------------------- +> +---------------------------------- +greater +---------------------------------- +< +---------------------------------- +less +---------------------------------- +inside > < here +_____________________________________________________________ +cmdAsteriskCombo *keep *these* *intact* +---------------------------------- +cmdAsteriskCombo +---------------------------------- +*keep +---------------------------------- +*these* +---------------------------------- +*intact* +_____________________________________________________________ +cmdUnderScores _preserve _these {underscores_} +---------------------------------- +cmdUnderScores +---------------------------------- +_preserve +---------------------------------- +_these +---------------------------------- +underscores_ +_____________________________________________________________ +cmdHyphenDash{## @file user-mode-memory-allocations.ds +# @author Sina Karvandi (sina@hyperdbg.org) +# @brief Gathers memory allocations made by a process +# @version 0.7 +# @date 2023-11-24 +# @copyright This script is released under the MIT License. +# +# @details In order to run this script, you should use '.script' +# command. +# @param ProcessPath: Please specify the target Process path to start +# +# Run it like: +# .script c:\users\sina\desktop\user-mode-memory-allocations.ds "C:\Windows\notepad.exe" +# +# It gathers different memory allocations (e.g., mallocs) like this: +# +# [SYSCALL] NtAllocateVirtualMemory called from, pid: 3a8, name: Notepad.exe | requested size: 11c0 +# [SYSRET] NtAllocateVirtualMemory called from, pid: 3a8, name: Notepad.exe | located at: 195a8880000, size: 2000 +# + +start path $arg1 + +? .thread_intercept_thread = 0; +? .target_pid = $pid; +? .target_tid = 0; +? .target_allocation_address = 0; +? .target_allocation_size = 0; + +!sysret script { + if ($pid == .target_pid && .thread_intercept_thread == 1 && $tid == .target_tid) { + spinlock_unlock(&.thread_intercept_thread); + .target_tid = 0; + printf("[SYSRET] NtAllocateVirtualMemory called from, pid: %x, name: %s | located at: %llx, actual allocated size: %llx\n", $pid, $pname, dq(.target_allocation_address), dq(.target_allocation_size)); + } +} + +!syscall 18 script { + + if ($pid == .target_pid) { + spinlock_lock(&.thread_intercept_thread); + .target_tid = $tid; + .target_allocation_address = @rdx; + .target_allocation_size = @r9; + + if (dq(rdx) == 0) { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx\n", $pid, $pname, dq(r9)); + } + else { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx, user-specific addr: %llx\n", $pid, $pname, dq(r9), dq(rdx)); + } + } +}} +---------------------------------- +cmdHyphenDash +---------------------------------- +## @file user-mode-memory-allocations.ds +# @author Sina Karvandi (sina@hyperdbg.org) +# @brief Gathers memory allocations made by a process +# @version 0.7 +# @date 2023-11-24 +# @copyright This script is released under the MIT License. +# +# @details In order to run this script, you should use '.script' +# command. +# @param ProcessPath: Please specify the target Process path to start +# +# Run it like: +# .script c:\users\sina\desktop\user-mode-memory-allocations.ds "C:\Windows\notepad.exe" +# +# It gathers different memory allocations (e.g., mallocs) like this: +# +# [SYSCALL] NtAllocateVirtualMemory called from, pid: 3a8, name: Notepad.exe | requested size: 11c0 +# [SYSRET] NtAllocateVirtualMemory called from, pid: 3a8, name: Notepad.exe | located at: 195a8880000, size: 2000 +# + +start path $arg1 + +? .thread_intercept_thread = 0; +? .target_pid = $pid; +? .target_tid = 0; +? .target_allocation_address = 0; +? .target_allocation_size = 0; + +!sysret script { + if ($pid == .target_pid && .thread_intercept_thread == 1 && $tid == .target_tid) { + spinlock_unlock(&.thread_intercept_thread); + .target_tid = 0; + printf("[SYSRET] NtAllocateVirtualMemory called from, pid: %x, name: %s | located at: %llx, actual allocated size: %llx\n", $pid, $pname, dq(.target_allocation_address), dq(.target_allocation_size)); + } +} + +!syscall 18 script { + + if ($pid == .target_pid) { + spinlock_lock(&.thread_intercept_thread); + .target_tid = $tid; + .target_allocation_address = @rdx; + .target_allocation_size = @r9; + + if (dq(rdx) == 0) { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx\n", $pid, $pname, dq(r9)); + } + else { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx, user-specific addr: %llx\n", $pid, $pname, dq(r9), dq(rdx)); + } + } +} +_____________________________________________________________ +cmdDigits123 123numbers 456inside {!syscall script { + + // + // IOCTL Codes: + // AFD_Connect: 0x12007 + // + /* + + typedef struct _AFD_CONNECT_INFO { + BOOLEAN UseSAN; + ULONG Root; + ULONG Unknown; + SOCKADDR RemoteAddress; + } AFD_CONNECT_INFO , *PAFD_CONNECT_INFO ; + + typedef struct sockaddr_in { + short sin_family; + USHORT sin_port; + IN_ADDR sin_addr; + CHAR sin_zero[8]; + } SOCKADDR_IN, *PSOCKADDR_IN; + + */ + + if (@rax == 0x7) { + + // printf("IoControlCode: %x\n", dd(@rsp + 30)); + + if (dd(@rsp + 30) == 0x12007) { + // + // Details derived from: https://www.cyberus-technology.de/posts/network-analysis-with-tycho/ + // + + // + // Get the port address + // + port_num_high_bit = db(poi(@rsp + 38) + 1a); + port_num_low_bit = db(poi(@rsp + 38) + 1b); + + port_num = 0; + port_num = port_num_high_bit << 8 | port_num_low_bit; + + // + // Get the IP address + // + part0 = db(poi(@rsp + 38) + 1c); + part1 = db(poi(@rsp + 38) + 1d); + part2 = db(poi(@rsp + 38) + 1e); + part3 = db(poi(@rsp + 38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Process Id: %x, name: %s connects to ====> IP address (hex): %x\n", $pid, $pname, ip_addr); + + printf("Process Id: %x, name: %s connects to ====> Address: %d.%d.%d.%d:%d\n", + $pid, + $pname, + (ip_addr & 0xFF000000) >> 0n24, + (ip_addr & 0x00FF0000) >> 0n16, + (ip_addr & 0x0000FF00) >> 0n8, + ip_addr & 0x000000FF, + port_num); + } + } +}} +---------------------------------- +cmdDigits123 +---------------------------------- +123numbers +---------------------------------- +456inside +---------------------------------- +!syscall script { + + // + // IOCTL Codes: + // AFD_Connect: 0x12007 + // + /* + + typedef struct _AFD_CONNECT_INFO { + BOOLEAN UseSAN; + ULONG Root; + ULONG Unknown; + SOCKADDR RemoteAddress; + } AFD_CONNECT_INFO , *PAFD_CONNECT_INFO ; + + typedef struct sockaddr_in { + short sin_family; + USHORT sin_port; + IN_ADDR sin_addr; + CHAR sin_zero[8]; + } SOCKADDR_IN, *PSOCKADDR_IN; + + */ + + if (@rax == 0x7) { + + // printf("IoControlCode: %x\n", dd(@rsp + 30)); + + if (dd(@rsp + 30) == 0x12007) { + // + // Details derived from: https://www.cyberus-technology.de/posts/network-analysis-with-tycho/ + // + + // + // Get the port address + // + port_num_high_bit = db(poi(@rsp + 38) + 1a); + port_num_low_bit = db(poi(@rsp + 38) + 1b); + + port_num = 0; + port_num = port_num_high_bit << 8 | port_num_low_bit; + + // + // Get the IP address + // + part0 = db(poi(@rsp + 38) + 1c); + part1 = db(poi(@rsp + 38) + 1d); + part2 = db(poi(@rsp + 38) + 1e); + part3 = db(poi(@rsp + 38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Process Id: %x, name: %s connects to ====> IP address (hex): %x\n", $pid, $pname, ip_addr); + + printf("Process Id: %x, name: %s connects to ====> Address: %d.%d.%d.%d:%d\n", + $pid, + $pname, + (ip_addr & 0xFF000000) >> 0n24, + (ip_addr & 0x00FF0000) >> 0n16, + (ip_addr & 0x0000FF00) >> 0n8, + ip_addr & 0x000000FF, + port_num); + } + } +} +_____________________________________________________________ +cmdDoubleQuotes ""empty quotes"" {preserve""} +---------------------------------- +cmdDoubleQuotes +---------------------------------- + +---------------------------------- +empty +---------------------------------- +quotes +---------------------------------- + +---------------------------------- +preserve"" +_____________________________________________________________ +///////* +cmdRandomSymbols @$#*keep #this {preserved$} +---------------------------------- +cmdRandomSymbols +---------------------------------- +@$#*keep +---------------------------------- +#this +---------------------------------- +preserved$ +_____________________________________________________________ +cmdColon :preserve :this {!syscall pid $arg1 script { + + // + // IOCTL Codes: + // AFD_Connect: 0x12007 + // + /* + + typedef struct _AFD_CONNECT_INFO { + BOOLEAN UseSAN; + ULONG Root; + ULONG Unknown; + SOCKADDR RemoteAddress; + } AFD_CONNECT_INFO , *PAFD_CONNECT_INFO ; + + typedef struct sockaddr_in { + short sin_family; + USHORT sin_port; + IN_ADDR sin_addr; + CHAR sin_zero[8]; + } SOCKADDR_IN, *PSOCKADDR_IN; + + */ + + if (@rax == 0x7) { + + // printf("IoControlCode: %x\n", dd(@rsp + 30)); + + if (dd(@rsp + 30) == 0x12007) { + // + // Details derived from: https://www.cyberus-technology.de/posts/network-analysis-with-tycho/ + // + + // + // Get the port address + // + port_num_high_bit = db(poi(@rsp + 38) + 1a); + port_num_low_bit = db(poi(@rsp + 38) + 1b); + + port_num = 0; + port_num = port_num_high_bit << 8 | port_num_low_bit; + + // + // Get the IP address + // + part0 = db(poi(@rsp + 38) + 1c); + part1 = db(poi(@rsp + 38) + 1d); + part2 = db(poi(@rsp + 38) + 1e); + part3 = db(poi(@rsp + 38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Process Id: %x, name: %s connects to ====> IP address (hex): %x\n", $pid, $pname, ip_addr); + + printf("Process Id: %x, name: %s connects to ====> Address: %d.%d.%d.%d:%d\n", + $pid, + $pname, + (ip_addr & 0xFF000000) >> 0n24, + (ip_addr & 0x00FF0000) >> 0n16, + (ip_addr & 0x0000FF00) >> 0n8, + ip_addr & 0x000000FF, + port_num); + } + } +}}{!syscall pid $arg1 script { + + // + // IOCTL Codes: + // AFD_Connect: 0x12007 + // + /* + + typedef struct _AFD_CONNECT_INFO { + BOOLEAN UseSAN; + ULONG Root; + ULONG Unknown; + SOCKADDR RemoteAddress; + } AFD_CONNECT_INFO , *PAFD_CONNECT_INFO ; + + typedef struct sockaddr_in { + short sin_family; + USHORT sin_port; + IN_ADDR sin_addr; + CHAR sin_zero[8]; + } SOCKADDR_IN, *PSOCKADDR_IN; + + */ + + if (@rax == 0x7) { + + // printf("IoControlCode: %x\n", dd(@rsp + 30)); + + if (dd(@rsp + 30) == 0x12007) { + // + // Details derived from: https://www.cyberus-technology.de/posts/network-analysis-with-tycho/ + // + + // + // Get the port address + // + port_num_high_bit = db(poi(@rsp + 38) + 1a); + port_num_low_bit = db(poi(@rsp + 38) + 1b); + + port_num = 0; + port_num = port_num_high_bit << 8 | port_num_low_bit; + + // + // Get the IP address + // + part0 = db(poi(@rsp + 38) + 1c); + part1 = db(poi(@rsp + 38) + 1d); + part2 = db(poi(@rsp + 38) + 1e); + part3 = db(poi(@rsp + 38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Process Id: %x, name: %s connects to ====> IP address (hex): %x\n", $pid, $pname, ip_addr); + + printf("Process Id: %x, name: %s connects to ====> Address: %d.%d.%d.%d:%d\n", + $pid, + $pname, + (ip_addr & 0xFF000000) >> 0n24, + (ip_addr & 0x00FF0000) >> 0n16, + (ip_addr & 0x0000FF00) >> 0n8, + ip_addr & 0x000000FF, + port_num); + } + } +}} +---------------------------------- +cmdColon +---------------------------------- +:preserve +---------------------------------- +:this +---------------------------------- +!syscall pid $arg1 script { + + // + // IOCTL Codes: + // AFD_Connect: 0x12007 + // + /* + + typedef struct _AFD_CONNECT_INFO { + BOOLEAN UseSAN; + ULONG Root; + ULONG Unknown; + SOCKADDR RemoteAddress; + } AFD_CONNECT_INFO , *PAFD_CONNECT_INFO ; + + typedef struct sockaddr_in { + short sin_family; + USHORT sin_port; + IN_ADDR sin_addr; + CHAR sin_zero[8]; + } SOCKADDR_IN, *PSOCKADDR_IN; + + */ + + if (@rax == 0x7) { + + // printf("IoControlCode: %x\n", dd(@rsp + 30)); + + if (dd(@rsp + 30) == 0x12007) { + // + // Details derived from: https://www.cyberus-technology.de/posts/network-analysis-with-tycho/ + // + + // + // Get the port address + // + port_num_high_bit = db(poi(@rsp + 38) + 1a); + port_num_low_bit = db(poi(@rsp + 38) + 1b); + + port_num = 0; + port_num = port_num_high_bit << 8 | port_num_low_bit; + + // + // Get the IP address + // + part0 = db(poi(@rsp + 38) + 1c); + part1 = db(poi(@rsp + 38) + 1d); + part2 = db(poi(@rsp + 38) + 1e); + part3 = db(poi(@rsp + 38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Process Id: %x, name: %s connects to ====> IP address (hex): %x\n", $pid, $pname, ip_addr); + + printf("Process Id: %x, name: %s connects to ====> Address: %d.%d.%d.%d:%d\n", + $pid, + $pname, + (ip_addr & 0xFF000000) >> 0n24, + (ip_addr & 0x00FF0000) >> 0n16, + (ip_addr & 0x0000FF00) >> 0n8, + ip_addr & 0x000000FF, + port_num); + } + } +} +---------------------------------- +!syscall pid $arg1 script { + + // + // IOCTL Codes: + // AFD_Connect: 0x12007 + // + /* + + typedef struct _AFD_CONNECT_INFO { + BOOLEAN UseSAN; + ULONG Root; + ULONG Unknown; + SOCKADDR RemoteAddress; + } AFD_CONNECT_INFO , *PAFD_CONNECT_INFO ; + + typedef struct sockaddr_in { + short sin_family; + USHORT sin_port; + IN_ADDR sin_addr; + CHAR sin_zero[8]; + } SOCKADDR_IN, *PSOCKADDR_IN; + + */ + + if (@rax == 0x7) { + + // printf("IoControlCode: %x\n", dd(@rsp + 30)); + + if (dd(@rsp + 30) == 0x12007) { + // + // Details derived from: https://www.cyberus-technology.de/posts/network-analysis-with-tycho/ + // + + // + // Get the port address + // + port_num_high_bit = db(poi(@rsp + 38) + 1a); + port_num_low_bit = db(poi(@rsp + 38) + 1b); + + port_num = 0; + port_num = port_num_high_bit << 8 | port_num_low_bit; + + // + // Get the IP address + // + part0 = db(poi(@rsp + 38) + 1c); + part1 = db(poi(@rsp + 38) + 1d); + part2 = db(poi(@rsp + 38) + 1e); + part3 = db(poi(@rsp + 38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Process Id: %x, name: %s connects to ====> IP address (hex): %x\n", $pid, $pname, ip_addr); + + printf("Process Id: %x, name: %s connects to ====> Address: %d.%d.%d.%d:%d\n", + $pid, + $pname, + (ip_addr & 0xFF000000) >> 0n24, + (ip_addr & 0x00FF0000) >> 0n16, + (ip_addr & 0x0000FF00) >> 0n8, + ip_addr & 0x000000FF, + port_num); + } + } +} +_____________________________________________________________ +cmdDollarSign $preserve $this {## @file process-behavior-logger.ds +# @author HyperDbg Development Team +# @brief Dataset maker script +# @version 0.1 +# @date 2021-10-01 +# @copyright This script is released under the MIT License. +# +# @details In order to run this script, you should use '.script' +# command. +# @param ProcessId The first parameter is the target Process Id +# +# First, you need to specify the Process ID as the first argument. +# For example, if your target process's ID is 0x1240, then you +# run the the scrip like this: +# +# After that, use the script like: +# .script c:\users\sina\desktop\process-behavior-logger.ds 0x1240 +# +# It gathers different parameters in order to create a dataset +# from the behavior of a special process. +# Some of the commands are commented, you can uncomment them if you +# need its results. +# + +# +# Configure the symbols, make sure that "ntoskrnl.exe"'s PDB is located +# at local symbol path +# +.sympath SRV*c:\Symbols*https://msdl.microsoft.com/download/symbols +.sym reload + +# +# The first parameter to investigate is system-call, +# generally, the system-calls are with Windows x86_64 FASTCALL calling convention. +# So, the parameters are passed in RCX, RDX, R8, R9, Stack +# However, RCX is modified by Intel through kernel-to-user transition as +# RCX will contain address of next instruction (RIP), but in Windows, it +# remains its convention and saves the RCX temporarily on R10, so the R10 +# register represents RCX in this case. +# +!syscall pid $arg1 script { + printf("method:syscall, pname: %s, pid: %x, tid: %x, syscall: %llx, rcx: %llx, rdx: %llx, r8: %llx, r9: %llx\n", + $pname, $pid, $tid, @rax, @r10, @rdx, @r8, @r9); + } + +# +# And we'll get SYSRET(s), it is because we want to get the result of SYSCALLs +# from the kernel, note that sysrets are related to the SYSCALLs by Thread ID +# It means that we can find the actual sysret for the specific syscall by +# looking for the Thread ID. +# Note that the return result is in the RAX register. +# +!sysret pid $arg1 script { + printf("method:sysret, pname: %s, pid: %x, tid: %x, rax: %llx\n", $pname, $pid, $tid, @rax); + } + +# +# The next parameter is kernel memory allocations +# For this purpose, we hook nt!ExAllocatePoolWithTag +# This is the prototype of this function from MSDN, and it's FASTCALL: +# Link: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-exallocatepoolwithtag +# +# PVOID ExAllocatePoolWithTag( +# __drv_strictTypeMatch(__drv_typeExpr)POOL_TYPE PoolType, +# SIZE_T NumberOfBytes, +# ULONG Tag +# ); +# +# +!epthook nt!ExAllocatePoolWithTag pid $arg1 script { + printf("method:kmem, pname: %s, pid: %x, tid: %x, ret: %llx, PoolType: %llx, PoolSize: %llx, PoolTag: %llx\n", + $pname, $pid, $tid, poi(@rsp), @rcx, @rdx, @r8); + } + +# +# Next, we'll interested in any execution of CPUID instruction +# +!cpuid pid $arg1 script { + printf("method:cpuid, pname: %s, pid: %x, tid: %x, rip: %llx, context: %x, eax: %x, ebx: %x, ecx: %x, edx: %x\n", + $pname, $pid, $tid, @rip, $context, @eax, @ebx, @ecx, @edx); + } + +# +# Create a log from accesses to hardware debug registers +# THIS COMMAND IS COMMENTED +# +# !dr pid $arg1 script { +# printf("method:debugregs, pname: %s, pid: %x, tid: %x, rip: %llx\n", $pname, $pid, $tid, @rip); +# } + +# +# The other parameter is to get any call to first 32-entries of +# Interrupt Descriptor Table (IDT) +# THIS COMMAND IS COMMENTED +# +# !exception pid $arg1 script { +# printf("method:exception, pname: %s, pid: %x, tid: %x, rip: %llx, context: %x\n", +# $pname, $pid, $tid, @rip, $context); +# } + +# +# getting the execution of RDTSC/RDTSCP +# THIS COMMAND IS COMMENTED +# +# !tsc pid $arg1 script { +# printf("method:tsc, pname: %s, pid: %x, tid: %x, rip: %llx\n", $pname, $pid, $tid, @rip); +# } + +# +# getting the execution of RDMSR/WRMSR +# THESE COMMANDS ARE COMMENTED +# +# !msrread pid $arg1 script { +# printf("method:rdmsr, pname: %s, pid: %x, tid: %x, rip: %llx, context: %llx\n", +# $pname, $pid, $tid, @rip, $context); +# } + +# !msrwrite pid $arg1 script { +# printf("method:wrmsr, pname: %s, pid: %x, tid: %x, rip: %llx, context: %llx\n", +# $pname, $pid, $tid, @rip, $context); +# } + +# +# getting the execution of I/O instructions (IN & OUT) +# THESE COMMANDS ARE COMMENTED +# +# !ioin pid $arg1 script { +# printf("method:in, pname: %s, pid: %x, tid: %x, rip: %llx, context: %llx\n", +# $pname, $pid, $tid, @rip, $context); +# } + +# !ioout pid $arg1 script { +# printf("method:out, pname: %s, pid: %x, tid: %x, rip: %llx, context: %llx\n", +# $pname, $pid, $tid, @rip, $context); +# }} +---------------------------------- +cmdDollarSign +---------------------------------- +$preserve +---------------------------------- +$this +---------------------------------- +## @file process-behavior-logger.ds +# @author HyperDbg Development Team +# @brief Dataset maker script +# @version 0.1 +# @date 2021-10-01 +# @copyright This script is released under the MIT License. +# +# @details In order to run this script, you should use '.script' +# command. +# @param ProcessId The first parameter is the target Process Id +# +# First, you need to specify the Process ID as the first argument. +# For example, if your target process's ID is 0x1240, then you +# run the the scrip like this: +# +# After that, use the script like: +# .script c:\users\sina\desktop\process-behavior-logger.ds 0x1240 +# +# It gathers different parameters in order to create a dataset +# from the behavior of a special process. +# Some of the commands are commented, you can uncomment them if you +# need its results. +# + +# +# Configure the symbols, make sure that "ntoskrnl.exe"'s PDB is located +# at local symbol path +# +.sympath SRV*c:\Symbols*https://msdl.microsoft.com/download/symbols +.sym reload + +# +# The first parameter to investigate is system-call, +# generally, the system-calls are with Windows x86_64 FASTCALL calling convention. +# So, the parameters are passed in RCX, RDX, R8, R9, Stack +# However, RCX is modified by Intel through kernel-to-user transition as +# RCX will contain address of next instruction (RIP), but in Windows, it +# remains its convention and saves the RCX temporarily on R10, so the R10 +# register represents RCX in this case. +# +!syscall pid $arg1 script { + printf("method:syscall, pname: %s, pid: %x, tid: %x, syscall: %llx, rcx: %llx, rdx: %llx, r8: %llx, r9: %llx\n", + $pname, $pid, $tid, @rax, @r10, @rdx, @r8, @r9); + } + +# +# And we'll get SYSRET(s), it is because we want to get the result of SYSCALLs +# from the kernel, note that sysrets are related to the SYSCALLs by Thread ID +# It means that we can find the actual sysret for the specific syscall by +# looking for the Thread ID. +# Note that the return result is in the RAX register. +# +!sysret pid $arg1 script { + printf("method:sysret, pname: %s, pid: %x, tid: %x, rax: %llx\n", $pname, $pid, $tid, @rax); + } + +# +# The next parameter is kernel memory allocations +# For this purpose, we hook nt!ExAllocatePoolWithTag +# This is the prototype of this function from MSDN, and it's FASTCALL: +# Link: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-exallocatepoolwithtag +# +# PVOID ExAllocatePoolWithTag( +# __drv_strictTypeMatch(__drv_typeExpr)POOL_TYPE PoolType, +# SIZE_T NumberOfBytes, +# ULONG Tag +# ); +# +# +!epthook nt!ExAllocatePoolWithTag pid $arg1 script { + printf("method:kmem, pname: %s, pid: %x, tid: %x, ret: %llx, PoolType: %llx, PoolSize: %llx, PoolTag: %llx\n", + $pname, $pid, $tid, poi(@rsp), @rcx, @rdx, @r8); + } + +# +# Next, we'll interested in any execution of CPUID instruction +# +!cpuid pid $arg1 script { + printf("method:cpuid, pname: %s, pid: %x, tid: %x, rip: %llx, context: %x, eax: %x, ebx: %x, ecx: %x, edx: %x\n", + $pname, $pid, $tid, @rip, $context, @eax, @ebx, @ecx, @edx); + } + +# +# Create a log from accesses to hardware debug registers +# THIS COMMAND IS COMMENTED +# +# !dr pid $arg1 script { +# printf("method:debugregs, pname: %s, pid: %x, tid: %x, rip: %llx\n", $pname, $pid, $tid, @rip); +# } + +# +# The other parameter is to get any call to first 32-entries of +# Interrupt Descriptor Table (IDT) +# THIS COMMAND IS COMMENTED +# +# !exception pid $arg1 script { +# printf("method:exception, pname: %s, pid: %x, tid: %x, rip: %llx, context: %x\n", +# $pname, $pid, $tid, @rip, $context); +# } + +# +# getting the execution of RDTSC/RDTSCP +# THIS COMMAND IS COMMENTED +# +# !tsc pid $arg1 script { +# printf("method:tsc, pname: %s, pid: %x, tid: %x, rip: %llx\n", $pname, $pid, $tid, @rip); +# } + +# +# getting the execution of RDMSR/WRMSR +# THESE COMMANDS ARE COMMENTED +# +# !msrread pid $arg1 script { +# printf("method:rdmsr, pname: %s, pid: %x, tid: %x, rip: %llx, context: %llx\n", +# $pname, $pid, $tid, @rip, $context); +# } + +# !msrwrite pid $arg1 script { +# printf("method:wrmsr, pname: %s, pid: %x, tid: %x, rip: %llx, context: %llx\n", +# $pname, $pid, $tid, @rip, $context); +# } + +# +# getting the execution of I/O instructions (IN & OUT) +# THESE COMMANDS ARE COMMENTED +# +# !ioin pid $arg1 script { +# printf("method:in, pname: %s, pid: %x, tid: %x, rip: %llx, context: %llx\n", +# $pname, $pid, $tid, @rip, $context); +# } + +# !ioout pid $arg1 script { +# printf("method:out, pname: %s, pid: %x, tid: %x, rip: %llx, context: %llx\n", +# $pname, $pid, $tid, @rip, $context); +# } +_____________________________________________________________ +cmdAtSymbol @keep @this { +start path $arg1 + +? .thread_intercept_thread = 0; +? .target_pid = $pid; +? .target_tid = 0; +? .target_allocation_address = 0; +? .target_allocation_size = 0; + +!sysret script { + if ($pid == .target_pid && .thread_intercept_thread == 1 && $tid == .target_tid) { + spinlock_unlock(&.thread_intercept_thread); + .target_tid = 0; + printf("[SYSRET] NtAllocateVirtualMemory called from, pid: %x, name: %s | located at: %llx, actual allocated size: %llx\n", $pid, $pname, dq(.target_allocation_address), dq(.target_allocation_size)); + } +} + +!syscall 18 script { + + if ($pid == .target_pid) { + spinlock_lock(&.thread_intercept_thread); + .target_tid = $tid; + .target_allocation_address = @rdx; + .target_allocation_size = @r9; + + if (dq(rdx) == 0) { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx\n", $pid, $pname, dq(r9)); + } + else { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx, user-specific addr: %llx\n", $pid, $pname, dq(r9), dq(rdx)); + } + } +} +} +---------------------------------- +cmdAtSymbol +---------------------------------- +@keep +---------------------------------- +@this +---------------------------------- + +start path $arg1 + +? .thread_intercept_thread = 0; +? .target_pid = $pid; +? .target_tid = 0; +? .target_allocation_address = 0; +? .target_allocation_size = 0; + +!sysret script { + if ($pid == .target_pid && .thread_intercept_thread == 1 && $tid == .target_tid) { + spinlock_unlock(&.thread_intercept_thread); + .target_tid = 0; + printf("[SYSRET] NtAllocateVirtualMemory called from, pid: %x, name: %s | located at: %llx, actual allocated size: %llx\n", $pid, $pname, dq(.target_allocation_address), dq(.target_allocation_size)); + } +} + +!syscall 18 script { + + if ($pid == .target_pid) { + spinlock_lock(&.thread_intercept_thread); + .target_tid = $tid; + .target_allocation_address = @rdx; + .target_allocation_size = @r9; + + if (dq(rdx) == 0) { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx\n", $pid, $pname, dq(r9)); + } + else { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx, user-specific addr: %llx\n", $pid, $pname, dq(r9), dq(rdx)); + } + } +} + +_____________________________________________________________ +cmdAlphanumeric a1b2c3 {preserve a4b5c6} next +---------------------------------- +cmdAlphanumeric +---------------------------------- +a1b2c3 +---------------------------------- +preserve a4b5c6 +---------------------------------- +next +_____________________________________________________________ +cmdMixedComments /*comment1*/ param //comment2\n {keep} +---------------------------------- +cmdMixedComments +---------------------------------- +param +---------------------------------- +keep +_____________________________________________________________ +cmdMixedComments /*comment1*/ param //comment2 {keep} +---------------------------------- +cmdMixedComments +---------------------------------- +param +_____________________________________________________________ +cmdAngleAndQuotes /* start path $arg1 + +? .thread_intercept_thread = 0; +? .target_pid = $pid; +? .target_tid = 0; +? .target_allocation_address = 0; +? .target_allocation_size = 0; + +!sysret script { + if ($pid == .target_pid && .thread_intercept_thread == 1 && $tid == .target_tid) { + spinlock_unlock(&.thread_intercept_thread); + .target_tid = 0; + printf("[SYSRET] NtAllocateVirtualMemory called from, pid: %x, name: %s | located at: %llx, actual allocated size: %llx\n", $pid, $pname, dq(.target_allocation_address), dq(.target_allocation_size)); + } +} + +!syscall 18 script { + + if ($pid == .target_pid) { + spinlock_lock(&.thread_intercept_thread); + .target_tid = $tid; + .target_allocation_address = @rdx; + .target_allocation_size = @r9; + + if (dq(rdx) == 0) { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx\n", $pid, $pname, dq(r9)); + } + else { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx, user-specific addr: %llx\n", $pid, $pname, dq(r9), dq(rdx)); + } + } +}*/ +---------------------------------- +cmdAngleAndQuotes +---------------------------------- + +_____________________________________________________________ +/* start path $arg1 + +? .thread_intercept_thread = 0; +? .target_pid = $pid; +? .target_tid = 0; +? .target_allocation_address = 0; +? .target_allocation_size = 0; + +!sysret script { + if ($pid == .target_pid && .thread_intercept_thread == 1 && $tid == .target_tid) { + spinlock_unlock(&.thread_intercept_thread); + .target_tid = 0; + printf("[SYSRET] NtAllocateVirtualMemory called from, pid: %x, name: %s | located at: %llx, actual allocated size: %llx\n", $pid, $pname, dq(.target_allocation_address), dq(.target_allocation_size)); + } +} + +!syscall 18 script { + + if ($pid == .target_pid) { + spinlock_lock(&.thread_intercept_thread); + .target_tid = $tid; + .target_allocation_address = @rdx; + .target_allocation_size = @r9; + + if (dq(rdx) == 0) { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx\n", $pid, $pname, dq(r9)); + } + else { + printf("[SYSCALL] NtAllocateVirtualMemory called from, pid: %x, name: %s | requested size: %llx, user-specific addr: %llx\n", $pid, $pname, dq(r9), dq(rdx)); + } + } +}*/cmdSpecialBraces {keep this} /*comment*/ {another preserve} +---------------------------------- +cmdSpecialBraces +---------------------------------- +keep this +---------------------------------- +another preserve +_____________________________________________________________ +cmdComplexSyntax !@#preserve%&*()_+\{\}:<>?[];',./ `~ | {and this} +---------------------------------- +cmdComplexSyntax +---------------------------------- +!@#preserve%&*()_+{}:<>?[];',./ +---------------------------------- +`~ +---------------------------------- +| +---------------------------------- +and this +_____________________________________________________________ + +// +? printf("Result : %s", @rcx); +---------------------------------- +? +---------------------------------- +printf( +---------------------------------- +Result : %s +---------------------------------- +, +---------------------------------- +@rcx); +_____________________________________________________________ +? printf("Process name: %s", $pname); + +---------------------------------- +? +---------------------------------- +printf( +---------------------------------- +Process name: %s +---------------------------------- +, +---------------------------------- +$pname); +_____________________________________________________________ +? print(dq(@rcx)); + +---------------------------------- +? +---------------------------------- +print(dq(@rcx)); +_____________________________________________________________ +? print($proc+@rdx); + +---------------------------------- +? +---------------------------------- +print($proc+@rdx); +_____________________________________________________________ +? print(poi(@rax+a0)); + +---------------------------------- +? +---------------------------------- +print(poi(@rax+a0)); +_____________________________________________________________ +? printf("Result : %ws\"", poi($proc+ 10)); + +---------------------------------- +? +---------------------------------- +printf( +---------------------------------- +Result : %ws" +---------------------------------- +, +---------------------------------- +poi($proc+ +---------------------------------- +10)); +_____________________________________________________________ +? printf("Result : %s", poi($proc+10)); + +---------------------------------- +? +---------------------------------- +printf( +---------------------------------- +Result : %s +---------------------------------- +, +---------------------------------- +poi($proc+10)); +_____________________________________________________________ +? print(dw(NtCreateFile+10)); + +---------------------------------- +? +---------------------------------- +print(dw(NtCreateFile+10)); +_____________________________________________________________ +? print(dw(NtCreateFile+@rcx+($proc|3+poi(poi(@rax)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))){ }))))); + +---------------------------------- +? +---------------------------------- +print(dw(NtCreateFile+@rcx+($proc|3+poi(poi(@rax)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +---------------------------------- + +---------------------------------- +))))); +_____________________________________________________________ +__kernel_entry NTSYSCALLAPI NTSTATUS NtOpenFile( + PHANDLE FileHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG ShareAccess, + ULONG OpenOptions +); +---------------------------------- +__kernel_entry +---------------------------------- +NTSYSCALLAPI +---------------------------------- +NTSTATUS +---------------------------------- +NtOpenFile( +---------------------------------- +PHANDLE +---------------------------------- +FileHandle, +---------------------------------- +ACCESS_MASK +---------------------------------- +DesiredAccess, +---------------------------------- +POBJECT_ATTRIBUTES +---------------------------------- +ObjectAttributes, +---------------------------------- +PIO_STATUS_BLOCK +---------------------------------- +IoStatusBlock, +---------------------------------- +ULONG +---------------------------------- +ShareAccess, +---------------------------------- +ULONG +---------------------------------- +OpenOptions +); +_____________________________________________________________ +From the relative-address point of view, this function is stored in the memory like this: +---------------------------------- +From +---------------------------------- +the +---------------------------------- +relative-address +---------------------------------- +point +---------------------------------- +of +---------------------------------- +view, +---------------------------------- +this +---------------------------------- +function +---------------------------------- +is +---------------------------------- +stored +---------------------------------- +in +---------------------------------- +the +---------------------------------- +memory +---------------------------------- +like +---------------------------------- +this: +_____________________________________________________________ + +0x000 Length : Uint2B + +0x002 MaximumLength : Uint2B + +0x008 Buffer : Ptr64 Wchar + +---------------------------------- ++0x000 +---------------------------------- +Length +---------------------------------- +: +---------------------------------- +Uint2B +---------------------------------- ++0x002 +---------------------------------- +MaximumLength +---------------------------------- +: +---------------------------------- +Uint2B +---------------------------------- ++0x008 +---------------------------------- +Buffer +---------------------------------- +: +---------------------------------- +Ptr64 +---------------------------------- +Wchar +_____________________________________________________________ +!epthook nt!NtOpenFile script { + printf("%ws\n", dq(poi(r8 + 10) + 0x8)); +} +---------------------------------- +!epthook +---------------------------------- +nt!NtOpenFile +---------------------------------- +script +---------------------------------- + + printf("%ws\n", dq(poi(r8 + 10) + 0x8)); + +_____________________________________________________________ + fffff801`639b1030 48 F mov qword ptr ss:[rsp+0x08], rbx +fffff801`639b1035 24 10 mov qword ptr ss:[rsp+0x10], rbp +---------------------------------- +fffff801`639b1030 +---------------------------------- +48 +---------------------------------- +F +---------------------------------- +mov +---------------------------------- +qword +---------------------------------- +ptr +---------------------------------- +ss:[rsp+0x08], +---------------------------------- +rbx +fffff801`639b1035 +---------------------------------- +24 +---------------------------------- +10 +---------------------------------- +mov +---------------------------------- +qword +---------------------------------- +ptr +---------------------------------- +ss:[rsp+0x10], +---------------------------------- +rbp +_____________________________________________________________ +!epthook nt!ExAllocatePoolWithTag script { + + if (poi(@rsp") == nt!CmpAllocatePoolWithTag+0x9") { + pause(); + } +} +---------------------------------- +!epthook +---------------------------------- +nt!ExAllocatePoolWithTag +---------------------------------- +script +---------------------------------- + + + if (poi(@rsp") == nt!CmpAllocatePoolWithTag+0x9") { + pause(); + } + +_____________________________________________________________ +? .my_lock = 0; +? .my_counter = 0; + +---------------------------------- +? +---------------------------------- +.my_lock +---------------------------------- += +---------------------------------- +0; +? +---------------------------------- +.my_counter +---------------------------------- += +---------------------------------- +0; +_____________________________________________________________ +{spinlock_lock(&.my_lock); + +.my_counter = .my_counter + 1; +printf("NtCreateFile syscall (0x0055) is called %llx times\n", .my_counter); + +spinlock_unlock(&.my_lock);{}} + +---------------------------------- +spinlock_lock(&.my_lock); + +.my_counter = .my_counter + 1; +printf("NtCreateFile syscall (0x0055) is called %llx times\n", .my_counter); + +spinlock_unlock(&.my_lock);{} +_____________________________________________________________ +? .my_lock = 0; +? .my_counter = 0; + +!syscall script { + +if ($context == 0x55) { + + spinlock_lock(&.my_lock); + + .my_counter = .my_counter + 1; + printf("NtCreateFile syscall (0x0055) is called %llx times\n", .my_counter); + + spinlock_unlock(&.my_lock); + + } +} +---------------------------------- +? +---------------------------------- +.my_lock +---------------------------------- += +---------------------------------- +0; +? +---------------------------------- +.my_counter +---------------------------------- += +---------------------------------- +0; + +!syscall +---------------------------------- +script +---------------------------------- + + +if ($context == 0x55) { + + spinlock_lock(&.my_lock); + + .my_counter = .my_counter + 1; + printf("NtCreateFile syscall (0x0055) is called %llx times\n", .my_counter); + + spinlock_unlock(&.my_lock); + + } + +_____________________________________________________________ +? @ebx = @rdx | 0xfffff550 + @edx; + +---------------------------------- +? +---------------------------------- +@ebx +---------------------------------- += +---------------------------------- +@rdx +---------------------------------- +| +---------------------------------- +0xfffff550 +---------------------------------- ++ +---------------------------------- +@edx; +_____________________________________________________________ +? @rip = 0xfffff8003ad6f010;" @rsp = fffff800`5b660000; + + +\" + + +" + +---------------------------------- +? +---------------------------------- +@rip +---------------------------------- += +---------------------------------- +0xfffff8003ad6f010; +---------------------------------- + @rsp = fffff800`5b660000; + + +" + + + +_____________________________________________________________ +if (check_address(@r11) == 1) +{ + printf("address is valid.\n"); +} +else +{ + printf("address is invalid.\n"); +} +---------------------------------- +if +---------------------------------- +(check_address(@r11) +---------------------------------- +== +---------------------------------- +1) +---------------------------------- + + printf("address is valid.\n"); + +---------------------------------- +else +---------------------------------- + + printf("address is invalid.\n"); + +_____________________________________________________________ +!epthook nt!NtCreateFile script { + if(wcscmp(L"\\??\\C:\\folder\\test.txt",poi(poi(@r8+10)+8)) == 0){ + pause(); + } +} +---------------------------------- +!epthook +---------------------------------- +nt!NtCreateFile +---------------------------------- +script +---------------------------------- + + if(wcscmp(L"\\??\\C:\\folder\\test.txt",poi(poi(@r8+10)+8)) == 0){ + pause(); + } + +_____________________________________________________________ +!epthook 004C5A1C pid 225c script { + @zf = 0; +} +---------------------------------- +!epthook +---------------------------------- +004C5A1C +---------------------------------- +pid +---------------------------------- +225c +---------------------------------- +script +---------------------------------- + + @zf = 0; + +_____________________________________________________________ +!exception 0xe pid 4 script "{ + + .Result = interlocked_increment(&.my_counter); +}" +---------------------------------- +!exception +---------------------------------- +0xe +---------------------------------- +pid +---------------------------------- +4 +---------------------------------- +script +---------------------------------- +{ + + .Result = interlocked_increment(&.my_counter); +} +_____________________________________________________________ +!sysret script { + + if (.thread_id == $tid) { + + printf("[%llx] result of syscall: %llx\n", $tid, @rax); + + // + // Reset the thread id holder + // + .thread_id = 0; + } +} +---------------------------------- +!sysret +---------------------------------- +script +---------------------------------- + + + if (.thread_id == $tid) { + + printf("[%llx] result of syscall: %llx\n", $tid, @rax); + + // + // Reset the thread id holder + // + .thread_id = 0; + } + +_____________________________________________________________ +!syscall script { + + if ($pid == $arg1 && @rax == $arg2) { + + spinlock_lock(&.thread_id_lock); + + if (.thread_id == 0) { + + // + // Save the thread id for the SYSRET event + // + .thread_id = $tid; + + // + // Show the parameters + // + printf("[%llx] syscall num: %llx, arg1: %llx, arg2: %llx, arg3: %llx, arg4: %llx\n", $tid, @rax, @rcx, @rdx, @r8, @r9); + + } + + spinlock_unlock(&.thread_id_lock); + } +} +---------------------------------- +!syscall +---------------------------------- +script +---------------------------------- + + + if ($pid == $arg1 && @rax == $arg2) { + + spinlock_lock(&.thread_id_lock); + + if (.thread_id == 0) { + + // + // Save the thread id for the SYSRET event + // + .thread_id = $tid; + + // + // Show the parameters + // + printf("[%llx] syscall num: %llx, arg1: %llx, arg2: %llx, arg3: %llx, arg4: %llx\n", $tid, @rax, @rcx, @rdx, @r8, @r9); + + } + + spinlock_unlock(&.thread_id_lock); + } + +_____________________________________________________________ +!sysret script { + + if (.thread_id == $tid) { + + printf("[%llx] result of syscall: %llx\n", $tid, @rax); + + // + // Reset the thread id holder + // + .thread_id = 0; + } +} + +!syscall script { + + if ($pid == $arg1 && @rax == $arg2) { + + spinlock_lock(&.thread_id_lock); + + if (.thread_id == 0) { + + // + // Save the thread id for the SYSRET event + // + .thread_id = $tid; + + // + // Show the parameters + // + printf("[%llx] syscall num: %llx, arg1: %llx, arg2: %llx, arg3: %llx, arg4: %llx\n", $tid, @rax, @rcx, @rdx, @r8, @r9); + + } + + spinlock_unlock(&.thread_id_lock); + } +} + +---------------------------------- +!sysret +---------------------------------- +script +---------------------------------- + + + if (.thread_id == $tid) { + + printf("[%llx] result of syscall: %llx\n", $tid, @rax); + + // + // Reset the thread id holder + // + .thread_id = 0; + } + +---------------------------------- +!syscall +---------------------------------- +script +---------------------------------- + + + if ($pid == $arg1 && @rax == $arg2) { + + spinlock_lock(&.thread_id_lock); + + if (.thread_id == 0) { + + // + // Save the thread id for the SYSRET event + // + .thread_id = $tid; + + // + // Show the parameters + // + printf("[%llx] syscall num: %llx, arg1: %llx, arg2: %llx, arg3: %llx, arg4: %llx\n", $tid, @rax, @rcx, @rdx, @r8, @r9); + + } + + spinlock_unlock(&.thread_id_lock); + } + +_____________________________________________________________ +? .script c:\users\sina\desktop\script.ds 1240 55 + +---------------------------------- +? +---------------------------------- +.script +---------------------------------- +c:\users\sina\desktop\script.ds +---------------------------------- +1240 +---------------------------------- +55 +_____________________________________________________________ +HyperDbg> !epthook fffff805`5cdb2030 script { print(@r8); } + +---------------------------------- +HyperDbg> +---------------------------------- +!epthook +---------------------------------- +fffff805`5cdb2030 +---------------------------------- +script +---------------------------------- + print(@r8); +_____________________________________________________________ +!syscall pid 1c38 script { + + printf("Syscall number : %llx\n", @rax); + + if ($context == 0x55) { + pause(); + } + +} + +---------------------------------- +!syscall +---------------------------------- +pid +---------------------------------- +1c38 +---------------------------------- +script +---------------------------------- + + + printf("Syscall number : %llx\n", @rax); + + if ($context == 0x55) { + pause(); + } + + +_____________________________________________________________ +.thread_intercept_thread = 0; + +!sysret script { + if ($tid == 60c && .thread_intercept_thread == 1) { + .thread_intercept_thread = 0; + printf("[%llx] result of syscall: %llx\n", $tid, @rax); + + @rax = 0xC0000005; + printf("[%llx] result of syscall changed to : %llx\n", $tid, @rax); + + } +} + +!syscall script { + if ($tid == 60c && @rax == 0x55) { + .thread_intercept_thread = 1; + printf("[%llx] syscall num: %llx, arg1: %llx, arg2: %llx, arg3: %llx, arg4: %llx\n", + $tid, @rax, @rcx, @rdx, @r8, @r9); + } +} + + +---------------------------------- +.thread_intercept_thread +---------------------------------- += +---------------------------------- +0; + +!sysret +---------------------------------- +script +---------------------------------- + + if ($tid == 60c && .thread_intercept_thread == 1) { + .thread_intercept_thread = 0; + printf("[%llx] result of syscall: %llx\n", $tid, @rax); + + @rax = 0xC0000005; + printf("[%llx] result of syscall changed to : %llx\n", $tid, @rax); + + } + +---------------------------------- +!syscall +---------------------------------- +script +---------------------------------- + + if ($tid == 60c && @rax == 0x55) { + .thread_intercept_thread = 1; + printf("[%llx] syscall num: %llx, arg1: %llx, arg2: %llx, arg3: %llx, arg4: %llx\n", + $tid, @rax, @rcx, @rdx, @r8, @r9); + } + +_____________________________________________________________ +# Address of test variable: 7ff7f6ba8210 | pid: 2a0c + + +!monitor w 7ff7f6ba8210 7ff7f6ba8210+4 stage all pid 2a0c script { + + if ($stage == 1) { + + // + // Called after the memory modification + // + final_val = dq($context); + + printf(" final value is: %d\n", final_val); + + } + else { + + // + // Called before the memory modification + // + prev_val = dq($context); + printf(" previous value is: %d", prev_val); + } +} + + + +!monitor w 7ff7f6ba8210 7ff7f6ba8210+4 stage all pid 2a0c script { + + if ($stage == 1) { + + // + // Called after the memory modification + // + final_val = dq($context); + + printf(" final value is: %d\n", final_val); + + if (final_val != 0 && final_val % 0n10 == 0) { + + // + // Reset the value + // + eq($context, 0x0); + + printf("reset\n"); + + } + + } + else { + + // + // Called before the memory modification + // + prev_val = dq($context); + printf(" previous value is: %d", prev_val); + } +} + +---------------------------------- +# +---------------------------------- +Address +---------------------------------- +of +---------------------------------- +test +---------------------------------- +variable: +---------------------------------- +7ff7f6ba8210 +---------------------------------- +| +---------------------------------- +pid: +---------------------------------- +2a0c + + +!monitor +---------------------------------- +w +---------------------------------- +7ff7f6ba8210 +---------------------------------- +7ff7f6ba8210+4 +---------------------------------- +stage +---------------------------------- +all +---------------------------------- +pid +---------------------------------- +2a0c +---------------------------------- +script +---------------------------------- + + + if ($stage == 1) { + + // + // Called after the memory modification + // + final_val = dq($context); + + printf(" final value is: %d\n", final_val); + + } + else { + + // + // Called before the memory modification + // + prev_val = dq($context); + printf(" previous value is: %d", prev_val); + } + +---------------------------------- +!monitor +---------------------------------- +w +---------------------------------- +7ff7f6ba8210 +---------------------------------- +7ff7f6ba8210+4 +---------------------------------- +stage +---------------------------------- +all +---------------------------------- +pid +---------------------------------- +2a0c +---------------------------------- +script +---------------------------------- + + + if ($stage == 1) { + + // + // Called after the memory modification + // + final_val = dq($context); + + printf(" final value is: %d\n", final_val); + + if (final_val != 0 && final_val % 0n10 == 0) { + + // + // Reset the value + // + eq($context, 0x0); + + printf("reset\n"); + + } + + } + else { + + // + // Called before the memory modification + // + prev_val = dq($context); + printf(" previous value is: %d", prev_val); + } + +_____________________________________________________________ +!cpuid 1 script { + + // + // Invalid supporting details + // + + @eax = 0; + + @ebx = 0; + @ecx = 0; + @edx = 0; + + event_sc(1); +} + +!cpuid 2 script { + + // + // Invalid supporting details + // + + @eax = 0; + + @ebx = 0; + @ecx = 0; + @edx = 0; + + event_sc(2); +} + + +---------------------------------- +!cpuid +---------------------------------- +1 +---------------------------------- +script +---------------------------------- + + + // + // Invalid supporting details + // + + @eax = 0; + + @ebx = 0; + @ecx = 0; + @edx = 0; + + event_sc(1); + +---------------------------------- +!cpuid +---------------------------------- +2 +---------------------------------- +script +---------------------------------- + + + // + // Invalid supporting details + // + + @eax = 0; + + @ebx = 0; + @ecx = 0; + @edx = 0; + + event_sc(2); + +_____________________________________________________________ +!exception 0xe script { + printf("page-fault in process : %s, pid: %x, addr: %llx\n", $pname, $pid, @cr2); +} + +!interrupt d1 script { + printf("core: %x, rip: %llx, %x\n", $core, @rip, $pid ); +} + +---------------------------------- +!exception +---------------------------------- +0xe +---------------------------------- +script +---------------------------------- + + printf("page-fault in process : %s, pid: %x, addr: %llx\n", $pname, $pid, @cr2); + +---------------------------------- +!interrupt +---------------------------------- +d1 +---------------------------------- +script +---------------------------------- + + printf("core: %x, rip: %llx, %x\n", $core, @rip, $pid ); + +_____________________________________________________________ +{ + + if (@rip & 0xff000000`00000000) { + printf("clk interrupt received at the kernel: %llx\n", @rip); + } + else{ + pause(); + } +}!interrupt d1 pid 0x2748 script script { + + if (@rip & 0xff000000`00000000) { + printf("clk interrupt received at the kernel: %llx\n", @rip); + } + else{ + pause(); + } +} + + +---------------------------------- + + + if (@rip & 0xff000000`00000000) { + printf("clk interrupt received at the kernel: %llx\n", @rip); + } + else{ + pause(); + } + +---------------------------------- +!interrupt +---------------------------------- +d1 +---------------------------------- +pid +---------------------------------- +0x2748 +---------------------------------- +script +---------------------------------- +script +---------------------------------- + + + if (@rip & 0xff000000`00000000) { + printf("clk interrupt received at the kernel: %llx\n", @rip); + } + else{ + pause(); + } + +_____________________________________________________________ +!syscall pid 0x16fc script {{}{}{}{{{}}} + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + pause(); + } + + } +} + + +---------------------------------- +!syscall +---------------------------------- +pid +---------------------------------- +0x16fc +---------------------------------- +script +---------------------------------- +{}{}{}{{{}}} + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + pause(); + } + + } + +_____________________________________________________________ +!syscall pid 0x16fc script { + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + printf("Port address is : %d \n", port_num); + + part0 = db(poi(@rsp+38) + 1c); + part1 = db(poi(@rsp+38) + 1d); + part2 = db(poi(@rsp+38) + 1e); + part3 = db(poi(@rsp+38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + printf("Ip address is : %x\n", ip_addr); + + + + } + + } +} + +---------------------------------- +!syscall +---------------------------------- +pid +---------------------------------- +0x16fc +---------------------------------- +script +---------------------------------- + + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + printf("Port address is : %d \n", port_num); + + part0 = db(poi(@rsp+38) + 1c); + part1 = db(poi(@rsp+38) + 1d); + part2 = db(poi(@rsp+38) + 1e); + part3 = db(poi(@rsp+38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + printf("Ip address is : %x\n", ip_addr); + + + + } + + } + +_____________________________________________________________ +? { + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + + printf("Port address is : %d \n", port_num); + + } + + } + +} + +---------------------------------- +? +---------------------------------- + + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + + printf("Port address is : %d \n", port_num); + + } + + } + + +_____________________________________________________________ +? { + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + printf("Port address is : %d \n", port_num); + + part0 = db(poi(@rsp+38) + 1c); + part1 = db(poi(@rsp+38) + 1d); + part2 = db(poi(@rsp+38) + 1e); + part3 = db(poi(@rsp+38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + printf("Ip address is : %x\n", ip_addr); + + printf("Ip address is : %d.%d.%d.%d\n", (ip_addr & 0xff000000) >> 0n24, (ip_addr & 0x00ff0000) >> 0n16, (ip_addr & 0x0000ff00) >> 0n8, (ip_addr & 0x000000ff)); + + + } + + } +} + +---------------------------------- +? +---------------------------------- + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + printf("Port address is : %d \n", port_num); + + part0 = db(poi(@rsp+38) + 1c); + part1 = db(poi(@rsp+38) + 1d); + part2 = db(poi(@rsp+38) + 1e); + part3 = db(poi(@rsp+38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + printf("Ip address is : %x\n", ip_addr); + + printf("Ip address is : %d.%d.%d.%d\n", (ip_addr & 0xff000000) >> 0n24, (ip_addr & 0x00ff0000) >> 0n16, (ip_addr & 0x0000ff00) >> 0n8, (ip_addr & 0x000000ff)); + + + } + + } + +_____________________________________________________________ +!syscall pid 0x16fc script { + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + //printf("Port address is : %d \n", port_num); + + part0 = db(poi(@rsp+38) + 1c); + part1 = db(poi(@rsp+38) + 1d); + part2 = db(poi(@rsp+38) + 1e); + part3 = db(poi(@rsp+38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Ip address is : %x\n", ip_addr); + + printf("Ip address is : %d.%d.%d.%d:%d\n", (ip_addr & 0xff000000) >> 0n24, (ip_addr & 0x00ff0000) >> 0n16, (ip_addr & 0x0000ff00) >> 0n8, (ip_addr & 0x000000ff),port_num ); + + + } + + } + +} + +---------------------------------- +!syscall +---------------------------------- +pid +---------------------------------- +0x16fc +---------------------------------- +script +---------------------------------- + + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + //printf("Port address is : %d \n", port_num); + + part0 = db(poi(@rsp+38) + 1c); + part1 = db(poi(@rsp+38) + 1d); + part2 = db(poi(@rsp+38) + 1e); + part3 = db(poi(@rsp+38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Ip address is : %x\n", ip_addr); + + printf("Ip address is : %d.%d.%d.%d:%d\n", (ip_addr & 0xff000000) >> 0n24, (ip_addr & 0x00ff0000) >> 0n16, (ip_addr & 0x0000ff00) >> 0n8, (ip_addr & 0x000000ff),port_num ); + + + } + + } + + +_____________________________________________________________ +!syscall script { + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + //printf("Port address is : %d \n", port_num); + + part0 = db(poi(@rsp+38) + 1c); + part1 = db(poi(@rsp+38) + 1d); + part2 = db(poi(@rsp+38) + 1e); + part3 = db(poi(@rsp+38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Ip address is : %x\n", ip_addr); + + printf("Process Id: %x, Process name: %s ====> Connects to Ip address: %d.%d.%d.%d:%d\n", $pid, $pname, (ip_addr & 0xff000000) >> 0n24, (ip_addr & 0x00ff0000) >> 0n16, (ip_addr & 0x0000ff00) >> 0n8, (ip_addr & 0x000000ff), port_num); + + } + } +} + +---------------------------------- +!syscall +---------------------------------- +script +---------------------------------- + + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + //printf("Port address is : %d \n", port_num); + + part0 = db(poi(@rsp+38) + 1c); + part1 = db(poi(@rsp+38) + 1d); + part2 = db(poi(@rsp+38) + 1e); + part3 = db(poi(@rsp+38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Ip address is : %x\n", ip_addr); + + printf("Process Id: %x, Process name: %s ====> Connects to Ip address: %d.%d.%d.%d:%d\n", $pid, $pname, (ip_addr & 0xff000000) >> 0n24, (ip_addr & 0x00ff0000) >> 0n16, (ip_addr & 0x0000ff00) >> 0n8, (ip_addr & 0x000000ff), port_num); + + } + } + +_____________________________________________________________ +!syscall pid 0x16fc script { + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x1201F) { + + pause(); + + } + } +} + + +---------------------------------- +!syscall +---------------------------------- +pid +---------------------------------- +0x16fc +---------------------------------- +script +---------------------------------- + + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x1201F) { + + pause(); + + } + } + +_____________________________________________________________ +!syscall pid 0x16fc script { + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x1201F) { + + buffer_len = dq(poi(poi(@rsp+38))); + printf("Packet buffer is: %s\n", dq(poi(poi(@rsp+38))+8)); + + for (i = 0; i< buffer_len;i++) { + printf(" %x", db(poi(poi(@rsp+38))+8)+i)); + } + + } + } +} + +---------------------------------- +!syscall +---------------------------------- +pid +---------------------------------- +0x16fc +---------------------------------- +script +---------------------------------- + + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x1201F) { + + buffer_len = dq(poi(poi(@rsp+38))); + printf("Packet buffer is: %s\n", dq(poi(poi(@rsp+38))+8)); + + for (i = 0; i< buffer_len;i++) { + printf(" %x", db(poi(poi(@rsp+38))+8)+i)); + } + + } + } + +_____________________________________________________________ +!syscall pid 0x16fc script { + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x1201F) { + + buffer_len = dq(poi(poi(@rsp+38))); + + + printf("\n\n=============={}{}{}{P}{{{{{{\}}}}=============================================================\n"); + printf("Packet buffer is: %s\n", dq(poi(poi(@rsp+38))+8)); + + for (i = 0; i < buffer_len;i++) { + printf(" %x", db(poi(poi(poi(@rsp+38))+8)+i)); + } + + } + } +} + +---------------------------------- +!syscall +---------------------------------- +pid +---------------------------------- +0x16fc +---------------------------------- +script +---------------------------------- + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x1201F) { + + buffer_len = dq(poi(poi(@rsp+38))); + + + printf("\n\n=============={}{}{}{P}{{{{{{\}}}}=============================================================\n"); + printf("Packet buffer is: %s\n", dq(poi(poi(@rsp+38))+8)); + + for (i = 0; i < buffer_len;i++) { + printf(" %x", db(poi(poi(poi(@rsp+38))+8)+i)); + } + + } + } + +_____________________________________________________________ +!syscall script { + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x1201F) { + + buffer_len = dq(poi(poi(@rsp+38))); + + + printf("\n\n===========================================================================\n"); + printf("Packet buffer is: %s\n", dq(poi(poi(@rsp+38))+8)); + + for (i = 0; i < buffer_len;i++) { + printf(" %x", db(poi(poi(poi(@rsp+38))+8)+i)); + } + + } + } +} + +---------------------------------- +!syscall +---------------------------------- +script +---------------------------------- + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x1201F) { + + buffer_len = dq(poi(poi(@rsp+38))); + + + printf("\n\n===========================================================================\n"); + printf("Packet buffer is: %s\n", dq(poi(poi(@rsp+38))+8)); + + for (i = 0; i < buffer_len;i++) { + printf(" %x", db(poi(poi(poi(@rsp+38))+8)+i)); + } + + } + } + +_____________________________________________________________ +syscall pid @arg1 script { + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + //printf("Port address is : %d \n", port_num); + + part0 = db(poi(@rsp+38) + 1c); + part1 = db(poi(@rsp+38) + 1d); + part2 = db(poi(@rsp+38) + 1e); + part3 = db(poi(@rsp+38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Ip address is : %x\n", ip_addr); + + printf("Process Id: %x, Process name: %s ====> Connects to Ip address: %d.%d.%d.%d:%d\n", $pid, $pname, (ip_addr & 0xff000000) >> 0n24, (ip_addr & 0x00ff0000) >> 0n16, (ip_addr & 0x0000ff00) >> 0n8, (ip_addr & 0x000000ff), port_num); + + } + } +} + +---------------------------------- +syscall +---------------------------------- +pid +---------------------------------- +@arg1 +---------------------------------- +script +---------------------------------- + + + if (@rax == 0x7) { + + if (dd(@rsp + 30) == 0x12007) { + + port_num_value_high = db(poi(rsp+38)+1a); + port_num_value_low = db(poi(rsp+38)+1b); + + port_num = 0; + port_num = port_num_value_high << 0n8 | port_num_value_low; + + //printf("Port address is : %d \n", port_num); + + part0 = db(poi(@rsp+38) + 1c); + part1 = db(poi(@rsp+38) + 1d); + part2 = db(poi(@rsp+38) + 1e); + part3 = db(poi(@rsp+38) + 1f); + + part0 = part0 << 0n24; + part1 = part1 << 0n16; + part2 = part2 << 0n8; + part3 = part3 << 0n0; + + ip_addr = part0 | part1 | part2 | part3; + + // printf("Ip address is : %x\n", ip_addr); + + printf("Process Id: %x, Process name: %s ====> Connects to Ip address: %d.%d.%d.%d:%d\n", $pid, $pname, (ip_addr & 0xff000000) >> 0n24, (ip_addr & 0x00ff0000) >> 0n16, (ip_addr & 0x0000ff00) >> 0n8, (ip_addr & 0x000000ff), port_num); + + } + } + +_____________________________________________________________ +!msrread c0000082 script { + + // + // Fill the EDX:EAX + // + @rdx = f0f0f0f0; + @rax = 10203040; + + event_sc(1); + + printf("%llx is read!\n", @rcx); + +} + + +---------------------------------- +!msrread +---------------------------------- +c0000082 +---------------------------------- +script +---------------------------------- + + + // + // Fill the EDX:EAX + // + @rdx = f0f0f0f0; + @rax = 10203040; + + event_sc(1); + + printf("%llx is read!\n", @rcx); + + +_____________________________________________________________ +!epthook nt!DbgBreakPointWithStatus script { + + @rip = poi(@rsp); // pop the return address from stack + @rsp = @rsp + 8; // adjust the stack {{{}}}{}{}{}{} + + printf("nt!DbgBreakPointWithStatus is ignored.\n"); + +} + + +---------------------------------- +!epthook +---------------------------------- +nt!DbgBreakPointWithStatus +---------------------------------- +script +---------------------------------- + + + @rip = poi(@rsp); // pop the return address from stack + @rsp = @rsp + 8; // adjust the stack {{{}}}{}{}{}{} + + printf("nt!DbgBreakPointWithStatus is ignored.\n"); + + +_____________________________________________________________ +!monitor rw ffffc105`a506b0a8 ffffc105`a506b0a8+7 script { + if (@rip != nt!SwapContext+0x25b && @rip != nt!KiStackAttachProcess+0x1b5 && @rip != nt!KiDetachProcess+0x184) { + pause(); + } +} + +---------------------------------- +!monitor +---------------------------------- +rw +---------------------------------- +ffffc105`a506b0a8 +---------------------------------- +ffffc105`a506b0a8+7 +---------------------------------- +script +---------------------------------- + + if (@rip != nt!SwapContext+0x25b && @rip != nt!KiStackAttachProcess+0x1b5 && @rip != nt!KiDetachProcess+0x184) { + pause(); + } + +_____________________________________________________________ +!epthook kdnet!KdSendPacket script { + + + printf("\n------------------------------------------------------------------------\n"); + printf("PacketType: %llx, FirstBuffer: %llx, SecondBuffer: %llx, KdContext: %llx\n", @rcx, @rdx, @r8, @r9); + + byte_len = 100; + + for (i = 0; i <= byte_len;i++) { + + if (dq(@rdx + i) == ffffc105a50f0080) { + pause(); + } + } + + for (i = 0; i <= byte_len;i++) { + + if (dq(@r8 + i) == ffffc105a50f0080) { + pause(); + } + } +} + +---------------------------------- +!epthook +---------------------------------- +kdnet!KdSendPacket +---------------------------------- +script +---------------------------------- + + + + printf("\n------------------------------------------------------------------------\n"); + printf("PacketType: %llx, FirstBuffer: %llx, SecondBuffer: %llx, KdContext: %llx\n", @rcx, @rdx, @r8, @r9); + + byte_len = 100; + + for (i = 0; i <= byte_len;i++) { + + if (dq(@rdx + i) == ffffc105a50f0080) { + pause(); + } + } + + for (i = 0; i <= byte_len;i++) { + + if (dq(@r8 + i) == ffffc105a50f0080) { + pause(); + } + } + +_____________________________________________________________ +!epthook nt!MmDbgCopyMemory script { + if (db(@rcx) == 0x4f && db(@rcx + 1) == 0x00 && db(@rcx + 2) == 0x6E ) { + printf("nt!MmDbgCopyMemory is called form RIP: %llx, Address: %llx, And the string is : %ws\n", @rip, @rcx, @rcx); + } +} + +!epthook nt!MiDbgCopyMemory script { + if (db(@rcx) == 0x4f && db(@rcx + 1) == 0x00 && db(@rcx + 2) == 0x6E ) { + printf("nt!MmDbgCopyMemory is called form RIP: %llx, Address: %llx, And the string is : %ws\n", @rip, @rcx, @rcx); + } +} +!epthook nt!MiCopyFromUntrustedMemory script { + if (db(@rcx) == 0x4f && db(@rcx + 1) == 0x00 && db(@rcx + 2) == 0x6E ) { + printf("nt!MmDbgCopyMemory is called form RIP: %llx, Address: %llx, And the string is : %ws\n", @rip, @rcx, @rcx); + } +} + +---------------------------------- +!epthook +---------------------------------- +nt!MmDbgCopyMemory +---------------------------------- +script +---------------------------------- + + if (db(@rcx) == 0x4f && db(@rcx + 1) == 0x00 && db(@rcx + 2) == 0x6E ) { + printf("nt!MmDbgCopyMemory is called form RIP: %llx, Address: %llx, And the string is : %ws\n", @rip, @rcx, @rcx); + } + +---------------------------------- +!epthook +---------------------------------- +nt!MiDbgCopyMemory +---------------------------------- +script +---------------------------------- + + if (db(@rcx) == 0x4f && db(@rcx + 1) == 0x00 && db(@rcx + 2) == 0x6E ) { + printf("nt!MmDbgCopyMemory is called form RIP: %llx, Address: %llx, And the string is : %ws\n", @rip, @rcx, @rcx); + } + +---------------------------------- +!epthook +---------------------------------- +nt!MiCopyFromUntrustedMemory +---------------------------------- +script +---------------------------------- + + if (db(@rcx) == 0x4f && db(@rcx + 1) == 0x00 && db(@rcx + 2) == 0x6E ) { + printf("nt!MmDbgCopyMemory is called form RIP: %llx, Address: %llx, And the string is : %ws\n", @rip, @rcx, @rcx); + } + +_____________________________________________________________ +cmdBacktick "backtick preserve" {inside ticks} +---------------------------------- +cmdBacktick +---------------------------------- +backtick preserve +---------------------------------- +inside ticks +_____________________________________________________________ +!monitor rw $proc $proc+0xb80 script { + printf("{ \"rip\": 0x%llx, \"context\": 0x%llx, \"buffer1\": \"%llx\", \"buffer2\": \"%llx\", \"inst_len\": 0x%x }\n", @rip, $context, dq(@rip), dq(@rip+8), disassemble_len(@rip)); +} +---------------------------------- +!monitor +---------------------------------- +rw +---------------------------------- +$proc +---------------------------------- +$proc+0xb80 +---------------------------------- +script +---------------------------------- + + printf("{ \"rip\": 0x%llx, \"context\": 0x%llx, \"buffer1\": \"%llx\", \"buffer2\": \"%llx\", \"inst_len\": 0x%x }\n", @rip, $context, dq(@rip), dq(@rip+8), disassemble_len(@rip)); + +_____________________________________________________________ + +.sympath "SRV*c:\Symbols*https://msdl.microsoft.com/download/symbols" +---------------------------------- +.sympath +---------------------------------- +SRV*c:\Symbols*https://msdl.microsoft.com/download/symbols +_____________________________________________________________ +.pe header c:\reverse\myfile.exe +---------------------------------- +.pe +---------------------------------- +header +---------------------------------- +c:\reverse\myfile.exe +_____________________________________________________________ +.pe section .text c:\reverse\myfile.exe +---------------------------------- +.pe +---------------------------------- +section +---------------------------------- +.text +---------------------------------- +c:\reverse\myfile.exe +_____________________________________________________________ +.pe section .rdata "c:\reverse files\myfile.exe" +---------------------------------- +.pe +---------------------------------- +section +---------------------------------- +.rdata +---------------------------------- +c:\reverse files\myfile.exe +_____________________________________________________________ +.pe section .text +---------------------------------- +.pe +---------------------------------- +section +---------------------------------- +.text +_____________________________________________________________ +.pe header c:\reverse\myfile.exe extra +---------------------------------- +.pe +---------------------------------- +header +---------------------------------- +c:\reverse\myfile.exe +---------------------------------- +extra +_____________________________________________________________ +.pe section .text c:\reverse\myfile.exe extra +---------------------------------- +.pe +---------------------------------- +section +---------------------------------- +.text +---------------------------------- +c:\reverse\myfile.exe +---------------------------------- +extra +_____________________________________________________________ +.sym reload +---------------------------------- +.sym +---------------------------------- +reload +_____________________________________________________________ +.sym reload pid 3a24 +---------------------------------- +.sym +---------------------------------- +reload +---------------------------------- +pid +---------------------------------- +3a24 +_____________________________________________________________ +.sym load +---------------------------------- +.sym +---------------------------------- +load +_____________________________________________________________ +.sym download +---------------------------------- +.sym +---------------------------------- +download +_____________________________________________________________ +.sym add base fffff8077356000 path c:\symbols\foo.pdb +---------------------------------- +.sym +---------------------------------- +add +---------------------------------- +base +---------------------------------- +fffff8077356000 +---------------------------------- +path +---------------------------------- +c:\symbols\foo.pdb +_____________________________________________________________ diff --git a/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statement_global_var.hds b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statement_global_var.hds new file mode 100644 index 00000000..83be2923 --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statement_global_var.hds @@ -0,0 +1,11 @@ +{ + .test_var = @hw_port0 + @hw_port1; + + if (.test_var == 4) { + @hw_pin10 = 0x1; + } elsif (.test_var == 0) { + @hw_pin11 = 0x1; + } else { + @hw_pin12 = 0x1; + } +} \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statements_pins.hds b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statements_pins.hds new file mode 100644 index 00000000..26c457fa --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statements_pins.hds @@ -0,0 +1,12 @@ +{ + if (@hw_pin0 == 1) { + @hw_pin2 = 0; + @hw_pin3 = 0; + } elsif (@hw_pin1 == 1) { + @hw_pin4 = 0; + @hw_pin5 = 0; + } else { + @hw_pin6 = 0; + @hw_pin7 = 0; + } +} \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statements_ports.hds b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statements_ports.hds new file mode 100644 index 00000000..235e6a78 --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statements_ports.hds @@ -0,0 +1,12 @@ +{ + if (@hw_port0 == 1) { + @hw_pin2 = 0; + @hw_pin3 = 0; + } elsif (@hw_port1 == 1) { + @hw_pin4 = 0; + @hw_pin5 = 0; + } else { + @hw_pin6 = 0; + @hw_pin7 = 0; + } +} \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statements_ports_with_port_assignments.hds b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statements_ports_with_port_assignments.hds new file mode 100644 index 00000000..4ef2f131 --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_conditional_statements_ports_with_port_assignments.hds @@ -0,0 +1,12 @@ +{ + if (@hw_pin0 == 1) { + @hw_port0 = 0x55; + @hw_port1 = 0x85; + } elsif (@hw_pin1 == 1) { + @hw_port0 = 0x99; + @hw_port1 = 0x12; + } else { + @hw_pin6 = 0; + @hw_pin7 = 0; + } +} \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/codes/script_simple_pin_assignments.hds b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_simple_pin_assignments.hds new file mode 100644 index 00000000..2dc83b3d --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_simple_pin_assignments.hds @@ -0,0 +1,10 @@ +{ + @hw_pin0 = 0x1; + @hw_pin1 = 0x0; + @hw_pin2 = 0x1; + @hw_pin3 = 0x0; + @hw_pin4 = 0x1; + @hw_pin5 = 0x0; + @hw_pin6 = 0x1; + @hw_pin7 = 0x0; +} \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/codes/script_simple_port_assignments.hds b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_simple_port_assignments.hds new file mode 100644 index 00000000..d134e1d0 --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/codes/script_simple_port_assignments.hds @@ -0,0 +1,13 @@ +{ + + // + // Assignment to @hw_port0 + // + .test_var = @hw_port0 + 1; + @hw_port0 = .test_var; + + // + // Assignment to @hw_port1 + // + @hw_port1 = @hw_port1 - 2; +} \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statement_global_var.hds.hex.txt b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statement_global_var.hds.hex.txt new file mode 100644 index 00000000..a9b18bac --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statement_global_var.hds.hex.txt @@ -0,0 +1,270 @@ +; The raw script file is available at: ..\..\..\tests\hwdbg-tests\scripts\compiled-scripts\script_conditional_statement_global_var.hds +; +; !hw script { +; .test_var = @hw_port0 + @hw_port1; +; +; if (.test_var == 4) { +; @hw_pin10 = 0x1; +; } elsif (.test_var == 0) { +; @hw_pin11 = 0x1; +; } else { +; @hw_pin12 = 0x1; +; } +; } +; +0000002f ; +0x0 | Checksum +00000000 ; +0x4 | Checksum +52444247 ; +0x8 | Indicator +48595045 ; +0xc | Indicator +00000004 ; +0x10 | TypeOfThePacket - DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL (0x4) +00000002 ; +0x14 | RequestedActionOfThePacket - Value (0x2) +0000002f ; +0x18 | Start of Optional Data +00000006 ; +0x1c +0000000a ; +0x20 +00000003 ; +0x24 +00000001 ; +0x28 +0000000f ; +0x2c +00000000 ; +0x30 +0000000f ; +0x34 +00000000 ; +0x38 +00000006 ; +0x3c +0000000a ; +0x40 +00000004 ; +0x44 +00000021 ; +0x48 +00000004 ; +0x4c +00000020 ; +0x50 +00000007 ; +0x54 +00000000 ; +0x58 +00000006 ; +0x5c +00000018 ; +0x60 +00000007 ; +0x64 +00000000 ; +0x68 +00000000 ; +0x6c +00000000 ; +0x70 +00000001 ; +0x74 +00000000 ; +0x78 +00000006 ; +0x7c +00000013 ; +0x80 +00000003 ; +0x84 +00000004 ; +0x88 +00000001 ; +0x8c +00000000 ; +0x90 +00000007 ; +0x94 +00000000 ; +0x98 +00000006 ; +0x9c +00000016 ; +0xa0 +00000003 ; +0xa4 +00000017 ; +0xa8 +00000007 ; +0xac +00000000 ; +0xb0 +00000000 ; +0xb4 +00000000 ; +0xb8 +00000006 ; +0xbc +00000018 ; +0xc0 +00000003 ; +0xc4 +00000001 ; +0xc8 +00000000 ; +0xcc +00000000 ; +0xd0 +00000004 ; +0xd4 +0000000a ; +0xd8 +00000006 ; +0xdc +00000015 ; +0xe0 +00000003 ; +0xe4 +00000026 ; +0xe8 +00000000 ; +0xec +00000000 ; +0xf0 +00000000 ; +0xf4 +00000000 ; +0xf8 +00000006 ; +0xfc +00000013 ; +0x100 +00000003 ; +0x104 +00000000 ; +0x108 +00000001 ; +0x10c +00000000 ; +0x110 +00000007 ; +0x114 +00000000 ; +0x118 +00000006 ; +0x11c +00000016 ; +0x120 +00000003 ; +0x124 +00000023 ; +0x128 +00000007 ; +0x12c +00000000 ; +0x130 +00000000 ; +0x134 +00000000 ; +0x138 +00000006 ; +0x13c +00000018 ; +0x140 +00000003 ; +0x144 +00000001 ; +0x148 +00000000 ; +0x14c +00000000 ; +0x150 +00000004 ; +0x154 +0000000b ; +0x158 +00000006 ; +0x15c +00000015 ; +0x160 +00000003 ; +0x164 +00000026 ; +0x168 +00000000 ; +0x16c +00000000 ; +0x170 +00000000 ; +0x174 +00000000 ; +0x178 +00000006 ; +0x17c +00000018 ; +0x180 +00000003 ; +0x184 +00000001 ; +0x188 +00000000 ; +0x18c +00000000 ; +0x190 +00000004 ; +0x194 +0000000c ; +0x198 +00000000 ; +0x19c +00000000 ; +0x1a0 +00000000 ; +0x1a4 +00000000 ; +0x1a8 +00000000 ; +0x1ac +00000000 ; +0x1b0 +00000000 ; +0x1b4 +00000000 ; +0x1b8 +00000000 ; +0x1bc +00000000 ; +0x1c0 +00000000 ; +0x1c4 +00000000 ; +0x1c8 +00000000 ; +0x1cc +00000000 ; +0x1d0 +00000000 ; +0x1d4 +00000000 ; +0x1d8 +00000000 ; +0x1dc +00000000 ; +0x1e0 +00000000 ; +0x1e4 +00000000 ; +0x1e8 +00000000 ; +0x1ec +00000000 ; +0x1f0 +00000000 ; +0x1f4 +00000000 ; +0x1f8 +00000000 ; +0x1fc +00000000 ; +0x200 +00000000 ; +0x204 +00000000 ; +0x208 +00000000 ; +0x20c +00000000 ; +0x210 +00000000 ; +0x214 +00000000 ; +0x218 +00000000 ; +0x21c +00000000 ; +0x220 +00000000 ; +0x224 +00000000 ; +0x228 +00000000 ; +0x22c +00000000 ; +0x230 +00000000 ; +0x234 +00000000 ; +0x238 +00000000 ; +0x23c +00000000 ; +0x240 +00000000 ; +0x244 +00000000 ; +0x248 +00000000 ; +0x24c +00000000 ; +0x250 +00000000 ; +0x254 +00000000 ; +0x258 +00000000 ; +0x25c +00000000 ; +0x260 +00000000 ; +0x264 +00000000 ; +0x268 +00000000 ; +0x26c +00000000 ; +0x270 +00000000 ; +0x274 +00000000 ; +0x278 +00000000 ; +0x27c +00000000 ; +0x280 +00000000 ; +0x284 +00000000 ; +0x288 +00000000 ; +0x28c +00000000 ; +0x290 +00000000 ; +0x294 +00000000 ; +0x298 +00000000 ; +0x29c +00000000 ; +0x2a0 +00000000 ; +0x2a4 +00000000 ; +0x2a8 +00000000 ; +0x2ac +00000000 ; +0x2b0 +00000000 ; +0x2b4 +00000000 ; +0x2b8 +00000000 ; +0x2bc +00000000 ; +0x2c0 +00000000 ; +0x2c4 +00000000 ; +0x2c8 +00000000 ; +0x2cc +00000000 ; +0x2d0 +00000000 ; +0x2d4 +00000000 ; +0x2d8 +00000000 ; +0x2dc +00000000 ; +0x2e0 +00000000 ; +0x2e4 +00000000 ; +0x2e8 +00000000 ; +0x2ec +00000000 ; +0x2f0 +00000000 ; +0x2f4 +00000000 ; +0x2f8 +00000000 ; +0x2fc +00000000 ; +0x300 +00000000 ; +0x304 +00000000 ; +0x308 +00000000 ; +0x30c +00000000 ; +0x310 +00000000 ; +0x314 +00000000 ; +0x318 +00000000 ; +0x31c +00000000 ; +0x320 +00000000 ; +0x324 +00000000 ; +0x328 +00000000 ; +0x32c +00000000 ; +0x330 +00000000 ; +0x334 +00000000 ; +0x338 +00000000 ; +0x33c +00000000 ; +0x340 +00000000 ; +0x344 +00000000 ; +0x348 +00000000 ; +0x34c +00000000 ; +0x350 +00000000 ; +0x354 +00000000 ; +0x358 +00000000 ; +0x35c +00000000 ; +0x360 +00000000 ; +0x364 +00000000 ; +0x368 +00000000 ; +0x36c +00000000 ; +0x370 +00000000 ; +0x374 +00000000 ; +0x378 +00000000 ; +0x37c +00000000 ; +0x380 +00000000 ; +0x384 +00000000 ; +0x388 +00000000 ; +0x38c +00000000 ; +0x390 +00000000 ; +0x394 +00000000 ; +0x398 +00000000 ; +0x39c +00000000 ; +0x3a0 +00000000 ; +0x3a4 +00000000 ; +0x3a8 +00000000 ; +0x3ac +00000000 ; +0x3b0 +00000000 ; +0x3b4 +00000000 ; +0x3b8 +00000000 ; +0x3bc +00000000 ; +0x3c0 +00000000 ; +0x3c4 +00000000 ; +0x3c8 +00000000 ; +0x3cc +00000000 ; +0x3d0 +00000000 ; +0x3d4 +00000000 ; +0x3d8 +00000000 ; +0x3dc +00000000 ; +0x3e0 +00000000 ; +0x3e4 +00000000 ; +0x3e8 +00000000 ; +0x3ec +00000000 ; +0x3f0 +00000000 ; +0x3f4 +00000000 ; +0x3f8 +00000000 ; +0x3fc \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statements_pins.hds.hex.txt b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statements_pins.hds.hex.txt new file mode 100644 index 00000000..34c8c562 --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statements_pins.hds.hex.txt @@ -0,0 +1,271 @@ +; The raw script file is available at: ..\..\..\tests\hwdbg-tests\scripts\compiled-scripts\script_conditional_statements_pins.hds +; +; !hw script { +; if (@hw_pin0 == 1) { +; @hw_pin2 = 0; +; @hw_pin3 = 0; +; } elsif (@hw_pin1 == 1) { +; @hw_pin4 = 0; +; @hw_pin5 = 0; +; } else { +; @hw_pin6 = 0; +; @hw_pin7 = 0; +; } +; } +; +00000017 ; +0x0 | Checksum +00000000 ; +0x4 | Checksum +52444247 ; +0x8 | Indicator +48595045 ; +0xc | Indicator +00000004 ; +0x10 | TypeOfThePacket - DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL (0x4) +00000002 ; +0x14 | RequestedActionOfThePacket - Value (0x2) +00000033 ; +0x18 | Start of Optional Data +00000006 ; +0x1c +0000000a ; +0x20 +00000003 ; +0x24 +00000001 ; +0x28 +0000000f ; +0x2c +00000000 ; +0x30 +0000000f ; +0x34 +00000000 ; +0x38 +00000006 ; +0x3c +00000013 ; +0x40 +00000003 ; +0x44 +00000001 ; +0x48 +00000004 ; +0x4c +00000000 ; +0x50 +00000007 ; +0x54 +00000000 ; +0x58 +00000006 ; +0x5c +00000016 ; +0x60 +00000003 ; +0x64 +00000013 ; +0x68 +00000007 ; +0x6c +00000000 ; +0x70 +00000000 ; +0x74 +00000000 ; +0x78 +00000006 ; +0x7c +00000018 ; +0x80 +00000003 ; +0x84 +00000000 ; +0x88 +00000000 ; +0x8c +00000000 ; +0x90 +00000004 ; +0x94 +00000002 ; +0x98 +00000006 ; +0x9c +00000018 ; +0xa0 +00000003 ; +0xa4 +00000000 ; +0xa8 +00000000 ; +0xac +00000000 ; +0xb0 +00000004 ; +0xb4 +00000003 ; +0xb8 +00000006 ; +0xbc +00000015 ; +0xc0 +00000003 ; +0xc4 +00000028 ; +0xc8 +00000000 ; +0xcc +00000000 ; +0xd0 +00000000 ; +0xd4 +00000000 ; +0xd8 +00000006 ; +0xdc +00000013 ; +0xe0 +00000003 ; +0xe4 +00000001 ; +0xe8 +00000004 ; +0xec +00000001 ; +0xf0 +00000007 ; +0xf4 +00000000 ; +0xf8 +00000006 ; +0xfc +00000016 ; +0x100 +00000003 ; +0x104 +00000022 ; +0x108 +00000007 ; +0x10c +00000000 ; +0x110 +00000000 ; +0x114 +00000000 ; +0x118 +00000006 ; +0x11c +00000018 ; +0x120 +00000003 ; +0x124 +00000000 ; +0x128 +00000000 ; +0x12c +00000000 ; +0x130 +00000004 ; +0x134 +00000004 ; +0x138 +00000006 ; +0x13c +00000018 ; +0x140 +00000003 ; +0x144 +00000000 ; +0x148 +00000000 ; +0x14c +00000000 ; +0x150 +00000004 ; +0x154 +00000005 ; +0x158 +00000006 ; +0x15c +00000015 ; +0x160 +00000003 ; +0x164 +00000028 ; +0x168 +00000000 ; +0x16c +00000000 ; +0x170 +00000000 ; +0x174 +00000000 ; +0x178 +00000006 ; +0x17c +00000018 ; +0x180 +00000003 ; +0x184 +00000000 ; +0x188 +00000000 ; +0x18c +00000000 ; +0x190 +00000004 ; +0x194 +00000006 ; +0x198 +00000006 ; +0x19c +00000018 ; +0x1a0 +00000003 ; +0x1a4 +00000000 ; +0x1a8 +00000000 ; +0x1ac +00000000 ; +0x1b0 +00000004 ; +0x1b4 +00000007 ; +0x1b8 +00000000 ; +0x1bc +00000000 ; +0x1c0 +00000000 ; +0x1c4 +00000000 ; +0x1c8 +00000000 ; +0x1cc +00000000 ; +0x1d0 +00000000 ; +0x1d4 +00000000 ; +0x1d8 +00000000 ; +0x1dc +00000000 ; +0x1e0 +00000000 ; +0x1e4 +00000000 ; +0x1e8 +00000000 ; +0x1ec +00000000 ; +0x1f0 +00000000 ; +0x1f4 +00000000 ; +0x1f8 +00000000 ; +0x1fc +00000000 ; +0x200 +00000000 ; +0x204 +00000000 ; +0x208 +00000000 ; +0x20c +00000000 ; +0x210 +00000000 ; +0x214 +00000000 ; +0x218 +00000000 ; +0x21c +00000000 ; +0x220 +00000000 ; +0x224 +00000000 ; +0x228 +00000000 ; +0x22c +00000000 ; +0x230 +00000000 ; +0x234 +00000000 ; +0x238 +00000000 ; +0x23c +00000000 ; +0x240 +00000000 ; +0x244 +00000000 ; +0x248 +00000000 ; +0x24c +00000000 ; +0x250 +00000000 ; +0x254 +00000000 ; +0x258 +00000000 ; +0x25c +00000000 ; +0x260 +00000000 ; +0x264 +00000000 ; +0x268 +00000000 ; +0x26c +00000000 ; +0x270 +00000000 ; +0x274 +00000000 ; +0x278 +00000000 ; +0x27c +00000000 ; +0x280 +00000000 ; +0x284 +00000000 ; +0x288 +00000000 ; +0x28c +00000000 ; +0x290 +00000000 ; +0x294 +00000000 ; +0x298 +00000000 ; +0x29c +00000000 ; +0x2a0 +00000000 ; +0x2a4 +00000000 ; +0x2a8 +00000000 ; +0x2ac +00000000 ; +0x2b0 +00000000 ; +0x2b4 +00000000 ; +0x2b8 +00000000 ; +0x2bc +00000000 ; +0x2c0 +00000000 ; +0x2c4 +00000000 ; +0x2c8 +00000000 ; +0x2cc +00000000 ; +0x2d0 +00000000 ; +0x2d4 +00000000 ; +0x2d8 +00000000 ; +0x2dc +00000000 ; +0x2e0 +00000000 ; +0x2e4 +00000000 ; +0x2e8 +00000000 ; +0x2ec +00000000 ; +0x2f0 +00000000 ; +0x2f4 +00000000 ; +0x2f8 +00000000 ; +0x2fc +00000000 ; +0x300 +00000000 ; +0x304 +00000000 ; +0x308 +00000000 ; +0x30c +00000000 ; +0x310 +00000000 ; +0x314 +00000000 ; +0x318 +00000000 ; +0x31c +00000000 ; +0x320 +00000000 ; +0x324 +00000000 ; +0x328 +00000000 ; +0x32c +00000000 ; +0x330 +00000000 ; +0x334 +00000000 ; +0x338 +00000000 ; +0x33c +00000000 ; +0x340 +00000000 ; +0x344 +00000000 ; +0x348 +00000000 ; +0x34c +00000000 ; +0x350 +00000000 ; +0x354 +00000000 ; +0x358 +00000000 ; +0x35c +00000000 ; +0x360 +00000000 ; +0x364 +00000000 ; +0x368 +00000000 ; +0x36c +00000000 ; +0x370 +00000000 ; +0x374 +00000000 ; +0x378 +00000000 ; +0x37c +00000000 ; +0x380 +00000000 ; +0x384 +00000000 ; +0x388 +00000000 ; +0x38c +00000000 ; +0x390 +00000000 ; +0x394 +00000000 ; +0x398 +00000000 ; +0x39c +00000000 ; +0x3a0 +00000000 ; +0x3a4 +00000000 ; +0x3a8 +00000000 ; +0x3ac +00000000 ; +0x3b0 +00000000 ; +0x3b4 +00000000 ; +0x3b8 +00000000 ; +0x3bc +00000000 ; +0x3c0 +00000000 ; +0x3c4 +00000000 ; +0x3c8 +00000000 ; +0x3cc +00000000 ; +0x3d0 +00000000 ; +0x3d4 +00000000 ; +0x3d8 +00000000 ; +0x3dc +00000000 ; +0x3e0 +00000000 ; +0x3e4 +00000000 ; +0x3e8 +00000000 ; +0x3ec +00000000 ; +0x3f0 +00000000 ; +0x3f4 +00000000 ; +0x3f8 +00000000 ; +0x3fc \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statements_ports.hds.hex.txt b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statements_ports.hds.hex.txt new file mode 100644 index 00000000..e019421c --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statements_ports.hds.hex.txt @@ -0,0 +1,271 @@ +; The raw script file is available at: ..\..\..\tests\hwdbg-tests\scripts\compiled-scripts\script_conditional_statements_ports.hds +; +; !hw script { +; if (@hw_port0 == 1) { +; @hw_pin2 = 0; +; @hw_pin3 = 0; +; } elsif (@hw_port1 == 1) { +; @hw_pin4 = 0; +; @hw_pin5 = 0; +; } else { +; @hw_pin6 = 0; +; @hw_pin7 = 0; +; } +; } +; +00000057 ; +0x0 | Checksum +00000000 ; +0x4 | Checksum +52444247 ; +0x8 | Indicator +48595045 ; +0xc | Indicator +00000004 ; +0x10 | TypeOfThePacket - DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL (0x4) +00000002 ; +0x14 | RequestedActionOfThePacket - Value (0x2) +00000033 ; +0x18 | Start of Optional Data +00000006 ; +0x1c +0000000a ; +0x20 +00000003 ; +0x24 +00000001 ; +0x28 +0000000f ; +0x2c +00000000 ; +0x30 +0000000f ; +0x34 +00000000 ; +0x38 +00000006 ; +0x3c +00000013 ; +0x40 +00000003 ; +0x44 +00000001 ; +0x48 +00000004 ; +0x4c +00000020 ; +0x50 +00000007 ; +0x54 +00000000 ; +0x58 +00000006 ; +0x5c +00000016 ; +0x60 +00000003 ; +0x64 +00000013 ; +0x68 +00000007 ; +0x6c +00000000 ; +0x70 +00000000 ; +0x74 +00000000 ; +0x78 +00000006 ; +0x7c +00000018 ; +0x80 +00000003 ; +0x84 +00000000 ; +0x88 +00000000 ; +0x8c +00000000 ; +0x90 +00000004 ; +0x94 +00000002 ; +0x98 +00000006 ; +0x9c +00000018 ; +0xa0 +00000003 ; +0xa4 +00000000 ; +0xa8 +00000000 ; +0xac +00000000 ; +0xb0 +00000004 ; +0xb4 +00000003 ; +0xb8 +00000006 ; +0xbc +00000015 ; +0xc0 +00000003 ; +0xc4 +00000028 ; +0xc8 +00000000 ; +0xcc +00000000 ; +0xd0 +00000000 ; +0xd4 +00000000 ; +0xd8 +00000006 ; +0xdc +00000013 ; +0xe0 +00000003 ; +0xe4 +00000001 ; +0xe8 +00000004 ; +0xec +00000021 ; +0xf0 +00000007 ; +0xf4 +00000000 ; +0xf8 +00000006 ; +0xfc +00000016 ; +0x100 +00000003 ; +0x104 +00000022 ; +0x108 +00000007 ; +0x10c +00000000 ; +0x110 +00000000 ; +0x114 +00000000 ; +0x118 +00000006 ; +0x11c +00000018 ; +0x120 +00000003 ; +0x124 +00000000 ; +0x128 +00000000 ; +0x12c +00000000 ; +0x130 +00000004 ; +0x134 +00000004 ; +0x138 +00000006 ; +0x13c +00000018 ; +0x140 +00000003 ; +0x144 +00000000 ; +0x148 +00000000 ; +0x14c +00000000 ; +0x150 +00000004 ; +0x154 +00000005 ; +0x158 +00000006 ; +0x15c +00000015 ; +0x160 +00000003 ; +0x164 +00000028 ; +0x168 +00000000 ; +0x16c +00000000 ; +0x170 +00000000 ; +0x174 +00000000 ; +0x178 +00000006 ; +0x17c +00000018 ; +0x180 +00000003 ; +0x184 +00000000 ; +0x188 +00000000 ; +0x18c +00000000 ; +0x190 +00000004 ; +0x194 +00000006 ; +0x198 +00000006 ; +0x19c +00000018 ; +0x1a0 +00000003 ; +0x1a4 +00000000 ; +0x1a8 +00000000 ; +0x1ac +00000000 ; +0x1b0 +00000004 ; +0x1b4 +00000007 ; +0x1b8 +00000000 ; +0x1bc +00000000 ; +0x1c0 +00000000 ; +0x1c4 +00000000 ; +0x1c8 +00000000 ; +0x1cc +00000000 ; +0x1d0 +00000000 ; +0x1d4 +00000000 ; +0x1d8 +00000000 ; +0x1dc +00000000 ; +0x1e0 +00000000 ; +0x1e4 +00000000 ; +0x1e8 +00000000 ; +0x1ec +00000000 ; +0x1f0 +00000000 ; +0x1f4 +00000000 ; +0x1f8 +00000000 ; +0x1fc +00000000 ; +0x200 +00000000 ; +0x204 +00000000 ; +0x208 +00000000 ; +0x20c +00000000 ; +0x210 +00000000 ; +0x214 +00000000 ; +0x218 +00000000 ; +0x21c +00000000 ; +0x220 +00000000 ; +0x224 +00000000 ; +0x228 +00000000 ; +0x22c +00000000 ; +0x230 +00000000 ; +0x234 +00000000 ; +0x238 +00000000 ; +0x23c +00000000 ; +0x240 +00000000 ; +0x244 +00000000 ; +0x248 +00000000 ; +0x24c +00000000 ; +0x250 +00000000 ; +0x254 +00000000 ; +0x258 +00000000 ; +0x25c +00000000 ; +0x260 +00000000 ; +0x264 +00000000 ; +0x268 +00000000 ; +0x26c +00000000 ; +0x270 +00000000 ; +0x274 +00000000 ; +0x278 +00000000 ; +0x27c +00000000 ; +0x280 +00000000 ; +0x284 +00000000 ; +0x288 +00000000 ; +0x28c +00000000 ; +0x290 +00000000 ; +0x294 +00000000 ; +0x298 +00000000 ; +0x29c +00000000 ; +0x2a0 +00000000 ; +0x2a4 +00000000 ; +0x2a8 +00000000 ; +0x2ac +00000000 ; +0x2b0 +00000000 ; +0x2b4 +00000000 ; +0x2b8 +00000000 ; +0x2bc +00000000 ; +0x2c0 +00000000 ; +0x2c4 +00000000 ; +0x2c8 +00000000 ; +0x2cc +00000000 ; +0x2d0 +00000000 ; +0x2d4 +00000000 ; +0x2d8 +00000000 ; +0x2dc +00000000 ; +0x2e0 +00000000 ; +0x2e4 +00000000 ; +0x2e8 +00000000 ; +0x2ec +00000000 ; +0x2f0 +00000000 ; +0x2f4 +00000000 ; +0x2f8 +00000000 ; +0x2fc +00000000 ; +0x300 +00000000 ; +0x304 +00000000 ; +0x308 +00000000 ; +0x30c +00000000 ; +0x310 +00000000 ; +0x314 +00000000 ; +0x318 +00000000 ; +0x31c +00000000 ; +0x320 +00000000 ; +0x324 +00000000 ; +0x328 +00000000 ; +0x32c +00000000 ; +0x330 +00000000 ; +0x334 +00000000 ; +0x338 +00000000 ; +0x33c +00000000 ; +0x340 +00000000 ; +0x344 +00000000 ; +0x348 +00000000 ; +0x34c +00000000 ; +0x350 +00000000 ; +0x354 +00000000 ; +0x358 +00000000 ; +0x35c +00000000 ; +0x360 +00000000 ; +0x364 +00000000 ; +0x368 +00000000 ; +0x36c +00000000 ; +0x370 +00000000 ; +0x374 +00000000 ; +0x378 +00000000 ; +0x37c +00000000 ; +0x380 +00000000 ; +0x384 +00000000 ; +0x388 +00000000 ; +0x38c +00000000 ; +0x390 +00000000 ; +0x394 +00000000 ; +0x398 +00000000 ; +0x39c +00000000 ; +0x3a0 +00000000 ; +0x3a4 +00000000 ; +0x3a8 +00000000 ; +0x3ac +00000000 ; +0x3b0 +00000000 ; +0x3b4 +00000000 ; +0x3b8 +00000000 ; +0x3bc +00000000 ; +0x3c0 +00000000 ; +0x3c4 +00000000 ; +0x3c8 +00000000 ; +0x3cc +00000000 ; +0x3d0 +00000000 ; +0x3d4 +00000000 ; +0x3d8 +00000000 ; +0x3dc +00000000 ; +0x3e0 +00000000 ; +0x3e4 +00000000 ; +0x3e8 +00000000 ; +0x3ec +00000000 ; +0x3f0 +00000000 ; +0x3f4 +00000000 ; +0x3f8 +00000000 ; +0x3fc \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statements_ports_with_port_assignments.hds.hex.txt b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statements_ports_with_port_assignments.hds.hex.txt new file mode 100644 index 00000000..c3cf6e41 --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_conditional_statements_ports_with_port_assignments.hds.hex.txt @@ -0,0 +1,271 @@ +; The raw script file is available at: ..\..\..\tests\hwdbg-tests\scripts\compiled-scripts\script_conditional_statements_ports_with_port_assignments.hds +; +; !hw script { +; if (@hw_pin0 == 1) { +; @hw_port0 = 0x55; +; @hw_port1 = 0x85; +; } elsif (@hw_pin1 == 1) { +; @hw_port0 = 0x99; +; @hw_port1 = 0x12; +; } else { +; @hw_pin6 = 0; +; @hw_pin7 = 0; +; } +; } +; +00000010 ; +0x0 | Checksum +00000000 ; +0x4 | Checksum +52444247 ; +0x8 | Indicator +48595045 ; +0xc | Indicator +00000004 ; +0x10 | TypeOfThePacket - DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL (0x4) +00000002 ; +0x14 | RequestedActionOfThePacket - Value (0x2) +00000033 ; +0x18 | Start of Optional Data +00000006 ; +0x1c +0000000a ; +0x20 +00000003 ; +0x24 +00000001 ; +0x28 +0000000f ; +0x2c +00000000 ; +0x30 +0000000f ; +0x34 +00000000 ; +0x38 +00000006 ; +0x3c +00000013 ; +0x40 +00000003 ; +0x44 +00000001 ; +0x48 +00000004 ; +0x4c +00000000 ; +0x50 +00000007 ; +0x54 +00000000 ; +0x58 +00000006 ; +0x5c +00000016 ; +0x60 +00000003 ; +0x64 +00000013 ; +0x68 +00000007 ; +0x6c +00000000 ; +0x70 +00000000 ; +0x74 +00000000 ; +0x78 +00000006 ; +0x7c +00000018 ; +0x80 +00000003 ; +0x84 +00000055 ; +0x88 +00000000 ; +0x8c +00000000 ; +0x90 +00000004 ; +0x94 +00000020 ; +0x98 +00000006 ; +0x9c +00000018 ; +0xa0 +00000003 ; +0xa4 +00000085 ; +0xa8 +00000000 ; +0xac +00000000 ; +0xb0 +00000004 ; +0xb4 +00000021 ; +0xb8 +00000006 ; +0xbc +00000015 ; +0xc0 +00000003 ; +0xc4 +00000028 ; +0xc8 +00000000 ; +0xcc +00000000 ; +0xd0 +00000000 ; +0xd4 +00000000 ; +0xd8 +00000006 ; +0xdc +00000013 ; +0xe0 +00000003 ; +0xe4 +00000001 ; +0xe8 +00000004 ; +0xec +00000001 ; +0xf0 +00000007 ; +0xf4 +00000000 ; +0xf8 +00000006 ; +0xfc +00000016 ; +0x100 +00000003 ; +0x104 +00000022 ; +0x108 +00000007 ; +0x10c +00000000 ; +0x110 +00000000 ; +0x114 +00000000 ; +0x118 +00000006 ; +0x11c +00000018 ; +0x120 +00000003 ; +0x124 +00000099 ; +0x128 +00000000 ; +0x12c +00000000 ; +0x130 +00000004 ; +0x134 +00000020 ; +0x138 +00000006 ; +0x13c +00000018 ; +0x140 +00000003 ; +0x144 +00000012 ; +0x148 +00000000 ; +0x14c +00000000 ; +0x150 +00000004 ; +0x154 +00000021 ; +0x158 +00000006 ; +0x15c +00000015 ; +0x160 +00000003 ; +0x164 +00000028 ; +0x168 +00000000 ; +0x16c +00000000 ; +0x170 +00000000 ; +0x174 +00000000 ; +0x178 +00000006 ; +0x17c +00000018 ; +0x180 +00000003 ; +0x184 +00000000 ; +0x188 +00000000 ; +0x18c +00000000 ; +0x190 +00000004 ; +0x194 +00000006 ; +0x198 +00000006 ; +0x19c +00000018 ; +0x1a0 +00000003 ; +0x1a4 +00000000 ; +0x1a8 +00000000 ; +0x1ac +00000000 ; +0x1b0 +00000004 ; +0x1b4 +00000007 ; +0x1b8 +00000000 ; +0x1bc +00000000 ; +0x1c0 +00000000 ; +0x1c4 +00000000 ; +0x1c8 +00000000 ; +0x1cc +00000000 ; +0x1d0 +00000000 ; +0x1d4 +00000000 ; +0x1d8 +00000000 ; +0x1dc +00000000 ; +0x1e0 +00000000 ; +0x1e4 +00000000 ; +0x1e8 +00000000 ; +0x1ec +00000000 ; +0x1f0 +00000000 ; +0x1f4 +00000000 ; +0x1f8 +00000000 ; +0x1fc +00000000 ; +0x200 +00000000 ; +0x204 +00000000 ; +0x208 +00000000 ; +0x20c +00000000 ; +0x210 +00000000 ; +0x214 +00000000 ; +0x218 +00000000 ; +0x21c +00000000 ; +0x220 +00000000 ; +0x224 +00000000 ; +0x228 +00000000 ; +0x22c +00000000 ; +0x230 +00000000 ; +0x234 +00000000 ; +0x238 +00000000 ; +0x23c +00000000 ; +0x240 +00000000 ; +0x244 +00000000 ; +0x248 +00000000 ; +0x24c +00000000 ; +0x250 +00000000 ; +0x254 +00000000 ; +0x258 +00000000 ; +0x25c +00000000 ; +0x260 +00000000 ; +0x264 +00000000 ; +0x268 +00000000 ; +0x26c +00000000 ; +0x270 +00000000 ; +0x274 +00000000 ; +0x278 +00000000 ; +0x27c +00000000 ; +0x280 +00000000 ; +0x284 +00000000 ; +0x288 +00000000 ; +0x28c +00000000 ; +0x290 +00000000 ; +0x294 +00000000 ; +0x298 +00000000 ; +0x29c +00000000 ; +0x2a0 +00000000 ; +0x2a4 +00000000 ; +0x2a8 +00000000 ; +0x2ac +00000000 ; +0x2b0 +00000000 ; +0x2b4 +00000000 ; +0x2b8 +00000000 ; +0x2bc +00000000 ; +0x2c0 +00000000 ; +0x2c4 +00000000 ; +0x2c8 +00000000 ; +0x2cc +00000000 ; +0x2d0 +00000000 ; +0x2d4 +00000000 ; +0x2d8 +00000000 ; +0x2dc +00000000 ; +0x2e0 +00000000 ; +0x2e4 +00000000 ; +0x2e8 +00000000 ; +0x2ec +00000000 ; +0x2f0 +00000000 ; +0x2f4 +00000000 ; +0x2f8 +00000000 ; +0x2fc +00000000 ; +0x300 +00000000 ; +0x304 +00000000 ; +0x308 +00000000 ; +0x30c +00000000 ; +0x310 +00000000 ; +0x314 +00000000 ; +0x318 +00000000 ; +0x31c +00000000 ; +0x320 +00000000 ; +0x324 +00000000 ; +0x328 +00000000 ; +0x32c +00000000 ; +0x330 +00000000 ; +0x334 +00000000 ; +0x338 +00000000 ; +0x33c +00000000 ; +0x340 +00000000 ; +0x344 +00000000 ; +0x348 +00000000 ; +0x34c +00000000 ; +0x350 +00000000 ; +0x354 +00000000 ; +0x358 +00000000 ; +0x35c +00000000 ; +0x360 +00000000 ; +0x364 +00000000 ; +0x368 +00000000 ; +0x36c +00000000 ; +0x370 +00000000 ; +0x374 +00000000 ; +0x378 +00000000 ; +0x37c +00000000 ; +0x380 +00000000 ; +0x384 +00000000 ; +0x388 +00000000 ; +0x38c +00000000 ; +0x390 +00000000 ; +0x394 +00000000 ; +0x398 +00000000 ; +0x39c +00000000 ; +0x3a0 +00000000 ; +0x3a4 +00000000 ; +0x3a8 +00000000 ; +0x3ac +00000000 ; +0x3b0 +00000000 ; +0x3b4 +00000000 ; +0x3b8 +00000000 ; +0x3bc +00000000 ; +0x3c0 +00000000 ; +0x3c4 +00000000 ; +0x3c8 +00000000 ; +0x3cc +00000000 ; +0x3d0 +00000000 ; +0x3d4 +00000000 ; +0x3d8 +00000000 ; +0x3dc +00000000 ; +0x3e0 +00000000 ; +0x3e4 +00000000 ; +0x3e8 +00000000 ; +0x3ec +00000000 ; +0x3f0 +00000000 ; +0x3f4 +00000000 ; +0x3f8 +00000000 ; +0x3fc \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_simple_pin_assignments.hds.hex.txt b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_simple_pin_assignments.hds.hex.txt new file mode 100644 index 00000000..84bf4dca --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_simple_pin_assignments.hds.hex.txt @@ -0,0 +1,269 @@ +; The raw script file is available at: ..\..\..\tests\hwdbg-tests\scripts\compiled-scripts\script_simple_pin_assignments.hds +; +; !hw script { +; @hw_pin0 = 0x1; +; @hw_pin1 = 0x0; +; @hw_pin2 = 0x1; +; @hw_pin3 = 0x0; +; @hw_pin4 = 0x1; +; @hw_pin5 = 0x0; +; @hw_pin6 = 0x1; +; @hw_pin7 = 0x0; +; } +; +000000f7 ; +0x0 | Checksum +00000000 ; +0x4 | Checksum +52444247 ; +0x8 | Indicator +48595045 ; +0xc | Indicator +00000004 ; +0x10 | TypeOfThePacket - DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL (0x4) +00000002 ; +0x14 | RequestedActionOfThePacket - Value (0x2) +00000023 ; +0x18 | Start of Optional Data +00000006 ; +0x1c +0000000a ; +0x20 +00000003 ; +0x24 +00000000 ; +0x28 +0000000f ; +0x2c +00000000 ; +0x30 +0000000f ; +0x34 +00000000 ; +0x38 +00000006 ; +0x3c +00000018 ; +0x40 +00000003 ; +0x44 +00000001 ; +0x48 +00000000 ; +0x4c +00000000 ; +0x50 +00000004 ; +0x54 +00000000 ; +0x58 +00000006 ; +0x5c +00000018 ; +0x60 +00000003 ; +0x64 +00000000 ; +0x68 +00000000 ; +0x6c +00000000 ; +0x70 +00000004 ; +0x74 +00000001 ; +0x78 +00000006 ; +0x7c +00000018 ; +0x80 +00000003 ; +0x84 +00000001 ; +0x88 +00000000 ; +0x8c +00000000 ; +0x90 +00000004 ; +0x94 +00000002 ; +0x98 +00000006 ; +0x9c +00000018 ; +0xa0 +00000003 ; +0xa4 +00000000 ; +0xa8 +00000000 ; +0xac +00000000 ; +0xb0 +00000004 ; +0xb4 +00000003 ; +0xb8 +00000006 ; +0xbc +00000018 ; +0xc0 +00000003 ; +0xc4 +00000001 ; +0xc8 +00000000 ; +0xcc +00000000 ; +0xd0 +00000004 ; +0xd4 +00000004 ; +0xd8 +00000006 ; +0xdc +00000018 ; +0xe0 +00000003 ; +0xe4 +00000000 ; +0xe8 +00000000 ; +0xec +00000000 ; +0xf0 +00000004 ; +0xf4 +00000005 ; +0xf8 +00000006 ; +0xfc +00000018 ; +0x100 +00000003 ; +0x104 +00000001 ; +0x108 +00000000 ; +0x10c +00000000 ; +0x110 +00000004 ; +0x114 +00000006 ; +0x118 +00000006 ; +0x11c +00000018 ; +0x120 +00000003 ; +0x124 +00000000 ; +0x128 +00000000 ; +0x12c +00000000 ; +0x130 +00000004 ; +0x134 +00000007 ; +0x138 +00000000 ; +0x13c +00000000 ; +0x140 +00000000 ; +0x144 +00000000 ; +0x148 +00000000 ; +0x14c +00000000 ; +0x150 +00000000 ; +0x154 +00000000 ; +0x158 +00000000 ; +0x15c +00000000 ; +0x160 +00000000 ; +0x164 +00000000 ; +0x168 +00000000 ; +0x16c +00000000 ; +0x170 +00000000 ; +0x174 +00000000 ; +0x178 +00000000 ; +0x17c +00000000 ; +0x180 +00000000 ; +0x184 +00000000 ; +0x188 +00000000 ; +0x18c +00000000 ; +0x190 +00000000 ; +0x194 +00000000 ; +0x198 +00000000 ; +0x19c +00000000 ; +0x1a0 +00000000 ; +0x1a4 +00000000 ; +0x1a8 +00000000 ; +0x1ac +00000000 ; +0x1b0 +00000000 ; +0x1b4 +00000000 ; +0x1b8 +00000000 ; +0x1bc +00000000 ; +0x1c0 +00000000 ; +0x1c4 +00000000 ; +0x1c8 +00000000 ; +0x1cc +00000000 ; +0x1d0 +00000000 ; +0x1d4 +00000000 ; +0x1d8 +00000000 ; +0x1dc +00000000 ; +0x1e0 +00000000 ; +0x1e4 +00000000 ; +0x1e8 +00000000 ; +0x1ec +00000000 ; +0x1f0 +00000000 ; +0x1f4 +00000000 ; +0x1f8 +00000000 ; +0x1fc +00000000 ; +0x200 +00000000 ; +0x204 +00000000 ; +0x208 +00000000 ; +0x20c +00000000 ; +0x210 +00000000 ; +0x214 +00000000 ; +0x218 +00000000 ; +0x21c +00000000 ; +0x220 +00000000 ; +0x224 +00000000 ; +0x228 +00000000 ; +0x22c +00000000 ; +0x230 +00000000 ; +0x234 +00000000 ; +0x238 +00000000 ; +0x23c +00000000 ; +0x240 +00000000 ; +0x244 +00000000 ; +0x248 +00000000 ; +0x24c +00000000 ; +0x250 +00000000 ; +0x254 +00000000 ; +0x258 +00000000 ; +0x25c +00000000 ; +0x260 +00000000 ; +0x264 +00000000 ; +0x268 +00000000 ; +0x26c +00000000 ; +0x270 +00000000 ; +0x274 +00000000 ; +0x278 +00000000 ; +0x27c +00000000 ; +0x280 +00000000 ; +0x284 +00000000 ; +0x288 +00000000 ; +0x28c +00000000 ; +0x290 +00000000 ; +0x294 +00000000 ; +0x298 +00000000 ; +0x29c +00000000 ; +0x2a0 +00000000 ; +0x2a4 +00000000 ; +0x2a8 +00000000 ; +0x2ac +00000000 ; +0x2b0 +00000000 ; +0x2b4 +00000000 ; +0x2b8 +00000000 ; +0x2bc +00000000 ; +0x2c0 +00000000 ; +0x2c4 +00000000 ; +0x2c8 +00000000 ; +0x2cc +00000000 ; +0x2d0 +00000000 ; +0x2d4 +00000000 ; +0x2d8 +00000000 ; +0x2dc +00000000 ; +0x2e0 +00000000 ; +0x2e4 +00000000 ; +0x2e8 +00000000 ; +0x2ec +00000000 ; +0x2f0 +00000000 ; +0x2f4 +00000000 ; +0x2f8 +00000000 ; +0x2fc +00000000 ; +0x300 +00000000 ; +0x304 +00000000 ; +0x308 +00000000 ; +0x30c +00000000 ; +0x310 +00000000 ; +0x314 +00000000 ; +0x318 +00000000 ; +0x31c +00000000 ; +0x320 +00000000 ; +0x324 +00000000 ; +0x328 +00000000 ; +0x32c +00000000 ; +0x330 +00000000 ; +0x334 +00000000 ; +0x338 +00000000 ; +0x33c +00000000 ; +0x340 +00000000 ; +0x344 +00000000 ; +0x348 +00000000 ; +0x34c +00000000 ; +0x350 +00000000 ; +0x354 +00000000 ; +0x358 +00000000 ; +0x35c +00000000 ; +0x360 +00000000 ; +0x364 +00000000 ; +0x368 +00000000 ; +0x36c +00000000 ; +0x370 +00000000 ; +0x374 +00000000 ; +0x378 +00000000 ; +0x37c +00000000 ; +0x380 +00000000 ; +0x384 +00000000 ; +0x388 +00000000 ; +0x38c +00000000 ; +0x390 +00000000 ; +0x394 +00000000 ; +0x398 +00000000 ; +0x39c +00000000 ; +0x3a0 +00000000 ; +0x3a4 +00000000 ; +0x3a8 +00000000 ; +0x3ac +00000000 ; +0x3b0 +00000000 ; +0x3b4 +00000000 ; +0x3b8 +00000000 ; +0x3bc +00000000 ; +0x3c0 +00000000 ; +0x3c4 +00000000 ; +0x3c8 +00000000 ; +0x3cc +00000000 ; +0x3d0 +00000000 ; +0x3d4 +00000000 ; +0x3d8 +00000000 ; +0x3dc +00000000 ; +0x3e0 +00000000 ; +0x3e4 +00000000 ; +0x3e8 +00000000 ; +0x3ec +00000000 ; +0x3f0 +00000000 ; +0x3f4 +00000000 ; +0x3f8 +00000000 ; +0x3fc \ No newline at end of file diff --git a/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_simple_port_assignments.hds.hex.txt b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_simple_port_assignments.hds.hex.txt new file mode 100644 index 00000000..4e929675 --- /dev/null +++ b/hyperdbg/tests/hwdbg-tests/scripts/compiled-scripts/script_simple_port_assignments.hds.hex.txt @@ -0,0 +1,272 @@ +; The raw script file is available at: ..\..\..\tests\hwdbg-tests\scripts\compiled-scripts\script_simple_port_assignments.hds +; +; !hw script { +; +; // +; // Assignment to @hw_port0 +; // +; .test_var = @hw_port0 + 1; +; @hw_port0 = .test_var; +; +; // +; // Assignment to @hw_port1 +; // +; @hw_port1 = @hw_port1 - 2; +; } +; +000000d8 ; +0x0 | Checksum +00000000 ; +0x4 | Checksum +52444247 ; +0x8 | Indicator +48595045 ; +0xc | Indicator +00000004 ; +0x10 | TypeOfThePacket - DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL (0x4) +00000002 ; +0x14 | RequestedActionOfThePacket - Value (0x2) +00000017 ; +0x18 | Start of Optional Data +00000006 ; +0x1c +0000000a ; +0x20 +00000003 ; +0x24 +00000001 ; +0x28 +0000000f ; +0x2c +00000000 ; +0x30 +0000000f ; +0x34 +00000000 ; +0x38 +00000006 ; +0x3c +0000000a ; +0x40 +00000003 ; +0x44 +00000001 ; +0x48 +00000004 ; +0x4c +00000020 ; +0x50 +00000007 ; +0x54 +00000000 ; +0x58 +00000006 ; +0x5c +00000018 ; +0x60 +00000007 ; +0x64 +00000000 ; +0x68 +00000000 ; +0x6c +00000000 ; +0x70 +00000001 ; +0x74 +00000000 ; +0x78 +00000006 ; +0x7c +00000018 ; +0x80 +00000001 ; +0x84 +00000000 ; +0x88 +00000000 ; +0x8c +00000000 ; +0x90 +00000004 ; +0x94 +00000020 ; +0x98 +00000006 ; +0x9c +0000000b ; +0xa0 +00000003 ; +0xa4 +00000002 ; +0xa8 +00000004 ; +0xac +00000021 ; +0xb0 +00000007 ; +0xb4 +00000000 ; +0xb8 +00000006 ; +0xbc +00000018 ; +0xc0 +00000007 ; +0xc4 +00000000 ; +0xc8 +00000000 ; +0xcc +00000000 ; +0xd0 +00000004 ; +0xd4 +00000021 ; +0xd8 +00000000 ; +0xdc +00000000 ; +0xe0 +00000000 ; +0xe4 +00000000 ; +0xe8 +00000000 ; +0xec +00000000 ; +0xf0 +00000000 ; +0xf4 +00000000 ; +0xf8 +00000000 ; +0xfc +00000000 ; +0x100 +00000000 ; +0x104 +00000000 ; +0x108 +00000000 ; +0x10c +00000000 ; +0x110 +00000000 ; +0x114 +00000000 ; +0x118 +00000000 ; +0x11c +00000000 ; +0x120 +00000000 ; +0x124 +00000000 ; +0x128 +00000000 ; +0x12c +00000000 ; +0x130 +00000000 ; +0x134 +00000000 ; +0x138 +00000000 ; +0x13c +00000000 ; +0x140 +00000000 ; +0x144 +00000000 ; +0x148 +00000000 ; +0x14c +00000000 ; +0x150 +00000000 ; +0x154 +00000000 ; +0x158 +00000000 ; +0x15c +00000000 ; +0x160 +00000000 ; +0x164 +00000000 ; +0x168 +00000000 ; +0x16c +00000000 ; +0x170 +00000000 ; +0x174 +00000000 ; +0x178 +00000000 ; +0x17c +00000000 ; +0x180 +00000000 ; +0x184 +00000000 ; +0x188 +00000000 ; +0x18c +00000000 ; +0x190 +00000000 ; +0x194 +00000000 ; +0x198 +00000000 ; +0x19c +00000000 ; +0x1a0 +00000000 ; +0x1a4 +00000000 ; +0x1a8 +00000000 ; +0x1ac +00000000 ; +0x1b0 +00000000 ; +0x1b4 +00000000 ; +0x1b8 +00000000 ; +0x1bc +00000000 ; +0x1c0 +00000000 ; +0x1c4 +00000000 ; +0x1c8 +00000000 ; +0x1cc +00000000 ; +0x1d0 +00000000 ; +0x1d4 +00000000 ; +0x1d8 +00000000 ; +0x1dc +00000000 ; +0x1e0 +00000000 ; +0x1e4 +00000000 ; +0x1e8 +00000000 ; +0x1ec +00000000 ; +0x1f0 +00000000 ; +0x1f4 +00000000 ; +0x1f8 +00000000 ; +0x1fc +00000000 ; +0x200 +00000000 ; +0x204 +00000000 ; +0x208 +00000000 ; +0x20c +00000000 ; +0x210 +00000000 ; +0x214 +00000000 ; +0x218 +00000000 ; +0x21c +00000000 ; +0x220 +00000000 ; +0x224 +00000000 ; +0x228 +00000000 ; +0x22c +00000000 ; +0x230 +00000000 ; +0x234 +00000000 ; +0x238 +00000000 ; +0x23c +00000000 ; +0x240 +00000000 ; +0x244 +00000000 ; +0x248 +00000000 ; +0x24c +00000000 ; +0x250 +00000000 ; +0x254 +00000000 ; +0x258 +00000000 ; +0x25c +00000000 ; +0x260 +00000000 ; +0x264 +00000000 ; +0x268 +00000000 ; +0x26c +00000000 ; +0x270 +00000000 ; +0x274 +00000000 ; +0x278 +00000000 ; +0x27c +00000000 ; +0x280 +00000000 ; +0x284 +00000000 ; +0x288 +00000000 ; +0x28c +00000000 ; +0x290 +00000000 ; +0x294 +00000000 ; +0x298 +00000000 ; +0x29c +00000000 ; +0x2a0 +00000000 ; +0x2a4 +00000000 ; +0x2a8 +00000000 ; +0x2ac +00000000 ; +0x2b0 +00000000 ; +0x2b4 +00000000 ; +0x2b8 +00000000 ; +0x2bc +00000000 ; +0x2c0 +00000000 ; +0x2c4 +00000000 ; +0x2c8 +00000000 ; +0x2cc +00000000 ; +0x2d0 +00000000 ; +0x2d4 +00000000 ; +0x2d8 +00000000 ; +0x2dc +00000000 ; +0x2e0 +00000000 ; +0x2e4 +00000000 ; +0x2e8 +00000000 ; +0x2ec +00000000 ; +0x2f0 +00000000 ; +0x2f4 +00000000 ; +0x2f8 +00000000 ; +0x2fc +00000000 ; +0x300 +00000000 ; +0x304 +00000000 ; +0x308 +00000000 ; +0x30c +00000000 ; +0x310 +00000000 ; +0x314 +00000000 ; +0x318 +00000000 ; +0x31c +00000000 ; +0x320 +00000000 ; +0x324 +00000000 ; +0x328 +00000000 ; +0x32c +00000000 ; +0x330 +00000000 ; +0x334 +00000000 ; +0x338 +00000000 ; +0x33c +00000000 ; +0x340 +00000000 ; +0x344 +00000000 ; +0x348 +00000000 ; +0x34c +00000000 ; +0x350 +00000000 ; +0x354 +00000000 ; +0x358 +00000000 ; +0x35c +00000000 ; +0x360 +00000000 ; +0x364 +00000000 ; +0x368 +00000000 ; +0x36c +00000000 ; +0x370 +00000000 ; +0x374 +00000000 ; +0x378 +00000000 ; +0x37c +00000000 ; +0x380 +00000000 ; +0x384 +00000000 ; +0x388 +00000000 ; +0x38c +00000000 ; +0x390 +00000000 ; +0x394 +00000000 ; +0x398 +00000000 ; +0x39c +00000000 ; +0x3a0 +00000000 ; +0x3a4 +00000000 ; +0x3a8 +00000000 ; +0x3ac +00000000 ; +0x3b0 +00000000 ; +0x3b4 +00000000 ; +0x3b8 +00000000 ; +0x3bc +00000000 ; +0x3c0 +00000000 ; +0x3c4 +00000000 ; +0x3c8 +00000000 ; +0x3cc +00000000 ; +0x3d0 +00000000 ; +0x3d4 +00000000 ; +0x3d8 +00000000 ; +0x3dc +00000000 ; +0x3e0 +00000000 ; +0x3e4 +00000000 ; +0x3e8 +00000000 ; +0x3ec +00000000 ; +0x3f0 +00000000 ; +0x3f4 +00000000 ; +0x3f8 +00000000 ; +0x3fc \ No newline at end of file diff --git a/hyperdbg/tests/script-engine-test b/hyperdbg/tests/script-engine-test new file mode 160000 index 00000000..cf27bae6 --- /dev/null +++ b/hyperdbg/tests/script-engine-test @@ -0,0 +1 @@ +Subproject commit cf27bae6ca10a6e9cd5810d605e8c0dca10931f8 diff --git a/utils/counter.py b/utils/counter.py index 9f9cd868..ce8fc309 100644 --- a/utils/counter.py +++ b/utils/counter.py @@ -8,7 +8,7 @@ def CountLines(start, lines=0, header=True, begin_start=None): for thing in os.listdir(start): thing = os.path.join(start, thing) if os.path.isfile(thing): - if ('\dependencies\zydis' not in thing and '\dependencies\phnt' not in thing and '\dependencies\ia32-doc' not in thing) and (thing.endswith('.c') or thing.endswith('.h') or thing.endswith('.cpp') or thing.endswith('.asm') or thing.endswith('.py') or thing.endswith('.cs') or thing.endswith('.ds')): + if ('\\dependencies\\zydis' not in thing and '\\dependencies\\ia32-doc' not in thing and '\\build\\bin' not in thing) and (thing.endswith('.c') or thing.endswith('.h') or thing.endswith('.cpp') or thing.endswith('.asm') or thing.endswith('.py') or thing.endswith('.cs') or thing.endswith('.scala') or thing.endswith('.tcl') or thing.endswith('.scala') or thing.endswith('.sh') or thing.endswith('.config') or thing.endswith('.ds') or thing.endswith('.hds') or thing.endswith('.hex') or thing.endswith('.txt') or thing.endswith('.md') or thing.endswith('.bat') or thing.endswith('.v') or thing.endswith('.sv') or thing.endswith('.vhd') or thing.endswith('.xdc')): with open(thing, 'r', encoding="latin-1") as f: newlines = f.readlines() @@ -35,4 +35,4 @@ def CountLines(start, lines=0, header=True, begin_start=None): ## This is fun script, I wrote to see that ## HyperDbg contains how many lines of code... ## -CountLines(r'..\\hyperdbg') +CountLines(r'..\\.') diff --git a/utils/replace-sdk-wdk.py b/utils/replace-sdk-wdk.py new file mode 100644 index 00000000..ffecbc45 --- /dev/null +++ b/utils/replace-sdk-wdk.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +""" +Walks the parent directory of this script (and all of its subdirectories) +looking for .vcxproj files. +""" + +import os + +TARGET_SDK_WDK_VERSION = "10.0.28000.0" # Update this version in case of updating NuGet packages + +# Only these .vcxproj files will be modified (matched by filename). +TARGET_PROJECTS = [ + "hyperhv.vcxproj", + "hyperkd.vcxproj", + "hypertrace.vcxproj", + "hyperlog.vcxproj", + "hyperevade.vcxproj", + "hyperperf.vcxproj", + "kdserial.vcxproj", + "hyperdbg_driver.vcxproj", +] + +REPLACEMENTS = { + "10.0": "" + TARGET_SDK_WDK_VERSION + "", + "$(LatestTargetPlatformVersion)": "" + TARGET_SDK_WDK_VERSION + "", +} + +# Directory *names* to skip wherever they appear in the tree. +EXCLUDED_DIR_NAMES = {".git"} + +def replace_in_file(filepath: str) -> bool: + with open(filepath, "r", encoding="utf-8", errors="ignore") as f: + content = f.read() + + original = content + for old, new in REPLACEMENTS.items(): + content = content.replace(old, new) + + if content != original: + with open(filepath, "w", encoding="utf-8") as f: + f.write(content) + return True + return False + + +def main() -> None: + script_path = os.path.abspath(__file__) + script_dir = os.path.dirname(script_path) + target_root = os.path.dirname(script_dir) # parent of this folder + + wanted = set(TARGET_PROJECTS) + found = set() + + print(f"Scanning under: {target_root}") + print(f"Looking for: {', '.join(sorted(wanted))}") + + changed_count = 0 + for root, dirs, files in os.walk(target_root): + # Prune in place so os.walk never descends into these directories. + dirs[:] = [d for d in dirs if d not in EXCLUDED_DIR_NAMES] + + for file in files: + if file in wanted: + filepath = os.path.join(root, file) + found.add(file) + + if replace_in_file(filepath): + print(f"Updated: {filepath}") + changed_count += 1 + else: + print(f"No matching text found, left unchanged: {filepath}") + + missing = wanted - found + for name in sorted(missing): + print(f"Warning: not found anywhere under {target_root}: {name}") + + print(f"Done. {changed_count} file(s) updated.") + + +if __name__ == "__main__": + main()