├── .gitignore ├── LICENSE ├── README.md ├── mapper └── my_mapper │ ├── includes │ ├── intel_driver.hpp │ ├── intel_driver_resource.hpp │ ├── kdmapper.hpp │ ├── nt.hpp │ ├── portable_executable.hpp │ ├── service.hpp │ └── utils.hpp │ ├── intel_driver.cpp │ ├── kdmapper.cpp │ ├── main.cpp │ ├── my_mapper.vcxproj │ ├── my_mapper.vcxproj.filters │ ├── portable_executable.cpp │ ├── service.cpp │ └── utils.cpp ├── phsymem_remap └── physmem_remapper_rewrite │ ├── main.cpp │ ├── physmem_remapper_rewrite.vcxproj │ ├── physmem_remapper_rewrite.vcxproj.filters │ └── project │ ├── communication │ ├── comm_assembly.asm │ ├── communication.cpp │ ├── communication.hpp │ ├── handler.cpp │ ├── shared_structs.hpp │ └── shellcode.hpp │ ├── cr3 decryption │ ├── cr3_decryption.cpp │ └── cr3_decryption.hpp │ ├── interrupts │ ├── interrupt_structs.hpp │ ├── interrupts.cpp │ ├── interrupts.hpp │ └── interrupts_asm.asm │ ├── logging │ ├── logging.cpp │ └── logging.hpp │ ├── physmem │ ├── page_table_helpers.hpp │ ├── physmem.cpp │ ├── physmem.hpp │ └── physmem_structs.hpp │ ├── project_api.hpp │ ├── project_includes.hpp │ ├── project_utility.cpp │ ├── project_utility.hpp │ └── windows_structs.hpp ├── physmem_remapper_rewrite.sln └── vext ├── api ├── debug │ ├── debug.cpp │ └── debug.hpp ├── driver │ ├── driver_includes.hpp │ ├── driver_shared.hpp │ ├── driver_um_lib.cpp │ ├── driver_um_lib.hpp │ └── nmi_restoring_assembly.asm ├── dumper │ └── driver_dumper.hpp └── proc │ └── process.hpp ├── dump_CLASSPNP.sys ├── main.cpp ├── vext.vcxproj └── vext.vcxproj.filters /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific files 2 | *.suo 3 | *.user 4 | *.sln.docstates 5 | 6 | # Build results 7 | [Dd]ebug/ 8 | [Dd]ebugPublic/ 9 | [Rr]elease/ 10 | [Rr]eleases/ 11 | x64/ 12 | x86/ 13 | .vs/ 14 | build/ 15 | bld/ 16 | [Bb]in/ 17 | [Oo]bj/ 18 | 19 | # Roslyn cache directories 20 | *.ide/ 21 | 22 | # MSTest test Results 23 | [Tt]est[Rr]esult*/ 24 | [Bb]uild[Ll]og.* 25 | 26 | #NUNIT 27 | *.VisualState.xml 28 | TestResult.xml 29 | 30 | # Build Results of an ATL Project 31 | [Dd]ebugPS/ 32 | [Rr]eleasePS/ 33 | dlldata.c 34 | 35 | *_i.c 36 | *_p.c 37 | *_i.h 38 | *.ilk 39 | *.meta 40 | *.obj 41 | *.pch 42 | *.pdb 43 | *.pgc 44 | *.pgd 45 | *.rsp 46 | *.sbr 47 | *.tlb 48 | *.tli 49 | *.tlh 50 | *.tmp 51 | *.tmp_proj 52 | *.log 53 | *.vspscc 54 | *.vssscc 55 | .builds 56 | *.pidb 57 | *.svclog 58 | *.scc 59 | 60 | # Chutzpah Test files 61 | _Chutzpah* 62 | 63 | # Visual C++ cache files 64 | ipch/ 65 | *.aps 66 | *.ncb 67 | *.opensdf 68 | *.sdf 69 | *.cachefile 70 | 71 | # Visual Studio profiler 72 | *.psess 73 | *.vsp 74 | *.vspx 75 | 76 | # TFS 2012 Local Workspace 77 | $tf/ 78 | 79 | # Guidance Automation Toolkit 80 | *.gpState 81 | 82 | # ReSharper is a .NET coding add-in 83 | _ReSharper*/ 84 | *.[Rr]e[Ss]harper 85 | *.DotSettings.user 86 | 87 | # JustCode is a .NET coding addin-in 88 | .JustCode 89 | 90 | # TeamCity is a build add-in 91 | _TeamCity* 92 | 93 | # DotCover is a Code Coverage Tool 94 | *.dotCover 95 | 96 | # NCrunch 97 | _NCrunch_* 98 | .*crunch*.local.xml 99 | 100 | # MightyMoose 101 | *.mm.* 102 | AutoTest.Net/ 103 | 104 | # Web workbench (sass) 105 | .sass-cache/ 106 | 107 | # Installshield output folder 108 | [Ee]xpress/ 109 | 110 | # DocProject is a documentation generator add-in 111 | DocProject/buildhelp/ 112 | DocProject/Help/*.HxT 113 | DocProject/Help/*.HxC 114 | DocProject/Help/*.hhc 115 | DocProject/Help/*.hhk 116 | DocProject/Help/*.hhp 117 | DocProject/Help/Html2 118 | DocProject/Help/html 119 | 120 | # Click-Once directory 121 | publish/ 122 | 123 | # Publish Web Output 124 | *.[Pp]ublish.xml 125 | *.azurePubxml 126 | # TODO: Comment the next line if you want to checkin your web deploy settings 127 | # but database connection strings (with potential passwords) will be unencrypted 128 | *.pubxml 129 | *.publishproj 130 | 131 | # NuGet Packages 132 | *.nupkg 133 | # The packages folder can be ignored because of Package Restore 134 | **/packages/* 135 | # except build/, which is used as an MSBuild target. 136 | !**/packages/build/ 137 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 138 | #!**/packages/repositories.config 139 | 140 | # Windows Azure Build Output 141 | csx/ 142 | *.build.csdef 143 | 144 | # Windows Store app package directory 145 | AppPackages/ 146 | 147 | # Others 148 | sql/ 149 | *.Cache 150 | ClientBin/ 151 | [Ss]tyle[Cc]op.* 152 | ~$* 153 | *~ 154 | *.dbmdl 155 | *.dbproj.schemaview 156 | *.pfx 157 | *.publishsettings 158 | node_modules/ 159 | 160 | # RIA/Silverlight projects 161 | Generated_Code/ 162 | 163 | # Backup & report files from converting an old project file 164 | # to a newer Visual Studio version. Backup files are not needed, 165 | # because we have git ;-) 166 | _UpgradeReport_Files/ 167 | Backup*/ 168 | UpgradeLog*.XML 169 | UpgradeLog*.htm 170 | 171 | # SQL Server files 172 | *.mdf 173 | *.ldf 174 | 175 | # Business Intelligence projects 176 | *.rdl.data 177 | *.bim.layout 178 | *.bim_*.settings 179 | 180 | # Microsoft Fakes 181 | FakesAssemblies/ 182 | 183 | 184 | ### Windows ### 185 | # Windows image file caches 186 | Thumbs.db 187 | ehthumbs.db 188 | 189 | # Folder config file 190 | Desktop.ini 191 | 192 | # Recycle Bin used on file shares 193 | $RECYCLE.BIN/ 194 | 195 | # Windows Installer files 196 | *.cab 197 | *.msi 198 | *.msm 199 | *.msp 200 | *.exe 201 | *.i64 202 | *.dll 203 | 204 | 205 | # Logs 206 | logs 207 | *.log 208 | npm-debug.log* 209 | yarn-debug.log* 210 | yarn-error.log* 211 | lerna-debug.log* 212 | .pnpm-debug.log* 213 | 214 | # Diagnostic reports (https://nodejs.org/api/report.html) 215 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 216 | 217 | # Runtime data 218 | pids 219 | *.pid 220 | *.seed 221 | *.pid.lock 222 | 223 | # Directory for instrumented libs generated by jscoverage/JSCover 224 | lib-cov 225 | 226 | # Coverage directory used by tools like istanbul 227 | coverage 228 | *.lcov 229 | 230 | # nyc test coverage 231 | .nyc_output 232 | 233 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 234 | .grunt 235 | 236 | # Bower dependency directory (https://bower.io/) 237 | bower_components 238 | 239 | # node-waf configuration 240 | .lock-wscript 241 | 242 | # Compiled binary addons (https://nodejs.org/api/addons.html) 243 | build/Release 244 | 245 | # Dependency directories 246 | node_modules/ 247 | jspm_packages/ 248 | 249 | # Snowpack dependency directory (https://snowpack.dev/) 250 | web_modules/ 251 | 252 | # TypeScript cache 253 | *.tsbuildinfo 254 | 255 | # Optional npm cache directory 256 | .npm 257 | 258 | # Optional eslint cache 259 | .eslintcache 260 | 261 | # Optional stylelint cache 262 | .stylelintcache 263 | 264 | # Microbundle cache 265 | .rpt2_cache/ 266 | .rts2_cache_cjs/ 267 | .rts2_cache_es/ 268 | .rts2_cache_umd/ 269 | 270 | # Optional REPL history 271 | .node_repl_history 272 | 273 | # Output of 'npm pack' 274 | *.tgz 275 | 276 | # Yarn Integrity file 277 | .yarn-integrity 278 | 279 | # dotenv environment variable files 280 | .env 281 | .env.development.local 282 | .env.test.local 283 | .env.production.local 284 | .env.local 285 | 286 | # parcel-bundler cache (https://parceljs.org/) 287 | .cache 288 | .parcel-cache 289 | 290 | # Next.js build output 291 | .next 292 | out 293 | 294 | # Nuxt.js build / generate output 295 | .nuxt 296 | dist 297 | 298 | # Gatsby files 299 | .cache/ 300 | # Comment in the public line in if your project uses Gatsby and not Next.js 301 | # https://nextjs.org/blog/next-9-1#public-directory-support 302 | # public 303 | 304 | # vuepress build output 305 | .vuepress/dist 306 | 307 | # vuepress v2.x temp and cache directory 308 | .temp 309 | .cache 310 | 311 | # Docusaurus cache and generated files 312 | .docusaurus 313 | 314 | # Serverless directories 315 | .serverless/ 316 | 317 | # FuseBox cache 318 | .fusebox/ 319 | 320 | # DynamoDB Local files 321 | .dynamodb/ 322 | 323 | # TernJS port file 324 | .tern-port 325 | 326 | # Stores VSCode versions used for testing VSCode extensions 327 | .vscode-test 328 | 329 | # yarn v2 330 | .yarn/cache 331 | .yarn/unplugged 332 | .yarn/build-state.yml 333 | .yarn/install-state.gz 334 | .pnp.* 335 | 336 | *jar 337 | 338 | ##### Windows 339 | # Windows thumbnail cache files 340 | Thumbs.db 341 | Thumbs.db:encryptable 342 | ehthumbs.db 343 | ehthumbs_vista.db 344 | 345 | # Dump file 346 | *.stackdump 347 | 348 | # Folder config file 349 | [Dd]esktop.ini 350 | 351 | # Recycle Bin used on file shares 352 | $RECYCLE.BIN/ 353 | 354 | # Windows Installer files 355 | *.cab 356 | *.msi 357 | *.msix 358 | *.msm 359 | *.msp 360 | 361 | # Windows shortcuts 362 | *.lnk 363 | 364 | ##### Linux 365 | *~ 366 | 367 | # temporary files which can be created if a process still has a handle open of a deleted file 368 | .fuse_hidden* 369 | 370 | # KDE directory preferences 371 | .directory 372 | 373 | # Linux trash folder which might appear on any partition or disk 374 | .Trash-* 375 | 376 | # .nfs files are created when an open file is removed but is still being accessed 377 | .nfs* 378 | 379 | ##### MacOS 380 | # General 381 | .DS_Store 382 | .AppleDouble 383 | .LSOverride 384 | 385 | # Icon must end with two \r 386 | Icon 387 | 388 | # Thumbnails 389 | ._* 390 | 391 | # Files that might appear in the root of a volume 392 | .DocumentRevisions-V100 393 | .fseventsd 394 | .Spotlight-V100 395 | .TemporaryItems 396 | .Trashes 397 | .VolumeIcon.icns 398 | .com.apple.timemachine.donotpresent 399 | 400 | # Directories potentially created on remote AFP share 401 | .AppleDB 402 | .AppleDesktop 403 | Network Trash Folder 404 | Temporary Items 405 | .apdisk 406 | 407 | ##### Backup 408 | *.bak 409 | *.gho 410 | *.ori 411 | *.orig 412 | *.tmp 413 | 414 | ##### GPG 415 | secring.* 416 | 417 | ##### Dropbox 418 | # Dropbox settings and caches 419 | .dropbox 420 | .dropbox.attr 421 | .dropbox.cache 422 | 423 | ##### SynopsysVCS 424 | # Waveform formats 425 | *.vcd 426 | *.vpd 427 | *.evcd 428 | *.fsdb 429 | 430 | # Default name of the simulation executable. A different name can be 431 | # specified with this switch (the associated daidir database name is 432 | # also taken from here): -o / 433 | simv 434 | 435 | # Generated for Verilog and VHDL top configs 436 | simv.daidir/ 437 | simv.db.dir/ 438 | 439 | # Infrastructure necessary to co-simulate SystemC models with 440 | # Verilog/VHDL models. An alternate directory may be specified with this 441 | # switch: -Mdir= 442 | csrc/ 443 | 444 | # Log file - the following switch allows to specify the file that will be 445 | # used to write all messages from simulation: -l 446 | *.log 447 | 448 | # Coverage results (generated with urg) and database location. The 449 | # following switch can also be used: urg -dir .vdb 450 | simv.vdb/ 451 | urgReport/ 452 | 453 | # DVE and UCLI related files. 454 | DVEfiles/ 455 | ucli.key 456 | 457 | # When the design is elaborated for DirectC, the following file is created 458 | # with declarations for C/C++ functions. 459 | vc_hdrs.h 460 | 461 | ##### SVN 462 | .svn/ 463 | 464 | ##### Mercurial 465 | .hg/ 466 | .hgignore 467 | .hgsigs 468 | .hgsub 469 | .hgsubstate 470 | .hgtags 471 | 472 | ##### Bazaar 473 | .bzr/ 474 | .bzrignore 475 | 476 | ##### CVS 477 | /CVS/* 478 | **/CVS/* 479 | .cvsignore 480 | */.cvsignore 481 | 482 | ##### TortoiseGit 483 | # Project-level settings 484 | /.tgitconfig 485 | 486 | ##### PuTTY 487 | # Private key 488 | *.ppk 489 | 490 | ##### Vim 491 | # Swap 492 | [._]*.s[a-v][a-z] 493 | !*.svg # comment out if you don't need vector files 494 | [._]*.sw[a-p] 495 | [._]s[a-rt-v][a-z] 496 | [._]ss[a-gi-z] 497 | [._]sw[a-p] 498 | 499 | # Session 500 | Session.vim 501 | Sessionx.vim 502 | 503 | # Temporary 504 | .netrwhist 505 | *~ 506 | # Auto-generated tag files 507 | tags 508 | # Persistent undo 509 | [._]*.un~ 510 | 511 | ##### Emacs 512 | # -*- mode: gitignore; -*- 513 | *~ 514 | \#*\# 515 | /.emacs.desktop 516 | /.emacs.desktop.lock 517 | *.elc 518 | auto-save-list 519 | tramp 520 | .\#* 521 | 522 | # Org-mode 523 | .org-id-locations 524 | *_archive 525 | 526 | # flymake-mode 527 | *_flymake.* 528 | 529 | # eshell files 530 | /eshell/history 531 | /eshell/lastdir 532 | 533 | # elpa packages 534 | /elpa/ 535 | 536 | # reftex files 537 | *.rel 538 | 539 | # AUCTeX auto folder 540 | /auto/ 541 | 542 | # cask packages 543 | .cask/ 544 | dist/ 545 | 546 | # Flycheck 547 | flycheck_*.el 548 | 549 | # server auth directory 550 | /server/ 551 | 552 | # projectiles files 553 | .projectile 554 | 555 | # directory configuration 556 | .dir-locals.el 557 | 558 | # network security 559 | /network-security.data 560 | 561 | ##### SublimeText 562 | # Cache files for Sublime Text 563 | *.tmlanguage.cache 564 | *.tmPreferences.cache 565 | *.stTheme.cache 566 | 567 | # Workspace files are user-specific 568 | *.sublime-workspace 569 | 570 | # Project files should be checked into the repository, unless a significant 571 | # proportion of contributors will probably not be using Sublime Text 572 | # *.sublime-project 573 | 574 | # SFTP configuration file 575 | sftp-config.json 576 | sftp-config-alt*.json 577 | 578 | # Package control specific files 579 | Package Control.last-run 580 | Package Control.ca-list 581 | Package Control.ca-bundle 582 | Package Control.system-ca-bundle 583 | Package Control.cache/ 584 | Package Control.ca-certs/ 585 | Package Control.merged-ca-bundle 586 | Package Control.user-ca-bundle 587 | oscrypto-ca-bundle.crt 588 | bh_unicode_properties.cache 589 | 590 | # Sublime-github package stores a github token in this file 591 | # https://packagecontrol.io/packages/sublime-github 592 | GitHub.sublime-settings 593 | 594 | ##### Notepad++ 595 | # Notepad++ backups # 596 | *.bak 597 | 598 | ##### TextMate 599 | *.tmproj 600 | *.tmproject 601 | tmtags 602 | 603 | ##### VisualStudioCode 604 | .vscode/* 605 | !.vscode/settings.json 606 | !.vscode/tasks.json 607 | !.vscode/launch.json 608 | !.vscode/extensions.json 609 | *.code-workspace 610 | 611 | # Local History for Visual Studio Code 612 | .history/ 613 | 614 | ##### NetBeans 615 | **/nbproject/private/ 616 | **/nbproject/Makefile-*.mk 617 | **/nbproject/Package-*.bash 618 | build/ 619 | nbbuild/ 620 | dist/ 621 | nbdist/ 622 | .nb-gradle/ 623 | 624 | ##### JetBrains 625 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 626 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 627 | 628 | # User-specific stuff 629 | .idea/**/workspace.xml 630 | .idea/**/tasks.xml 631 | .idea/**/usage.statistics.xml 632 | .idea/**/dictionaries 633 | .idea/**/shelf 634 | 635 | # Generated files 636 | .idea/**/contentModel.xml 637 | 638 | # Sensitive or high-churn files 639 | .idea/**/dataSources/ 640 | .idea/**/dataSources.ids 641 | .idea/**/dataSources.local.xml 642 | .idea/**/sqlDataSources.xml 643 | .idea/**/dynamic.xml 644 | .idea/**/uiDesigner.xml 645 | .idea/**/dbnavigator.xml 646 | 647 | # Gradle 648 | .idea/**/gradle.xml 649 | .idea/**/libraries 650 | 651 | # Gradle and Maven with auto-import 652 | # When using Gradle or Maven with auto-import, you should exclude module files, 653 | # since they will be recreated, and may cause churn. Uncomment if using 654 | # auto-import. 655 | # .idea/artifacts 656 | # .idea/compiler.xml 657 | # .idea/jarRepositories.xml 658 | # .idea/modules.xml 659 | # .idea/*.iml 660 | # .idea/modules 661 | # *.iml 662 | # *.ipr 663 | 664 | # CMake 665 | cmake-build-*/ 666 | 667 | # Mongo Explorer plugin 668 | .idea/**/mongoSettings.xml 669 | 670 | # File-based project format 671 | *.iws 672 | 673 | # IntelliJ 674 | out/ 675 | 676 | # mpeltonen/sbt-idea plugin 677 | .idea_modules/ 678 | 679 | # JIRA plugin 680 | atlassian-ide-plugin.xml 681 | 682 | # Cursive Clojure plugin 683 | .idea/replstate.xml 684 | 685 | # Crashlytics plugin (for Android Studio and IntelliJ) 686 | com_crashlytics_export_strings.xml 687 | crashlytics.properties 688 | crashlytics-build.properties 689 | fabric.properties 690 | 691 | # Editor-based Rest Client 692 | .idea/httpRequests 693 | 694 | # Android studio 3.1+ serialized cache file 695 | .idea/caches/build_file_checksums.ser 696 | 697 | ##### Eclipse 698 | .metadata 699 | bin/ 700 | tmp/ 701 | *.tmp 702 | *.bak 703 | *.swp 704 | *~.nib 705 | local.properties 706 | .settings/ 707 | .loadpath 708 | .recommenders 709 | 710 | # External tool builders 711 | .externalToolBuilders/ 712 | 713 | # Locally stored "Eclipse launch configurations" 714 | *.launch 715 | 716 | # PyDev specific (Python IDE for Eclipse) 717 | *.pydevproject 718 | 719 | # CDT-specific (C/C++ Development Tooling) 720 | .cproject 721 | 722 | # CDT- autotools 723 | .autotools 724 | 725 | # Java annotation processor (APT) 726 | .factorypath 727 | 728 | # PDT-specific (PHP Development Tools) 729 | .buildpath 730 | 731 | # sbteclipse plugin 732 | .target 733 | 734 | # Tern plugin 735 | .tern-project 736 | 737 | # TeXlipse plugin 738 | .texlipse 739 | 740 | # STS (Spring Tool Suite) 741 | .springBeans 742 | 743 | # Code Recommenders 744 | .recommenders/ 745 | 746 | # Annotation Processing 747 | .apt_generated/ 748 | .apt_generated_test/ 749 | 750 | # Scala IDE specific (Scala & Java development for Eclipse) 751 | .cache-main 752 | .scala_dependencies 753 | .worksheet 754 | 755 | # Uncomment this line if you wish to ignore the project description file. 756 | # Typically, this file would be tracked if it contains build/dependency configurations: 757 | #.project 758 | 759 | ##### Dreamweaver 760 | # DW Dreamweaver added files 761 | _notes 762 | _compareTemp 763 | configs/ 764 | dwsync.xml 765 | dw_php_codehinting.config 766 | *.mno 767 | 768 | ##### CodeKit 769 | # General CodeKit files to ignore 770 | config.codekit 771 | config.codekit3 772 | /min 773 | 774 | ##### Gradle 775 | .gradle 776 | **/build/ 777 | !src/**/build/ 778 | 779 | # Ignore Gradle GUI config 780 | gradle-app.setting 781 | 782 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 783 | !gradle-wrapper.jar 784 | 785 | # Cache of project 786 | .gradletasknamecache 787 | 788 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 789 | # gradle/wrapper/gradle-wrapper.properties 790 | 791 | ##### Composer 792 | composer.phar 793 | /vendor/ 794 | 795 | # Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control 796 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file 797 | composer.lock 798 | 799 | ##### PHP CodeSniffer 800 | # gitignore for the PHP Codesniffer framework 801 | # website: https://github.com/squizlabs/PHP_CodeSniffer 802 | # 803 | # Recommended template: PHP.gitignore 804 | 805 | /wpcs/* 806 | 807 | ##### SASS 808 | .sass-cache/ 809 | *.css.map 810 | *.sass.map 811 | *.scss.map 812 | 813 | # serverless files 814 | .serverless 815 | *.vsidx 816 | *.woff 817 | *.woff2 818 | *.eot 819 | *.svg 820 | *.ttf 821 | 822 | 823 | DashboardTemplates/ 824 | .idea/ 825 | 826 | # Generated by Cargo 827 | # will have compiled files and executables 828 | debug/ 829 | target/ 830 | 831 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 832 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 833 | Cargo.lock 834 | 835 | # These are backup files generated by rustfmt 836 | **/*.rs.bk 837 | 838 | # MSVC Windows builds of rustc generate these, which store debugging information 839 | *.pdb 840 | 841 | intermediate directory/ 842 | output directory/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Erik Drexler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Material Bread logo 3 |

PhysMeme Remapper

4 |

Run Code in a Address Space not associated with a Process

5 |

