├── .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 |
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 |
--------------------------------------------------------------------------------