6 | 7 | # Procedure 8 | has to be written 9 | 10 | # Usage 11 | - has to be written 12 | 13 | # Credits 14 | - [**TheCruz/z175**](https://github.com/TheCruZ/kdmapper) - kdmapper example used in this project 15 | -------------------------------------------------------------------------------- /mapper/my_mapper/includes/intel_driver.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "intel_driver_resource.hpp" 9 | #include "includes/service.hpp" 10 | #include "includes/utils.hpp" 11 | 12 | namespace intel_driver 13 | { 14 | extern char driver_name[100]; //"iqvw64e.sys" 15 | constexpr uint32_t ioctl1 = 0x80862007; 16 | constexpr DWORD iqvw64e_timestamp = 0x5284EAC3; 17 | extern ULONG64 ntoskrnlAddr; 18 | 19 | typedef struct _COPY_MEMORY_BUFFER_INFO 20 | { 21 | uint64_t case_number; 22 | uint64_t reserved; 23 | uint64_t source; 24 | uint64_t dst; 25 | uint64_t length; 26 | }COPY_MEMORY_BUFFER_INFO, * PCOPY_MEMORY_BUFFER_INFO; 27 | 28 | typedef struct _FILL_MEMORY_BUFFER_INFO 29 | { 30 | uint64_t case_number; 31 | uint64_t reserved1; 32 | uint32_t value; 33 | uint32_t reserved2; 34 | uint64_t dst; 35 | uint64_t length; 36 | }FILL_MEMORY_BUFFER_INFO, * PFILL_MEMORY_BUFFER_INFO; 37 | 38 | typedef struct _GET_PHYS_ADDRESS_BUFFER_INFO 39 | { 40 | uint64_t case_number; 41 | uint64_t reserved; 42 | uint64_t return_physical_address; 43 | uint64_t address_to_translate; 44 | }GET_PHYS_ADDRESS_BUFFER_INFO, * PGET_PHYS_ADDRESS_BUFFER_INFO; 45 | 46 | typedef struct _MAP_IO_SPACE_BUFFER_INFO 47 | { 48 | uint64_t case_number; 49 | uint64_t reserved; 50 | uint64_t return_value; 51 | uint64_t return_virtual_address; 52 | uint64_t physical_address_to_map; 53 | uint32_t size; 54 | }MAP_IO_SPACE_BUFFER_INFO, * PMAP_IO_SPACE_BUFFER_INFO; 55 | 56 | typedef struct _UNMAP_IO_SPACE_BUFFER_INFO 57 | { 58 | uint64_t case_number; 59 | uint64_t reserved1; 60 | uint64_t reserved2; 61 | uint64_t virt_address; 62 | uint64_t reserved3; 63 | uint32_t number_of_bytes; 64 | }UNMAP_IO_SPACE_BUFFER_INFO, * PUNMAP_IO_SPACE_BUFFER_INFO; 65 | 66 | typedef struct _RTL_BALANCED_LINKS { 67 | struct _RTL_BALANCED_LINKS* Parent; 68 | struct _RTL_BALANCED_LINKS* LeftChild; 69 | struct _RTL_BALANCED_LINKS* RightChild; 70 | CHAR Balance; 71 | UCHAR Reserved[3]; 72 | } RTL_BALANCED_LINKS; 73 | typedef RTL_BALANCED_LINKS* PRTL_BALANCED_LINKS; 74 | 75 | typedef struct _RTL_AVL_TABLE { 76 | RTL_BALANCED_LINKS BalancedRoot; 77 | PVOID OrderedPointer; 78 | ULONG WhichOrderedElement; 79 | ULONG NumberGenericTableElements; 80 | ULONG DepthOfTree; 81 | PVOID RestartKey; 82 | ULONG DeleteCount; 83 | PVOID CompareRoutine; 84 | PVOID AllocateRoutine; 85 | PVOID FreeRoutine; 86 | PVOID TableContext; 87 | } RTL_AVL_TABLE; 88 | typedef RTL_AVL_TABLE* PRTL_AVL_TABLE; 89 | 90 | typedef struct _PiDDBCacheEntry 91 | { 92 | LIST_ENTRY List; 93 | UNICODE_STRING DriverName; 94 | ULONG TimeDateStamp; 95 | NTSTATUS LoadStatus; 96 | char _0x0028[16]; // data from the shim engine, or uninitialized memory for custom drivers 97 | } PiDDBCacheEntry, * NPiDDBCacheEntry; 98 | 99 | typedef struct _HashBucketEntry 100 | { 101 | struct _HashBucketEntry* Next; 102 | UNICODE_STRING DriverName; 103 | ULONG CertHash[5]; 104 | } HashBucketEntry, * PHashBucketEntry; 105 | 106 | bool ClearPiDDBCacheTable(HANDLE device_handle); 107 | bool ExAcquireResourceExclusiveLite(HANDLE device_handle, PVOID Resource, BOOLEAN wait); 108 | bool ExReleaseResourceLite(HANDLE device_handle, PVOID Resource); 109 | BOOLEAN RtlDeleteElementGenericTableAvl(HANDLE device_handle, PVOID Table, PVOID Buffer); 110 | PVOID RtlLookupElementGenericTableAvl(HANDLE device_handle, PRTL_AVL_TABLE Table, PVOID Buffer); 111 | PiDDBCacheEntry* LookupEntry(HANDLE device_handle, PRTL_AVL_TABLE PiDDBCacheTable, ULONG timestamp, const wchar_t * name); 112 | PVOID ResolveRelativeAddress(HANDLE device_handle, _In_ PVOID Instruction, _In_ ULONG OffsetOffset, _In_ ULONG InstructionSize); 113 | 114 | uintptr_t FindPatternAtKernel(HANDLE device_handle, uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, const char* szMask); 115 | uintptr_t FindSectionAtKernel(HANDLE device_handle, const char* sectionName, uintptr_t modulePtr, PULONG size); 116 | uintptr_t FindPatternInSectionAtKernel(HANDLE device_handle, const char* sectionName, uintptr_t modulePtr, BYTE* bMask, const char* szMask); 117 | 118 | bool ClearKernelHashBucketList(HANDLE device_handle); 119 | bool ClearWdFilterDriverList(HANDLE device_handle); 120 | 121 | bool IsRunning(); 122 | HANDLE Load(); 123 | bool Unload(HANDLE device_handle); 124 | 125 | bool MemCopy(HANDLE device_handle, uint64_t dst, uint64_t source, uint64_t size); 126 | bool SetMemory(HANDLE device_handle, uint64_t address, uint32_t value, uint64_t size); 127 | bool GetPhysicalAddress(HANDLE device_handle, uint64_t address, uint64_t* out_physical_address); 128 | uint64_t MapIoSpace(HANDLE device_handle, uint64_t physical_address, uint32_t size); 129 | bool UnmapIoSpace(HANDLE device_handle, uint64_t address, uint32_t size); 130 | bool ReadMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size); 131 | bool WriteMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size); 132 | bool WriteToReadOnlyMemory(HANDLE device_handle, uint64_t address, void* buffer, uint32_t size); 133 | /*added by herooyyy*/ 134 | uint64_t MmAllocateIndependentPagesEx(HANDLE device_handle, uint32_t size); 135 | bool MmFreeIndependentPages(HANDLE device_handle, uint64_t address, uint32_t size); 136 | BOOLEAN MmSetPageProtection(HANDLE device_handle, uint64_t address, uint32_t size, ULONG new_protect); 137 | 138 | uint64_t AllocContiguousMemory(HANDLE iqvw64e_device_handle, uint64_t size); 139 | bool RemovePhysicalMemory(HANDLE iqvw64e_device_handle, PLARGE_INTEGER phys_base, PLARGE_INTEGER size); 140 | bool FreeContiguousMemory(HANDLE iqvw64e_device_handle, uint64_t base); 141 | uint64_t AllocatePool(HANDLE device_handle, nt::POOL_TYPE pool_type, uint64_t size); 142 | /*added by psec*/ 143 | uint64_t MmAllocatePagesForMdl(HANDLE device_handle, LARGE_INTEGER LowAddress, LARGE_INTEGER HighAddress, LARGE_INTEGER SkipBytes, SIZE_T TotalBytes); 144 | uint64_t MmMapLockedPagesSpecifyCache(HANDLE device_handle, uint64_t pmdl, nt::KPROCESSOR_MODE AccessMode, nt::MEMORY_CACHING_TYPE CacheType, uint64_t RequestedAddress, ULONG BugCheckOnFailure, ULONG Priority); 145 | bool MmProtectMdlSystemAddress(HANDLE device_handle, uint64_t MemoryDescriptorList, ULONG NewProtect); 146 | bool MmUnmapLockedPages(HANDLE device_handle, uint64_t BaseAddress, uint64_t pmdl); 147 | bool MmFreePagesFromMdl(HANDLE device_handle, uint64_t MemoryDescriptorList); 148 | /**/ 149 | 150 | bool FreePool(HANDLE device_handle, uint64_t address); 151 | uint64_t GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string& function_name); 152 | bool ClearMmUnloadedDrivers(HANDLE device_handle); 153 | std::wstring GetDriverNameW(); 154 | std::wstring GetDriverPath(); 155 | 156 | template 157 | bool CallKernelFunction(HANDLE device_handle, T* out_result, uint64_t kernel_function_address, const A ...arguments) { 158 | constexpr auto call_void = std::is_same_v; 159 | 160 | if constexpr (!call_void) { 161 | if (!out_result) 162 | return false; 163 | } 164 | else { 165 | UNREFERENCED_PARAMETER(out_result); 166 | } 167 | 168 | if (!kernel_function_address) 169 | return false; 170 | 171 | // Setup function call 172 | HMODULE ntdll = GetModuleHandleA("ntdll.dll"); 173 | if (ntdll == 0) { 174 | Log(L"[-] Failed to load ntdll.dll" << std::endl); //never should happens 175 | return false; 176 | } 177 | 178 | const auto NtAddAtom = reinterpret_cast(GetProcAddress(ntdll, "NtAddAtom")); 179 | if (!NtAddAtom) 180 | { 181 | Log(L"[-] Failed to get export ntdll.NtAddAtom" << std::endl); 182 | return false; 183 | } 184 | 185 | uint8_t kernel_injected_jmp[] = { 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0 }; 186 | uint8_t original_kernel_function[sizeof(kernel_injected_jmp)]; 187 | *(uint64_t*)&kernel_injected_jmp[2] = kernel_function_address; 188 | 189 | static uint64_t kernel_NtAddAtom = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "NtAddAtom"); 190 | if (!kernel_NtAddAtom) { 191 | Log(L"[-] Failed to get export ntoskrnl.NtAddAtom" << std::endl); 192 | return false; 193 | } 194 | 195 | if (!ReadMemory(device_handle, kernel_NtAddAtom, &original_kernel_function, sizeof(kernel_injected_jmp))) 196 | return false; 197 | 198 | if (original_kernel_function[0] == kernel_injected_jmp[0] && 199 | original_kernel_function[1] == kernel_injected_jmp[1] && 200 | original_kernel_function[sizeof(kernel_injected_jmp) - 2] == kernel_injected_jmp[sizeof(kernel_injected_jmp) - 2] && 201 | original_kernel_function[sizeof(kernel_injected_jmp) - 1] == kernel_injected_jmp[sizeof(kernel_injected_jmp) - 1]) { 202 | Log(L"[-] FAILED!: The code was already hooked!! another instance of kdmapper running?!" << std::endl); 203 | return false; 204 | } 205 | 206 | // Overwrite the pointer with kernel_function_address 207 | if (!WriteToReadOnlyMemory(device_handle, kernel_NtAddAtom, &kernel_injected_jmp, sizeof(kernel_injected_jmp))) 208 | return false; 209 | 210 | // Call function 211 | if constexpr (!call_void) { 212 | using FunctionFn = T(__stdcall*)(A...); 213 | const auto Function = reinterpret_cast(NtAddAtom); 214 | 215 | *out_result = Function(arguments...); 216 | } 217 | else { 218 | using FunctionFn = void(__stdcall*)(A...); 219 | const auto Function = reinterpret_cast(NtAddAtom); 220 | 221 | Function(arguments...); 222 | } 223 | 224 | // Restore the pointer/jmp 225 | return WriteToReadOnlyMemory(device_handle, kernel_NtAddAtom, original_kernel_function, sizeof(kernel_injected_jmp)); 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /mapper/my_mapper/includes/kdmapper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "includes/portable_executable.hpp" 8 | #include "includes/utils.hpp" 9 | #include "nt.hpp" 10 | #include "includes/intel_driver.hpp" 11 | 12 | #define PAGE_SIZE 0x1000 13 | 14 | namespace kdmapper 15 | { 16 | enum class AllocationMode 17 | { 18 | AllocatePool, 19 | AllocateMdl, 20 | AllocateIndependentPages, 21 | AllocateContiguousMemory, 22 | }; 23 | 24 | typedef bool (*mapCallback)(ULONG64* param1, ULONG64* param2, ULONG64 allocationPtr, ULONG64 allocationSize, ULONG64 mdlptr); 25 | 26 | //Note: if you set PassAllocationAddressAsFirstParam as true, param1 will be ignored 27 | uint64_t MapDriver(HANDLE iqvw64e_device_handle, BYTE* data, ULONG64 param1, ULONG64 param2, bool free, bool remove_from_system_page_tables, bool destroyHeader, AllocationMode mode, bool PassAllocationAddressAsFirstParam, bool PassSizeAsSecondParam, mapCallback callback, NTSTATUS* exitCode); 28 | void RelocateImageByDelta(portable_executable::vec_relocs relocs, const uint64_t delta); 29 | bool FixSecurityCookie(void* local_image, uint64_t kernel_image_base); 30 | bool ResolveImports(HANDLE iqvw64e_device_handle, portable_executable::vec_imports imports); 31 | uint64_t AllocIndependentPages(HANDLE device_handle, uint32_t size); 32 | uint64_t AllocMdlMemory(HANDLE iqvw64e_device_handle, uint64_t size, uint64_t* mdlPtr); 33 | } -------------------------------------------------------------------------------- /mapper/my_mapper/includes/nt.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #pragma comment(lib, "ntdll.lib") 5 | 6 | namespace nt 7 | { 8 | constexpr auto PAGE_SIZE = 0x1000; 9 | constexpr auto STATUS_INFO_LENGTH_MISMATCH = 0xC0000004; 10 | 11 | constexpr auto SystemModuleInformation = 11; 12 | constexpr auto SystemHandleInformation = 16; 13 | constexpr auto SystemExtendedHandleInformation = 64; 14 | 15 | typedef NTSTATUS(*NtLoadDriver)(PUNICODE_STRING DriverServiceName); 16 | typedef NTSTATUS(*NtUnloadDriver)(PUNICODE_STRING DriverServiceName); 17 | typedef NTSTATUS(*RtlAdjustPrivilege)(_In_ ULONG Privilege, _In_ BOOLEAN Enable, _In_ BOOLEAN Client, _Out_ PBOOLEAN WasEnabled); 18 | 19 | typedef struct _SYSTEM_HANDLE 20 | { 21 | PVOID Object; 22 | HANDLE UniqueProcessId; 23 | HANDLE HandleValue; 24 | ULONG GrantedAccess; 25 | USHORT CreatorBackTraceIndex; 26 | USHORT ObjectTypeIndex; 27 | ULONG HandleAttributes; 28 | ULONG Reserved; 29 | } SYSTEM_HANDLE, *PSYSTEM_HANDLE; 30 | 31 | typedef struct _SYSTEM_HANDLE_INFORMATION_EX 32 | { 33 | ULONG_PTR HandleCount; 34 | ULONG_PTR Reserved; 35 | SYSTEM_HANDLE Handles[1]; 36 | } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; 37 | 38 | //Thanks to Pvt Comfy for remember to update this https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ne-wdm-_pool_type 39 | typedef enum class _POOL_TYPE { 40 | NonPagedPool, 41 | NonPagedPoolExecute = NonPagedPool, 42 | PagedPool, 43 | NonPagedPoolMustSucceed = NonPagedPool + 2, 44 | DontUseThisType, 45 | NonPagedPoolCacheAligned = NonPagedPool + 4, 46 | PagedPoolCacheAligned, 47 | NonPagedPoolCacheAlignedMustS = NonPagedPool + 6, 48 | MaxPoolType, 49 | NonPagedPoolBase = 0, 50 | NonPagedPoolBaseMustSucceed = NonPagedPoolBase + 2, 51 | NonPagedPoolBaseCacheAligned = NonPagedPoolBase + 4, 52 | NonPagedPoolBaseCacheAlignedMustS = NonPagedPoolBase + 6, 53 | NonPagedPoolSession = 32, 54 | PagedPoolSession = NonPagedPoolSession + 1, 55 | NonPagedPoolMustSucceedSession = PagedPoolSession + 1, 56 | DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1, 57 | NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1, 58 | PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1, 59 | NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1, 60 | NonPagedPoolNx = 512, 61 | NonPagedPoolNxCacheAligned = NonPagedPoolNx + 4, 62 | NonPagedPoolSessionNx = NonPagedPoolNx + 32, 63 | } POOL_TYPE; 64 | 65 | typedef struct _RTL_PROCESS_MODULE_INFORMATION 66 | { 67 | HANDLE Section; 68 | PVOID MappedBase; 69 | PVOID ImageBase; 70 | ULONG ImageSize; 71 | ULONG Flags; 72 | USHORT LoadOrderIndex; 73 | USHORT InitOrderIndex; 74 | USHORT LoadCount; 75 | USHORT OffsetToFileName; 76 | UCHAR FullPathName[256]; 77 | } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; 78 | 79 | typedef struct _RTL_PROCESS_MODULES 80 | { 81 | ULONG NumberOfModules; 82 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 83 | } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; 84 | 85 | /*added by psec*/ 86 | typedef enum _MEMORY_CACHING_TYPE_ORIG { 87 | MmFrameBufferCached = 2 88 | } MEMORY_CACHING_TYPE_ORIG; 89 | 90 | typedef enum _MEMORY_CACHING_TYPE { 91 | MmNonCached = FALSE, 92 | MmCached = TRUE, 93 | MmWriteCombined = MmFrameBufferCached, 94 | MmHardwareCoherentCached, 95 | MmNonCachedUnordered, // IA64 96 | MmUSWCCached, 97 | MmMaximumCacheType, 98 | MmNotMapped = -1 99 | } MEMORY_CACHING_TYPE; 100 | 101 | typedef CCHAR KPROCESSOR_MODE; 102 | 103 | typedef enum _MODE { 104 | KernelMode, 105 | UserMode, 106 | MaximumMode 107 | } MODE; 108 | 109 | typedef enum _MM_PAGE_PRIORITY { 110 | LowPagePriority, 111 | NormalPagePriority = 16, 112 | HighPagePriority = 32 113 | } MM_PAGE_PRIORITY; 114 | /**/ 115 | } 116 | -------------------------------------------------------------------------------- /mapper/my_mapper/includes/portable_executable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace portable_executable 8 | { 9 | struct RelocInfo 10 | { 11 | uint64_t address; 12 | uint16_t* item; 13 | uint32_t count; 14 | }; 15 | 16 | struct ImportFunctionInfo 17 | { 18 | std::string name; 19 | uint64_t* address; 20 | }; 21 | 22 | struct ImportInfo 23 | { 24 | std::string module_name; 25 | std::vector function_datas; 26 | }; 27 | 28 | using vec_sections = std::vector; 29 | using vec_relocs = std::vector; 30 | using vec_imports = std::vector; 31 | 32 | PIMAGE_NT_HEADERS64 GetNtHeaders(void* image_base); 33 | vec_relocs GetRelocs(void* image_base); 34 | vec_imports GetImports(void* image_base); 35 | } -------------------------------------------------------------------------------- /mapper/my_mapper/includes/service.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include "includes/intel_driver.hpp" 6 | 7 | namespace service 8 | { 9 | bool RegisterAndStart(const std::wstring& driver_path); 10 | bool StopAndRemove(const std::wstring& driver_name); 11 | }; -------------------------------------------------------------------------------- /mapper/my_mapper/includes/utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(DISABLE_OUTPUT) 4 | #define Log(content) 5 | #else 6 | #define Log(content) std::wcout << content 7 | #endif 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "nt.hpp" 19 | 20 | namespace utils 21 | { 22 | std::wstring GetFullTempPath(); 23 | bool ReadFileToMemory(const std::wstring& file_path, std::vector* out_buffer); 24 | bool CreateFileFromMemory(const std::wstring& desired_file_path, const char* address, size_t size); 25 | uint64_t GetKernelModuleAddress(const std::string& module_name); 26 | BOOLEAN bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask); 27 | uintptr_t FindPattern(uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, const char* szMask); 28 | PVOID FindSection(const char* sectionName, uintptr_t modulePtr, PULONG size); 29 | } -------------------------------------------------------------------------------- /mapper/my_mapper/kdmapper.cpp: -------------------------------------------------------------------------------- 1 | #include "includes/kdmapper.hpp" 2 | 3 | uint64_t kdmapper::AllocMdlMemory(HANDLE iqvw64e_device_handle, uint64_t size, uint64_t* mdlPtr) { 4 | /*added by psec*/ 5 | LARGE_INTEGER LowAddress, HighAddress; 6 | LowAddress.QuadPart = 0; 7 | HighAddress.QuadPart = 0xffff'ffff'ffff'ffffULL; 8 | 9 | uint64_t pages = (size / PAGE_SIZE) + 1; 10 | auto mdl = intel_driver::MmAllocatePagesForMdl(iqvw64e_device_handle, LowAddress, HighAddress, LowAddress, pages * (uint64_t)PAGE_SIZE); 11 | if (!mdl) { 12 | Log(L"[-] Can't allocate pages for mdl" << std::endl); 13 | return { 0 }; 14 | } 15 | 16 | uint32_t byteCount = 0; 17 | if (!intel_driver::ReadMemory(iqvw64e_device_handle, mdl + 0x028 /*_MDL : byteCount*/, &byteCount, sizeof(uint32_t))) { 18 | Log(L"[-] Can't read the _MDL : byteCount" << std::endl); 19 | return { 0 }; 20 | } 21 | 22 | if (byteCount < size) { 23 | Log(L"[-] Couldn't allocate enough memory, cleaning up" << std::endl); 24 | intel_driver::MmFreePagesFromMdl(iqvw64e_device_handle, mdl); 25 | intel_driver::FreePool(iqvw64e_device_handle, mdl); 26 | return { 0 }; 27 | } 28 | 29 | auto mappingStartAddress = intel_driver::MmMapLockedPagesSpecifyCache(iqvw64e_device_handle, mdl, nt::KernelMode, nt::MmCached, NULL, FALSE, nt::NormalPagePriority); 30 | if (!mappingStartAddress) { 31 | Log(L"[-] Can't set mdl pages cache, cleaning up." << std::endl); 32 | intel_driver::MmFreePagesFromMdl(iqvw64e_device_handle, mdl); 33 | intel_driver::FreePool(iqvw64e_device_handle, mdl); 34 | return { 0 }; 35 | } 36 | 37 | const auto result = intel_driver::MmProtectMdlSystemAddress(iqvw64e_device_handle, mdl, PAGE_EXECUTE_READWRITE); 38 | if (!result) { 39 | Log(L"[-] Can't change protection for mdl pages, cleaning up" << std::endl); 40 | intel_driver::MmUnmapLockedPages(iqvw64e_device_handle, mappingStartAddress, mdl); 41 | intel_driver::MmFreePagesFromMdl(iqvw64e_device_handle, mdl); 42 | intel_driver::FreePool(iqvw64e_device_handle, mdl); 43 | return { 0 }; 44 | } 45 | Log(L"[+] Allocated pages for mdl" << std::endl); 46 | 47 | if (mdlPtr) 48 | *mdlPtr = mdl; 49 | 50 | return mappingStartAddress; 51 | } 52 | 53 | uint64_t kdmapper::AllocIndependentPages(HANDLE device_handle, uint32_t size) 54 | { 55 | const auto base = intel_driver::MmAllocateIndependentPagesEx(device_handle, size); 56 | if (!base) 57 | { 58 | Log(L"[-] Error allocating independent pages" << std::endl); 59 | return 0; 60 | } 61 | 62 | if (!intel_driver::MmSetPageProtection(device_handle, base, size, PAGE_EXECUTE_READWRITE)) 63 | { 64 | Log(L"[-] Failed to change page protections" << std::endl); 65 | intel_driver::MmFreeIndependentPages(device_handle, base, size); 66 | return 0; 67 | } 68 | 69 | return base; 70 | } 71 | 72 | uint64_t kdmapper::MapDriver(HANDLE iqvw64e_device_handle, BYTE* data, ULONG64 param1, ULONG64 param2, bool free, bool remove_from_system_page_tables ,bool destroyHeader, AllocationMode mode, bool PassAllocationAddressAsFirstParam, bool PassSizeAsSecondParam,mapCallback callback, NTSTATUS* exitCode) { 73 | 74 | const PIMAGE_NT_HEADERS64 nt_headers = portable_executable::GetNtHeaders(data); 75 | 76 | if (!nt_headers) { 77 | Log(L"[-] Invalid format of PE image" << std::endl); 78 | return 0; 79 | } 80 | 81 | if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) { 82 | Log(L"[-] Image is not 64 bit" << std::endl); 83 | return 0; 84 | } 85 | 86 | uint32_t image_size = nt_headers->OptionalHeader.SizeOfImage; 87 | 88 | void* local_image_base = VirtualAlloc(nullptr, image_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 89 | if (!local_image_base) 90 | return 0; 91 | 92 | DWORD TotalVirtualHeaderSize = (IMAGE_FIRST_SECTION(nt_headers))->VirtualAddress; 93 | image_size = image_size - (destroyHeader ? TotalVirtualHeaderSize : 0); 94 | 95 | uint64_t kernel_image_base = 0; 96 | uint64_t mdlptr = 0; 97 | if (mode == AllocationMode::AllocateMdl) { 98 | kernel_image_base = AllocMdlMemory(iqvw64e_device_handle, image_size, &mdlptr); 99 | } 100 | else if (mode == AllocationMode::AllocateIndependentPages) { 101 | kernel_image_base = AllocIndependentPages(iqvw64e_device_handle, image_size); 102 | } 103 | else if (mode == AllocationMode::AllocateContiguousMemory) { 104 | kernel_image_base = intel_driver::AllocContiguousMemory(iqvw64e_device_handle, image_size); 105 | } 106 | else { // AllocatePool by default 107 | kernel_image_base = intel_driver::AllocatePool(iqvw64e_device_handle, nt::POOL_TYPE::NonPagedPool, image_size); 108 | } 109 | 110 | if (!kernel_image_base) { 111 | Log(L"[-] Failed to allocate remote image in kernel" << std::endl); 112 | 113 | VirtualFree(local_image_base, 0, MEM_RELEASE); 114 | return 0; 115 | } 116 | 117 | do { 118 | Log(L"[+] Image base has been allocated at 0x" << reinterpret_cast(kernel_image_base) << std::endl); 119 | 120 | // Copy image headers 121 | 122 | memcpy(local_image_base, data, nt_headers->OptionalHeader.SizeOfHeaders); 123 | 124 | // Copy image sections 125 | 126 | const PIMAGE_SECTION_HEADER current_image_section = IMAGE_FIRST_SECTION(nt_headers); 127 | 128 | for (auto i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i) { 129 | if ((current_image_section[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) > 0) 130 | continue; 131 | auto local_section = reinterpret_cast(reinterpret_cast(local_image_base) + current_image_section[i].VirtualAddress); 132 | memcpy(local_section, reinterpret_cast(reinterpret_cast(data) + current_image_section[i].PointerToRawData), current_image_section[i].SizeOfRawData); 133 | } 134 | 135 | uint64_t realBase = kernel_image_base; 136 | if (destroyHeader) { 137 | kernel_image_base -= TotalVirtualHeaderSize; 138 | Log(L"[+] Skipped 0x" << std::hex << TotalVirtualHeaderSize << L" bytes of PE Header" << std::endl); 139 | } 140 | 141 | // Resolve relocs and imports 142 | 143 | RelocateImageByDelta(portable_executable::GetRelocs(local_image_base), kernel_image_base - nt_headers->OptionalHeader.ImageBase); 144 | 145 | if (!FixSecurityCookie(local_image_base, kernel_image_base)) 146 | { 147 | Log(L"[-] Failed to fix cookie" << std::endl); 148 | return 0; 149 | } 150 | 151 | if (!ResolveImports(iqvw64e_device_handle, portable_executable::GetImports(local_image_base))) { 152 | Log(L"[-] Failed to resolve imports" << std::endl); 153 | kernel_image_base = realBase; 154 | break; 155 | } 156 | 157 | // Write fixed image to kernel 158 | 159 | if (!intel_driver::WriteMemory(iqvw64e_device_handle, realBase, (PVOID)((uintptr_t)local_image_base + (destroyHeader ? TotalVirtualHeaderSize : 0)), image_size)) { 160 | Log(L"[-] Failed to write local image to remote image" << std::endl); 161 | kernel_image_base = realBase; 162 | break; 163 | } 164 | 165 | // Call driver entry point 166 | 167 | const uint64_t address_of_entry_point = kernel_image_base + nt_headers->OptionalHeader.AddressOfEntryPoint; 168 | 169 | Log(L"[<] Calling DriverEntry 0x" << reinterpret_cast(address_of_entry_point) << std::endl); 170 | 171 | if (callback) { 172 | if (!callback(¶m1, ¶m2, realBase, image_size, mdlptr)) { 173 | Log(L"[-] Callback returns false, failed!" << std::endl); 174 | kernel_image_base = realBase; 175 | break; 176 | } 177 | } 178 | 179 | NTSTATUS status = 0; 180 | if (!intel_driver::CallKernelFunction(iqvw64e_device_handle, &status, address_of_entry_point, PassAllocationAddressAsFirstParam ? realBase : 0, PassSizeAsSecondParam ? image_size : 0)) { 181 | Log(L"[-] Failed to call driver entry" << std::endl); 182 | kernel_image_base = realBase; 183 | break; 184 | } 185 | 186 | if (exitCode) 187 | *exitCode = status; 188 | 189 | Log(L"[+] DriverEntry returned 0x" << std::hex << status << std::endl); 190 | 191 | uint64_t physical_image_base = 0; 192 | 193 | if (remove_from_system_page_tables) { 194 | 195 | // Get the physical image base if we want to remove it from physmem before we free it 196 | if (!intel_driver::GetPhysicalAddress(iqvw64e_device_handle, kernel_image_base, &physical_image_base)) { 197 | Log("[-] Failed to get physical image base"); 198 | return false; 199 | } 200 | } 201 | 202 | // Free memory 203 | if (free) { 204 | Log(L"[+] Freeing memory" << std::endl); 205 | bool free_status = false; 206 | 207 | if (mode == AllocationMode::AllocateMdl) { 208 | free_status = intel_driver::MmUnmapLockedPages(iqvw64e_device_handle, realBase, mdlptr); 209 | free_status = (!free_status ? false : intel_driver::MmFreePagesFromMdl(iqvw64e_device_handle, mdlptr)); 210 | free_status = (!free_status ? false : intel_driver::FreePool(iqvw64e_device_handle, mdlptr)); 211 | } 212 | else if (mode == AllocationMode::AllocateIndependentPages) 213 | { 214 | free_status = intel_driver::MmFreeIndependentPages(iqvw64e_device_handle, realBase, image_size); 215 | } 216 | else if (mode == AllocationMode::AllocateContiguousMemory) { 217 | free_status = intel_driver::FreeContiguousMemory(iqvw64e_device_handle, realBase); 218 | } 219 | else { 220 | free_status = intel_driver::FreePool(iqvw64e_device_handle, realBase); 221 | } 222 | 223 | if (free_status) { 224 | Log(L"[+] Memory has been released" << std::endl); 225 | } 226 | else { 227 | Log(L"[-] WARNING: Failed to free memory!" << std::endl); 228 | } 229 | } 230 | 231 | if (remove_from_system_page_tables) { 232 | LARGE_INTEGER size = { 0 }; 233 | LARGE_INTEGER lphys_base = { 0 }; 234 | 235 | size.QuadPart = image_size; 236 | lphys_base.QuadPart = physical_image_base; 237 | 238 | if (!intel_driver::RemovePhysicalMemory(iqvw64e_device_handle, &lphys_base, &size)) { 239 | Log(L"[-] Failed to remove physical memory!" << std::endl); 240 | } 241 | 242 | Log(L"[+] Memory has removed from system page tables" << std::endl); 243 | } 244 | 245 | VirtualFree(local_image_base, 0, MEM_RELEASE); 246 | return realBase; 247 | 248 | } while (false); 249 | 250 | 251 | VirtualFree(local_image_base, 0, MEM_RELEASE); 252 | 253 | Log(L"[+] Freeing memory" << std::endl); 254 | bool free_status = false; 255 | 256 | if (mode == AllocationMode::AllocateMdl) { 257 | free_status = intel_driver::MmUnmapLockedPages(iqvw64e_device_handle, kernel_image_base, mdlptr); 258 | free_status = (!free_status ? false : intel_driver::MmFreePagesFromMdl(iqvw64e_device_handle, mdlptr)); 259 | free_status = (!free_status ? false : intel_driver::FreePool(iqvw64e_device_handle, mdlptr)); 260 | } 261 | else if (mode == AllocationMode::AllocateIndependentPages) 262 | { 263 | free_status = intel_driver::MmFreeIndependentPages(iqvw64e_device_handle, kernel_image_base, image_size); 264 | } 265 | else if (mode == AllocationMode::AllocateContiguousMemory) { 266 | free_status = intel_driver::FreeContiguousMemory(iqvw64e_device_handle, kernel_image_base); 267 | } 268 | else { 269 | free_status = intel_driver::FreePool(iqvw64e_device_handle, kernel_image_base); 270 | } 271 | 272 | if (free_status) { 273 | Log(L"[+] Memory has been released" << std::endl); 274 | } 275 | else { 276 | Log(L"[-] WARNING: Failed to free memory!" << std::endl); 277 | } 278 | 279 | return 0; 280 | } 281 | 282 | void kdmapper::RelocateImageByDelta(portable_executable::vec_relocs relocs, const uint64_t delta) { 283 | for (const auto& current_reloc : relocs) { 284 | for (auto i = 0u; i < current_reloc.count; ++i) { 285 | const uint16_t type = current_reloc.item[i] >> 12; 286 | const uint16_t offset = current_reloc.item[i] & 0xFFF; 287 | 288 | if (type == IMAGE_REL_BASED_DIR64) 289 | *reinterpret_cast(current_reloc.address + offset) += delta; 290 | } 291 | } 292 | } 293 | 294 | // Fix cookie by @Jerem584 295 | bool kdmapper::FixSecurityCookie(void* local_image, uint64_t kernel_image_base) 296 | { 297 | auto headers = portable_executable::GetNtHeaders(local_image); 298 | if (!headers) 299 | return false; 300 | 301 | auto load_config_directory = headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress; 302 | if (!load_config_directory) 303 | { 304 | Log(L"[+] Load config directory wasn't found, probably StackCookie not defined, fix cookie skipped" << std::endl); 305 | return true; 306 | } 307 | 308 | auto load_config_struct = (PIMAGE_LOAD_CONFIG_DIRECTORY)((uintptr_t)local_image + load_config_directory); 309 | auto stack_cookie = load_config_struct->SecurityCookie; 310 | if (!stack_cookie) 311 | { 312 | Log(L"[+] StackCookie not defined, fix cookie skipped" << std::endl); 313 | return true; // as I said, it is not an error and we should allow that behavior 314 | } 315 | 316 | stack_cookie = stack_cookie - (uintptr_t)kernel_image_base + (uintptr_t)local_image; //since our local image is already relocated the base returned will be kernel address 317 | 318 | if (*(uintptr_t*)(stack_cookie) != 0x2B992DDFA232) { 319 | Log(L"[-] StackCookie already fixed!? this probably wrong" << std::endl); 320 | return false; 321 | } 322 | 323 | Log(L"[+] Fixing stack cookie" << std::endl); 324 | 325 | auto new_cookie = 0x2B992DDFA232 ^ GetCurrentProcessId() ^ GetCurrentThreadId(); // here we don't really care about the value of stack cookie, it will still works and produce nice result 326 | if (new_cookie == 0x2B992DDFA232) 327 | new_cookie = 0x2B992DDFA233; 328 | 329 | *(uintptr_t*)(stack_cookie) = new_cookie; // the _security_cookie_complement will be init by the driver itself if they use crt 330 | return true; 331 | } 332 | 333 | bool kdmapper::ResolveImports(HANDLE iqvw64e_device_handle, portable_executable::vec_imports imports) { 334 | for (const auto& current_import : imports) { 335 | ULONG64 Module = utils::GetKernelModuleAddress(current_import.module_name); 336 | if (!Module) { 337 | #if !defined(DISABLE_OUTPUT) 338 | std::cout << "[-] Dependency " << current_import.module_name << " wasn't found" << std::endl; 339 | #endif 340 | return false; 341 | } 342 | 343 | for (auto& current_function_data : current_import.function_datas) { 344 | uint64_t function_address = intel_driver::GetKernelModuleExport(iqvw64e_device_handle, Module, current_function_data.name); 345 | 346 | if (!function_address) { 347 | //Lets try with ntoskrnl 348 | if (Module != intel_driver::ntoskrnlAddr) { 349 | function_address = intel_driver::GetKernelModuleExport(iqvw64e_device_handle, intel_driver::ntoskrnlAddr, current_function_data.name); 350 | if (!function_address) { 351 | #if !defined(DISABLE_OUTPUT) 352 | std::cout << "[-] Failed to resolve import " << current_function_data.name << " (" << current_import.module_name << ")" << std::endl; 353 | #endif 354 | return false; 355 | } 356 | } 357 | } 358 | 359 | *current_function_data.address = function_address; 360 | } 361 | } 362 | 363 | return true; 364 | } 365 | -------------------------------------------------------------------------------- /mapper/my_mapper/main.cpp: -------------------------------------------------------------------------------- 1 | #ifndef KDLIBMODE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "includes/kdmapper.hpp" 9 | 10 | HANDLE iqvw64e_device_handle; 11 | 12 | 13 | LONG WINAPI SimplestCrashHandler(EXCEPTION_POINTERS* ExceptionInfo) 14 | { 15 | if (ExceptionInfo && ExceptionInfo->ExceptionRecord) 16 | Log(L"[!!] Crash at addr 0x" << ExceptionInfo->ExceptionRecord->ExceptionAddress << L" by 0x" << std::hex << ExceptionInfo->ExceptionRecord->ExceptionCode << std::endl); 17 | else 18 | Log(L"[!!] Crash" << std::endl); 19 | 20 | if (iqvw64e_device_handle) 21 | intel_driver::Unload(iqvw64e_device_handle); 22 | 23 | return EXCEPTION_EXECUTE_HANDLER; 24 | } 25 | 26 | int paramExists(const int argc, wchar_t** argv, const wchar_t* param) { 27 | size_t plen = wcslen(param); 28 | for (int i = 1; i < argc; i++) { 29 | if (wcslen(argv[i]) == plen + 1ull && _wcsicmp(&argv[i][1], param) == 0 && argv[i][0] == '/') { // with slash 30 | return i; 31 | } 32 | else if (wcslen(argv[i]) == plen + 2ull && _wcsicmp(&argv[i][2], param) == 0 && argv[i][0] == '-' && argv[i][1] == '-') { // with double dash 33 | return i; 34 | } 35 | } 36 | return -1; 37 | } 38 | 39 | void help() { 40 | Log(L"\r\n\r\n[!] Incorrect Usage!" << std::endl); 41 | Log(L"[+] Usage: kdmapper.exe [--free][--mdl][--PassAllocationPtr] driver" << std::endl); 42 | } 43 | 44 | bool callbackExample(ULONG64* param1, ULONG64* param2, ULONG64 allocationPtr, ULONG64 allocationSize, ULONG64 mdlptr) { 45 | UNREFERENCED_PARAMETER(param1); 46 | UNREFERENCED_PARAMETER(param2); 47 | UNREFERENCED_PARAMETER(allocationPtr); 48 | UNREFERENCED_PARAMETER(allocationSize); 49 | UNREFERENCED_PARAMETER(mdlptr); 50 | Log("[+] Callback example called" << std::endl); 51 | 52 | /* 53 | This callback occurs before call driver entry and 54 | can be usefull to pass more customized params in 55 | the last step of the mapping procedure since you 56 | know now the mapping address and other things 57 | */ 58 | return true; 59 | } 60 | 61 | DWORD getParentProcess() 62 | { 63 | HANDLE hSnapshot; 64 | PROCESSENTRY32 pe32; 65 | DWORD ppid = 0, pid = GetCurrentProcessId(); 66 | 67 | hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 68 | __try { 69 | if (hSnapshot == INVALID_HANDLE_VALUE) __leave; 70 | 71 | ZeroMemory(&pe32, sizeof(pe32)); 72 | pe32.dwSize = sizeof(pe32); 73 | if (!Process32First(hSnapshot, &pe32)) __leave; 74 | 75 | do { 76 | if (pe32.th32ProcessID == pid) { 77 | ppid = pe32.th32ParentProcessID; 78 | break; 79 | } 80 | } while (Process32Next(hSnapshot, &pe32)); 81 | 82 | } 83 | __finally { 84 | if (hSnapshot != INVALID_HANDLE_VALUE) CloseHandle(hSnapshot); 85 | } 86 | return ppid; 87 | } 88 | 89 | //Help people that don't understand how to open a console 90 | void PauseIfParentIsExplorer() { 91 | DWORD explorerPid = 0; 92 | GetWindowThreadProcessId(GetShellWindow(), &explorerPid); 93 | DWORD parentPid = getParentProcess(); 94 | if (parentPid == explorerPid) { 95 | Log(L"[+] Pausing to allow for debugging" << std::endl); 96 | Log(L"[+] Press enter to close" << std::endl); 97 | std::cin.get(); 98 | } 99 | } 100 | 101 | int wmain(const int argc, wchar_t** argv) { 102 | SetUnhandledExceptionFilter(SimplestCrashHandler); 103 | 104 | bool free = paramExists(argc, argv, L"free") > 0; 105 | bool mdlMode = paramExists(argc, argv, L"mdl") > 0; 106 | bool indPagesMode = paramExists(argc, argv, L"indPages") > 0; 107 | bool passAllocationPtr = paramExists(argc, argv, L"PassAllocationPtr") > 0; 108 | 109 | if (free) { 110 | Log(L"[+] Free pool memory after usage enabled" << std::endl); 111 | } 112 | 113 | if (mdlMode) { 114 | Log(L"[+] Mdl memory usage enabled" << std::endl); 115 | } 116 | 117 | if (indPagesMode) { 118 | Log(L"[+] Allocate Independent Pages mode enabled" << std::endl); 119 | } 120 | 121 | if (passAllocationPtr) { 122 | Log(L"[+] Pass Allocation Ptr as first param enabled" << std::endl); 123 | } 124 | 125 | int drvIndex = -1; 126 | for (int i = 1; i < argc; i++) { 127 | if (std::filesystem::path(argv[i]).extension().string().compare(".sys") == 0) { 128 | drvIndex = i; 129 | break; 130 | } 131 | } 132 | 133 | if (drvIndex <= 0) { 134 | help(); 135 | return -1; 136 | } 137 | 138 | const std::wstring driver_path = argv[drvIndex]; 139 | 140 | if (!std::filesystem::exists(driver_path)) { 141 | Log(L"[-] File " << driver_path << L" doesn't exist" << std::endl); 142 | PauseIfParentIsExplorer(); 143 | return -1; 144 | } 145 | 146 | iqvw64e_device_handle = intel_driver::Load(); 147 | 148 | if (iqvw64e_device_handle == INVALID_HANDLE_VALUE) { 149 | PauseIfParentIsExplorer(); 150 | return -1; 151 | } 152 | 153 | std::vector raw_image = { 0 }; 154 | if (!utils::ReadFileToMemory(driver_path, &raw_image)) { 155 | Log(L"[-] Failed to read image to memory" << std::endl); 156 | intel_driver::Unload(iqvw64e_device_handle); 157 | PauseIfParentIsExplorer(); 158 | return -1; 159 | } 160 | 161 | kdmapper::AllocationMode mode = kdmapper::AllocationMode::AllocateContiguousMemory; 162 | 163 | bool free_mem = false; //change it to false if we're using the driver api call -> hide_driver 164 | bool remove_from_system_page_tables = false; //change it to false if we're using the driver api call -> hide_driver 165 | bool destroy_header = false; 166 | bool pass_allocation = true; 167 | bool pass_size = true; 168 | 169 | 170 | NTSTATUS exitCode = 0; 171 | if (!kdmapper::MapDriver(iqvw64e_device_handle, raw_image.data(), 0, 0, free_mem, remove_from_system_page_tables, destroy_header, mode, pass_allocation, pass_size, callbackExample, &exitCode)) { 172 | Log(L"[-] Failed to map " << driver_path << std::endl); 173 | intel_driver::Unload(iqvw64e_device_handle); 174 | PauseIfParentIsExplorer(); 175 | return -1; 176 | } 177 | 178 | if (!intel_driver::Unload(iqvw64e_device_handle)) { 179 | Log(L"[-] Warning failed to fully unload vulnerable driver " << std::endl); 180 | PauseIfParentIsExplorer(); 181 | } 182 | Log(L"[+] success" << std::endl); 183 | } 184 | 185 | #endif -------------------------------------------------------------------------------- /mapper/my_mapper/my_mapper.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Release 6 | x64 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 16.0 28 | Win32Proj 29 | {278b99ac-c438-472a-8272-79f83def7f7d} 30 | mymapper 31 | 10.0 32 | mapper 33 | 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | ..\..\output directory\ 53 | .\intermediate directory\ 54 | mapper 55 | 56 | 57 | 58 | Level3 59 | true 60 | true 61 | true 62 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 63 | true 64 | stdcpp20 65 | stdc17 66 | StdCall 67 | 68 | 69 | Console 70 | true 71 | true 72 | true 73 | RequireAdministrator 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /mapper/my_mapper/my_mapper.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8035dce0-3979-4627-9248-788a95799d0e} 18 | 19 | 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | 41 | 42 | Source Files\includes 43 | 44 | 45 | Source Files\includes 46 | 47 | 48 | Source Files\includes 49 | 50 | 51 | Source Files\includes 52 | 53 | 54 | Source Files\includes 55 | 56 | 57 | Source Files\includes 58 | 59 | 60 | Source Files\includes 61 | 62 | 63 | -------------------------------------------------------------------------------- /mapper/my_mapper/portable_executable.cpp: -------------------------------------------------------------------------------- 1 | #include "includes/portable_executable.hpp" 2 | 3 | PIMAGE_NT_HEADERS64 portable_executable::GetNtHeaders(void* image_base) { 4 | const auto dos_header = reinterpret_cast(image_base); 5 | 6 | if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) 7 | return nullptr; 8 | 9 | const auto nt_headers = reinterpret_cast(reinterpret_cast(image_base) + dos_header->e_lfanew); 10 | 11 | if (nt_headers->Signature != IMAGE_NT_SIGNATURE) 12 | return nullptr; 13 | 14 | return nt_headers; 15 | } 16 | 17 | portable_executable::vec_relocs portable_executable::GetRelocs(void* image_base) { 18 | const PIMAGE_NT_HEADERS64 nt_headers = GetNtHeaders(image_base); 19 | 20 | if (!nt_headers) 21 | return {}; 22 | 23 | vec_relocs relocs; 24 | DWORD reloc_va = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; 25 | 26 | if (!reloc_va) //Fix from @greetmark of UnknownCheats Forum 27 | return {}; 28 | 29 | auto current_base_relocation = reinterpret_cast(reinterpret_cast(image_base) + reloc_va); 30 | const auto reloc_end = reinterpret_cast(reinterpret_cast(current_base_relocation) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); 31 | 32 | while (current_base_relocation < reloc_end && current_base_relocation->SizeOfBlock) { 33 | RelocInfo reloc_info; 34 | 35 | reloc_info.address = reinterpret_cast(image_base) + current_base_relocation->VirtualAddress; 36 | reloc_info.item = reinterpret_cast(reinterpret_cast(current_base_relocation) + sizeof(IMAGE_BASE_RELOCATION)); 37 | reloc_info.count = (current_base_relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(uint16_t); 38 | 39 | relocs.push_back(reloc_info); 40 | 41 | current_base_relocation = reinterpret_cast(reinterpret_cast(current_base_relocation) + current_base_relocation->SizeOfBlock); 42 | } 43 | 44 | return relocs; 45 | } 46 | 47 | portable_executable::vec_imports portable_executable::GetImports(void* image_base) { 48 | const PIMAGE_NT_HEADERS64 nt_headers = GetNtHeaders(image_base); 49 | 50 | if (!nt_headers) 51 | return {}; 52 | 53 | DWORD import_va = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 54 | 55 | //not imports necesary 56 | if (!import_va) 57 | return {}; 58 | 59 | vec_imports imports; 60 | 61 | auto current_import_descriptor = reinterpret_cast(reinterpret_cast(image_base) + import_va); 62 | 63 | while (current_import_descriptor->FirstThunk) { 64 | ImportInfo import_info; 65 | 66 | import_info.module_name = std::string(reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->Name)); 67 | 68 | auto current_first_thunk = reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->FirstThunk); 69 | auto current_originalFirstThunk = reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->OriginalFirstThunk); 70 | 71 | while (current_originalFirstThunk->u1.Function) { 72 | ImportFunctionInfo import_function_data; 73 | 74 | auto thunk_data = reinterpret_cast(reinterpret_cast(image_base) + current_originalFirstThunk->u1.AddressOfData); 75 | 76 | import_function_data.name = thunk_data->Name; 77 | import_function_data.address = ¤t_first_thunk->u1.Function; 78 | 79 | import_info.function_datas.push_back(import_function_data); 80 | 81 | ++current_originalFirstThunk; 82 | ++current_first_thunk; 83 | } 84 | 85 | imports.push_back(import_info); 86 | ++current_import_descriptor; 87 | } 88 | 89 | return imports; 90 | } -------------------------------------------------------------------------------- /mapper/my_mapper/service.cpp: -------------------------------------------------------------------------------- 1 | #include "includes/service.hpp" 2 | 3 | bool service::RegisterAndStart(const std::wstring& driver_path) { 4 | const static DWORD ServiceTypeKernel = 1; 5 | const std::wstring driver_name = intel_driver::GetDriverNameW(); 6 | const std::wstring servicesPath = L"SYSTEM\\CurrentControlSet\\Services\\" + driver_name; 7 | const std::wstring nPath = L"\\??\\" + driver_path; 8 | 9 | HKEY dservice; 10 | LSTATUS status = RegCreateKeyW(HKEY_LOCAL_MACHINE, servicesPath.c_str(), &dservice); //Returns Ok if already exists 11 | if (status != ERROR_SUCCESS) { 12 | Log("[-] Can't create service key" << std::endl); 13 | return false; 14 | } 15 | 16 | status = RegSetKeyValueW(dservice, NULL, L"ImagePath", REG_EXPAND_SZ, nPath.c_str(), (DWORD)(nPath.size()*sizeof(wchar_t))); 17 | if (status != ERROR_SUCCESS) { 18 | RegCloseKey(dservice); 19 | Log("[-] Can't create 'ImagePath' registry value" << std::endl); 20 | return false; 21 | } 22 | 23 | status = RegSetKeyValueW(dservice, NULL, L"Type", REG_DWORD, &ServiceTypeKernel, sizeof(DWORD)); 24 | if (status != ERROR_SUCCESS) { 25 | RegCloseKey(dservice); 26 | Log("[-] Can't create 'Type' registry value" << std::endl); 27 | return false; 28 | } 29 | 30 | RegCloseKey(dservice); 31 | 32 | HMODULE ntdll = GetModuleHandleA("ntdll.dll"); 33 | if (ntdll == NULL) { 34 | return false; 35 | } 36 | 37 | auto RtlAdjustPrivilege = (nt::RtlAdjustPrivilege)GetProcAddress(ntdll, "RtlAdjustPrivilege"); 38 | auto NtLoadDriver = (nt::NtLoadDriver)GetProcAddress(ntdll, "NtLoadDriver"); 39 | 40 | ULONG SE_LOAD_DRIVER_PRIVILEGE = 10UL; 41 | BOOLEAN SeLoadDriverWasEnabled; 42 | NTSTATUS Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE, &SeLoadDriverWasEnabled); 43 | if (!NT_SUCCESS(Status)) { 44 | Log("Fatal error: failed to acquire SE_LOAD_DRIVER_PRIVILEGE. Make sure you are running as administrator." << std::endl); 45 | return false; 46 | } 47 | 48 | std::wstring wdriver_reg_path = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + driver_name; 49 | UNICODE_STRING serviceStr; 50 | RtlInitUnicodeString(&serviceStr, wdriver_reg_path.c_str()); 51 | 52 | Status = NtLoadDriver(&serviceStr); 53 | 54 | 55 | Log("[+] NtLoadDriver Status 0x" << std::hex << Status << std::endl); 56 | 57 | if (Status == 0xC0000603) { //STATUS_IMAGE_CERT_REVOKED 58 | Log("[-] Your vulnerable driver list is enabled and have blocked the driver loading, you must disable vulnerable driver list to use kdmapper with intel driver" << std::endl); 59 | Log("[-] Registry path to disable vulnerable driver list: HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\CI\\Config" << std::endl); 60 | Log("[-] Set 'VulnerableDriverBlocklistEnable' as dword to 0" << std::endl); 61 | } 62 | 63 | 64 | //Never should occur since kdmapper checks for "IsRunning" driver before 65 | if (Status == 0xC000010E) {// STATUS_IMAGE_ALREADY_LOADED 66 | return true; 67 | } 68 | 69 | return NT_SUCCESS(Status); 70 | } 71 | 72 | bool service::StopAndRemove(const std::wstring& driver_name) { 73 | HMODULE ntdll = GetModuleHandleA("ntdll.dll"); 74 | if (ntdll == NULL) 75 | return false; 76 | 77 | std::wstring wdriver_reg_path = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + driver_name; 78 | UNICODE_STRING serviceStr; 79 | RtlInitUnicodeString(&serviceStr, wdriver_reg_path.c_str()); 80 | 81 | HKEY driver_service; 82 | std::wstring servicesPath = L"SYSTEM\\CurrentControlSet\\Services\\" + driver_name; 83 | LSTATUS status = RegOpenKeyW(HKEY_LOCAL_MACHINE, servicesPath.c_str(), &driver_service); 84 | if (status != ERROR_SUCCESS) { 85 | if (status == ERROR_FILE_NOT_FOUND) { 86 | return true; 87 | } 88 | return false; 89 | } 90 | RegCloseKey(driver_service); 91 | 92 | auto NtUnloadDriver = (nt::NtUnloadDriver)GetProcAddress(ntdll, "NtUnloadDriver"); 93 | NTSTATUS st = NtUnloadDriver(&serviceStr); 94 | Log("[+] NtUnloadDriver Status 0x" << std::hex << st << std::endl); 95 | if (st != 0x0) { 96 | Log("[-] Driver Unload Failed!!" << std::endl); 97 | status = RegDeleteTreeW(HKEY_LOCAL_MACHINE, servicesPath.c_str()); 98 | return false; //lets consider unload fail as error because can cause problems with anti cheats later 99 | } 100 | 101 | 102 | status = RegDeleteTreeW(HKEY_LOCAL_MACHINE, servicesPath.c_str()); 103 | if (status != ERROR_SUCCESS) { 104 | return false; 105 | } 106 | return true; 107 | } 108 | -------------------------------------------------------------------------------- /mapper/my_mapper/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "includes/utils.hpp" 2 | 3 | std::wstring utils::GetFullTempPath() { 4 | wchar_t temp_directory[MAX_PATH + 1] = { 0 }; 5 | const uint32_t get_temp_path_ret = GetTempPathW(sizeof(temp_directory) / 2, temp_directory); 6 | if (!get_temp_path_ret || get_temp_path_ret > MAX_PATH + 1) { 7 | Log(L"[-] Failed to get temp path" << std::endl); 8 | return L""; 9 | } 10 | if (temp_directory[wcslen(temp_directory) - 1] == L'\\') 11 | temp_directory[wcslen(temp_directory) - 1] = 0x0; 12 | 13 | return std::wstring(temp_directory); 14 | } 15 | 16 | bool utils::ReadFileToMemory(const std::wstring& file_path, std::vector* out_buffer) { 17 | std::ifstream file_ifstream(file_path, std::ios::binary); 18 | 19 | if (!file_ifstream) 20 | return false; 21 | 22 | out_buffer->assign((std::istreambuf_iterator(file_ifstream)), std::istreambuf_iterator()); 23 | file_ifstream.close(); 24 | 25 | return true; 26 | } 27 | 28 | bool utils::CreateFileFromMemory(const std::wstring& desired_file_path, const char* address, size_t size) { 29 | std::ofstream file_ofstream(desired_file_path.c_str(), std::ios_base::out | std::ios_base::binary); 30 | 31 | if (!file_ofstream.write(address, size)) { 32 | file_ofstream.close(); 33 | return false; 34 | } 35 | 36 | file_ofstream.close(); 37 | return true; 38 | } 39 | 40 | uint64_t utils::GetKernelModuleAddress(const std::string& module_name) { 41 | void* buffer = nullptr; 42 | DWORD buffer_size = 0; 43 | 44 | NTSTATUS status = NtQuerySystemInformation(static_cast(nt::SystemModuleInformation), buffer, buffer_size, &buffer_size); 45 | 46 | while (status == nt::STATUS_INFO_LENGTH_MISMATCH) { 47 | if (buffer != nullptr) 48 | VirtualFree(buffer, 0, MEM_RELEASE); 49 | 50 | buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 51 | status = NtQuerySystemInformation(static_cast(nt::SystemModuleInformation), buffer, buffer_size, &buffer_size); 52 | } 53 | 54 | if (!NT_SUCCESS(status)) { 55 | if (buffer != nullptr) 56 | VirtualFree(buffer, 0, MEM_RELEASE); 57 | return 0; 58 | } 59 | 60 | const auto modules = static_cast(buffer); 61 | if (!modules) 62 | return 0; 63 | 64 | for (auto i = 0u; i < modules->NumberOfModules; ++i) { 65 | const std::string current_module_name = std::string(reinterpret_cast(modules->Modules[i].FullPathName) + modules->Modules[i].OffsetToFileName); 66 | 67 | if (!_stricmp(current_module_name.c_str(), module_name.c_str())) 68 | { 69 | const uint64_t result = reinterpret_cast(modules->Modules[i].ImageBase); 70 | 71 | VirtualFree(buffer, 0, MEM_RELEASE); 72 | return result; 73 | } 74 | } 75 | 76 | VirtualFree(buffer, 0, MEM_RELEASE); 77 | return 0; 78 | } 79 | 80 | BOOLEAN utils::bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask) { 81 | for (; *szMask; ++szMask, ++pData, ++bMask) 82 | if (*szMask == 'x' && *pData != *bMask) 83 | return 0; 84 | return (*szMask) == 0; 85 | } 86 | 87 | uintptr_t utils::FindPattern(uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, const char* szMask) { 88 | size_t max_len = dwLen - strlen(szMask); 89 | for (uintptr_t i = 0; i < max_len; i++) 90 | if (bDataCompare((BYTE*)(dwAddress + i), bMask, szMask)) 91 | return (uintptr_t)(dwAddress + i); 92 | return 0; 93 | } 94 | 95 | PVOID utils::FindSection(const char* sectionName, uintptr_t modulePtr, PULONG size) { 96 | size_t namelength = strlen(sectionName); 97 | PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)(modulePtr + ((PIMAGE_DOS_HEADER)modulePtr)->e_lfanew); 98 | PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(headers); 99 | for (DWORD i = 0; i < headers->FileHeader.NumberOfSections; ++i) { 100 | PIMAGE_SECTION_HEADER section = §ions[i]; 101 | if (memcmp(section->Name, sectionName, namelength) == 0 && 102 | namelength == strlen((char*)section->Name)) { 103 | if (!section->VirtualAddress) { 104 | return 0; 105 | } 106 | if (size) { 107 | *size = section->Misc.VirtualSize; 108 | } 109 | return (PVOID)(modulePtr + section->VirtualAddress); 110 | } 111 | } 112 | return 0; 113 | } -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/main.cpp: -------------------------------------------------------------------------------- 1 | #include "project/project_api.hpp" 2 | 3 | NTSTATUS driver_entry(void* driver_base, uint64_t driver_size) { 4 | project_log_success("Driver loaded at %p with size %p", driver_base, driver_size); 5 | 6 | if (!driver_base || !driver_size) { 7 | project_log_success("Wrong usage: You have to pass the allocation base and the allocation size of the driver pool to the driver_entry!"); 8 | return STATUS_UNSUCCESSFUL; 9 | } 10 | 11 | g_driver_base = driver_base; 12 | g_driver_size = driver_size; 13 | 14 | project_status status = status_success; 15 | status = interrupts::init_interrupts(); 16 | if (status != status_success) { 17 | project_log_error("Failed to init interrupts with status %d", status); 18 | return STATUS_UNSUCCESSFUL; 19 | } 20 | 21 | status = physmem::init_physmem(); 22 | if (status != status_success) { 23 | project_log_error("Failed to init physmem with status %d", status); 24 | return STATUS_UNSUCCESSFUL; 25 | } 26 | 27 | status = cr3_decryption::init_eac_cr3_decryption(); 28 | if (status != status_success) { 29 | project_log_error("Failed to init cr3 decryption with status %d", status); 30 | return STATUS_UNSUCCESSFUL; 31 | } 32 | 33 | status = logging::init_root_logger(); 34 | if (status != status_success) { 35 | project_log_error("Failed to init logger with status %d", status); 36 | return STATUS_UNSUCCESSFUL; 37 | } 38 | 39 | status = communication::init_communication(driver_base, driver_size); 40 | if (status != status_success) { 41 | project_log_error("Failed to init communication with status %d", status); 42 | return STATUS_UNSUCCESSFUL; 43 | } 44 | 45 | project_log_success("Loading process finished sucessfully"); 46 | 47 | return STATUS_SUCCESS; 48 | } -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/physmem_remapper_rewrite.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Release 7 | x64 8 | 9 | 10 | 11 | {0b8eacb8-a4b3-4f37-ba0c-2aa50f087351} 12 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 13 | v4.5 14 | 12.0 15 | Debug 16 | x64 17 | physmem_remapper_rewrite 18 | $(LatestTargetPlatformVersion) 19 | driver 20 | 21 | 22 | 23 | Windows10 24 | false 25 | WindowsKernelModeDriver10.0 26 | Driver 27 | WDM 28 | Spectre 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | DbgengKernelDebugger 40 | ..\..\output directory\ 41 | .\intermediate directory\ 42 | remapper 43 | false 44 | 45 | 46 | 47 | sha256 48 | 49 | 50 | driver_entry 51 | 52 | 53 | stdcpp20 54 | 55 | 56 | stdc17 57 | MaxSpeed 58 | true 59 | 4201;4996;%(DisableSpecificWarnings) 60 | false 61 | Default 62 | false 63 | Speed 64 | false 65 | false 66 | 67 | 68 | Cdecl 69 | true 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/physmem_remapper_rewrite.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {e46b5aa0-d56e-4797-993d-7854526a02d4} 10 | 11 | 12 | {329363f3-aea4-4e88-aa7f-8810da83ab50} 13 | 14 | 15 | {57daedc6-f132-4146-be4b-6acd50789b4b} 16 | 17 | 18 | {57735056-3050-4cc8-aa8c-bcfde2acc6c5} 19 | 20 | 21 | {09f662ba-097b-43ea-8aa3-544329a8947a} 22 | 23 | 24 | {096ab70b-e180-4e88-90f7-c99514cd23ef} 25 | 26 | 27 | {87dae439-1c8c-4e5f-8c81-278a7ebf2807} 28 | 29 | 30 | {d40ef54c-1ccf-4ce7-b3fc-30052e11da2b} 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | project\physmem 39 | 40 | 41 | project\interrupts 42 | 43 | 44 | project\communication 45 | 46 | 47 | project 48 | 49 | 50 | project\communication\handler 51 | 52 | 53 | project\cr3 decryption 54 | 55 | 56 | project\logging 57 | 58 | 59 | 60 | 61 | project\physmem 62 | 63 | 64 | project\interrupts 65 | 66 | 67 | project 68 | 69 | 70 | project 71 | 72 | 73 | project\physmem 74 | 75 | 76 | project\physmem 77 | 78 | 79 | project 80 | 81 | 82 | project\interrupts 83 | 84 | 85 | project\communication 86 | 87 | 88 | project 89 | 90 | 91 | project\communication\asm 92 | 93 | 94 | project\communication\handler 95 | 96 | 97 | project\cr3 decryption 98 | 99 | 100 | project\logging 101 | 102 | 103 | 104 | 105 | project\interrupts 106 | 107 | 108 | project\communication\asm 109 | 110 | 111 | -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/communication/comm_assembly.asm: -------------------------------------------------------------------------------- 1 | .code 2 | 3 | extern exit_constructed_space:qword 4 | extern handler: proc 5 | extern g_info_page:qword 6 | 7 | ; 8 | ; Helper functions 9 | ; 10 | get_proc_number proc 11 | push rbx 12 | push rcx 13 | push rdx 14 | 15 | xor eax, eax ; Clear eax 16 | mov eax, 0Bh ; Set eax to leaf 0x0B 17 | xor ecx, ecx ; Set ecx to 0 (subleaf 0) 18 | cpuid 19 | 20 | mov eax, edx ; Save apic id 21 | 22 | pop rdx 23 | pop rcx 24 | pop rbx 25 | 26 | ret 27 | get_proc_number endp 28 | 29 | ; Assembly wrapper for the main handler 30 | asm_handler proc 31 | 32 | ; Allocate stack memory for our handler 33 | ; (Allocate quite some memory to account for msvc compiler stupidity) 34 | ; and align to a 16 byte boundary 35 | sub rsp, 40h 36 | call handler 37 | add rsp, 40h 38 | 39 | jmp qword ptr [exit_constructed_space] 40 | asm_handler endp 41 | 42 | end -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/communication/communication.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../project_includes.hpp" 3 | #include "shellcode.hpp" 4 | 5 | namespace communication { 6 | // Initialization functions 7 | project_status init_communication(void* driver_base, uint64_t driver_size); 8 | 9 | // Teardown functions 10 | project_status unhook_data_ptr(void); 11 | }; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/communication/handler.cpp: -------------------------------------------------------------------------------- 1 | #include "communication.hpp" 2 | #include "shared_structs.hpp" 3 | 4 | #include "../project_api.hpp" 5 | #include "../project_utility.hpp" 6 | #include "../cr3 decryption/cr3_decryption.hpp" 7 | 8 | bool is_removed = false; 9 | 10 | /* 11 | Our main handler that handles communication with um 12 | a) It assumes that the call to it is valid; Validity is checked for in shell code via rdx 13 | hwnd: ptr to cmd 14 | flags: non valid (is used as a validation key in the shellcode) 15 | dw_data: non valid 16 | */ 17 | extern "C" __int64 __fastcall handler(uint64_t hwnd, uint32_t flags, ULONG_PTR dw_data) { 18 | UNREFERENCED_PARAMETER(flags); 19 | UNREFERENCED_PARAMETER(dw_data); 20 | 21 | if (!hwnd) 22 | return status_invalid_parameter; 23 | 24 | project_status status = status_success; 25 | command_t cmd; 26 | 27 | uint64_t user_cr3 = shellcode::get_current_user_cr3(); 28 | status = physmem::runtime::copy_memory_to_constructed_cr3(&cmd, (void*)hwnd, sizeof(command_t), user_cr3); 29 | if (status != status_success) 30 | return 0; 31 | 32 | switch (cmd.call_type) { 33 | case cmd_copy_virtual_memory: { 34 | copy_virtual_memory_t sub_cmd; 35 | 36 | status = physmem::runtime::copy_memory_to_constructed_cr3(&sub_cmd, cmd.sub_command_ptr, sizeof(sub_cmd), user_cr3); 37 | if (status != status_success) 38 | break; 39 | 40 | status = physmem::runtime::copy_virtual_memory(sub_cmd.dst, sub_cmd.src, sub_cmd.size, sub_cmd.dst_cr3, sub_cmd.src_cr3); 41 | if (status != status_success) 42 | break; 43 | 44 | // Do not copy back to improve performance; There is no return value for this 45 | } break; 46 | 47 | case cmd_get_pid_by_name: { 48 | get_pid_by_name_t sub_cmd; 49 | status = physmem::runtime::copy_memory_to_constructed_cr3(&sub_cmd, cmd.sub_command_ptr, sizeof(sub_cmd), user_cr3); 50 | if (status != status_success) 51 | break; 52 | 53 | sub_cmd.pid = cr3_decryption::eproc::get_pid(sub_cmd.name); 54 | if (!sub_cmd.pid) 55 | status = status_failure; 56 | 57 | if (status != status_success) 58 | break; 59 | 60 | status = physmem::runtime::copy_memory_from_constructed_cr3(cmd.sub_command_ptr, &sub_cmd, sizeof(sub_cmd), user_cr3); 61 | if (status != status_success) 62 | break; 63 | } break; 64 | 65 | case cmd_get_cr3: { 66 | 67 | get_cr3_t sub_cmd; 68 | status = physmem::runtime::copy_memory_to_constructed_cr3(&sub_cmd, cmd.sub_command_ptr, sizeof(sub_cmd), user_cr3); 69 | if (status != status_success) 70 | break; 71 | 72 | sub_cmd.cr3 = cr3_decryption::eproc::get_cr3(sub_cmd.pid); 73 | if (!sub_cmd.cr3) 74 | status = status_failure; 75 | 76 | if (status != status_success) 77 | break; 78 | 79 | status = physmem::runtime::copy_memory_from_constructed_cr3(cmd.sub_command_ptr, &sub_cmd, sizeof(sub_cmd), user_cr3); 80 | if (status != status_success) 81 | break; 82 | 83 | } break; 84 | 85 | case cmd_get_module_base: { 86 | get_module_base_t sub_cmd; 87 | status = physmem::runtime::copy_memory_to_constructed_cr3(&sub_cmd, cmd.sub_command_ptr, sizeof(sub_cmd), user_cr3); 88 | if (status != status_success) 89 | break; 90 | 91 | sub_cmd.module_base = cr3_decryption::peb::get_module_base(sub_cmd.pid, sub_cmd.module_name); 92 | if (!sub_cmd.module_base) 93 | status = status_failure; 94 | 95 | if (status != status_success) 96 | break; 97 | 98 | status = physmem::runtime::copy_memory_from_constructed_cr3(cmd.sub_command_ptr, &sub_cmd, sizeof(sub_cmd), user_cr3); 99 | if (status != status_success) 100 | break; 101 | } break; 102 | 103 | case cmd_get_module_size: { 104 | get_module_size_t sub_cmd; 105 | status = physmem::runtime::copy_memory_to_constructed_cr3(&sub_cmd, cmd.sub_command_ptr, sizeof(sub_cmd), user_cr3); 106 | if (status != status_success) 107 | break; 108 | 109 | sub_cmd.module_size = cr3_decryption::peb::get_module_size(sub_cmd.pid, sub_cmd.module_name); 110 | if (!sub_cmd.module_size) 111 | status = status_failure; 112 | 113 | if (status != status_success) 114 | break; 115 | 116 | status = physmem::runtime::copy_memory_from_constructed_cr3(cmd.sub_command_ptr, &sub_cmd, sizeof(sub_cmd), user_cr3); 117 | if (status != status_success) 118 | break; 119 | } break; 120 | 121 | case cmd_get_ldr_data_table_entry_count: { 122 | get_ldr_data_table_entry_count_t sub_cmd; 123 | status = physmem::runtime::copy_memory_to_constructed_cr3(&sub_cmd, cmd.sub_command_ptr, sizeof(sub_cmd), user_cr3); 124 | if (status != status_success) 125 | break; 126 | 127 | sub_cmd.count = cr3_decryption::peb::get_data_table_entry_count(sub_cmd.pid); 128 | if (!sub_cmd.count) 129 | status = status_failure; 130 | 131 | if (status != status_success) 132 | break; 133 | 134 | status = physmem::runtime::copy_memory_from_constructed_cr3(cmd.sub_command_ptr, &sub_cmd, sizeof(sub_cmd), user_cr3); 135 | if (status != status_success) 136 | break; 137 | } break; 138 | 139 | case cmd_get_data_table_entry_info: { 140 | cmd_get_data_table_entry_info_t sub_cmd; 141 | status = physmem::runtime::copy_memory_to_constructed_cr3(&sub_cmd, cmd.sub_command_ptr, sizeof(sub_cmd), user_cr3); 142 | if (status != status_success) 143 | break; 144 | 145 | status = cr3_decryption::peb::get_data_table_entry_info(sub_cmd.pid, sub_cmd.info_array, user_cr3); 146 | if (status != status_success) 147 | break; 148 | 149 | // Do not copy back to improve performance; There is no return value for this 150 | } break; 151 | 152 | case cmd_output_logs: { 153 | cmd_output_logs_t sub_cmd; 154 | status = physmem::runtime::copy_memory_to_constructed_cr3(&sub_cmd, cmd.sub_command_ptr, sizeof(sub_cmd), user_cr3); 155 | if (status != status_success) 156 | break; 157 | 158 | logging::output_root_logs(sub_cmd.log_array, user_cr3, sub_cmd.count); 159 | 160 | status = physmem::runtime::copy_memory_from_constructed_cr3(cmd.sub_command_ptr, &sub_cmd, sizeof(sub_cmd), user_cr3); 161 | if (status != status_success) 162 | break; 163 | 164 | } break; 165 | 166 | // This is a substitute for MmRemovePhysicalMemory (= 167 | case cmd_remove_from_system_page_tables: { 168 | 169 | // Do not try to double remove it, it won't work... 170 | if (is_removed) 171 | break; 172 | 173 | status = physmem::paging_manipulation::win_unmap_memory_range(g_driver_base, physmem::util::get_system_cr3().flags, g_driver_size); 174 | if (status != status_success) 175 | break; 176 | 177 | is_removed = true; 178 | 179 | } break; 180 | 181 | case cmd_unload_driver: { 182 | 183 | status = communication::unhook_data_ptr(); 184 | if (status != status_success) 185 | break; 186 | 187 | } break; 188 | 189 | case cmd_ping_driver: { 190 | 191 | // Hello usermode 192 | 193 | } break; 194 | 195 | default: { 196 | 197 | logging::root_printf("UNKNOWN CMD %d", cmd.call_type); 198 | 199 | } break; 200 | } 201 | 202 | // Set the success flag in the main cmd 203 | if (status == status_success) { 204 | cmd.status = true; 205 | } 206 | else { 207 | cmd.status = false; 208 | } 209 | 210 | // Copy back th main cmd 211 | physmem::runtime::copy_memory_from_constructed_cr3((void*)hwnd, &cmd, sizeof(command_t), user_cr3); 212 | return 0; 213 | } -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/communication/shared_structs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma optimize("", off) 3 | // Designed to be a standalone, includable .hpp, thus we need to make our own definitions etc. 4 | 5 | /* 6 | Typedefs and Definitions 7 | */ 8 | 9 | #ifndef _In_ 10 | #define _In_ 11 | #endif // !_In_ 12 | 13 | #ifndef _Out_ 14 | #define _Out_ 15 | #endif // !_Out_ 16 | 17 | #ifndef MAX_PATH 18 | #define MAX_PATH 260 19 | #endif // !MAX_PATH 20 | 21 | using uint8_t = unsigned char; 22 | using uint16_t = unsigned short; 23 | using uint32_t = unsigned int; 24 | using uint64_t = unsigned long long; 25 | 26 | /* 27 | Communication structs 28 | */ 29 | 30 | struct copy_virtual_memory_t { 31 | _In_ uint64_t src_cr3; 32 | _In_ uint64_t dst_cr3; 33 | 34 | _In_ void* src; 35 | _In_ void* dst; 36 | 37 | _In_ uint64_t size; 38 | }; 39 | 40 | struct get_cr3_t { 41 | _In_ uint64_t pid; 42 | 43 | _Out_ uint64_t cr3; 44 | }; 45 | 46 | struct get_module_base_t { 47 | _In_ char module_name[MAX_PATH]; 48 | _In_ uint64_t pid; 49 | 50 | _Out_ uint64_t module_base; 51 | }; 52 | 53 | struct get_module_size_t { 54 | _In_ char module_name[MAX_PATH]; 55 | _In_ uint64_t pid; 56 | 57 | _Out_ uint64_t module_size; 58 | }; 59 | 60 | struct get_pid_by_name_t { 61 | _In_ char name[MAX_PATH]; 62 | 63 | _Out_ uint64_t pid; 64 | }; 65 | 66 | struct get_ldr_data_table_entry_count_t { 67 | _In_ uint64_t pid; 68 | 69 | _Out_ uint64_t count; 70 | }; 71 | 72 | struct module_info_t { 73 | _In_ char name[MAX_PATH]; 74 | _In_ uint64_t base; 75 | _In_ uint64_t size; 76 | }; 77 | 78 | struct cmd_get_data_table_entry_info_t { 79 | _In_ uint64_t pid; 80 | _In_ module_info_t* info_array; 81 | }; 82 | 83 | #define MAX_MESSAGES 512 84 | #define MAX_MESSAGE_SIZE 256 85 | 86 | struct log_entry_t { 87 | bool present; 88 | char payload[MAX_MESSAGE_SIZE]; 89 | }; 90 | 91 | struct cmd_output_logs_t { 92 | _In_ uint32_t count; 93 | _In_ log_entry_t* log_array; 94 | }; 95 | 96 | enum call_types_t : uint32_t { 97 | cmd_get_pid_by_name, 98 | cmd_get_cr3, 99 | 100 | cmd_get_module_base, 101 | cmd_get_module_size, 102 | cmd_get_ldr_data_table_entry_count, 103 | cmd_get_data_table_entry_info, 104 | 105 | cmd_copy_virtual_memory, 106 | 107 | cmd_output_logs, 108 | 109 | cmd_remove_from_system_page_tables, 110 | cmd_unload_driver, 111 | cmd_ping_driver, 112 | }; 113 | 114 | struct command_t { 115 | bool status; 116 | call_types_t call_type; 117 | void* sub_command_ptr; 118 | }; 119 | #pragma optimize("", on) -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/communication/shellcode.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../project_includes.hpp" 3 | #include "../project/interrupts/interrupt_structs.hpp" 4 | #include "../project/interrupts/interrupts.hpp" 5 | 6 | #pragma pack(push, 1) 7 | struct info_page_t { 8 | segment_descriptor_register_64 constructed_idt; 9 | 10 | segment_descriptor_register_64 user_idt_storage; 11 | uint64_t user_cr3_storage; 12 | uint64_t nmi_panic_function_storage; 13 | }; 14 | #pragma pack(pop) 15 | 16 | static_assert(offsetof(struct info_page_t, constructed_idt) == 0, "Offset of constructed_idt is incorrect"); 17 | static_assert(offsetof(struct info_page_t, user_idt_storage) == 0xA, "Offset of user_idt_storage is incorrect"); 18 | static_assert(offsetof(struct info_page_t, user_cr3_storage) == 0x14, "Offset of user_cr3_storage is incorrect"); 19 | static_assert(offsetof(struct info_page_t, nmi_panic_function_storage) == 0x1C, "Offset of nmi_panic_function_storage is incorrect"); 20 | static_assert(sizeof(struct info_page_t) == 0x24, "Size of info_page_t is incorrect"); 21 | 22 | namespace shellcode { 23 | inline void* g_enter_constructed_space_executed = 0; 24 | inline void* g_enter_constructed_space_shown = 0; 25 | inline void* g_exit_constructed_space = 0; 26 | inline void* g_nmi_shellcode = 0; 27 | 28 | extern "C" info_page_t* g_info_page; // An array of info_page_t's 29 | 30 | inline void construct_executed_enter_shellcode(void* enter_constructed_space, void* orig_data_ptr_value, void* handler_address, 31 | uint64_t constructed_cr3, info_page_t* info_page_base) { 32 | static const uint8_t start_place_holder_shellcode[] = { 33 | 0xFA, // cli 34 | 0x0F, 0xAE, 0xF0, // mfence 35 | 0x81, 0xFA, 0x69, 0x69, 0x00, 0x00, // cmp edx, 0x6969 36 | 0x74, 0x0D, // je skip_orig_function 37 | 0xFB, // sti 38 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, imm64 (address of orig_data_ptr_value) 39 | 0xFF, 0xE0, // jmp rax 40 | }; 41 | 42 | static const uint8_t cr3_pushing_shellcode[] = { 43 | // Store the User Cr3 44 | 0x48, 0x0F, 0x20, 0xD8, // mov rax, cr3 45 | 0x50, // push rax 46 | }; 47 | 48 | static const uint8_t cr3_changing_shellcode[] = { 49 | // Change to constructed Cr3 50 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, imm64 (constructed cr3 value) 51 | 0x48, 0x0F, 0x22, 0xD8, // mov cr3, rax 52 | 53 | // Flush the TLB for this page 54 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, imm64 (page address) <- doesn't matter what to put here, it will not be executed 55 | 0x0F, 0x01, 0x38, // invlpg rax] 56 | }; 57 | 58 | static const uint8_t calculate_base_shellcode[] = { 59 | 0x53, // push rbx 60 | 0x51, // push rcx 61 | 0x52, // push rdx 62 | 0x48, 0x31, 0xC0, // xor rax, rax (only eax, eax would be necessary but I want to clear rax fully for the imul) 63 | 0xB8, 0x0B, 0x00, 0x00, 0x00, // mov eax, 0x0B (Leaf) 64 | 0x31, 0xC9, // xor ecx, ecx 65 | 0x0F, 0xA2, // cpuid 66 | 0x8B, 0xC2, // mov eax, edx (Store Apic id in eax) 67 | 0x5A, // pop rdx 68 | 0x59, // pop rcx 69 | 0x5B, // pop rbx 70 | 0x48, 0x6B, 0xC0, 0x00, // imul rax, rax, sizeof(info_page_t) (calculate the offset) 71 | 0x53, // push rbx 72 | 0x48, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rbx, imm64 (info_page_base) 73 | 0x48, 0x01, 0xD8, // add rax, rbx 74 | 0x5B, // pop rbx 75 | 0x48, 0x8B, 0xD0, // mov rdx, rax (save &info_page_base[apic_id] into rdx) 76 | }; 77 | 78 | static const uint8_t cr3_saving_shellcode[] = { 79 | // Store the User Cr3 80 | 0x52, // push rdx 81 | 0x48, 0x83, 0xC0, 0x00, // add rax, offsetof(info_page_t, user_cr3_storage) 82 | 0x48, 0x8B, 0x54, 0x24, 0x08, // mov rdx, [rsp + 8] 83 | 0x48, 0x89, 0x10, // mov [rax], rdx 84 | 0x5A, // pop rdx 85 | 0x48, 0x83, 0xC4, 0x08, // add rsp, 8 (pop cr3 to avoid stack pollution) 86 | 87 | }; 88 | 89 | static const uint8_t nmi_panic_shellcode[] = { 90 | 0x48, 0x8B, 0xC2, // mov rax, rdx 91 | 92 | // Store the NMI panic function 93 | 0x48, 0x83, 0xC0, 0x00, // add rax, offsetof(info_page_t, nmi_panic_function_storage) 94 | 0x4C, 0x89, 0x00, // mov [rax], r8 95 | }; 96 | 97 | static const uint8_t idt_shellcode[] = { 98 | 0x48, 0x8B, 0xC2, // mov rax, rdx 99 | 100 | // Save the user IDT 101 | 0x48, 0x83, 0xC0, 0x00, // add rax, offsetof(info_page_t, user_idt_storage) 102 | 0x0F, 0x01, 0x08, // sidt [rax] 103 | 0x48, 0x8B, 0xC2, // mov rax, rdx 104 | 105 | // Load the constructed IDT 106 | 0x48, 0x83, 0xC0, 0x00, // add rax, offsetof(info_page_t, constructed_idt) 107 | 0x0F, 0x01, 0x18, // lidt [rax] 108 | }; 109 | 110 | 111 | static const uint8_t jump_to_handler_shellcode[] = { 112 | // Jump to my handler 113 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, imm64 (address of my asm handler) 114 | 0xFF, 0xE0 // jmp rax 115 | }; 116 | 117 | *(void**)((uint8_t*)start_place_holder_shellcode + 15) = orig_data_ptr_value; 118 | 119 | *(uint64_t*)((uint8_t*)cr3_changing_shellcode + 2) = constructed_cr3; 120 | *(uint64_t*)((uint8_t*)cr3_changing_shellcode + 16) = (uint64_t)enter_constructed_space; 121 | 122 | *(uint8_t*)((uint8_t*)calculate_base_shellcode + 23) = sizeof(info_page_t); 123 | *(void**)((uint8_t*)calculate_base_shellcode + 27) = info_page_base; 124 | 125 | *(uint8_t*)((uint8_t*)cr3_saving_shellcode + 4) = offsetof(info_page_t, user_cr3_storage); 126 | 127 | *(uint8_t*)((uint8_t*)nmi_panic_shellcode + 6) = offsetof(info_page_t, nmi_panic_function_storage); 128 | 129 | *(uint8_t*)((uint8_t*)idt_shellcode + 6) = offsetof(info_page_t, user_idt_storage); 130 | 131 | *(uint8_t*)((uint8_t*)idt_shellcode + 16) = offsetof(info_page_t, constructed_idt); 132 | 133 | *(void**)((uint8_t*)jump_to_handler_shellcode + 2) = handler_address; 134 | 135 | uint8_t* current_position = (uint8_t*)enter_constructed_space; 136 | memcpy(current_position, start_place_holder_shellcode, sizeof(start_place_holder_shellcode)); 137 | current_position += sizeof(start_place_holder_shellcode); 138 | 139 | memcpy(current_position, cr3_pushing_shellcode, sizeof(cr3_pushing_shellcode)); 140 | current_position += sizeof(cr3_pushing_shellcode); 141 | 142 | memcpy(current_position, cr3_changing_shellcode, sizeof(cr3_changing_shellcode)); 143 | current_position += sizeof(cr3_changing_shellcode); 144 | 145 | memcpy(current_position, calculate_base_shellcode, sizeof(calculate_base_shellcode)); 146 | current_position += sizeof(calculate_base_shellcode); 147 | 148 | memcpy(current_position, cr3_saving_shellcode, sizeof(cr3_saving_shellcode)); 149 | current_position += sizeof(cr3_saving_shellcode); 150 | 151 | memcpy(current_position, nmi_panic_shellcode, sizeof(nmi_panic_shellcode)); 152 | current_position += sizeof(nmi_panic_shellcode); 153 | 154 | memcpy(current_position, idt_shellcode, sizeof(idt_shellcode)); 155 | current_position += sizeof(idt_shellcode); 156 | 157 | memcpy(current_position, jump_to_handler_shellcode, sizeof(jump_to_handler_shellcode)); 158 | } 159 | 160 | inline void construct_shown_enter_shellcode(void* enter_constructed_space, void* orig_data_ptr_value, uint64_t constructed_cr3) { 161 | static const uint8_t start_place_holder_shellcode[] = { 162 | 0xFA, // cli 163 | 0x0F, 0xAE, 0xF0, // mfence 164 | 0x81, 0xFA, 0x69, 0x69, 0x00, 0x00, // cmp edx, 0x6969 165 | 0x74, 0x0D, // je skip_orig_function 166 | 0xFB, // sti 167 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, imm64 (address of orig_data_ptr_value) 168 | 0xFF, 0xE0, // jmp rax 169 | }; 170 | 171 | static const uint8_t cr3_pushing_shellcode[] = { 172 | // Store the User Cr3 173 | 0x48, 0x0F, 0x20, 0xD8, // mov rax, cr3 174 | 0x50, // push rax 175 | }; 176 | 177 | static const uint8_t cr3_changing_shellcode[] = { 178 | // Change to constructed Cr3 179 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, imm64 (constructed cr3 value) 180 | 0x48, 0x0F, 0x22, 0xD8, // mov cr3, rax 181 | 182 | // Flush the TLB for this page 183 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, imm64 (page address) 184 | 0x0F, 0x01, 0x38, // invlpg [rax] 185 | 0x58, // pop rax <- Won't be executed anymore 186 | }; 187 | 188 | static const uint8_t return_shellcode[] = { 189 | 0xC3 190 | }; 191 | 192 | *(void**)((uint8_t*)start_place_holder_shellcode + 15) = orig_data_ptr_value; 193 | *(uint64_t*)((uint8_t*)cr3_changing_shellcode + 2) = constructed_cr3; 194 | *(uint64_t*)((uint8_t*)cr3_changing_shellcode + 16) = (uint64_t)enter_constructed_space; 195 | 196 | 197 | uint8_t* current_position = (uint8_t*)enter_constructed_space; 198 | memcpy(current_position, start_place_holder_shellcode, sizeof(start_place_holder_shellcode)); 199 | current_position += sizeof(start_place_holder_shellcode); 200 | 201 | memcpy(current_position, cr3_pushing_shellcode, sizeof(cr3_pushing_shellcode)); 202 | current_position += sizeof(cr3_pushing_shellcode); 203 | 204 | memcpy(current_position, cr3_changing_shellcode, sizeof(cr3_changing_shellcode)); 205 | current_position += sizeof(cr3_changing_shellcode); 206 | 207 | memcpy(current_position, return_shellcode, sizeof(return_shellcode)); 208 | current_position += sizeof(return_shellcode); 209 | } 210 | 211 | inline void construct_exit_shellcode(void* exit_constructed_space, info_page_t* info_page_base) { 212 | 213 | static const uint8_t calculate_base_shellcode[] = { 214 | 0x53, // push rbx 215 | 0x51, // push rcx 216 | 0x52, // push rdx 217 | 0x48, 0x31, 0xC0, // xor rax, rax (only eax, eax would be necessary but I want to clear rax fully for the imul) 218 | 0xB8, 0x0B, 0x00, 0x00, 0x00, // mov eax, 0x0B (Leaf) 219 | 0x31, 0xC9, // xor ecx, ecx 220 | 0x0F, 0xA2, // cpuid 221 | 0x8B, 0xC2, // mov eax, edx (Store Apic id in eax) 222 | 0x5A, // pop rdx 223 | 0x59, // pop rcx 224 | 0x5B, // pop rbx 225 | 0x48, 0x6B, 0xC0, 0x00, // imul rax, rax, sizeof(info_page_t) (calculate the offset) 226 | 0x53, // push rbx 227 | 0x48, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rbx, imm64 (info_page_base) 228 | 0x48, 0x01, 0xD8, // add rax, rbx 229 | 0x5B, // pop rbx 230 | 0x48, 0x8B, 0xD0, // mov rdx, rax (save &info_page_base[apic_id] into rdx) 231 | }; 232 | 233 | 234 | static const uint8_t restore_cr3_shellcode[] = { 235 | 0x48, 0x83, 0xC0, 0x00, // add rax, offsetof(info_page_t, user_cr3_storage) 236 | 0x48, 0x8B, 0x00, // mov rax, [rax] 237 | 0x0F, 0x22, 0xD8, // mov cr3, rax 238 | }; 239 | 240 | static const uint8_t restore_idt_shellcode[] = { 241 | 0x48, 0x8B, 0xC2, // mov rax, rdx (Restore &info_page_base[apic_id] from rdx) 242 | 0x48, 0x83, 0xC0, 0x00, // add rax, offsetof(info_page_t, user_idt_storage) 243 | 0x0F, 0x01, 0x18, // lidt [rax] 244 | }; 245 | 246 | static const uint8_t return_shellcode[] = { 247 | 0xC3 // ret 248 | }; 249 | 250 | 251 | *(uint8_t*)((uint8_t*)calculate_base_shellcode + 23) = sizeof(info_page_t); 252 | 253 | *(void**)((uint8_t*)calculate_base_shellcode + 27) = info_page_base; 254 | 255 | *(uint8_t*)((uint8_t*)restore_cr3_shellcode + 3) = offsetof(info_page_t, user_cr3_storage); 256 | 257 | *(uint8_t*)((uint8_t*)restore_idt_shellcode + 6) = offsetof(info_page_t, user_idt_storage); 258 | 259 | uint8_t* current_position = (uint8_t*)exit_constructed_space; 260 | memcpy(current_position, calculate_base_shellcode, sizeof(calculate_base_shellcode)); 261 | current_position += sizeof(calculate_base_shellcode); 262 | 263 | memcpy(current_position, restore_cr3_shellcode, sizeof(restore_cr3_shellcode)); 264 | current_position += sizeof(restore_cr3_shellcode); 265 | 266 | memcpy(current_position, restore_idt_shellcode, sizeof(restore_idt_shellcode)); 267 | current_position += sizeof(restore_idt_shellcode); 268 | 269 | memcpy(current_position, return_shellcode, sizeof(return_shellcode)); 270 | current_position += sizeof(return_shellcode); 271 | } 272 | 273 | inline void construct_nmi_shellcode(void* nmi_shellcode, void* windows_nmi_handler) { 274 | 275 | static const uint8_t restore_cr3_shellcode[] = { 276 | 0x48, 0x83, 0xC0, 0x00, // add rax, offsetof(info_page_t, user_cr3_storage) 277 | 0x48, 0x8B, 0x00, // mov rax, [rax] 278 | 0x0F, 0x22, 0xD8, // mov cr3, rax 279 | }; 280 | 281 | static const uint8_t restore_idt_shellcode[] = { 282 | 0x48, 0x8B, 0xC2, // mov rax, rdx (Restore &info_page_base[apic_id] from rdx) 283 | 0x48, 0x83, 0xC0, 0x00, // add rax, offsetof(info_page_t, user_idt_storage) 284 | 0x0F, 0x01, 0x18, // lidt [rax] 285 | }; 286 | 287 | static const uint8_t jump_windows_handler[] = { 288 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, imm64 (address of handler_address) 289 | 0xFF, 0xE0, // jmp rax 290 | }; 291 | 292 | 293 | *(uint8_t*)((uint8_t*)restore_cr3_shellcode + 3) = offsetof(info_page_t, user_cr3_storage); 294 | 295 | *(uint8_t*)((uint8_t*)restore_idt_shellcode + 6) = offsetof(info_page_t, user_idt_storage); 296 | 297 | *(void**)((uint8_t*)jump_windows_handler + 2) = windows_nmi_handler; 298 | 299 | uint8_t* current_position = (uint8_t*)nmi_shellcode; 300 | memcpy(current_position, restore_cr3_shellcode, sizeof(restore_cr3_shellcode)); 301 | current_position += sizeof(restore_cr3_shellcode); 302 | 303 | memcpy(current_position, restore_idt_shellcode, sizeof(restore_idt_shellcode)); 304 | current_position += sizeof(restore_idt_shellcode); 305 | 306 | memcpy(current_position, jump_windows_handler, sizeof(jump_windows_handler)); 307 | current_position += sizeof(jump_windows_handler); 308 | } 309 | 310 | inline project_status construct_shellcodes(void*& enter_constructed_space_executed, void*& enter_constructed_space_shown, void*& exit_constructed_space, void*& nmi_shellcode, 311 | segment_descriptor_register_64 my_idt_ptr, 312 | void* orig_data_ptr_value, void* handler_address, 313 | uint64_t constructed_cr3) { 314 | 315 | PHYSICAL_ADDRESS max_addr = { 0 }; 316 | info_page_t* info_page = 0; 317 | 318 | max_addr.QuadPart = MAXULONG64; 319 | 320 | enter_constructed_space_executed = MmAllocateContiguousMemory(PAGE_SIZE, max_addr); 321 | enter_constructed_space_shown = MmAllocateContiguousMemory(PAGE_SIZE, max_addr); 322 | exit_constructed_space = MmAllocateContiguousMemory(PAGE_SIZE, max_addr); 323 | nmi_shellcode = MmAllocateContiguousMemory(PAGE_SIZE, max_addr); 324 | info_page = (info_page_t*)MmAllocateContiguousMemory(KeQueryActiveProcessorCount(0) * sizeof(info_page_t), max_addr); 325 | 326 | if (!enter_constructed_space_executed || !enter_constructed_space_shown 327 | || !exit_constructed_space || !info_page) { 328 | return status_memory_allocation_failed; 329 | } 330 | 331 | memset(enter_constructed_space_executed, 0, PAGE_SIZE); 332 | memset(enter_constructed_space_shown, 0, PAGE_SIZE); 333 | memset(exit_constructed_space, 0, PAGE_SIZE); 334 | memset(nmi_shellcode, 0, PAGE_SIZE); 335 | memset(info_page, 0, PAGE_SIZE); 336 | 337 | /* 338 | Setup every info page for each core 339 | */ 340 | for (uint32_t i = 0; i < KeQueryActiveProcessorCount(0); i++) { 341 | info_page[i].constructed_idt = my_idt_ptr; 342 | } 343 | 344 | construct_executed_enter_shellcode(enter_constructed_space_executed, orig_data_ptr_value, handler_address, constructed_cr3, info_page); 345 | 346 | construct_shown_enter_shellcode(enter_constructed_space_shown, orig_data_ptr_value, constructed_cr3); 347 | 348 | construct_exit_shellcode(exit_constructed_space, info_page); 349 | 350 | construct_nmi_shellcode(nmi_shellcode, interrupts::get_windows_nmi_handler()); 351 | 352 | g_enter_constructed_space_executed = enter_constructed_space_executed; 353 | g_enter_constructed_space_shown = enter_constructed_space_shown; 354 | g_exit_constructed_space = exit_constructed_space; 355 | g_nmi_shellcode = nmi_shellcode; 356 | 357 | g_info_page = info_page; 358 | 359 | return status_success; 360 | } 361 | 362 | inline uint64_t get_current_user_cr3(void) { 363 | return g_info_page[get_proc_number()].user_cr3_storage; 364 | } 365 | 366 | inline uint64_t get_current_nmi_panic_function(void) { 367 | return g_info_page[get_proc_number()].nmi_panic_function_storage; 368 | } 369 | }; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/cr3 decryption/cr3_decryption.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../project_api.hpp" 3 | #include "../project_utility.hpp" 4 | #include "../communication/shared_structs.hpp" 5 | 6 | #pragma warning(push) 7 | #pragma warning(disable:4201) 8 | struct _MMPFN { 9 | uintptr_t flags; 10 | uintptr_t pte_address; 11 | uintptr_t Unused_1; 12 | uintptr_t Unused_2; 13 | uintptr_t Unused_3; 14 | uintptr_t Unused_4; 15 | }; 16 | static_assert(sizeof(_MMPFN) == 0x30); 17 | 18 | constexpr size_t operator ""_MiB(size_t num) { return num << 20; } 19 | 20 | enum iteration_status { 21 | status_stop_iteration, 22 | status_continue_iteration 23 | }; 24 | 25 | namespace cr3_decryption { 26 | // Initialization 27 | project_status init_eac_cr3_decryption(void); 28 | 29 | namespace eproc { 30 | // Exposed API'S 31 | uint64_t get_cr3(uint64_t target_pid); 32 | uint64_t get_pid(const char* target_process_name); 33 | }; 34 | 35 | namespace peb { 36 | // Exposed API'S 37 | project_status get_data_table_entry_info(uint64_t target_pid, module_info_t* info_array, uint64_t proc_cr3); 38 | uint64_t get_data_table_entry_count(uint64_t target_pid); 39 | 40 | uint64_t get_module_base(uint64_t target_pid, char* module_name); 41 | uint64_t get_module_size(uint64_t target_pid, char* module_name); 42 | }; 43 | } -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/interrupts/interrupt_structs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../project_includes.hpp" 3 | 4 | typedef enum { 5 | /** 6 | * Nonmaskable Interrupt. 7 | * Source: Generated externally by asserting the processor's NMI pin or 8 | * through an NMI request set by the I/O APIC to the local APIC. 9 | * Error Code: No. 10 | */ 11 | nmi = 0x00000002, 12 | } exception_vector; 13 | 14 | #pragma pack(push, 1) 15 | typedef struct { 16 | uint16_t limit; 17 | uint64_t base_address; 18 | } segment_descriptor_register_64; 19 | #pragma pack(pop) 20 | 21 | #pragma pack(push, 1) 22 | struct trap_frame_t { 23 | uint64_t r15; 24 | uint64_t r14; 25 | uint64_t r13; 26 | uint64_t r12; 27 | uint64_t r11; 28 | uint64_t r10; 29 | uint64_t r9; 30 | uint64_t r8; 31 | uint64_t rbp; 32 | uint64_t rdi; 33 | uint64_t rsi; 34 | uint64_t rdx; 35 | uint64_t rcx; 36 | uint64_t rbx; 37 | uint64_t rax; 38 | 39 | uint64_t rip; 40 | uint64_t cs_selector; 41 | uint64_t rflags; 42 | uint64_t rsp; 43 | uint64_t ss_selector; 44 | }; 45 | #pragma pack(pop) 46 | 47 | typedef struct { 48 | uint16_t offset_low; 49 | uint16_t segment_selector; 50 | union { 51 | struct { 52 | uint32_t interrupt_stack_table : 3; 53 | uint32_t must_be_zero_0 : 5; 54 | uint32_t type : 4; 55 | uint32_t must_be_zero_1 : 1; 56 | uint32_t descriptor_privilege_level : 2; 57 | uint32_t present : 1; 58 | uint32_t offset_middle : 16; 59 | }; 60 | 61 | uint32_t flags; 62 | }; 63 | uint32_t offset_high; 64 | uint32_t reserved; 65 | } segment_descriptor_interrupt_gate_64; 66 | 67 | typedef union { 68 | struct { 69 | uint64_t carry_flag : 1; 70 | uint64_t read_as_1 : 1; 71 | uint64_t parity_flag : 1; 72 | uint64_t reserved1 : 1; 73 | uint64_t auxiliary_carry_flag : 1; 74 | uint64_t reserved2 : 1; 75 | uint64_t zero_flag : 1; 76 | uint64_t sign_flag : 1; 77 | uint64_t trap_flag : 1; 78 | uint64_t interrupt_enable_flag : 1; 79 | uint64_t direction_flag : 1; 80 | uint64_t overflow_flag : 1; 81 | uint64_t io_privilege_level : 2; 82 | uint64_t nested_task_flag : 1; 83 | uint64_t reserved3 : 1; 84 | uint64_t resume_flag : 1; 85 | uint64_t virtual_8086_mode_flag : 1; 86 | uint64_t alignment_check_flag : 1; 87 | uint64_t virtual_interrupt_flag : 1; 88 | uint64_t virtual_interrupt_pending_flag : 1; 89 | uint64_t identification_flag : 1; 90 | uint64_t reserved4 : 42; 91 | }; 92 | 93 | uint64_t flags; 94 | } rflags; 95 | 96 | #define IA32_STAR 0xC0000081 -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/interrupts/interrupts.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "interrupts.hpp" 3 | 4 | #include "../physmem/physmem.hpp" 5 | 6 | namespace interrupts { 7 | /* 8 | Definitions 9 | */ 10 | #define SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE 0xE; 11 | 12 | /* 13 | Global variables 14 | */ 15 | bool initialized = false; 16 | segment_descriptor_interrupt_gate_64* constructed_idt_table = 0; 17 | segment_descriptor_register_64 constructed_idt_ptr = { 0 }; 18 | uint64_t g_windows_nmi_handler; 19 | 20 | 21 | /* 22 | Utility 23 | */ 24 | segment_descriptor_interrupt_gate_64 create_interrupt_gate(void* assembly_handler, segment_descriptor_interrupt_gate_64 windows_gate) { 25 | segment_descriptor_interrupt_gate_64 gate; 26 | 27 | gate.interrupt_stack_table = windows_gate.interrupt_stack_table; 28 | gate.segment_selector = __readcs(); 29 | gate.must_be_zero_0 = 0; 30 | gate.type = SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE; 31 | gate.must_be_zero_1 = 0; 32 | gate.descriptor_privilege_level = 0; 33 | gate.present = 1; 34 | gate.reserved = 0; 35 | 36 | uint64_t offset = (uint64_t)assembly_handler; 37 | gate.offset_low = (offset >> 0) & 0xFFFF; 38 | gate.offset_middle = (offset >> 16) & 0xFFFF; 39 | gate.offset_high = (offset >> 32) & 0xFFFFFFFF; 40 | 41 | return gate; 42 | } 43 | 44 | segment_descriptor_register_64 get_constructed_idt_ptr(void) { 45 | return constructed_idt_ptr; 46 | } 47 | 48 | /* 49 | Core 50 | */ 51 | extern "C" void nmi_handler(trap_frame_t* trap_frame) { 52 | uint64_t star_msr = __readmsr(IA32_STAR); 53 | KPCR* kcpr = __getpcr(); // Only valid if you call this while gs == kernel_gs 54 | uint64_t curr_user_panic_rip = 0; 55 | rflags curr_user_rflags = { 0 }; 56 | 57 | // Enable the interrupt flag again 58 | curr_user_rflags.flags = trap_frame->rflags; 59 | curr_user_rflags.interrupt_enable_flag = 1; 60 | curr_user_rflags.virtual_8086_mode_flag = 0; 61 | curr_user_rflags.reserved1 = 0; 62 | curr_user_rflags.reserved2 = 0; 63 | curr_user_rflags.reserved3 = 0; 64 | curr_user_rflags.reserved4 = 0; 65 | curr_user_rflags.read_as_1 = 1; 66 | curr_user_rflags.nested_task_flag = 0; 67 | curr_user_rflags.io_privilege_level = 3; 68 | curr_user_rflags.resume_flag = 0; 69 | curr_user_rflags.alignment_check_flag = 0; 70 | 71 | // RPL is forced to 3 72 | uint16_t sysret_cs = (uint16_t)(((star_msr >> 48) + 16) | 3); // (STAR[63:48] + 16) | 3 73 | uint16_t sysret_ss = (uint16_t)(((star_msr >> 48) + 8) | 3); // (STAR[63:48] + 8) | 3 74 | 75 | trap_frame->rsp = kcpr->UserRsp; 76 | trap_frame->rip = curr_user_panic_rip; 77 | trap_frame->rflags = curr_user_rflags.flags; 78 | trap_frame->cs_selector = sysret_cs; 79 | trap_frame->ss_selector = sysret_ss; 80 | 81 | // Swap back to the um gs 82 | __swapgs(); 83 | } 84 | 85 | /* 86 | Initialization functions 87 | */ 88 | 89 | project_status init_interrupts() { 90 | PHYSICAL_ADDRESS max_addr = { 0 }; 91 | max_addr.QuadPart = MAXULONG64; 92 | 93 | constructed_idt_table = (segment_descriptor_interrupt_gate_64*)MmAllocateContiguousMemory(sizeof(segment_descriptor_interrupt_gate_64) * 256, max_addr); 94 | if (!constructed_idt_table) { 95 | return status_memory_allocation_failed; 96 | } 97 | 98 | memset(constructed_idt_table, 0, sizeof(segment_descriptor_interrupt_gate_64) * 256); 99 | 100 | segment_descriptor_register_64 idt = { 0 }; 101 | __sidt(&idt); 102 | 103 | segment_descriptor_interrupt_gate_64* windows_idt = (segment_descriptor_interrupt_gate_64*)idt.base_address; 104 | if (!windows_idt) 105 | return status_failure; 106 | 107 | g_windows_nmi_handler = (static_cast(windows_idt[exception_vector::nmi].offset_high) << 32) | 108 | (static_cast(windows_idt[exception_vector::nmi].offset_middle) << 16) | 109 | (windows_idt[exception_vector::nmi].offset_low); 110 | 111 | constructed_idt_table[exception_vector::nmi] = create_interrupt_gate(asm_nmi_handler, windows_idt[exception_vector::nmi]); 112 | 113 | constructed_idt_ptr.base_address = (uint64_t)constructed_idt_table; 114 | constructed_idt_ptr.limit = (sizeof(segment_descriptor_interrupt_gate_64) * 256) - 1; 115 | 116 | initialized = true; 117 | 118 | return status_success; 119 | } 120 | 121 | /* 122 | Exposed API's 123 | */ 124 | bool is_initialized(void) { 125 | return initialized; 126 | } 127 | 128 | void* get_windows_nmi_handler(void) { 129 | return (void*)g_windows_nmi_handler; 130 | } 131 | }; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/interrupts/interrupts.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../project_includes.hpp" 3 | #include "interrupt_structs.hpp" 4 | #include "../windows_structs.hpp" 5 | #include 6 | 7 | extern "C" uint16_t __readcs(void); 8 | extern "C" void _cli(void); 9 | extern "C" void _sti(void); 10 | extern "C" void __swapgs(void); 11 | extern "C" KPCR* __getpcr(void); 12 | 13 | extern "C" void asm_nmi_handler(void); 14 | 15 | namespace interrupts { 16 | // Initialization functions 17 | project_status init_interrupts(); 18 | 19 | // Exposed API's 20 | bool is_initialized(void); 21 | void* get_windows_nmi_handler(void); 22 | 23 | segment_descriptor_register_64 get_constructed_idt_ptr(void); 24 | }; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/interrupts/interrupts_asm.asm: -------------------------------------------------------------------------------- 1 | .code 2 | 3 | extern nmi_handler:proc 4 | extern nmi_shellcode:qword 5 | 6 | save_general_regs macro 7 | push rax 8 | push rbx 9 | push rcx 10 | push rdx 11 | push rsi 12 | push rdi 13 | push rbp 14 | push r8 15 | push r9 16 | push r10 17 | push r11 18 | push r12 19 | push r13 20 | push r14 21 | push r15 22 | endm 23 | 24 | restore_general_regs macro 25 | pop r15 26 | pop r14 27 | pop r13 28 | pop r12 29 | pop r11 30 | pop r10 31 | pop r9 32 | pop r8 33 | pop rbp 34 | pop rdi 35 | pop rsi 36 | pop rdx 37 | pop rcx 38 | pop rbx 39 | pop rax 40 | endm 41 | 42 | asm_nmi_handler proc 43 | save_general_regs 44 | 45 | ; Pass a ptr to the struct as the first arg 46 | mov rcx, rsp 47 | 48 | sub rsp, 40h 49 | call nmi_handler 50 | add rsp, 40h 51 | 52 | restore_general_regs 53 | 54 | ; Will basically change idt, cr3 and will jump to the windows nmi handler 55 | jmp qword ptr [nmi_shellcode] 56 | asm_nmi_handler endp 57 | 58 | __readcs proc 59 | mov rax, cs 60 | ret 61 | __readcs endp 62 | 63 | _sti proc 64 | sti 65 | ret 66 | _sti endp 67 | 68 | _cli proc 69 | cli 70 | ret 71 | _cli endp 72 | 73 | __swapgs proc 74 | swapgs 75 | ret 76 | __swapgs endp 77 | 78 | __getpcr proc 79 | mov rax, qword ptr gs:[18h] 80 | ret 81 | __getpcr endp 82 | 83 | end -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/logging/logging.cpp: -------------------------------------------------------------------------------- 1 | #include "logging.hpp" 2 | #include 3 | 4 | namespace logging { 5 | log_entry_t messages[MAX_MESSAGES] = { 0 }; 6 | 7 | uint32_t head_idx = 0; 8 | uint32_t tail_idx = 0; 9 | 10 | /* 11 | Utility 12 | */ 13 | template 14 | char* lukas_itoa(T value, char* result, int base, bool upper = false) 15 | { 16 | // check that the base if valid 17 | if (base < 2 || base > 36) { 18 | *result = '\0'; 19 | return result; 20 | } 21 | 22 | char* ptr = result, * ptr1 = result, tmp_char; 23 | T tmp_value; 24 | 25 | if (upper) 26 | { 27 | do 28 | { 29 | tmp_value = value; 30 | value /= base; 31 | *ptr++ = "ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" 32 | [35 + (tmp_value - value * base)]; 33 | } while (value); 34 | } 35 | else 36 | { 37 | do 38 | { 39 | tmp_value = value; 40 | value /= base; 41 | *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" 42 | [35 + (tmp_value - value * base)]; 43 | } while (value); 44 | } 45 | 46 | // Apply negative sign 47 | if (tmp_value < 0) 48 | *ptr++ = '-'; 49 | 50 | *ptr-- = '\0'; 51 | while (ptr1 < ptr) 52 | { 53 | tmp_char = *ptr; 54 | *ptr-- = *ptr1; 55 | *ptr1++ = tmp_char; 56 | } 57 | 58 | return result; 59 | } 60 | 61 | bool logger_format_copy_str(char* const buffer, char const* const src, uint32_t& idx) { 62 | for (uint32_t i = 0; src[i]; ++i) { 63 | buffer[idx++] = src[i]; 64 | 65 | // buffer end has been reached 66 | if (idx >= MAX_MESSAGE_SIZE - 1) { 67 | buffer[MAX_MESSAGE_SIZE] = '\0'; 68 | return true; 69 | } 70 | } 71 | 72 | return false; 73 | } 74 | 75 | // format a string into a logger buffer, using 76 | // a limited subset of printf specifiers: 77 | // %s, %i, %d, %u, %x, %X, %p 78 | void logger_format(char* const buffer, char const* const format, va_list& args) 79 | { 80 | uint32_t buffer_idx = 0; 81 | uint32_t format_idx = 0; 82 | 83 | // true if the last character was a '%' 84 | bool specifying = false; 85 | 86 | while (true) { 87 | auto const c = format[format_idx++]; 88 | 89 | // format end has been reached 90 | if (c == '\0') 91 | break; 92 | 93 | if (c == '%') { 94 | specifying = true; 95 | continue; 96 | } 97 | 98 | // just copy the character directly 99 | if (!specifying) { 100 | buffer[buffer_idx++] = c; 101 | 102 | // buffer end has been reached 103 | if (buffer_idx >= MAX_MESSAGE_SIZE - 1) 104 | break; 105 | 106 | specifying = false; 107 | continue; 108 | } 109 | 110 | char fmt_buffer[128]; 111 | 112 | // format the string according to the specifier 113 | switch (c) { 114 | case 's': { 115 | if (logger_format_copy_str(buffer, va_arg(args, char const*), buffer_idx)) 116 | return; 117 | break; 118 | } 119 | case 'd': 120 | case 'i': { 121 | if (logger_format_copy_str(buffer, 122 | lukas_itoa(va_arg(args, int), fmt_buffer, 10), buffer_idx)) 123 | return; 124 | break; 125 | } 126 | case 'u': { 127 | if (logger_format_copy_str(buffer, 128 | lukas_itoa(va_arg(args, unsigned int), fmt_buffer, 10), buffer_idx)) 129 | return; 130 | break; 131 | } 132 | case 'x': { 133 | if (logger_format_copy_str(buffer, "0x", buffer_idx)) 134 | return; 135 | if (logger_format_copy_str(buffer, 136 | lukas_itoa(va_arg(args, unsigned int), fmt_buffer, 16), buffer_idx)) 137 | return; 138 | break; 139 | } 140 | case 'X': { 141 | if (logger_format_copy_str(buffer, "0x", buffer_idx)) 142 | return; 143 | if (logger_format_copy_str(buffer, 144 | lukas_itoa(va_arg(args, unsigned int), fmt_buffer, 16, true), buffer_idx)) 145 | return; 146 | break; 147 | } 148 | case 'p': { 149 | if (logger_format_copy_str(buffer, "0x", buffer_idx)) 150 | return; 151 | if (logger_format_copy_str(buffer, 152 | lukas_itoa(va_arg(args, uint64_t), fmt_buffer, 16, true), buffer_idx)) 153 | return; 154 | break; 155 | } 156 | } 157 | 158 | specifying = false; 159 | } 160 | 161 | buffer[buffer_idx] = '\0'; 162 | } 163 | 164 | /* 165 | Exposed API'S 166 | */ 167 | void root_printf(const char* fmt, ...) { 168 | #ifndef ROOT_MODE_LOGGING 169 | return; 170 | #endif // !ROOT_MODE_LOGGING 171 | // Check if buffer is full. If it is, then tail needs to move ahead 172 | if ((head_idx + 1) % MAX_MESSAGES == tail_idx) { 173 | tail_idx = (tail_idx + 1) % MAX_MESSAGES; 174 | } 175 | 176 | log_entry_t* curr_entry = &messages[head_idx]; 177 | curr_entry->present = true; 178 | 179 | va_list args; 180 | va_start(args, fmt); 181 | logger_format(curr_entry->payload, fmt, args); 182 | va_end(args); 183 | head_idx = (head_idx + 1) % MAX_MESSAGES; 184 | } 185 | 186 | void output_root_logs(log_entry_t* user_message_buffer, uint64_t user_cr3, uint32_t message_count) { 187 | #ifndef ROOT_MODE_LOGGING 188 | return; 189 | #endif // !ROOT_MODE_LOGGING 190 | 191 | uint32_t current_idx = tail_idx; // Oldest message 192 | uint32_t buffer_index = 0; 193 | 194 | while (current_idx != head_idx && buffer_index < message_count) { 195 | 196 | if (physmem::runtime::copy_memory_from_constructed_cr3( 197 | (void*)&user_message_buffer[buffer_index], // destination 198 | (void*)&messages[current_idx], // source 199 | sizeof(log_entry_t), 200 | user_cr3) != status_success) { 201 | return; 202 | } 203 | memset(&messages[buffer_index], 0, sizeof(messages[buffer_index])); 204 | 205 | buffer_index++; 206 | current_idx = (current_idx + 1) % MAX_MESSAGES; 207 | } 208 | 209 | tail_idx = head_idx; 210 | } 211 | /* 212 | Initialization 213 | */ 214 | project_status init_root_logger() { 215 | 216 | memset(messages, 0, sizeof(messages)); 217 | head_idx = 0; 218 | tail_idx = 0; 219 | 220 | return status_success; 221 | } 222 | }; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/logging/logging.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../project_api.hpp" 4 | #include "../project_utility.hpp" 5 | #include "../communication/shared_structs.hpp" 6 | 7 | #define ROOT_MODE_LOGGING 8 | 9 | namespace logging { 10 | // Initialization 11 | project_status init_root_logger(); 12 | 13 | // Exposed API'S 14 | void root_printf(const char* fmt, ...); 15 | void output_root_logs(log_entry_t* user_message_buffer, uint64_t user_cr3, uint32_t message_count); 16 | }; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/physmem/page_table_helpers.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../project_includes.hpp" 3 | #include "physmem_structs.hpp" 4 | 5 | namespace pt_helpers { 6 | inline bool is_index_valid(uint64_t index) { 7 | return index < 512; 8 | } 9 | 10 | inline uint32_t find_free_pml4e_index(pml4e_64* pml4e_table) { 11 | for (uint32_t i = 0; i < 512; i++) { 12 | if (!pml4e_table[i].present) { 13 | return i; 14 | } 15 | } 16 | 17 | return MAXULONG32; 18 | } 19 | 20 | inline uint32_t find_free_pdpt_index(pdpte_64* pdpte_table) { 21 | for (uint32_t i = 0; i < 512; i++) { 22 | if (!pdpte_table[i].present) { 23 | return i; 24 | } 25 | } 26 | 27 | return MAXULONG32; 28 | } 29 | 30 | inline uint32_t find_free_pd_index(pde_64* pde_table) { 31 | for (uint32_t i = 0; i < 512; i++) { 32 | if (!pde_table[i].present) { 33 | return i; 34 | } 35 | } 36 | 37 | return MAXULONG32; 38 | } 39 | 40 | inline uint32_t find_free_pt_index(pte_64* pte_table) { 41 | for (uint32_t i = 0; i < 512; i++) { 42 | if (!pte_table[i].present) { 43 | return i; 44 | } 45 | } 46 | 47 | return MAXULONG32; 48 | } 49 | }; 50 | 51 | namespace pt_manager { 52 | // Allocation helpers 53 | inline pdpte_64* get_free_pdpt_table(remapping_tables_t* table) { 54 | for (uint32_t i = 0; i < REMAPPING_TABLE_COUNT; i++) { 55 | if (!table->is_pdpt_table_occupied[i]) { 56 | table->is_pdpt_table_occupied[i] = true; 57 | return table->pdpt_table[i]; 58 | } 59 | } 60 | 61 | return 0; 62 | } 63 | 64 | inline pde_64* get_free_pd_table(remapping_tables_t* table) { 65 | for (uint32_t i = 0; i < REMAPPING_TABLE_COUNT; i++) { 66 | if (!table->is_pd_table_occupied[i]) { 67 | table->is_pd_table_occupied[i] = true; 68 | return table->pd_table[i]; 69 | } 70 | } 71 | 72 | return 0; 73 | } 74 | 75 | inline pte_64* get_free_pt_table(remapping_tables_t* table) { 76 | for (uint32_t i = 0; i < REMAPPING_TABLE_COUNT; i++) { 77 | if (!table->is_pt_table_occupied[i]) { 78 | table->is_pt_table_occupied[i] = true; 79 | return table->pt_table[i]; 80 | } 81 | } 82 | 83 | return 0; 84 | } 85 | 86 | // Freeing helpers 87 | inline void free_pdpt_table(remapping_tables_t* table, pdpte_64* pdpt_table) { 88 | for (uint32_t i = 0; i < REMAPPING_TABLE_COUNT; i++) { 89 | if (table->pdpt_table[i] == pdpt_table) { 90 | table->is_pdpt_table_occupied[i] = false; 91 | memset(pdpt_table, 0, 512 * sizeof(pdpte_64)); 92 | return; 93 | } 94 | } 95 | } 96 | 97 | inline void free_pd_table(remapping_tables_t* table, pde_64* pd_table) { 98 | for (uint32_t i = 0; i < REMAPPING_TABLE_COUNT; i++) { 99 | if (table->pd_table[i] == pd_table) { 100 | table->is_pd_table_occupied[i] = false; 101 | memset(pd_table, 0, 512 * sizeof(pde_64)); 102 | return; 103 | } 104 | } 105 | } 106 | 107 | inline void free_pt_table(remapping_tables_t* table, pte_64* pt_table) { 108 | for (uint32_t i = 0; i < REMAPPING_TABLE_COUNT; i++) { 109 | if (table->pt_table[i] == pt_table) { 110 | table->is_pt_table_occupied[i] = false; 111 | memset(pt_table, 0, 512 * sizeof(pte_64)); 112 | return; 113 | } 114 | } 115 | } 116 | }; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/physmem/physmem.hpp: -------------------------------------------------------------------------------- 1 | #include "../project_includes.hpp" 2 | #include "../windows_structs.hpp" 3 | 4 | #include "physmem_structs.hpp" 5 | #include "page_table_helpers.hpp" 6 | 7 | namespace physmem { 8 | // Initialization functions 9 | project_status init_physmem(void); 10 | bool is_initialized(void); 11 | 12 | namespace util { 13 | cr3 get_constructed_cr3(void); 14 | cr3 get_system_cr3(void); 15 | }; 16 | 17 | namespace runtime { 18 | project_status translate_to_physical_address(uint64_t outside_target_cr3, void* virtual_address, uint64_t& physical_address, uint64_t* remaining_bytes = 0); 19 | 20 | void copy_physical_memory(uint64_t dst_physical, uint64_t src_physical, uint64_t size); 21 | project_status copy_virtual_memory(void* dst, void* src, uint64_t size, uint64_t dst_cr3, uint64_t src_cr3); 22 | project_status copy_memory_to_constructed_cr3(void* dst, void* src, uint64_t size, uint64_t src_cr3); 23 | project_status copy_memory_from_constructed_cr3(void* dst, void* src, uint64_t size, uint64_t dst_cr3); 24 | }; 25 | 26 | namespace remapping { 27 | project_status ensure_memory_mapping_for_range(void* target_address, uint64_t size, uint64_t mem_cr3_u64); 28 | project_status overwrite_virtual_address_mapping(void* target_address, void* new_memory, uint64_t target_address_cr3_u64, uint64_t new_mem_cr3_u64); 29 | }; 30 | 31 | namespace paging_manipulation { 32 | // ONLY IN HANDLER 33 | project_status win_unmap_memory_range(void* memory, uint64_t mem_cr3_u64, uint64_t size); 34 | }; 35 | 36 | namespace testing { 37 | bool memory_copy_test1(void); 38 | }; 39 | 40 | }; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/physmem/physmem_structs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../project_includes.hpp" 3 | 4 | typedef struct { 5 | uint32_t eax; 6 | uint32_t ebx; 7 | uint32_t ecx; 8 | uint32_t edx; 9 | } cpuidsplit_t; 10 | 11 | typedef struct { 12 | union { 13 | struct { 14 | uint32_t stepping_id : 4; 15 | uint32_t model : 4; 16 | uint32_t family_id : 4; 17 | uint32_t processor_type : 2; 18 | uint32_t reserved1 : 2; 19 | uint32_t extended_model_id : 4; 20 | uint32_t extended_family_id : 8; 21 | uint32_t reserved2 : 4; 22 | }; 23 | 24 | uint32_t flags; 25 | } cpuid_version_information; 26 | 27 | union { 28 | struct { 29 | uint32_t brand_index : 8; 30 | uint32_t clflush_line_size : 8; 31 | uint32_t max_addressable_ids : 8; 32 | uint32_t initial_apic_id : 8; 33 | }; 34 | 35 | uint32_t flags; 36 | } cpuid_additional_information; 37 | 38 | union { 39 | struct { 40 | uint32_t streaming_simd_extensions_3 : 1; 41 | uint32_t pclmulqdq_instruction : 1; 42 | uint32_t ds_area_64bit_layout : 1; 43 | uint32_t monitor_mwait_instruction : 1; 44 | uint32_t cpl_qualified_debug_store : 1; 45 | uint32_t virtual_machine_extensions : 1; 46 | uint32_t safer_mode_extensions : 1; 47 | uint32_t enhanced_intel_speedstep_technology : 1; 48 | uint32_t thermal_monitor_2 : 1; 49 | uint32_t supplemental_streaming_simd_extensions_3 : 1; 50 | uint32_t l1_context_id : 1; 51 | uint32_t silicon_debug : 1; 52 | uint32_t fma_extensions : 1; 53 | uint32_t cmpxchg16b_instruction : 1; 54 | uint32_t xtpr_update_control : 1; 55 | uint32_t perfmon_and_debug_capability : 1; 56 | uint32_t reserved1 : 1; 57 | uint32_t process_context_identifiers : 1; // Support for PCIDs 58 | uint32_t direct_cache_access : 1; 59 | uint32_t sse41_support : 1; 60 | uint32_t sse42_support : 1; 61 | uint32_t x2apic_support : 1; 62 | uint32_t movbe_instruction : 1; 63 | uint32_t popcnt_instruction : 1; 64 | uint32_t tsc_deadline : 1; 65 | uint32_t aesni_instruction_extensions : 1; 66 | uint32_t xsave_xrstor_instruction : 1; 67 | uint32_t osx_save : 1; 68 | uint32_t avx_support : 1; 69 | uint32_t half_precision_conversion_instructions : 1; 70 | uint32_t rdrand_instruction : 1; 71 | uint32_t reserved2 : 1; 72 | }; 73 | 74 | uint32_t flags; 75 | } cpuid_feature_information_ecx; 76 | 77 | union { 78 | struct { 79 | uint32_t floating_point_unit_on_chip : 1; 80 | uint32_t virtual_8086_mode_enhancements : 1; 81 | uint32_t debugging_extensions : 1; 82 | uint32_t page_size_extension : 1; 83 | uint32_t timestamp_counter : 1; 84 | uint32_t rdmsr_wrmsr_instructions : 1; 85 | uint32_t physical_address_extension : 1; // Physical addresses greater than 32 bits are supported, 2MB pages supported instead of 5MB pages if set 86 | uint32_t machine_check_exception : 1; 87 | uint32_t cmpxchg8b : 1; 88 | uint32_t apic_on_chip : 1; 89 | uint32_t reserved1 : 1; 90 | uint32_t sysenter_sysexit_instructions : 1; 91 | uint32_t memory_type_range_registers : 1; 92 | uint32_t page_global_bit : 1; // If set global pages are supported 93 | uint32_t machine_check_architecture : 1; 94 | uint32_t conditional_move_instructions : 1; 95 | uint32_t page_attribute_table : 1; 96 | uint32_t page_size_extension_36bit : 1; 97 | uint32_t processor_serial_number : 1; 98 | uint32_t clflush : 1; 99 | uint32_t reserved2 : 1; 100 | uint32_t debug_store : 1; 101 | uint32_t thermal_control_msrs_for_acpi : 1; 102 | uint32_t mmx_support : 1; 103 | uint32_t fxsave_fxrstor_instructions : 1; 104 | uint32_t sse_support : 1; 105 | uint32_t sse2_support : 1; 106 | uint32_t self_snoop : 1; 107 | uint32_t hyper_threading_technology : 1; 108 | uint32_t thermal_monitor : 1; 109 | uint32_t reserved3 : 1; 110 | uint32_t pending_break_enable : 1; 111 | }; 112 | 113 | uint32_t flags; 114 | } cpuid_feature_information_edx; 115 | 116 | } cpuid_eax_01; 117 | 118 | typedef union { 119 | struct { 120 | uint64_t reserved1 : 3; 121 | uint64_t page_level_write_through : 1; 122 | uint64_t page_level_cache_disable : 1; 123 | uint64_t reserved2 : 7; 124 | uint64_t address_of_page_directory : 36; 125 | uint64_t reserved3 : 16; 126 | }; 127 | 128 | uint64_t flags; 129 | } cr3; 130 | 131 | typedef union { 132 | struct { 133 | uint64_t virtual_mode_extensions : 1; 134 | uint64_t protected_mode_virtual_interrupts : 1; 135 | uint64_t timestamp_disable : 1; 136 | uint64_t debugging_extensions : 1; 137 | uint64_t page_size_extensions : 1; 138 | uint64_t physical_address_extension : 1; 139 | uint64_t machine_check_enable : 1; 140 | uint64_t page_global_enable : 1; 141 | uint64_t performance_monitoring_counter_enable : 1; 142 | uint64_t os_fxsave_fxrstor_support : 1; 143 | uint64_t os_xmm_exception_support : 1; 144 | uint64_t usermode_instruction_prevention : 1; 145 | uint64_t linear_addresses_57_bit : 1; 146 | uint64_t vmx_enable : 1; 147 | uint64_t smx_enable : 1; 148 | uint64_t reserved1 : 1; 149 | uint64_t fsgsbase_enable : 1; 150 | uint64_t pcid_enable : 1; 151 | uint64_t os_xsave : 1; 152 | uint64_t key_locker_enable : 1; 153 | uint64_t smep_enable : 1; 154 | uint64_t smap_enable : 1; 155 | uint64_t protection_key_enable : 1; 156 | uint64_t control_flow_enforcement_enable : 1; 157 | uint64_t protection_key_for_supervisor_mode_enable : 1; 158 | uint64_t reserved2 : 39; 159 | }; 160 | 161 | uint64_t flags; 162 | } cr4; 163 | 164 | typedef union { 165 | struct { 166 | uint64_t present : 1; 167 | uint64_t write : 1; 168 | uint64_t supervisor : 1; 169 | uint64_t page_level_write_through : 1; 170 | uint64_t page_level_cache_disable : 1; 171 | uint64_t accessed : 1; 172 | uint64_t reserved1 : 1; 173 | uint64_t must_be_zero : 1; 174 | uint64_t ignored_1 : 4; 175 | uint64_t page_frame_number : 36; 176 | uint64_t reserved2 : 4; 177 | uint64_t ignored_2 : 11; 178 | uint64_t execute_disable : 1; 179 | }; 180 | 181 | uint64_t flags; 182 | } pml4e_64; 183 | 184 | typedef union { 185 | struct { 186 | uint64_t present : 1; 187 | uint64_t write : 1; 188 | uint64_t supervisor : 1; 189 | uint64_t page_level_write_through : 1; 190 | uint64_t page_level_cache_disable : 1; 191 | uint64_t accessed : 1; 192 | uint64_t dirty : 1; 193 | uint64_t large_page : 1; 194 | uint64_t global : 1; 195 | uint64_t ignored_1 : 3; 196 | uint64_t pat : 1; 197 | uint64_t reserved1 : 17; 198 | uint64_t page_frame_number : 18; 199 | uint64_t reserved2 : 4; 200 | uint64_t ignored_2 : 7; 201 | uint64_t protection_key : 4; 202 | uint64_t execute_disable : 1; 203 | }; 204 | 205 | uint64_t flags; 206 | } pdpte_1gb_64; 207 | 208 | typedef union { 209 | struct { 210 | uint64_t present : 1; 211 | uint64_t write : 1; 212 | uint64_t supervisor : 1; 213 | uint64_t page_level_write_through : 1; 214 | uint64_t page_level_cache_disable : 1; 215 | uint64_t accessed : 1; 216 | uint64_t reserved1 : 1; 217 | uint64_t large_page : 1; 218 | uint64_t ignored_1 : 4; 219 | uint64_t page_frame_number : 36; 220 | uint64_t reserved2 : 4; 221 | uint64_t ignored_2 : 11; 222 | uint64_t execute_disable : 1; 223 | }; 224 | 225 | uint64_t flags; 226 | } pdpte_64; 227 | 228 | typedef union { 229 | struct { 230 | uint64_t present : 1; 231 | uint64_t write : 1; 232 | uint64_t supervisor : 1; 233 | uint64_t page_level_write_through : 1; 234 | uint64_t page_level_cache_disable : 1; 235 | uint64_t accessed : 1; 236 | uint64_t dirty : 1; 237 | uint64_t large_page : 1; 238 | uint64_t global : 1; 239 | uint64_t ignored_1 : 3; 240 | uint64_t pat : 1; 241 | uint64_t reserved1 : 8; 242 | uint64_t page_frame_number : 27; 243 | uint64_t reserved2 : 4; 244 | uint64_t ignored_2 : 7; 245 | uint64_t protection_key : 4; 246 | uint64_t execute_disable : 1; 247 | }; 248 | 249 | uint64_t flags; 250 | } pde_2mb_64; 251 | 252 | typedef union { 253 | struct { 254 | uint64_t present : 1; 255 | uint64_t write : 1; 256 | uint64_t supervisor : 1; 257 | uint64_t page_level_write_through : 1; 258 | uint64_t page_level_cache_disable : 1; 259 | uint64_t accessed : 1; 260 | uint64_t reserved1 : 1; 261 | uint64_t large_page : 1; 262 | uint64_t ignored_1 : 4; 263 | uint64_t page_frame_number : 36; 264 | uint64_t reserved2 : 4; 265 | uint64_t ignored_2 : 11; 266 | uint64_t execute_disable : 1; 267 | }; 268 | 269 | uint64_t flags; 270 | } pde_64; 271 | 272 | typedef union { 273 | struct { 274 | uint64_t present : 1; 275 | uint64_t write : 1; 276 | uint64_t supervisor : 1; 277 | uint64_t page_level_write_through : 1; 278 | uint64_t page_level_cache_disable : 1; 279 | uint64_t accessed : 1; 280 | uint64_t dirty : 1; 281 | uint64_t pat : 1; 282 | uint64_t global : 1; 283 | uint64_t ignored_1 : 3; 284 | uint64_t page_frame_number : 36; 285 | uint64_t reserved1 : 4; 286 | uint64_t ignored_2 : 7; 287 | uint64_t protection_key : 4; 288 | uint64_t execute_disable : 1; 289 | }; 290 | 291 | uint64_t flags; 292 | } pte_64; 293 | 294 | typedef union { 295 | struct { 296 | uint64_t present : 1; 297 | uint64_t write : 1; 298 | uint64_t supervisor : 1; 299 | uint64_t page_level_write_through : 1; 300 | uint64_t page_level_cache_disable : 1; 301 | uint64_t accessed : 1; 302 | uint64_t dirty : 1; 303 | uint64_t large_page : 1; 304 | uint64_t global : 1; 305 | uint64_t ignored_1 : 2; 306 | uint64_t restart : 1; 307 | uint64_t page_frame_number : 36; 308 | uint64_t reserved1 : 4; 309 | uint64_t ignored_2 : 7; 310 | uint64_t protection_key : 4; 311 | uint64_t execute_disable : 1; 312 | }; 313 | 314 | uint64_t flags; 315 | } pt_entry_64; 316 | 317 | typedef union { 318 | 319 | struct { 320 | uint64_t offset_1gb : 30; 321 | uint64_t pdpte_idx : 9; 322 | uint64_t pml4e_idx : 9; 323 | uint64_t reserved : 16; 324 | }; 325 | 326 | struct { 327 | uint64_t offset_2mb : 21; 328 | uint64_t pde_idx : 9; 329 | uint64_t pdpte_idx : 9; 330 | uint64_t pml4e_idx : 9; 331 | uint64_t reserved : 16; 332 | }; 333 | 334 | struct { 335 | uint64_t offset_4kb : 12; 336 | uint64_t pte_idx : 9; 337 | uint64_t pde_idx : 9; 338 | uint64_t pdpte_idx : 9; 339 | uint64_t pml4e_idx : 9; 340 | uint64_t reserved : 16; 341 | }; 342 | 343 | uint64_t flags; 344 | } va_64_t; 345 | 346 | typedef struct { 347 | void* table; 348 | bool large_page; 349 | } slot_t; 350 | 351 | typedef struct { 352 | va_64_t remapped_va; 353 | 354 | // Pml4 slot not needed as we only have 1 anyways 355 | slot_t pdpt_table; 356 | slot_t pd_table; 357 | void* pt_table; 358 | 359 | bool used; 360 | } remapped_entry_t; 361 | 362 | typedef enum { 363 | pdpt_table_valid, // Means that the pml4 at the correct index already points to a remapped pdpt table 364 | pde_table_valid, // Means that the pdpt at the correct index already points to a remapped pde table 365 | pte_table_valid, // Means that the pde at the correct index already points to a remapped pte table 366 | non_valid, // Means that the pml4 indexes didn't match 367 | } usable_until_t; 368 | 369 | #define PAGE_TABLE_ENTRY_COUNT 512 370 | typedef struct { 371 | alignas(0x1000) pml4e_64 pml4_table[PAGE_TABLE_ENTRY_COUNT]; // Basically only is a windows copy; We replace one entry and point it to our paging structure 372 | alignas(0x1000) pdpte_64 pdpt_table[PAGE_TABLE_ENTRY_COUNT]; 373 | alignas(0x1000) pde_2mb_64 pd_2mb_table[PAGE_TABLE_ENTRY_COUNT][PAGE_TABLE_ENTRY_COUNT]; 374 | } page_tables_t; 375 | 376 | #define REMAPPING_TABLE_COUNT 100 377 | #define MAX_REMAPPINGS 100 378 | typedef struct { 379 | union { 380 | pdpte_64* pdpt_table[REMAPPING_TABLE_COUNT]; 381 | pdpte_1gb_64* pdpt_1gb_table[REMAPPING_TABLE_COUNT]; 382 | }; 383 | union { 384 | pde_64* pd_table[REMAPPING_TABLE_COUNT]; 385 | pde_2mb_64* pd_2mb_table[REMAPPING_TABLE_COUNT]; 386 | }; 387 | 388 | pte_64* pt_table[REMAPPING_TABLE_COUNT]; 389 | 390 | bool is_pdpt_table_occupied[REMAPPING_TABLE_COUNT]; 391 | bool is_pd_table_occupied[REMAPPING_TABLE_COUNT]; 392 | bool is_pt_table_occupied[REMAPPING_TABLE_COUNT]; 393 | 394 | remapped_entry_t remapping_list[MAX_REMAPPINGS]; 395 | } remapping_tables_t; 396 | 397 | typedef struct { 398 | // These page tables make up our cr3 399 | page_tables_t* page_tables; 400 | 401 | // These page tables are sole entries we use to 402 | // remap addresses in our cr3 403 | remapping_tables_t remapping_tables; 404 | 405 | cr3 kernel_cr3; 406 | 407 | cr3 constructed_cr3; 408 | uint64_t mapped_physical_mem_base; // Is the base where we mapped the first 512 gb of physical memory 409 | 410 | bool initialized; 411 | } physmem_t; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/project_api.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "interrupts/interrupts.hpp" 3 | #include "physmem/physmem.hpp" 4 | #include "communication/communication.hpp" 5 | #include "cr3 decryption/cr3_decryption.hpp" 6 | #include "logging/logging.hpp" -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/project_includes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include "windows_structs.hpp" 6 | 7 | // We like nice declarations 8 | typedef signed char int8_t; 9 | typedef short int16_t; 10 | typedef int int32_t; 11 | typedef long long int64_t; 12 | typedef unsigned char uint8_t; 13 | typedef unsigned short uint16_t; 14 | typedef unsigned int uint32_t; 15 | typedef unsigned long long uint64_t; 16 | 17 | 18 | /* 19 | Enums 20 | */ 21 | 22 | // A return type to use instead of bool 23 | // to get more information from the return 24 | enum project_status { 25 | /* 26 | GENERAL 27 | */ 28 | status_success, 29 | status_failure, 30 | status_invalid_parameter, 31 | status_memory_allocation_failed, 32 | status_win_address_translation_failed, 33 | status_not_supported, 34 | 35 | /* 36 | WINDOWS 37 | */ 38 | status_cr3_not_found, 39 | 40 | /* 41 | PHYSMEM 42 | */ 43 | status_invalid_paging_idx, 44 | status_paging_entry_not_present, 45 | status_remapping_entry_found, 46 | status_no_valid_remapping_entry, 47 | status_no_available_page_tables, 48 | status_remapping_list_full, 49 | status_wrong_context, 50 | status_invalid_my_page_table, 51 | status_address_already_remapped, 52 | status_non_aligned, 53 | status_paging_wrong_granularity, 54 | status_page_already_unmapped, 55 | status_potential_mem_unmapping_overflow, 56 | 57 | /* 58 | Communication 59 | */ 60 | status_data_ptr_invalid, 61 | status_no_gadget_found, 62 | }; 63 | 64 | /* 65 | Macros 66 | */ 67 | 68 | #define extract_file_name(file) (strrchr(file, '\\') ? strrchr(file, '\\') + 1 : file) 69 | 70 | #define project_log_error(fmt, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] " "[%s:%d] " fmt "\n", extract_file_name(__FILE__), __LINE__, ##__VA_ARGS__) 71 | #define project_log_warning(fmt, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[~] " "[%s:%d] " fmt "\n", extract_file_name(__FILE__), __LINE__, ##__VA_ARGS__) 72 | #define project_log_success(fmt, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] " "[%s:%d] " fmt "\n", extract_file_name(__FILE__), __LINE__, ##__VA_ARGS__) 73 | #define project_log_info(fmt, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[*] " "[%s:%d] " fmt "\n", extract_file_name(__FILE__), __LINE__, ##__VA_ARGS__) 74 | 75 | /* 76 | Win API wrappers 77 | */ 78 | 79 | inline uint64_t win_get_physical_address(void* virtual_address) { 80 | return MmGetPhysicalAddress(virtual_address).QuadPart; 81 | } 82 | 83 | inline uint64_t win_get_virtual_address(uint64_t physical_address) { 84 | PHYSICAL_ADDRESS phys_addr = { 0 }; 85 | phys_addr.QuadPart = physical_address; 86 | 87 | return (uint64_t)(MmGetVirtualForPhysical(phys_addr)); 88 | } 89 | 90 | inline void sleep(LONG milliseconds) { 91 | LARGE_INTEGER interval; 92 | 93 | // Convert milliseconds to 100-nanosecond intervals 94 | interval.QuadPart = -((LONGLONG)milliseconds * 10000); 95 | 96 | KeDelayExecutionThread(KernelMode, false, &interval); 97 | } 98 | 99 | /* 100 | Assembly function declaration 101 | */ 102 | 103 | extern "C" uint32_t get_proc_number(void); 104 | extern "C" void asm_handler(void); 105 | 106 | /* 107 | Declaration of imports 108 | */ 109 | extern "C" NTKERNELAPI VOID KeStackAttachProcess(PRKPROCESS PROCESS, PKAPC_STATE ApcState); 110 | extern "C" NTKERNELAPI VOID KeUnstackDetachProcess(PKAPC_STATE ApcState); 111 | extern "C" PLIST_ENTRY PsLoadedModuleList; 112 | 113 | /* 114 | Driver globals 115 | */ 116 | inline void* g_driver_base; 117 | inline uint64_t g_driver_size; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/project_utility.cpp: -------------------------------------------------------------------------------- 1 | #include "project_includes.hpp" 2 | #include "windows_structs.hpp" 3 | #include 4 | 5 | namespace utility { 6 | project_status get_driver_module_base(const wchar_t* driver_name, void*& driver_base) { 7 | PLIST_ENTRY head = PsLoadedModuleList; 8 | PLIST_ENTRY curr = head->Flink; 9 | 10 | // Just loop over the modules 11 | while (curr != head) { 12 | LDR_DATA_TABLE_ENTRY* curr_mod = CONTAINING_RECORD(curr, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 13 | 14 | if (_wcsicmp(curr_mod->BaseDllName.Buffer, driver_name) == 0) { 15 | driver_base = curr_mod->DllBase; 16 | return status_success; 17 | } 18 | 19 | curr = curr->Flink; 20 | } 21 | 22 | return status_failure; 23 | } 24 | 25 | project_status get_eprocess(const char* process_name, PEPROCESS& pe_proc) { 26 | PEPROCESS sys_process = PsInitialSystemProcess; 27 | PEPROCESS curr_entry = sys_process; 28 | 29 | char image_name[15]; 30 | 31 | do { 32 | memcpy((void*)(&image_name), (void*)((uintptr_t)curr_entry + 0x5a8), sizeof(image_name)); 33 | 34 | if (strcmp(image_name, process_name) == 0) { 35 | uint32_t active_threads; 36 | 37 | memcpy((void*)&active_threads, (void*)((uintptr_t)curr_entry + ACTIVE_THREADS), sizeof(active_threads)); 38 | 39 | if (active_threads) { 40 | pe_proc = curr_entry; 41 | return status_success; 42 | } 43 | } 44 | 45 | PLIST_ENTRY list = (PLIST_ENTRY)((uintptr_t)(curr_entry)+0x448); 46 | curr_entry = (PEPROCESS)((uintptr_t)list->Flink - 0x448); 47 | 48 | } while (curr_entry != sys_process); 49 | 50 | return status_failure; 51 | } 52 | 53 | uintptr_t find_pattern_in_range(uintptr_t region_base, size_t region_size, const char* pattern, size_t pattern_size, char wildcard) { 54 | // Ensure there are enough bytes left to check the pattern 55 | char* region_end = (char*)region_base + region_size - pattern_size + 1; 56 | 57 | for (char* byte = (char*)region_base; byte < region_end; ++byte) { 58 | 59 | if (*byte == *pattern || *pattern == wildcard) { 60 | bool found = true; 61 | 62 | for (size_t i = 1; i < pattern_size; ++i) { 63 | if (pattern[i] != byte[i] && pattern[i] != wildcard) { 64 | found = false; 65 | break; 66 | } 67 | } 68 | if (found) { 69 | return (uintptr_t)byte; 70 | } 71 | } 72 | } 73 | 74 | return 0; 75 | } 76 | 77 | uintptr_t search_pattern_in_section(void* module_handle, const char* section_name, const char* pattern, uint64_t pattern_size, char wildcard) { 78 | 79 | IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)module_handle; 80 | if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { 81 | return 0; 82 | } 83 | 84 | IMAGE_NT_HEADERS64* nt_headers = (IMAGE_NT_HEADERS64*)((uintptr_t)module_handle + dos_header->e_lfanew); 85 | if (nt_headers->Signature != IMAGE_NT_SIGNATURE) { 86 | return 0; 87 | } 88 | 89 | // First section header is directly after NT Headers 90 | IMAGE_SECTION_HEADER* sections = (IMAGE_SECTION_HEADER*)((uintptr_t)nt_headers + sizeof(IMAGE_NT_HEADERS64)); 91 | 92 | for (uint32_t i = 0; i < nt_headers->FileHeader.NumberOfSections; i++) { 93 | // Limit yourself to only executable non-discardable sections 94 | if (!(sections[i].Characteristics & IMAGE_SCN_CNT_CODE) || 95 | !(sections[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) || 96 | (sections[i].Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) 97 | continue; 98 | if (strncmp((const char*)sections[i].Name, section_name, IMAGE_SIZEOF_SHORT_NAME) == 0) { 99 | uintptr_t section_start = (uintptr_t)module_handle + sections[i].VirtualAddress; 100 | uint32_t section_size = sections[i].Misc.VirtualSize; 101 | 102 | uintptr_t result = find_pattern_in_range((uintptr_t)section_start, section_size, pattern, pattern_size, wildcard); 103 | 104 | return result; 105 | } 106 | } 107 | 108 | return 0; 109 | } 110 | 111 | project_status is_data_ptr_in_valid_region(uint64_t data_ptr) { 112 | PLIST_ENTRY head = PsLoadedModuleList; 113 | PLIST_ENTRY curr = head->Flink; 114 | 115 | // Just loop over the modules 116 | while (curr != head) { 117 | LDR_DATA_TABLE_ENTRY* curr_mod = CONTAINING_RECORD(curr, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 118 | 119 | uint64_t driver_base = (uint64_t)curr_mod->DllBase; 120 | uint64_t driver_end = (uint64_t)curr_mod->DllBase + curr_mod->SizeOfImage; 121 | 122 | // If the data ptr resides in a legit driver, it is considered valid 123 | if (data_ptr >= driver_base && driver_end >= data_ptr) { 124 | return status_success; 125 | } 126 | 127 | curr = curr->Flink; 128 | } 129 | 130 | return status_data_ptr_invalid; 131 | } 132 | 133 | uint64_t get_cr3(uint64_t target_pid) { 134 | PEPROCESS sys_process = PsInitialSystemProcess; 135 | PEPROCESS curr_entry = sys_process; 136 | 137 | do { 138 | uint64_t curr_pid; 139 | 140 | memcpy(&curr_pid, (void*)((uintptr_t)curr_entry + 0x440), sizeof(curr_pid)); 141 | 142 | // Check whether we found our process 143 | if (target_pid == curr_pid) { 144 | 145 | uint32_t active_threads; 146 | 147 | memcpy((void*)&active_threads, (void*)((uintptr_t)curr_entry + ACTIVE_THREADS), sizeof(active_threads)); 148 | 149 | if (active_threads || target_pid == 4) { 150 | uint64_t cr3; 151 | 152 | memcpy(&cr3, (void*)((uintptr_t)curr_entry + 0x28), sizeof(cr3)); 153 | 154 | return cr3; 155 | } 156 | } 157 | 158 | PLIST_ENTRY list = (PLIST_ENTRY)((uintptr_t)(curr_entry)+0x448); 159 | curr_entry = (PEPROCESS)((uintptr_t)list->Flink - 0x448); 160 | } while (curr_entry != sys_process); 161 | 162 | return 0; 163 | } 164 | }; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/project_utility.hpp: -------------------------------------------------------------------------------- 1 | #include "project_includes.hpp" 2 | 3 | /* 4 | Exposed utility 5 | */ 6 | namespace utility { 7 | project_status get_driver_module_base(const wchar_t* driver_name, void*& driver_base); 8 | project_status get_eprocess(const char* process_name, PEPROCESS& pe_proc); 9 | project_status is_data_ptr_in_valid_region(uint64_t data_ptr); 10 | uint64_t get_cr3(uint64_t target_pid); 11 | 12 | uintptr_t find_pattern_in_range(uintptr_t region_base, size_t region_size, const char* pattern, size_t pattern_size, char wildcard); 13 | uintptr_t search_pattern_in_section(void* module_handle, const char* section_name, const char* pattern, uint64_t pattern_size, char wildcard); 14 | }; -------------------------------------------------------------------------------- /phsymem_remap/physmem_remapper_rewrite/project/windows_structs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | /* 6 | Constants in windows; To do: Make them dynamic to windows version etc 7 | */ 8 | #define IMAGE_NAME_OFFSET 0x5a8 9 | #define PID_OFFSET 0x440 10 | #define FLINK_OFFSET 0x448 11 | #define SYSTEM_PID 4 12 | #define IMAGE_NAME_LENGTH 15 13 | #define LIST_ENTRY_OFFSET 0x448 14 | #define DIRECTORY_TABLE_BASE_OFFSET 0x28 15 | #define PEB_OFFSET 0x550 16 | #define ACTIVE_THREADS 0x5f0 17 | 18 | #define LDR_DATA_OFFSET 0x18 19 | 20 | union _KEXECUTE_OPTIONS { 21 | UCHAR ExecuteDisable : 1; //0x0 22 | UCHAR ExecuteEnable : 1; //0x0 23 | UCHAR DisableThunkEmulation : 1; //0x0 24 | UCHAR Permanent : 1; //0x0 25 | UCHAR ExecuteDispatchEnable : 1; //0x0 26 | UCHAR ImageDispatchEnable : 1; //0x0 27 | UCHAR DisableExceptionChainValidation : 1; //0x0 28 | UCHAR Spare : 1; //0x0 29 | volatile UCHAR ExecuteOptions; //0x0 30 | UCHAR ExecuteOptionsNV; //0x0 31 | }; 32 | 33 | union _KSTACK_COUNT { 34 | LONG Value; //0x0 35 | ULONG State : 3; //0x0 36 | ULONG StackCount : 29; //0x0 37 | }; 38 | 39 | struct _KAFFINITY_EX { 40 | USHORT Count; //0x0 41 | USHORT Size; //0x2 42 | ULONG Reserved; //0x4 43 | ULONGLONG Bitmap[20]; //0x8 44 | }; 45 | 46 | struct _KPROCESS { 47 | struct _DISPATCHER_HEADER Header; //0x0 48 | struct _LIST_ENTRY ProfileListHead; //0x18 49 | ULONGLONG DirectoryTableBase; //0x28 50 | struct _LIST_ENTRY ThreadListHead; //0x30 51 | ULONG ProcessLock; //0x40 52 | ULONG ProcessTimerDelay; //0x44 53 | ULONGLONG DeepFreezeStartTime; //0x48 54 | struct _KAFFINITY_EX Affinity; //0x50 55 | ULONGLONG AffinityPadding[12]; //0xf8 56 | struct _LIST_ENTRY ReadyListHead; //0x158 57 | struct _SINGLE_LIST_ENTRY SwapListEntry; //0x168 58 | volatile struct _KAFFINITY_EX ActiveProcessors; //0x170 59 | ULONGLONG ActiveProcessorsPadding[12]; //0x218 60 | union { 61 | struct { 62 | ULONG AutoAlignment : 1; //0x278 63 | ULONG DisableBoost : 1; //0x278 64 | ULONG DisableQuantum : 1; //0x278 65 | ULONG DeepFreeze : 1; //0x278 66 | ULONG TimerVirtualization : 1; //0x278 67 | ULONG CheckStackExtents : 1; //0x278 68 | ULONG CacheIsolationEnabled : 1; //0x278 69 | ULONG PpmPolicy : 3; //0x278 70 | ULONG VaSpaceDeleted : 1; //0x278 71 | ULONG ReservedFlags : 21; //0x278 72 | }; 73 | volatile LONG ProcessFlags; //0x278 74 | }; 75 | ULONG ActiveGroupsMask; //0x27c 76 | CHAR BasePriority; //0x280 77 | CHAR QuantumReset; //0x281 78 | CHAR Visited; //0x282 79 | union _KEXECUTE_OPTIONS Flags; //0x283 80 | USHORT ThreadSeed[20]; //0x284 81 | USHORT ThreadSeedPadding[12]; //0x2ac 82 | USHORT IdealProcessor[20]; //0x2c4 83 | USHORT IdealProcessorPadding[12]; //0x2ec 84 | USHORT IdealNode[20]; //0x304 85 | USHORT IdealNodePadding[12]; //0x32c 86 | USHORT IdealGlobalNode; //0x344 87 | USHORT Spare1; //0x346 88 | _KSTACK_COUNT StackCount; //0x348 89 | struct _LIST_ENTRY ProcessListEntry; //0x350 90 | ULONGLONG CycleTime; //0x360 91 | ULONGLONG ContextSwitches; //0x368 92 | struct _KSCHEDULING_GROUP* SchedulingGroup; //0x370 93 | ULONG FreezeCount; //0x378 94 | ULONG KernelTime; //0x37c 95 | ULONG UserTime; //0x380 96 | ULONG ReadyTime; //0x384 97 | ULONGLONG UserDirectoryTableBase; //0x388 98 | UCHAR AddressPolicy; //0x390 99 | UCHAR Spare2[71]; //0x391 100 | VOID* InstrumentationCallback; //0x3d8 101 | union { 102 | ULONGLONG SecureHandle; //0x3e0 103 | struct { 104 | ULONGLONG SecureProcess : 1; //0x3e0 105 | ULONGLONG Unused : 1; //0x3e0 106 | } Flags; //0x3e0 107 | } SecureState; //0x3e0 108 | ULONGLONG KernelWaitTime; //0x3e8 109 | ULONGLONG UserWaitTime; //0x3f0 110 | ULONGLONG EndPadding[8]; //0x3f8 111 | }; 112 | 113 | typedef struct { 114 | struct _LIST_ENTRY InLoadOrderLinks; //0x0 115 | struct _LIST_ENTRY InMemoryOrderLinks; //0x10 116 | struct _LIST_ENTRY InInitializationOrderLinks; //0x20 117 | VOID* DllBase; //0x30 118 | VOID* EntryPoint; //0x38 119 | ULONG SizeOfImage; //0x40 120 | struct _UNICODE_STRING FullDllName; //0x48 121 | struct _UNICODE_STRING BaseDllName; //0x58 122 | union { 123 | UCHAR FlagGroup[4]; //0x68 124 | ULONG Flags; //0x68 125 | struct { 126 | ULONG PackagedBinary : 1; //0x68 127 | ULONG MarkedForRemoval : 1; //0x68 128 | ULONG ImageDll : 1; //0x68 129 | ULONG LoadNotificationsSent : 1; //0x68 130 | ULONG TelemetryEntryProcessed : 1; //0x68 131 | ULONG ProcessStaticImport : 1; //0x68 132 | ULONG InLegacyLists : 1; //0x68 133 | ULONG InIndexes : 1; //0x68 134 | ULONG ShimDll : 1; //0x68 135 | ULONG InExceptionTable : 1; //0x68 136 | ULONG ReservedFlags1 : 2; //0x68 137 | ULONG LoadInProgress : 1; //0x68 138 | ULONG LoadConfigProcessed : 1; //0x68 139 | ULONG EntryProcessed : 1; //0x68 140 | ULONG ProtectDelayLoad : 1; //0x68 141 | ULONG ReservedFlags3 : 2; //0x68 142 | ULONG DontCallForThreads : 1; //0x68 143 | ULONG ProcessAttachCalled : 1; //0x68 144 | ULONG ProcessAttachFailed : 1; //0x68 145 | ULONG CorDeferredValidate : 1; //0x68 146 | ULONG CorImage : 1; //0x68 147 | ULONG DontRelocate : 1; //0x68 148 | ULONG CorILOnly : 1; //0x68 149 | ULONG ChpeImage : 1; //0x68 150 | ULONG ReservedFlags5 : 2; //0x68 151 | ULONG Redirected : 1; //0x68 152 | ULONG ReservedFlags6 : 2; //0x68 153 | ULONG CompatDatabaseProcessed : 1; //0x68 154 | }; 155 | }; 156 | USHORT ObsoleteLoadCount; //0x6c 157 | USHORT TlsIndex; //0x6e 158 | struct _LIST_ENTRY HashLinks; //0x70 159 | ULONG TimeDateStamp; //0x80 160 | struct _ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88 161 | VOID* Lock; //0x90 162 | struct _LDR_DDAG_NODE* DdagNode; //0x98 163 | struct _LIST_ENTRY NodeModuleLink; //0xa0 164 | struct _LDRP_LOAD_CONTEXT* LoadContext; //0xb0 165 | VOID* ParentDllBase; //0xb8 166 | VOID* SwitchBackContext; //0xc0 167 | struct _RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8 168 | struct _RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0 169 | ULONGLONG OriginalBase; //0xf8 170 | union _LARGE_INTEGER LoadTime; //0x100 171 | ULONG BaseNameHashValue; //0x108 172 | //enum _LDR_DLL_LOAD_REASON LoadReason; //0x10c 173 | ULONG ImplicitPathOptions; //0x110 174 | ULONG ReferenceCount; //0x114 175 | ULONG DependentLoadFlags; //0x118 176 | UCHAR SigningLevel; //0x11c 177 | }LDR_DATA_TABLE_ENTRY; 178 | 179 | typedef struct _KAPC_STATE { 180 | LIST_ENTRY ApcListHead[MaximumMode]; 181 | struct _KPROCESS* Process; 182 | union { 183 | UCHAR InProgressFlags; 184 | struct { 185 | BOOLEAN KernelApcInProgress : 1; 186 | BOOLEAN SpecialApcInProgress : 1; 187 | }; 188 | }; 189 | 190 | BOOLEAN KernelApcPending; 191 | union { 192 | BOOLEAN UserApcPendingAll; 193 | struct { 194 | BOOLEAN SpecialUserApcPending : 1; 195 | BOOLEAN UserApcPending : 1; 196 | }; 197 | }; 198 | } KAPC_STATE, * PKAPC_STATE, * PRKAPC_STATE; 199 | 200 | typedef struct { 201 | ULONG Length; //0x0 202 | UCHAR Initialized; //0x4 203 | VOID* SsHandle; //0x8 204 | struct _LIST_ENTRY InLoadOrderModuleList; //0x10 205 | struct _LIST_ENTRY InMemoryOrderModuleList; //0x20 206 | struct _LIST_ENTRY InInitializationOrderModuleList; //0x30 207 | VOID* EntryInProgress; //0x40 208 | UCHAR ShutdownInProgress; //0x48 209 | VOID* ShutdownThreadId; //0x50 210 | }PEB_LDR_DATA; -------------------------------------------------------------------------------- /physmem_remapper_rewrite.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.6.33815.320 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver", "phsymem_remap\physmem_remapper_rewrite\physmem_remapper_rewrite.vcxproj", "{0B8EACB8-A4B3-4F37-BA0C-2AA50F087351}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "um", "vext\vext.vcxproj", "{3115ECC5-0DA7-4743-B2D0-234F3F46A97F}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mapper", "mapper\my_mapper\my_mapper.vcxproj", "{278B99AC-C438-472A-8272-79F83DEF7F7D}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Release|x64 = Release|x64 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {0B8EACB8-A4B3-4F37-BA0C-2AA50F087351}.Release|x64.ActiveCfg = Release|x64 18 | {0B8EACB8-A4B3-4F37-BA0C-2AA50F087351}.Release|x64.Build.0 = Release|x64 19 | {3115ECC5-0DA7-4743-B2D0-234F3F46A97F}.Release|x64.ActiveCfg = Release|x64 20 | {3115ECC5-0DA7-4743-B2D0-234F3F46A97F}.Release|x64.Build.0 = Release|x64 21 | {278B99AC-C438-472A-8272-79F83DEF7F7D}.Release|x64.ActiveCfg = Release|x64 22 | {278B99AC-C438-472A-8272-79F83DEF7F7D}.Release|x64.Build.0 = Release|x64 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | GlobalSection(ExtensibilityGlobals) = postSolution 28 | SolutionGuid = {0ABA995A-73F6-44B7-BDD2-6AD0321D92D1} 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /vext/api/debug/debug.cpp: -------------------------------------------------------------------------------- 1 | #include "debug.hpp" 2 | 3 | namespace debug { 4 | // Is only part of the initialization, only the part that does not actually call the driver 5 | bool skeleton_init_lib(void) { 6 | // For some reason user32.dll has to also be loaded for calls to NtUser functions to work? 7 | if (!LoadLibraryW(L"user32.dll")) { 8 | log("Failed to load user32.dll"); 9 | return false; 10 | } 11 | 12 | HMODULE win32u = LoadLibraryW(L"win32u.dll"); 13 | if (!win32u) { 14 | log("Failed to get win32u.dll handle"); 15 | return false; 16 | } 17 | 18 | uint64_t handler_address = (uint64_t)GetProcAddress(win32u, "NtUserGetCPD"); 19 | 20 | NtUserGetCPD = (NtUserGetCPD_type)handler_address; 21 | physmem::inited = true; 22 | 23 | return true; 24 | } 25 | 26 | bool test_ping(void) { 27 | return physmem::ping_driver(); 28 | } 29 | 30 | bool test_hiding(void) { 31 | return physmem::hide_driver(); 32 | } 33 | 34 | bool test_getting_cr3(void) { 35 | uint64_t curr_cr3 = physmem::get_cr3(GetCurrentProcessId()); 36 | if (!curr_cr3) 37 | return false; 38 | 39 | return true; 40 | } 41 | 42 | bool test_memory_copying(void) { 43 | uint64_t curr_cr3 = physmem::get_cr3(GetCurrentProcessId()); 44 | if (!curr_cr3) 45 | return true; 46 | 47 | uint64_t a = 0; 48 | uint64_t b = 1; 49 | 50 | if (!physmem::copy_virtual_memory(curr_cr3, curr_cr3, &b, &a, sizeof(uint64_t))) 51 | return false; 52 | 53 | return a == b; 54 | } 55 | 56 | bool test_unloading() { 57 | return physmem::unload_driver(); 58 | } 59 | 60 | void test_driver(void) { 61 | log("Press enter to continue"); 62 | log("Loading lib..."); 63 | getchar(); 64 | if (!skeleton_init_lib()) { 65 | log("Failed loading the remapper lib"); 66 | return; 67 | } 68 | 69 | log("Press enter to continue"); 70 | log("Pinging driver..."); 71 | getchar(); 72 | if (!test_ping()) { 73 | log("Failed pinging the driver"); 74 | return; 75 | } 76 | 77 | log("Press enter to continue"); 78 | log("Hiding driver..."); 79 | getchar(); 80 | if (!test_hiding()) { 81 | log("Failed hiding the driver"); 82 | return; 83 | } 84 | 85 | log("Press enter to continue"); 86 | log("Cr3 getting..."); 87 | getchar(); 88 | if (!test_getting_cr3()) { 89 | log("Failed getting cr3"); 90 | return; 91 | } 92 | 93 | log("Press enter to continue"); 94 | log("Memory copying..."); 95 | getchar(); 96 | if (!test_memory_copying()) { 97 | log("Failed memory copying"); 98 | return; 99 | } 100 | 101 | log("Press enter to continue"); 102 | log("Unloading driver..."); 103 | getchar(); 104 | if (!test_unloading()) { 105 | log("Failed unloading the driver"); 106 | return; 107 | } 108 | 109 | log("Sucessfully tested driver"); 110 | } 111 | }; -------------------------------------------------------------------------------- /vext/api/debug/debug.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma warning (disable: 4003) 3 | #include "../driver/driver_um_lib.hpp" 4 | 5 | namespace debug { 6 | void test_driver(void); 7 | }; -------------------------------------------------------------------------------- /vext/api/driver/driver_includes.hpp: -------------------------------------------------------------------------------- 1 | #pragma warning (disable: 4091 6328 6031) 2 | #pragma once 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // Logging macros 12 | #define log(fmt, ...) printf("[Physmeme] " fmt "\n", ##__VA_ARGS__) 13 | #define log_new_line(fmt) printf(fmt "\n") -------------------------------------------------------------------------------- /vext/api/driver/driver_shared.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma optimize("", off) 3 | // Designed to be a standalone, includable .hpp, thus we need to make our own definitions etc. 4 | 5 | /* 6 | Typedefs and Definitions 7 | */ 8 | 9 | #ifndef _In_ 10 | #define _In_ 11 | #endif // !_In_ 12 | 13 | #ifndef _Out_ 14 | #define _Out_ 15 | #endif // !_Out_ 16 | 17 | #ifndef MAX_PATH 18 | #define MAX_PATH 260 19 | #endif // !MAX_PATH 20 | 21 | using uint8_t = unsigned char; 22 | using uint16_t = unsigned short; 23 | using uint32_t = unsigned int; 24 | using uint64_t = unsigned long long; 25 | 26 | /* 27 | Communication structs 28 | */ 29 | 30 | struct copy_virtual_memory_t { 31 | _In_ uint64_t src_cr3; 32 | _In_ uint64_t dst_cr3; 33 | 34 | _In_ void* src; 35 | _In_ void* dst; 36 | 37 | _In_ uint64_t size; 38 | }; 39 | 40 | struct get_cr3_t { 41 | _In_ uint64_t pid; 42 | 43 | _Out_ uint64_t cr3; 44 | }; 45 | 46 | struct get_module_base_t { 47 | _In_ char module_name[MAX_PATH]; 48 | _In_ uint64_t pid; 49 | 50 | _Out_ uint64_t module_base; 51 | }; 52 | 53 | struct get_module_size_t { 54 | _In_ char module_name[MAX_PATH]; 55 | _In_ uint64_t pid; 56 | 57 | _Out_ uint64_t module_size; 58 | }; 59 | 60 | struct get_pid_by_name_t { 61 | _In_ char name[MAX_PATH]; 62 | 63 | _Out_ uint64_t pid; 64 | }; 65 | 66 | struct get_ldr_data_table_entry_count_t { 67 | _In_ uint64_t pid; 68 | 69 | _Out_ uint64_t count; 70 | }; 71 | 72 | struct module_info_t { 73 | _In_ char name[MAX_PATH]; 74 | _In_ uint64_t base; 75 | _In_ uint64_t size; 76 | }; 77 | 78 | struct cmd_get_data_table_entry_info_t { 79 | _In_ uint64_t pid; 80 | _In_ module_info_t* info_array; 81 | }; 82 | 83 | #define MAX_MESSAGES 512 84 | #define MAX_MESSAGE_SIZE 256 85 | 86 | struct log_entry_t { 87 | bool present; 88 | char payload[MAX_MESSAGE_SIZE]; 89 | }; 90 | 91 | struct cmd_output_logs_t { 92 | _In_ uint32_t count; 93 | _In_ log_entry_t* log_array; 94 | }; 95 | 96 | enum call_types_t : uint32_t { 97 | cmd_get_pid_by_name, 98 | cmd_get_cr3, 99 | 100 | cmd_get_module_base, 101 | cmd_get_module_size, 102 | cmd_get_ldr_data_table_entry_count, 103 | cmd_get_data_table_entry_info, 104 | 105 | cmd_copy_virtual_memory, 106 | 107 | cmd_output_logs, 108 | 109 | cmd_remove_from_system_page_tables, 110 | cmd_unload_driver, 111 | cmd_ping_driver, 112 | }; 113 | 114 | struct command_t { 115 | bool status; 116 | call_types_t call_type; 117 | void* sub_command_ptr; 118 | }; 119 | #pragma optimize("", on) -------------------------------------------------------------------------------- /vext/api/driver/driver_um_lib.cpp: -------------------------------------------------------------------------------- 1 | #include "driver_um_lib.hpp" 2 | #include 3 | #include 4 | 5 | extern "C" NtUserGetCPD_type NtUserGetCPD = 0; 6 | 7 | // Restores from a nmi 8 | extern "C" void nmi_restoring(trap_frame_t* trap_frame) { 9 | uint64_t* stack_ptr = (uint64_t*)trap_frame->rsp; 10 | 11 | while (true) { 12 | if (*stack_ptr != stack_id) { 13 | stack_ptr++; // Move up the stack 14 | continue; 15 | } 16 | 17 | trap_frame->rax = nmi_occured; 18 | 19 | // Restore rsp 20 | trap_frame->rsp = (uint64_t)stack_ptr + 0x8; // Point top of rsp to a ret address 21 | 22 | // Return to the send request 23 | return; 24 | } 25 | } 26 | 27 | namespace physmem { 28 | 29 | __int64 send_request(void* cmd) { 30 | 31 | __int64 ret = asm_call_driver((uint64_t)cmd, caller_signature, (uint64_t)asm_nmi_restoring); 32 | if (ret == nmi_occured) { 33 | // The nmi handler code pops stack id for us, so just recurively call the request 34 | return send_request(cmd); 35 | } 36 | 37 | return ret; 38 | } 39 | 40 | bool copy_virtual_memory(uint64_t src_cr3, uint64_t dst_cr3, void* src, void* dst, uint64_t size) { 41 | if (!inited || !NtUserGetCPD) 42 | return false; 43 | 44 | copy_virtual_memory_t copy_mem_cmd = { 0 }; 45 | copy_mem_cmd.src_cr3 = src_cr3; 46 | copy_mem_cmd.dst_cr3 = dst_cr3; 47 | copy_mem_cmd.src = src; 48 | copy_mem_cmd.dst = dst; 49 | copy_mem_cmd.size = size; 50 | 51 | command_t cmd = { 0 }; 52 | cmd.call_type = cmd_copy_virtual_memory; 53 | cmd.sub_command_ptr = ©_mem_cmd; 54 | 55 | send_request(&cmd); 56 | 57 | return cmd.status; 58 | } 59 | 60 | uint64_t get_cr3(uint64_t pid) { 61 | if (!inited || !NtUserGetCPD) 62 | return 0; 63 | 64 | get_cr3_t get_cr3_cmd = { 0 }; 65 | get_cr3_cmd.pid = pid; 66 | 67 | command_t cmd = { 0 }; 68 | cmd.call_type = cmd_get_cr3; 69 | cmd.sub_command_ptr = &get_cr3_cmd; 70 | 71 | send_request(&cmd); 72 | 73 | return get_cr3_cmd.cr3; 74 | } 75 | 76 | uint64_t get_module_base(const char* module_name, uint64_t pid) { 77 | if (!inited || !NtUserGetCPD) 78 | return 0; 79 | 80 | get_module_base_t get_module_base_cmd = { 0 }; 81 | strncpy(get_module_base_cmd.module_name, module_name, MAX_PATH - 1); 82 | get_module_base_cmd.pid = pid; 83 | 84 | command_t cmd = { 0 }; 85 | cmd.call_type = cmd_get_module_base; 86 | cmd.sub_command_ptr = &get_module_base_cmd; 87 | 88 | send_request(&cmd); 89 | 90 | return get_module_base_cmd.module_base; 91 | } 92 | 93 | uint64_t get_module_size(const char* module_name, uint64_t pid) { 94 | if (!inited || !NtUserGetCPD) 95 | return 0; 96 | 97 | get_module_size_t get_module_size_cmd = { 0 }; 98 | strncpy(get_module_size_cmd.module_name, module_name, MAX_PATH - 1); 99 | get_module_size_cmd.pid = pid; 100 | 101 | command_t cmd = { 0 }; 102 | cmd.call_type = cmd_get_module_size; 103 | cmd.sub_command_ptr = &get_module_size_cmd; 104 | 105 | send_request(&cmd); 106 | 107 | return get_module_size_cmd.module_size; 108 | } 109 | 110 | uint64_t get_pid_by_name(const char* name) { 111 | if (!inited || !NtUserGetCPD) 112 | return 0; 113 | 114 | get_pid_by_name_t get_pid_by_name_cmd = { 0 }; 115 | strncpy(get_pid_by_name_cmd.name, name, MAX_PATH - 1); 116 | 117 | command_t cmd = { 0 }; 118 | cmd.call_type = cmd_get_pid_by_name; 119 | cmd.sub_command_ptr = &get_pid_by_name_cmd; 120 | 121 | send_request(&cmd); 122 | 123 | return get_pid_by_name_cmd.pid; 124 | } 125 | 126 | uint64_t get_ldr_data_table_entry_count(uint64_t pid) { 127 | if (!inited || !NtUserGetCPD) 128 | return 0; 129 | 130 | get_ldr_data_table_entry_count_t get_ldr_data_table_entry = { 0 }; 131 | get_ldr_data_table_entry.pid = pid; 132 | 133 | command_t cmd = { 0 }; 134 | cmd.call_type = cmd_get_ldr_data_table_entry_count; 135 | cmd.sub_command_ptr = &get_ldr_data_table_entry; 136 | 137 | send_request(&cmd); 138 | 139 | return get_ldr_data_table_entry.count; 140 | } 141 | 142 | bool get_data_table_entry_info(uint64_t pid, module_info_t* info_array) { 143 | if (!inited || !NtUserGetCPD) 144 | return false; 145 | 146 | cmd_get_data_table_entry_info_t get_module_at_index = { 0 }; 147 | get_module_at_index.pid = pid; 148 | get_module_at_index.info_array = info_array; 149 | 150 | command_t cmd = { 0 }; 151 | cmd.call_type = cmd_get_data_table_entry_info; 152 | cmd.sub_command_ptr = &get_module_at_index; 153 | 154 | send_request(&cmd); 155 | 156 | return cmd.status; 157 | } 158 | 159 | bool hide_driver(void) { 160 | if (!inited || !NtUserGetCPD) 161 | return false; 162 | 163 | command_t cmd = { 0 }; 164 | cmd.call_type = cmd_remove_from_system_page_tables; 165 | 166 | send_request(&cmd); 167 | 168 | return cmd.status; 169 | } 170 | 171 | bool unload_driver(void) { 172 | if (!inited || !NtUserGetCPD) { 173 | if(!physmem::init_physmem_remapper_lib()) 174 | return false; 175 | } 176 | 177 | command_t cmd = { 0 }; 178 | cmd.call_type = cmd_unload_driver; 179 | 180 | send_request(&cmd); 181 | 182 | return cmd.status; 183 | } 184 | 185 | bool ping_driver(void) { 186 | if (!inited || !NtUserGetCPD) 187 | return false; 188 | 189 | command_t cmd = { 0 }; 190 | cmd.call_type = cmd_ping_driver; 191 | 192 | send_request(&cmd); 193 | 194 | return cmd.status; 195 | } 196 | 197 | void flush_logs(void) { 198 | if (!inited || !NtUserGetCPD) 199 | return; 200 | 201 | log_entry_t* log_array = new log_entry_t[512]; 202 | memset(log_array, 0, sizeof(log_entry_t) * 512); 203 | 204 | cmd_output_logs_t sub_cmd; 205 | sub_cmd.count = 512; 206 | sub_cmd.log_array = log_array; 207 | 208 | command_t cmd = { 0 }; 209 | cmd.call_type = cmd_output_logs; 210 | cmd.sub_command_ptr = &sub_cmd; 211 | 212 | send_request(&cmd); 213 | if (!cmd.status) { 214 | log("Failed flushing logs"); 215 | return; 216 | } 217 | 218 | if (!log_array[0].present) { 219 | delete[] log_array; 220 | return; 221 | } 222 | 223 | log_new_line(); 224 | log("Root Log:"); 225 | for (uint32_t i = 0; i < 512; i++) { 226 | if (!log_array[i].present) 227 | continue; 228 | 229 | log("Root: %s", log_array[i].payload); 230 | } 231 | log_new_line(); 232 | 233 | delete[] log_array; 234 | } 235 | }; -------------------------------------------------------------------------------- /vext/api/driver/driver_um_lib.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "driver_includes.hpp" 3 | #include "driver_shared.hpp" 4 | 5 | constexpr uint64_t stack_id = 0xdeed; 6 | constexpr uint64_t nmi_occured = 0x01010101; 7 | 8 | constexpr uint32_t caller_signature = 0x6969; 9 | 10 | typedef __int64(__fastcall* NtUserGetCPD_type)(uint64_t hwnd, uint32_t flags, ULONG_PTR dw_data); 11 | extern "C" NtUserGetCPD_type NtUserGetCPD; 12 | 13 | extern "C" void asm_nmi_wrapper(void); 14 | extern "C" void asm_nmi_restoring(void); 15 | extern "C" __int64 __fastcall asm_call_driver(uint64_t hwnd, uint32_t flags, ULONG_PTR dw_data); 16 | 17 | namespace physmem { 18 | inline bool inited = false; 19 | __int64 send_request(void* cmd); 20 | 21 | 22 | bool copy_virtual_memory(uint64_t src_cr3, uint64_t dst_cr3, void* src, void* dst, uint64_t size); 23 | uint64_t get_cr3(uint64_t pid); 24 | uint64_t get_module_base(const char* module_name, uint64_t pid); 25 | uint64_t get_module_size(const char* module_name, uint64_t pid); 26 | uint64_t get_pid_by_name(const char* name); 27 | uint64_t get_ldr_data_table_entry_count(uint64_t pid); 28 | bool get_data_table_entry_info(uint64_t pid, module_info_t* info_array); 29 | 30 | bool hide_driver(void); // <- Should be called upon initialization 31 | bool unload_driver(void); 32 | bool ping_driver(void); 33 | void flush_logs(void); 34 | 35 | inline bool init_physmem_remapper_lib() { 36 | if (inited) 37 | return true; 38 | 39 | // For some reason user32.dll has to also be loaded for calls to NtUser functions to work? 40 | if (!LoadLibraryW(L"user32.dll")) { 41 | log("Failed to load user32.dll"); 42 | return false; 43 | } 44 | 45 | HMODULE win32u = LoadLibraryW(L"win32u.dll"); 46 | if (!win32u) { 47 | log("Failed to get win32u.dll handle"); 48 | return false; 49 | } 50 | 51 | uint64_t handler_address = (uint64_t)GetProcAddress(win32u, "NtUserGetCPD"); 52 | 53 | NtUserGetCPD = (NtUserGetCPD_type)handler_address; 54 | inited = true; 55 | 56 | if (!ping_driver()) { 57 | log("Driver is not loaded"); 58 | return false; 59 | } 60 | 61 | if(!hide_driver()) { 62 | log("Failed to hide driver"); 63 | return false; 64 | } 65 | 66 | return true; 67 | } 68 | 69 | inline bool is_lib_inited(void) { 70 | return inited; 71 | } 72 | }; 73 | 74 | 75 | #pragma pack(push, 1) 76 | struct trap_frame_t { 77 | uint64_t r15; 78 | uint64_t r14; 79 | uint64_t r13; 80 | uint64_t r12; 81 | uint64_t r11; 82 | uint64_t r10; 83 | uint64_t r9; 84 | uint64_t r8; 85 | uint64_t rbp; 86 | uint64_t rdi; 87 | uint64_t rsi; 88 | uint64_t rdx; 89 | uint64_t rcx; 90 | uint64_t rbx; 91 | uint64_t rax; 92 | uint64_t rsp; 93 | }; 94 | #pragma pack(pop) -------------------------------------------------------------------------------- /vext/api/driver/nmi_restoring_assembly.asm: -------------------------------------------------------------------------------- 1 | .data 2 | stack_id qword 0deedh 3 | 4 | .code 5 | 6 | extern nmi_restoring:proc 7 | extern NtUserGetCPD:qword 8 | 9 | save_general_regs macro 10 | push rsp 11 | push rax 12 | push rbx 13 | push rcx 14 | push rdx 15 | push rsi 16 | push rdi 17 | push rbp 18 | push r8 19 | push r9 20 | push r10 21 | push r11 22 | push r12 23 | push r13 24 | push r14 25 | push r15 26 | endm 27 | 28 | restore_general_regs macro 29 | pop r15 30 | pop r14 31 | pop r13 32 | pop r12 33 | pop r11 34 | pop r10 35 | pop r9 36 | pop r8 37 | pop rbp 38 | pop rdi 39 | pop rsi 40 | pop rdx 41 | pop rcx 42 | pop rbx 43 | pop rax 44 | pop rsp 45 | endm 46 | 47 | asm_nmi_restoring proc 48 | 49 | save_general_regs 50 | 51 | ; Pass a ptr to the struct as the first arg 52 | mov rcx, rsp 53 | 54 | sub rsp, 40h 55 | call nmi_restoring ; Loads info from the nmi info struct and restores rsp and recursively calls the target function again 56 | add rsp, 40h 57 | 58 | restore_general_regs 59 | 60 | ; the c handler set up the stack for us to be just able to return 61 | ret 62 | asm_nmi_restoring endp 63 | 64 | asm_call_driver proc 65 | 66 | push qword ptr [stack_id] 67 | call qword ptr [NtUserGetCPD] 68 | add rsp, 8h 69 | 70 | ret 71 | asm_call_driver endp 72 | 73 | end -------------------------------------------------------------------------------- /vext/api/dumper/driver_dumper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma warning (disable: 4003) 3 | #include "../driver/driver_um_lib.hpp" 4 | 5 | namespace driver_dumper { 6 | inline bool inited = false; 7 | 8 | // Owner specific data 9 | inline uint64_t owner_pid = 0; 10 | inline uint64_t owner_cr3 = 0; 11 | 12 | // Kernel data 13 | inline uint64_t kernel_cr3 = 0; 14 | 15 | namespace core { 16 | inline bool init_physmem() { 17 | if (!physmem::init_physmem_remapper_lib()) { 18 | log("Can't init process if the physmem instance is not allocated"); 19 | return false; 20 | } 21 | 22 | if (!physmem::is_lib_inited()) { 23 | log("Can't init process if the physmem instance is not initialized"); 24 | return false; 25 | } 26 | 27 | owner_pid = GetCurrentProcessId(); 28 | if (!owner_pid) { 29 | log("Failed to get pid of owner process"); 30 | return false; 31 | } 32 | 33 | owner_cr3 = physmem::get_cr3(owner_pid); 34 | if (!owner_cr3) { 35 | log("Failed to get cr3 of owner process"); 36 | return false; 37 | } 38 | 39 | kernel_cr3 = physmem::get_cr3(4); 40 | if (!kernel_cr3) { 41 | log("Failed to get cr3 of the kernel"); 42 | return false; 43 | } 44 | 45 | inited = true; 46 | 47 | return true; 48 | } 49 | 50 | struct RTL_PROCESS_MODULE_INFORMATION { 51 | PVOID Section; 52 | PVOID MappedBase; 53 | PVOID ImageBase; 54 | ULONG ImageSize; 55 | ULONG Flags; 56 | USHORT LoadOrderIndex; 57 | USHORT InitOrderIdnex; 58 | USHORT LoadCount; 59 | USHORT OffsetToFileName; 60 | CHAR FullPathName[0x100]; 61 | }; 62 | 63 | struct RTL_PROCESS_MODULES { 64 | ULONG NumberOfModules; 65 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 66 | }; 67 | 68 | // get the image base and image size of a loaded driver 69 | bool find_loaded_driver(char const* const name, void*& imagebase, uint32_t& imagesize) { 70 | using NtQuerySystemInformationFn = NTSTATUS(NTAPI*)(uint32_t SystemInformationClass, 71 | PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); 72 | static auto const NtQuerySystemInformation = (NtQuerySystemInformationFn)( 73 | GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation")); 74 | 75 | // get the size of the buffer that we need to allocate 76 | unsigned long length = 0; 77 | NtQuerySystemInformation(0x0B, nullptr, 0, &length); 78 | 79 | auto const info = (RTL_PROCESS_MODULES*)(new uint8_t[length + 0x200]); 80 | NtQuerySystemInformation(0x0B, info, length + 0x200, &length); 81 | 82 | for (unsigned int i = 0; i < info->NumberOfModules; ++i) { 83 | auto const& m = info->Modules[i]; 84 | if (_stricmp(m.FullPathName + m.OffsetToFileName, name) != 0) 85 | continue; 86 | 87 | imagebase = m.ImageBase; 88 | imagesize = m.ImageSize; 89 | 90 | delete info; 91 | return true; 92 | } 93 | 94 | delete info; 95 | return false; 96 | } 97 | 98 | template 99 | inline t read_kernel(void* src, uint64_t size = sizeof(t)) { 100 | t buffer{}; 101 | 102 | if (!physmem::copy_virtual_memory(physmem::get_cr3(4), owner_cr3, src, &buffer, sizeof(t))) { 103 | log("Failed to copy memory from src: [%p] to dest: [%p]", (void*)src, &buffer); 104 | return { 0 }; 105 | } 106 | 107 | return buffer; 108 | } 109 | }; 110 | 111 | 112 | inline bool dump_driver(std::string driver_name, std::string output_path) { 113 | if (!core::init_physmem()) 114 | return false; 115 | 116 | log("Trying to dump %s\n", driver_name.c_str()); 117 | 118 | void* imagebase = nullptr; 119 | uint32_t imagesize = 0; 120 | 121 | if (!core::find_loaded_driver(driver_name.c_str(), imagebase, imagesize)) { 122 | log("Driver %s not loaded", driver_name.c_str()); 123 | return false; 124 | } 125 | 126 | log("Found %s at %p with size %p\n", driver_name.c_str(), imagebase, imagesize); 127 | 128 | std::vector image; 129 | image.resize(imagesize); 130 | 131 | // Copy headers 132 | if (!physmem::copy_virtual_memory(kernel_cr3, owner_cr3, imagebase, image.data(), 0x1000)) { 133 | log("Failed to copy driver headers"); 134 | return false; 135 | } 136 | 137 | // Copy the "meat" of the driver; 138 | // Cause of virtual alignment and bs the last pages might not be present -> no error check possible 139 | physmem::copy_virtual_memory(kernel_cr3, owner_cr3, imagebase, image.data(), imagesize); 140 | 141 | // Fix the headers 142 | IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)image.data(); 143 | IMAGE_NT_HEADERS* nt_header = (IMAGE_NT_HEADERS*)((uint64_t)image.data() + dos_header->e_lfanew); 144 | IMAGE_SECTION_HEADER* sections = (IMAGE_SECTION_HEADER*)(nt_header + 1); 145 | 146 | nt_header->OptionalHeader.ImageBase = (uintptr_t)imagebase; 147 | for (size_t i = 0; i < nt_header->FileHeader.NumberOfSections; ++i) { 148 | std::string section_name((char*)sections[i].Name); 149 | sections[i].PointerToRawData = sections[i].VirtualAddress; 150 | sections[i].SizeOfRawData = sections[i].Misc.VirtualSize; 151 | 152 | if (i == nt_header->FileHeader.NumberOfSections - 1) { 153 | log("[%s] Va: %08x; Size %08x\n", section_name.c_str(), sections[i].PointerToRawData, sections[i].SizeOfRawData); 154 | continue; 155 | } 156 | 157 | log("[%s] Va: %08x; Size: %08x", section_name.c_str(), sections[i].PointerToRawData, sections[i].SizeOfRawData); 158 | } 159 | 160 | output_path.append("\\dump_" + driver_name); 161 | 162 | std::ofstream output_file(output_path, std::ios::binary); 163 | if (!output_file.is_open()) { 164 | log("Failed to open output file: %s", output_path.c_str()); 165 | return false; 166 | } 167 | output_file.write((char*)image.data(), imagesize); 168 | output_file.close(); 169 | 170 | log("Successfully dumped %s\n", output_path.c_str()); 171 | 172 | return true; 173 | } 174 | }; -------------------------------------------------------------------------------- /vext/api/proc/process.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma warning (disable: 4003) 3 | #include "../driver/driver_um_lib.hpp" 4 | 5 | namespace process { 6 | inline bool inited = false; 7 | 8 | // Owner specific data 9 | inline uint64_t owner_pid = 0; 10 | inline uint64_t owner_cr3 = 0; 11 | 12 | // Target specific data 13 | inline std::string target_process_name; 14 | inline uint64_t target_pid = 0; 15 | inline uint64_t target_cr3 = 0; 16 | 17 | inline uint64_t target_module_count = 0; 18 | 19 | inline module_info_t* target_modules = 0; 20 | 21 | inline bool init_process(std::string process_name) { 22 | 23 | target_process_name = process_name; 24 | 25 | if (!physmem::init_physmem_remapper_lib()) { 26 | return false; 27 | } 28 | 29 | if (!physmem::is_lib_inited()) { 30 | log("Can't init process if the physmem instance is not initialized"); 31 | return false; 32 | } 33 | 34 | owner_pid = GetCurrentProcessId(); 35 | if (!owner_pid) { 36 | log("Failed to get pid of owner process"); 37 | return false; 38 | } 39 | 40 | owner_cr3 = physmem::get_cr3(owner_pid); 41 | if (!owner_cr3) { 42 | log("Failed to get cr3 of owner process"); 43 | physmem::flush_logs(); 44 | return false; 45 | } 46 | 47 | target_pid = physmem::get_pid_by_name(process_name.c_str()); 48 | if (!target_pid) { 49 | log("Failed to get pid of target process: %s", process_name.c_str()); 50 | physmem::flush_logs(); 51 | return false; 52 | } 53 | 54 | // Then get the cr3 55 | target_cr3 = physmem::get_cr3(target_pid); 56 | if (!target_cr3) { 57 | log("Failed to get cr3 of target process: %s", process_name.c_str()); 58 | physmem::flush_logs(); 59 | return false; 60 | } 61 | 62 | target_module_count = physmem::get_ldr_data_table_entry_count(target_pid); 63 | if (!target_module_count) { 64 | log("Failed get target module count"); 65 | physmem::flush_logs(); 66 | return false; 67 | } 68 | 69 | target_modules = (module_info_t*)malloc(sizeof(module_info_t) * target_module_count); 70 | if (!target_modules) { 71 | log("Failed to alloc memory for modules"); 72 | return false; 73 | } 74 | 75 | // Ensure that the memory is present (mark pte as present) 76 | memset(target_modules, 0, sizeof(module_info_t) * target_module_count); 77 | 78 | if (!physmem::get_data_table_entry_info(target_pid, target_modules)) { 79 | log("Failed getting data table entry info"); 80 | physmem::flush_logs(); 81 | return false; 82 | } 83 | 84 | inited = true; 85 | 86 | return true; 87 | } 88 | 89 | inline bool attach_to_proc(std::string process_name) { 90 | return init_process(process_name); 91 | } 92 | 93 | template 94 | inline t read(void* src, uint64_t size = sizeof(t)) { 95 | t buffer{}; 96 | 97 | if (!physmem::copy_virtual_memory(target_cr3, owner_cr3, src, &buffer, sizeof(t))) { 98 | log("Failed to copy memory from src: [%p] to dest: [%p]", (void*)src, &buffer); 99 | return { 0 }; 100 | } 101 | 102 | return buffer; 103 | } 104 | 105 | inline bool write(void* dest, void* src, uint64_t size) { 106 | return physmem::copy_virtual_memory(owner_cr3, target_cr3, src, dest, size); 107 | } 108 | 109 | inline module_info_t get_module(std::string module_name) { 110 | for (uint64_t i = 0; i < target_module_count - 1; i++) { 111 | 112 | if (strstr(module_name.c_str(),target_modules[i].name)) { 113 | return target_modules[i]; 114 | } 115 | } 116 | 117 | return { 0 }; 118 | } 119 | 120 | inline uint64_t get_module_base(std::string module_name) { 121 | module_info_t module = get_module(module_name); 122 | return module.base; 123 | } 124 | 125 | inline uint64_t get_module_size(std::string module_name) { 126 | module_info_t module = get_module(module_name); 127 | return module.size; 128 | } 129 | 130 | inline void log_modules(void) { 131 | for (uint64_t i = 0; i < target_module_count - 1; i++) { 132 | log("%s", target_modules[i].name); 133 | } 134 | } 135 | 136 | namespace testing { 137 | inline void speed_test(void) { 138 | if (!inited) { 139 | log("Init with a process first"); 140 | return; 141 | } 142 | 143 | log("Speedtest:"); 144 | std::chrono::steady_clock::time_point start_time, end_time; 145 | double elapsed_seconds; 146 | start_time = std::chrono::steady_clock::now(); 147 | 148 | char buffer[0x1000]; 149 | 150 | uint64_t mod_base = get_module_base(target_process_name); 151 | 152 | for (uint64_t iteration = 0; iteration < 1000; iteration++) { 153 | physmem::copy_virtual_memory(target_cr3, owner_cr3, (void*)mod_base, &buffer, 0x1000); 154 | } 155 | 156 | end_time = std::chrono::steady_clock::now(); 157 | elapsed_seconds = std::chrono::duration_cast>(end_time - start_time).count(); 158 | double reads_per_second = 1000.0 / elapsed_seconds; 159 | 160 | log("PAGE_SIZE Read"); 161 | log("Took %e seconds to read PAGE_SIZE bytes 1000 times -> %e reads per second", elapsed_seconds, reads_per_second); 162 | 163 | start_time = std::chrono::steady_clock::now(); 164 | for (uint64_t iteration = 0; iteration < 1000; iteration++) { 165 | physmem::copy_virtual_memory(target_cr3, owner_cr3, (void*)mod_base, &buffer, 4); 166 | } 167 | 168 | end_time = std::chrono::steady_clock::now(); 169 | elapsed_seconds = std::chrono::duration_cast>(end_time - start_time).count(); 170 | reads_per_second = 1000.0 / elapsed_seconds; 171 | 172 | log("4 Byte Read"); 173 | log("Took %e seconds to read 4 bytes 1000 times -> %e reads per second\n", elapsed_seconds, reads_per_second); 174 | } 175 | }; 176 | }; -------------------------------------------------------------------------------- /vext/dump_CLASSPNP.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LowLevelSys/physmem_remapper/b513ec9e1fd58b62d0816d48c7f3745dc49b99d3/vext/dump_CLASSPNP.sys -------------------------------------------------------------------------------- /vext/main.cpp: -------------------------------------------------------------------------------- 1 | #include "api/driver/driver_um_lib.hpp" 2 | #include "api/proc/process.hpp" 3 | #include "api/dumper/driver_dumper.hpp" 4 | #include "api/debug/debug.hpp" 5 | 6 | void proc_test(void) { 7 | // FortniteClient-Win64-Shipping.exe 8 | // FortniteClient-Win64-Shipping_EAC_EOS.exe 9 | // VALORANT-Win64-Shipping.exe 10 | // r5apex.exe 11 | // DeadByDaylight-Win64-Shipping.exe 12 | // notepad.exe 13 | std::string proc = "notepad.exe"; 14 | if (!process::attach_to_proc(proc)) { 15 | return; 16 | } 17 | 18 | process::testing::speed_test(); 19 | process::log_modules(); 20 | physmem::flush_logs(); 21 | 22 | return; 23 | } 24 | 25 | int main(void) { 26 | debug::test_driver(); 27 | getchar(); 28 | return 0; 29 | } -------------------------------------------------------------------------------- /vext/vext.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Release 6 | x64 7 | 8 | 9 | 10 | 16.0 11 | Win32Proj 12 | {3115ecc5-0da7-4743-b2d0-234f3f46a97f} 13 | vext 14 | 10.0 15 | um 16 | 17 | 18 | 19 | Application 20 | false 21 | v143 22 | true 23 | Unicode 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | ..\output directory\ 37 | .\intermediate directory\ 38 | 39 | 40 | 41 | Level3 42 | true 43 | true 44 | true 45 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 46 | true 47 | stdcpp20 48 | stdc17 49 | 4091;6328;6031;4996 50 | MultiThreaded 51 | MaxSpeed 52 | true 53 | StdCall 54 | Async 55 | true 56 | AnySuitable 57 | Speed 58 | 59 | 60 | Console 61 | true 62 | true 63 | true 64 | 65 | 66 | 67 | 68 | 69 | Disabled 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /vext/vext.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {f54bc66c-607f-4c04-bcb5-4c89a668872b} 10 | 11 | 12 | {0b303ee2-7a45-4bd5-a053-0f8f7d410a4d} 13 | 14 | 15 | {86f8fd30-3ba8-41f8-bda4-b331cc72f519} 16 | 17 | 18 | {93c01cc6-f937-4f24-bc61-d74406dc1691} 19 | 20 | 21 | {276ed56e-7add-41b0-920b-fd6c040acc4a} 22 | 23 | 24 | 25 | 26 | Source Files\api\core 27 | 28 | 29 | Source Files 30 | 31 | 32 | Source Files\api\debug 33 | 34 | 35 | 36 | 37 | Source Files\api\core 38 | 39 | 40 | Source Files\api\core 41 | 42 | 43 | Source Files\api\core 44 | 45 | 46 | Source Files\api\process 47 | 48 | 49 | Source Files\api\driver dumper 50 | 51 | 52 | Source Files\api\debug 53 | 54 | 55 | 56 | 57 | Source Files\api\core 58 | 59 | 60 | --------------------------------------------------------------------------------