├── PowerParse.psm1 ├── LICENSE ├── README.md ├── Parsers ├── Get-Strings.ps1 ├── Export-PE.ps1 ├── Get-PESize.ps1 ├── Get-MZHeaders.ps1 ├── Get-PEInfo.ps1 └── Get-TTPs.ps1 ├── PowerParse.psd1 ├── VirusTotal └── Get-VTScore.ps1 └── APIs └── APIs.json /PowerParse.psm1: -------------------------------------------------------------------------------- 1 | Get-ChildItem $PSScriptRoot | 2 | ? {$_.PSIsContainer} | 3 | % {Get-ChildItem "$($_.FullName)\*" -Include '*.ps1'} | 4 | % {. $_.FullName} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2023, Jonathan Johnson 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PowerParse v0.01 2 | PowerShell PE Parser designed to help and aid reverse engineers. Module allows initial triage of a PE by supporting modules that do the following: 3 | * Obtain basic information about a PE. 4 | * Identify if the PE in question has multiple embedded PEs within it. If there is, an option to export each PE is available. 5 | * Ability to ship up a VT search. 6 | * Ability to identify if certain behaviors (TTPs) are performed within the PE. 7 | 8 | # Usage 9 | 10 | To use this module, type: `Import-Module PowerParse.psd1`. 11 | 12 | The following functions are supported: 13 | 14 | * `Get-PEInfo` - Obtains information about a PE (type, architectrue, etc), checks to see if multiple PEs are embedded within the binary. Has switches `-Export` to export embedded PEs, `GetVTScore` to get the score of the PE, and `GetTTPs` to run analysis on what behaviors the PE executes. 15 | 16 | * `Get-MZHeaders` - Identifies how many PEs are embedded within 1 file. 17 | 18 | * `Get-PESize` - Obtains the size of a PE file. 19 | 20 | * `Export-PE` - Helper function to export PEs. Used within Get-PEInfo. 21 | 22 | * `Get-VTScore` - Obtains the positive results of a PE based off a file's hash. Future versions will allow for more dynamic queries. Need to supply VTAPI for query to work. 23 | 24 | * `Get-TTPs` - Uses string matching to identify if certain behaviors are being performed within a PE. 25 | 26 | 27 | # Acknowledgements 28 | * Matt Graeber - PowerShell Arsenal was a huge inspiration for this module. Also thank you to Matt for reviewing this module and giving suggestions which will be added to future versions. 29 | * Matt Hand - Talking to me about this module and giving me ideas to implement. 30 | -------------------------------------------------------------------------------- /Parsers/Get-Strings.ps1: -------------------------------------------------------------------------------- 1 | function Get-Strings 2 | { 3 | <# 4 | .SYNOPSIS 5 | 6 | Pulls ASCII and Unicode strings. 7 | 8 | The strings portion is altered from Matt Graeber's original Get-Strings cmdlet. The original can be found here: https://github.com/mattifestation/PowerShellArsenal/blob/9149c29e829455c763e211a2f9501ae6395360da/Misc/Get-Strings.ps1 9 | 10 | .DESCRIPTION 11 | Get-Strings pulls ASCII and Unicode strings from a file. The strings are then returned in a PSCustomObject. 12 | 13 | .PARAMETER FilePath 14 | The path to the PE file. 15 | 16 | .OUTPUTS 17 | A PSCustomObject with the following properties: 18 | * Strings - The strings found in the file. 19 | 20 | 21 | .EXAMPLE 22 | Get-Strings -FilePath C:\Windows\System32\cmd.exe 23 | 24 | Gets the strings from cmd.exe. 25 | 26 | 27 | #> 28 | 29 | param 30 | ( 31 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)] 32 | [String] 33 | [ValidateNotNullOrEmpty()] 34 | [Alias('FullName')] 35 | $FilePath 36 | 37 | ) 38 | 39 | $ResolvedFilePath = Resolve-Path -Path $FilePath 40 | 41 | $MinimumLength = 4 42 | $Results = @() 43 | foreach ($File in $ResolvedFilePath) 44 | { 45 | #Pulling Unicode Strings 46 | $UnicodeFileContents = Get-Content -Encoding 'Unicode' $File 47 | $UnicodeRegex = [Regex] "[\u0020-\u007E]{$MinimumLength,}" 48 | $Results += ($UnicodeRegex.Matches($UnicodeFileContents)).Value 49 | 50 | #Pulling Ascii Strings 51 | $AsciiFileContents = Get-Content -Encoding 'UTF7' $File 52 | $AsciiRegex = [Regex] "[\x20-\x7E]{$MinimumLength,}" 53 | $Results += ($AsciiRegex.Matches($AsciiFileContents)).Value 54 | 55 | } 56 | $Strings = $Results | Select-Object -Unique 57 | 58 | [PSCustomObject] @{ 59 | Strings = $Strings 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /PowerParse.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | 3 | # Script module or binary module file associated with this manifest. 4 | RootModule = 'PowerParse.psm1' 5 | 6 | # Version number of this module. 7 | ModuleVersion = '0.0.0.1' 8 | 9 | # ID used to uniquely identify this module 10 | GUID = '7c94a7a6-1f58-42ca-b7f2-11c052fb121b' 11 | 12 | # Author of this module 13 | Author = 'Jonathan Johnson' 14 | 15 | # Company or vendor of this module 16 | CompanyName = '' 17 | 18 | # Copyright statement for this module 19 | Copyright = '' 20 | 21 | # Description of the functionality provided by this module 22 | Description = 'A module to facilitate the testing of attack techniques and their corresponding procedures.' 23 | 24 | # Minimum version of the Windows PowerShell engine required by this module 25 | PowerShellVersion = '5.0' 26 | 27 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 28 | FunctionsToExport = 'Get-VTScore', 29 | 'Export-PE', 30 | 'Get-PESize', 31 | 'Get-MZHeaders', 32 | 'Get-PEInfo', 33 | 'Get-TTPs', 34 | 'Get-Strings' 35 | 36 | 37 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 38 | PrivateData = @{ 39 | 40 | PSData = @{ 41 | 42 | # Tags applied to this module. These help with module discovery in online galleries. 43 | Tags = @('Security', 'Defense') 44 | 45 | # A URL to the license for this module. 46 | LicenseUri = '' 47 | 48 | # A URL to the main website for this project. 49 | ProjectUri = '' 50 | 51 | # ReleaseNotes of this module 52 | ReleaseNotes = @' 53 | 54 | '@ 55 | 56 | } # End of PSData hashtable 57 | 58 | } # End of PrivateData hashtable 59 | 60 | } 61 | -------------------------------------------------------------------------------- /Parsers/Export-PE.ps1: -------------------------------------------------------------------------------- 1 | function Export-PE{ 2 | <# 3 | .SYNOPSIS 4 | 5 | Exports a PE file based off of the beginning and end of the PE file. 6 | 7 | .DESCRIPTION 8 | Export-PE exports a PE file based off of the beginning and end of the PE file. 9 | 10 | .PARAMETER PEStart 11 | The starting address of the PE file. 12 | 13 | .PARAMETER PEEnd 14 | The ending address of the PE file. 15 | 16 | .PARAMETER FilePath 17 | The path to the PE to extract the PE file from. 18 | 19 | .OUTPUTS 20 | A PSCustomObject with the following properties: 21 | * FilePath - The path to the exported PE file. 22 | 23 | .EXAMPLE 24 | Export-PE -FilePath $RelativeFilePath.Path -PEStart 1000 -PEEnd 2000 25 | 26 | Exports the PE file from the beginning address of 1000 to the ending address of 2000. 27 | 28 | #> 29 | 30 | param( 31 | [Parameter(Mandatory)] 32 | [Int32] 33 | $PEStart, 34 | 35 | [Parameter(Mandatory)] 36 | [Int32] 37 | $PEEnd, 38 | 39 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)] 40 | [String] 41 | [ValidateNotNullOrEmpty()] 42 | [Alias('FullName')] 43 | $FilePath, 44 | 45 | [Parameter()] 46 | [String] 47 | [ValidateSet('SHA256', 'MD5', 'SHA1')] 48 | $Algorithm = 'SHA256' 49 | ) 50 | 51 | $NewFilePath = "pe" 52 | $null = New-Item $NewFilePath 53 | 54 | $ResolvedPath = Resolve-Path -Path $NewFilePath 55 | 56 | $fileStream = [System.IO.File]::OpenRead($FilePath) 57 | $fileStream.Seek($PEStart, [System.IO.SeekOrigin]::Begin) 58 | $bufferLength = $PEEnd - $PEStart 59 | $buffer = New-Object byte[] $bufferLength 60 | $fileStream.Read($buffer, 0, $bufferLength) 61 | 62 | $null = [System.IO.File]::WriteAllBytes($ResolvedPath, $buffer) 63 | 64 | $Hash = (Get-FileHash -Path "pe" -Algorithm $Algorithm).Hash 65 | 66 | $null = Rename-Item -Path $NewFilePath -NewName $Hash 67 | 68 | $RenamedFile = (Resolve-Path -Path $Hash).Path 69 | 70 | $fileStream.Close() 71 | 72 | 73 | [PSCustomObject] @{ 74 | FilePath = $RenamedFile 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /VirusTotal/Get-VTScore.ps1: -------------------------------------------------------------------------------- 1 | function Get-VTScore{ 2 | <# 3 | .SYSNOPSIS 4 | Gets the VirusTotal score for a file hash. 5 | 6 | .DESCRIPTION 7 | Get-VTScore gets the VirusTotal score for a file hash. It does this by using the VirusTotal API. 8 | 9 | .PARAMETER FilePath 10 | The path to the file to get the VirusTotal score for. 11 | 12 | .PARAMETER Hash 13 | The hash of the file to get the VirusTotal score for. 14 | 15 | .PARAMETER VTAPI 16 | The VirusTotal API key. This is required to get the VirusTotal score. 17 | 18 | .PARAMETER ReturnPositive 19 | If this switch is used, the function will only return the VirusTotal score if it is positive. 20 | 21 | .OUTPUTS 22 | A PSCustomObject with the following properties: 23 | * PositiveHits - The number of positive hits. 24 | * Hash - The hash of the file. 25 | 26 | #> 27 | 28 | param( 29 | [Parameter(ValueFromPipelineByPropertyName)] 30 | [String] 31 | [Alias('FullName')] 32 | $FilePath, 33 | 34 | [Parameter()] 35 | [String] 36 | $Hash, 37 | 38 | [Parameter(Mandatory)] 39 | [String] 40 | $VTAPI, 41 | 42 | [Parameter()] 43 | [Switch] 44 | $ReturnPositive 45 | ) 46 | 47 | if($FilePath){ 48 | $ResolvedPath = Resolve-Path -Path $FilePath 49 | $Hash = Get-FileHash -Path $ResolvedPath.Path -Algorithm SHA256 | Select-Object -ExpandProperty Hash 50 | $global:foo = $Hash 51 | } 52 | 53 | $MsgBody = @{resource = $Hash; apikey = $VTAPI} 54 | $ReturnedResult = $null 55 | $VirtusTotalResult = Invoke-RestMethod -Method GET -Uri 'https://www.virustotal.com/vtapi/v2/file/report' -Body $MsgBody 56 | if($ReturnPositive){ 57 | if($VirtusTotalResult.positives -gt 0){ 58 | $ReturnedResult = $VirtusTotalResult 59 | } 60 | } 61 | else{ 62 | $ReturnedResult = $VirtusTotalResult 63 | } 64 | 65 | if($VirtusTotalResult.response_code -eq 0){ 66 | $ResultCode = 1 #No matches 67 | } 68 | else{ 69 | $PositiveHits = $ReturnedResult.positives 70 | $VTHash = $ReturnedResult.sha256 71 | $ResultCode = 0 72 | } 73 | 74 | [PSCustomObject] @{ 75 | PositiveHits = $PositiveHits 76 | Hash = $VTHash 77 | ResultCode = $ResultCode 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /Parsers/Get-PESize.ps1: -------------------------------------------------------------------------------- 1 | function Get-PESize{ 2 | 3 | <# 4 | .SYNOPSIS 5 | Gets the size of the PE file. 6 | 7 | .DESCRIPTION 8 | Get-PESize gets the size of the PE file. It does this by either getting the size of the file or by subtracting the PEStart from the PEEnd. Future versions will be able to get the size of the PE file based off of the last section information. 9 | 10 | .PARAMETER PEStart 11 | The starting address of the PE file. 12 | 13 | .PARAMETER PEEnd 14 | The ending address of the PE file. 15 | 16 | .PARAMETER FilePath 17 | The path to the PE. 18 | 19 | .OUTPUTS 20 | A PSCustomObject with the following properties: 21 | * PESizeBytes - The size of the PE file in bytes. 22 | 23 | .EXAMPLE 24 | Get-PESize -FilePath C:\Windows\System32\cmd.exe 25 | Gets the size of the cmd.exe file. 26 | 27 | .EXAMPLE 28 | Get-PESize -PEStart 1000 -PEEnd 2000 29 | 30 | Gets the size of the PE file from the beginning address of 1000 to the ending address of 2000. 31 | 32 | #> 33 | 34 | [CmdletBinding(DefaultParameterSetName = 'FilePath')] 35 | param( 36 | [Parameter(ParameterSetName = 'Address')] 37 | [Int32] 38 | $PEStart, 39 | 40 | [Parameter(ParameterSetName = 'Address')] 41 | [Int32] 42 | $PEEnd, 43 | 44 | [Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'FilePath')] 45 | [Alias('FullName')] 46 | [String] 47 | $FilePath 48 | ) 49 | $PESize = @() 50 | 51 | switch ($PSCmdlet.ParameterSetName) { 52 | 'FilePath'{ 53 | $RelativeFilePath = Resolve-Path -Path $FilePath 54 | 55 | $FileBytes = [IO.File]::ReadAllBytes($RelativeFilePath) 56 | 57 | $numOfMzHeaders = Get-MZHeaders -FilePath $RelativeFilePath -FileBytes $FileBytes 58 | $PESizeCount = ($numOfMzHeaders.intOffsets | Measure).Count 59 | 60 | if ($PESizeCount -eq 1) { 61 | 62 | $PESize = (Get-Item -LiteralPath $RelativeFilePath).Length 63 | 64 | } 65 | else { 66 | # Only will get the first PESize 67 | $adjustedSize = (Get-PESize -PEStart $numOfMzHeaders.intOffsets[$i] -PEEnd $numOfMzHeaders.intOffsets[$i + 1]).PESize 68 | 69 | $PESize = $adjustedSize 70 | } 71 | } 72 | 'Address'{ 73 | $PESize = ($PEEnd - $PEStart) 74 | } 75 | 76 | } 77 | 78 | [PSCustomObject] @{ 79 | PESizeBytes = $PESize 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /Parsers/Get-MZHeaders.ps1: -------------------------------------------------------------------------------- 1 | function Get-MZHeaders{ 2 | <# 3 | .SYNOPSIS 4 | Gets the number of MZ headers in a file. 5 | 6 | .DESCRIPTION 7 | Get-MZHeaders gets the number of MZ headers in a file. This is helpful in situations where malware has dropped one file but has multiple PEs embedded within it. 8 | 9 | .PARAMETER FilePath 10 | The path to the PE file. 11 | 12 | .PARAMETER FileBytes 13 | The bytes of the PE file. This is used to speed up the process of getting the number of MZ headers. If this is not provided, the function will read the bytes from the file. 14 | 15 | .OUTPUTS 16 | A PSCustomObject with the following properties: 17 | * NumOfMz - The number of MZ headers. 18 | * Offsets - The offsets of the MZ headers. 19 | * IntOffsets - The offsets of the MZ headers as integers. 20 | 21 | .EXAMPLE 22 | Get-MZHeaders -FilePath C:\Windows\System32\cmd.exe 23 | 24 | Gets the number of MZ headers in the cmd.exe file. 25 | 26 | .EXAMPLE 27 | Get-MZHeaders -FilePath C:\Windows\System32\cmd.exe -FileBytes $FileBytes 28 | 29 | Gets the number of MZ headers in the cmd.exe file. The FileBytes parameter is used to speed up the process of getting the number of MZ headers. 30 | 31 | #> 32 | 33 | param( 34 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)] 35 | [String] 36 | [ValidateNotNullOrEmpty()] 37 | [Alias('FullName')] 38 | $FilePath, 39 | 40 | [Parameter()] 41 | [byte[]] 42 | $FileBytes 43 | ) 44 | 45 | $RelativeFilePath = Resolve-Path -Path $FilePath 46 | 47 | if($FileBytes -eq $null){ 48 | $FileBytes = [System.IO.File]::ReadAllBytes($RelativeFilePath) 49 | } 50 | 51 | $byteSequence = [byte[]](0x4D, 0x5A) 52 | $occurrences = 0 53 | $offset = @() 54 | $intOffsets = @() 55 | 56 | 57 | 58 | for ($i = 0; $i -lt ($FileBytes.Length - $byteSequence.Length + 1); $i++) 59 | { 60 | $subArray = $FileBytes[$i..($i + $byteSequence.Length - 1)] 61 | 62 | 63 | # Check if the current bytes match the desired sequence 64 | if (-join $subArray -eq -join $byteSequence) { 65 | $MemoryStream = New-Object -TypeName IO.MemoryStream -ArgumentList @(,$FileBytes) 66 | $BinaryReader = New-Object -TypeName IO.BinaryReader -ArgumentList $MemoryStream 67 | 68 | $E_LFANEW_Offset = ($i + 0x3C) 69 | $null = $MemoryStream.Seek($E_LFANEW_Offset, 'Begin') 70 | 71 | $E_LFANEW_Value = $BinaryReader.ReadUInt32() 72 | 73 | $E_LFANEW = $E_LFANEW_Value + $i 74 | 75 | #Check to see if the E_LFANEW is within the bounds of the file 76 | if($E_LFANEW -gt $FileBytes.Length){ 77 | $MemoryStream.Dispose() 78 | $BinaryReader.Dispose() 79 | continue 80 | } 81 | 82 | # Seek to the PE signature from the beginning of the stream 83 | $null = $MemoryStream.Seek($E_LFANEW, 'Begin') 84 | # Check if there are enough bytes available to read the PE signature 85 | $PESignature = $BinaryReader.ReadBytes(4) 86 | # Check if it is a valid PE signature 87 | if ([Text.Encoding]::ASCII.GetString($PESignature[0..1]) -eq 'PE') { 88 | $occurrences++ 89 | $offset += $i.ToString("X") 90 | $intOffsets += $i 91 | 92 | } 93 | $MemoryStream.Dispose() 94 | $BinaryReader.Dispose() 95 | } 96 | 97 | } 98 | [PSCustomObject] @{ 99 | NumOfMz = $occurrences 100 | Offsets = $offset 101 | IntOffsets = $intOffsets 102 | } 103 | } -------------------------------------------------------------------------------- /APIs/APIs.json: -------------------------------------------------------------------------------- 1 | { 2 | "apis": [ 3 | { 4 | "name": "AddAce", 5 | "tag": "TX_MiscAction" 6 | }, 7 | { 8 | "name": "AdjustTokenPrivileges", 9 | "tag": "TX_MiscAction" 10 | }, 11 | { 12 | "name": "GetProcAddress", 13 | "tag": "TX_MiscAction" 14 | }, 15 | { 16 | "name": "BCryptGenRandom", 17 | "tag": "T1486_Encryption" 18 | }, 19 | { 20 | "name": "NetServerEnum", 21 | "tag": "TX_MiscAction" 22 | }, 23 | { 24 | "name": "NetShareEnum", 25 | "tag": "TX_MiscAction" 26 | }, 27 | { 28 | "name": "IISReset", 29 | "tag": "TX_MiscAction" 30 | }, 31 | { 32 | "name" : "^(Beacon)\\w*", 33 | "tag" : "T1024_002_CommandAndControl" 34 | }, 35 | { 36 | "name" : "^(Beacon)\\w*", 37 | "tag" : "TX_CobaltStrikeAPI" 38 | }, 39 | { 40 | "name": "^(CreateProcess)[AW]?$", 41 | "tag": "TA0002_CreateProcess" 42 | }, 43 | { 44 | "name": "^(CreateProcessAsUser)[AW]?$", 45 | "tag": "TA0002_CreateProcess" 46 | }, 47 | { 48 | "name": "NtCreateUserProcess", 49 | "tag": "TA0002_CreateProcess" 50 | }, 51 | { 52 | "name": "NtCreateProcess", 53 | "tag": "TA0002_CreateProcess" 54 | }, 55 | { 56 | "name": "OpenProcess", 57 | "tag": "TX_ProcessHandle" 58 | }, 59 | { 60 | "name": "NtOpenProcess", 61 | "tag": "TX_ProcessHandle" 62 | }, 63 | { 64 | "name": "CreateToolhelp32Snapshot", 65 | "tag": "TX_ProcessHandle" 66 | }, 67 | { 68 | "name": "CoCreateInstance", 69 | "tag": "TX_COMInitialization" 70 | }, 71 | { 72 | "name": "CoCreateInstanceEx", 73 | "tag": "TX_COMInitialization" 74 | }, 75 | { 76 | "name": "CoGetClassObject", 77 | "tag": "TX_COMInitialization" 78 | }, 79 | { 80 | "name": "CoGetObject", 81 | "tag": "TX_COMInitialization" 82 | }, 83 | { 84 | "name": "^(CreateNamedPipe)[AW]?$", 85 | "tag": "TX_NamedPipeCreation" 86 | }, 87 | { 88 | "name": "^(CreateFile)[AW]?$", 89 | "tag": "TX_FileCreate" 90 | }, 91 | { 92 | "name": "NtCreateFile", 93 | "tag": "TX_FileCreate" 94 | }, 95 | { 96 | "name": "^(CreateService)[AW]?$", 97 | "tag": "T1543_003_ServiceCreation" 98 | }, 99 | { 100 | "name": "^(StartService)[AW]?$", 101 | "tag": "T1569_002_ServiceExecution" 102 | }, 103 | { 104 | "name": "IsDebuggerPresent", 105 | "tag": "T1497_AntiAnalysis" 106 | }, 107 | { 108 | "name": "GetSystemInfo", 109 | "tag": "T1497_AntiAnalysis" 110 | }, 111 | { 112 | "name": "GlobalMemoryStatusEx", 113 | "tag": "T1497_AntiAnalysis" 114 | }, 115 | { 116 | "name": "^(CreateProcessWithLogon)[AW]?$", 117 | "tag": "T1134_TokenImpersonation" 118 | }, 119 | { 120 | "name": "^(CreateProcessWithToken)[AW]?$", 121 | "tag": "T1134_TokenImpersonation" 122 | }, 123 | { 124 | "name": "ImpersonateLoggedOnUser", 125 | "tag": "T1134_TokenImpersonation" 126 | }, 127 | { 128 | "name": "WinCrypt", 129 | "tag": "T1486_Encryption" 130 | }, 131 | { 132 | "name": "CryptAcquireContext", 133 | "tag": "T1486_Encryption" 134 | }, 135 | { 136 | "name": "CryptGenKey", 137 | "tag": "T1486_Encryption" 138 | }, 139 | { 140 | "name": "CryptDeriveKey", 141 | "tag": "T1486_Encryption" 142 | }, 143 | { 144 | "name": "CryptDecrypt", 145 | "tag": "T1486_Encryption" 146 | }, 147 | { 148 | "name": "CryptReleaseContext", 149 | "tag": "T1486_Encryption" 150 | }, 151 | { 152 | "name": "VirtualAllocEx", 153 | "tag": "ProcessInjection_Allocation" 154 | }, 155 | { 156 | "name": "WriteProcessMemory", 157 | "tag": "ProcessInjection_Write" 158 | }, 159 | { 160 | "name": "NtWriteVirtualMemory", 161 | "tag": "ProcessInjection_Write" 162 | }, 163 | { 164 | "name": "GobalAddAtom", 165 | "tag": "ProcessInjection_Write" 166 | }, 167 | { 168 | "name": "QueueUserAPC", 169 | "tag": "ProcessInjection_Execute" 170 | }, 171 | { 172 | "name": "NtQueueApcThread", 173 | "tag": "ProcessInjection_Execute" 174 | }, 175 | { 176 | "name": "^(LoadLibrary)[AW]?$", 177 | "tag": "ProcessInjection_Execute" 178 | }, 179 | { 180 | "name": "^(LoadLibraryEx)[AW]?$", 181 | "tag": "ProcessInjection_Execute" 182 | }, 183 | { 184 | "name": "CreateRemoteThread", 185 | "tag": "ProcessInjection_Execute" 186 | }, 187 | { 188 | "name": "NtCreateThreadEx", 189 | "tag": "ProcessInjection_Execute" 190 | }, 191 | { 192 | "name": "RtlCreateUserThread", 193 | "tag": "ProcessInjection_Execute" 194 | }, 195 | { 196 | "name": "NtUnmapViewOfSection", 197 | "tag": "SectionMapping" 198 | }, 199 | { 200 | "name": "ZwUnmapViewOfSection", 201 | "tag": "SectionMapping" 202 | }, 203 | { 204 | "name": "ResumeThread", 205 | "tag": "ThreadContinuation" 206 | }, 207 | { 208 | "name": "DuplicateToken", 209 | "tag": "TokenDuplicate" 210 | }, 211 | { 212 | "name": "DuplicateTokenEx", 213 | "tag": "TokenDuplicate" 214 | }, 215 | { 216 | "name": "NtDuplicateToken", 217 | "tag": "TokenDuplicate" 218 | }, 219 | { 220 | "name": "SetThreadToken", 221 | "tag": "ThreadTokenSet" 222 | }, 223 | { 224 | "name": "NtSetInformationThread", 225 | "tag": "ThreadTokenSet" 226 | }, 227 | { 228 | "name": "MiniDumpWriteDump", 229 | "tag": "ProcessRead" 230 | }, 231 | { 232 | "name": "NtReadVirtualMemory", 233 | "tag": "ProcessRead" 234 | }, 235 | { 236 | "name": "ReadProcessMemory", 237 | "tag": "ProcessRead" 238 | }, 239 | { 240 | "name": "DeviceIoControl", 241 | "tag": "DeviceCodeExecution" 242 | }, 243 | { 244 | "name": "NtDeviceIoControlFile", 245 | "tag": "DeviceCodeExecution" 246 | }, 247 | { 248 | "name": "NtFsControlFile", 249 | "tag": "DeviceCodeExecution" 250 | }, 251 | { 252 | "name": "^(LogonUserExEx|LogonUserEx|LogonUser)[AW]?$", 253 | "tag": "UserLogon" 254 | }, 255 | { 256 | "name": "NtCreateMailslotFile", 257 | "tag": "TX_MailslotCreation" 258 | }, 259 | { 260 | "name": "^(CreateMailslot)[AW]?$", 261 | "tag": "TX_MailslotCreation" 262 | }, 263 | { 264 | "name": "memcpy", 265 | "tag": "TX_MemoryCpy" 266 | }, 267 | { 268 | "name": "memset", 269 | "tag": "TX_MemoryCpy" 270 | }, 271 | { 272 | "name": "VirtualProtect", 273 | "tag": "TX_MemoryProtectionManipulation" 274 | }, 275 | { 276 | "name": "VirtualProtectEx", 277 | "tag": "TX_MemoryProtectionManipulation" 278 | }, 279 | { 280 | "name": "NtProtectVirtualMemory", 281 | "tag": "TX_MemoryProtectionManipulation" 282 | } 283 | ] 284 | } -------------------------------------------------------------------------------- /Parsers/Get-PEInfo.ps1: -------------------------------------------------------------------------------- 1 | function Get-PEInfo { 2 | <# 3 | .SYNOPSIS 4 | 5 | Gets information about a PE file. 6 | 7 | .DESCRIPTION 8 | Get-PEInfo was designed to pull information about a file, such as the PE Arch, PE Type, if it is a .NET binary, the number of MZ headers, etc. 9 | 10 | .PARAMETER FilePath 11 | The path to the PE file. 12 | 13 | .PARAMETER Export 14 | Exports a PE file if there are multiple MZ headers. 15 | 16 | .PARAMETER GetVTScore 17 | Gets the VirusTotal score for each PE file. 18 | 19 | .PARAMETER VTAPI 20 | The VirusTotal API key. 21 | 22 | .PARAMETER GetTTPs 23 | Gets the TTPs for each PE file. 24 | 25 | .OUTPUTS 26 | A PSCustomObject with the following properties: 27 | * PEFilePath - The path to the PE file. 28 | * MagicValueOffset - The offset of the Magic Value. 29 | * PEArch - The PE architecture. 30 | * PEType - The PE type. 31 | * FileSizeBytes - The size of the file in bytes. 32 | * NumberofSections - The number of sections in the PE file. 33 | * Sha256 - The SHA256 hash of the PE file. 34 | * ImportTableAddress - The address of the Import Table. 35 | * ImportTableAddressOffset - The offset of the Import Table. 36 | * IsDotNetBinary - Whether or not the PE file is a .NET binary. 37 | * NumberOfPEs - The number of MZ headers. 38 | * PEOffsets - The offsets of the MZ headers. 39 | * PESizes - The sizes of the MZ headers. 40 | * PEExported - Whether or not the PE file was exported. 41 | * NewPEFilePath - The path to the exported PE file. 42 | * VTPositiveResults - The VirusTotal score for each PE file. 43 | * TTPs - The TTPs for each PE file. 44 | 45 | 46 | .EXAMPLE 47 | 48 | Get-PEInfo -FilePath C:\Windows\System32\cmd.exe 49 | 50 | Gets information about the cmd.exe file. Will not grab information about TTps or VirusTotal score. 51 | 52 | .EXAMPLE 53 | 54 | ls C:\Windows\System32\cmd.exe | Get-PEInfo 55 | 56 | Gets information about the cmd.exe file. Will not grab information about TTps or VirusTotal score. 57 | 58 | .EXAMPLE 59 | Get-PEInfo -FilePath C:\Windows\System32\cmd.exe -TTPs 60 | 61 | Gets information about the cmd.exe file. Will grab information about TTPs. 62 | 63 | .EXAMPLE 64 | Get-PEInfo -FilePath C:\Windows\System32\cmd.exe -GetVTScore -VTAPI 65 | 66 | Gets information about the cmd.exe file. Will grab information about the VirusTotal score. 67 | 68 | .EXAMPLE 69 | Get-PEInfo -FilePath C:\Windows\System32\cmd.exe -Export 70 | 71 | Gets information about the cmd.exe file. Will export the PE file if there are multiple MZ headers. 72 | 73 | #> 74 | 75 | param ( 76 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)] 77 | [String] 78 | [ValidateNotNullOrEmpty()] 79 | [Alias('FullName')] 80 | $FilePath, 81 | 82 | [Parameter()] 83 | [Switch] 84 | $Export, 85 | 86 | [Parameter()] 87 | [Switch] 88 | $GetVTScore, 89 | 90 | [Parameter()] 91 | [String] 92 | $VTAPI, 93 | 94 | [Parameter()] 95 | [Switch] 96 | $GetTTPs 97 | 98 | ) 99 | 100 | $RelativeFilePath = Resolve-Path -Path $FilePath 101 | 102 | $FileBytes = [IO.File]::ReadAllBytes($RelativeFilePath) 103 | 104 | $MemoryStream = New-Object -TypeName IO.MemoryStream -ArgumentList @(,$FileBytes) 105 | $BinaryReader = New-Object -TypeName IO.BinaryReader -ArgumentList $MemoryStream 106 | 107 | #Checking to see if valid PE 108 | $null = $MemoryStream.Seek(0x3C, 'Begin') 109 | 110 | $E_LFANEW = $BinaryReader.ReadUInt32() 111 | 112 | # Seek to NT headers 113 | $null = $MemoryStream.Seek($E_LFANEW, 'Begin') 114 | 115 | $PESignature = $BinaryReader.ReadBytes(4) 116 | 117 | $Machine = $BinaryReader.ReadUInt16() 118 | 119 | # 2 bytes after machine type holds the number of sections 120 | $numberOfSections = $BinaryReader.ReadUInt16() 121 | 122 | 123 | # 14 bytes after numberOfSections holds the PE Characteristics 124 | $null = $MemoryStream.Seek(0xE, 'Current') 125 | $Characteristics = $BinaryReader.ReadUInt16() 126 | $PEType = $null 127 | if(($Characteristics -band 0x0002) -eq 0x0002) 128 | { 129 | $PEType = "EXE" 130 | } 131 | 132 | if(($Characteristics -band 0x2000) -eq 0x2000) 133 | { 134 | $PEType = "DLL" 135 | } 136 | 137 | # 2 bytes after Characteristics holds the MagicValue 138 | $MagicValueOffset = $BinaryReader.BaseStream.Position 139 | $MagicValue = $BinaryReader.ReadUInt16() 140 | 141 | 142 | # Checking to see if the binary is a .NET binary: 143 | $MachineHex = $Machine.ToString("X") 144 | $machineType = "NotSupported" 145 | $PEArch = "NotSupported" 146 | switch($MachineHex) 147 | { 148 | "8664" { 149 | $machineType = "IMAGE_FILE_MACHINE_AMD64" 150 | $PEArch = "AMD64" 151 | $null = $MemoryStream.Seek(0xDE, 'Current') 152 | $NetfileOffset = $binaryReader.BaseStream.Position 153 | $NetDirectoryValue = $BinaryReader.ReadUInt32() 154 | 155 | # Add MagicValueOffset to 0x78 to get Import Table Address Offset 156 | $ImportTableAddressOffset = $MagicValueOffset + 0x78 157 | $null = $MemoryStream.Seek($ImportTableAddressOffset, 'Begin') 158 | $ImportTableAddress = $BinaryReader.ReadUInt32() 159 | 160 | } 161 | "14c" { 162 | $machineType = "IMAGE_FILE_MACHINE_I386" 163 | $PEArch = "PE32" 164 | $null = $MemoryStream.Seek(0xCE, 'Current') 165 | $NetfileOffset = $binaryReader.BaseStream.Position 166 | $NetDirectoryValue = $BinaryReader.ReadUInt32() 167 | 168 | # Add MagicValueOffset to 0x68 to get Import Table Address Offset 169 | $ImportTableAddressOffset = $MagicValueOffset + 0x68 170 | $null = $MemoryStream.Seek($ImportTableAddressOffset, 'Begin') 171 | $ImportTableAddress = $BinaryReader.ReadUInt32() 172 | } 173 | "AA64" { 174 | Write-Error "File type is not supported" 175 | return 176 | } 177 | "AA64" { 178 | Write-Error "ARM64 filetype is not supported" 179 | return 180 | } 181 | "1C0"{ 182 | Write-Error "ARM32 filetype is not supported" 183 | return 184 | } 185 | 186 | } 187 | #If NetDirectoryValue is not equal to 00000000, then it is a .NET binary 188 | if($NetDirectoryValue -ne 0){ 189 | $DotNetBinary = $true 190 | } 191 | else{ 192 | $DotNetBinary = $false 193 | } 194 | 195 | 196 | # Search for number of MZ headers 197 | $null = $MemoryStream.Seek(0x0, 'Begin') 198 | $MZValue = $BinaryReader.ReadBytes(4) 199 | 200 | 201 | if([Text.Encoding]::ASCII.GetString($MZValue[0..1]) -cne 'MZ') { 202 | Write-Error "Not a valid PE" 203 | return 204 | } 205 | 206 | #Pulling Number of MZ Headers to see if there are any embedded files 207 | $numOfMzHeaders = Get-MZHeaders -FilePath $RelativeFilePath -FileBytes $FileBytes 208 | $BinaryReader.Close() 209 | $MemoryStream.Close() 210 | 211 | $PESize = @() 212 | $Exported = @() 213 | $PESizeCount = ($numOfMzHeaders.intOffsets | Measure).Count 214 | 215 | if ($PESizeCount -eq 1) { 216 | 217 | $PESize = (Get-Item -LiteralPath $RelativeFilePath).Length 218 | 219 | } elseif ($PESizeCount -gt 1) { 220 | # Subtract each offset from the next one 221 | for ($i = 0; $i -lt $PESizeCount - 1; $i++) { 222 | $adjustedSize = (Get-PESize -PEStart $numOfMzHeaders.intOffsets[$i] -PEEnd $numOfMzHeaders.intOffsets[$i + 1]).PESizeBytes 223 | if($Export){ 224 | $Exported += (Export-PE -FilePath $RelativeFilePath.Path -PEStart $numOfMzHeaders.intOffsets[$i] -PEEnd $numOfMzHeaders.intOffsets[$i + 1]).FilePath 225 | } 226 | 227 | $PESize += $adjustedSize 228 | } 229 | 230 | # Add the size between the last offset and the file length 231 | $lastAdjustedSize = (Get-PESize -PEStart $numOfMzHeaders.intOffsets[-1] -PEEnd (Get-Item -LiteralPath $RelativeFilePath).Length).PESizeBytes 232 | if($Export){ 233 | $Exported += (Export-PE -FilePath $RelativeFilePath.Path -PEStart $numOfMzHeaders.intOffsets[-1] -PEEnd (Get-Item -LiteralPath $RelativeFilePath).Length).FilePath 234 | } 235 | $PESize += $lastAdjustedSize 236 | } 237 | 238 | if($GetVTScore){ 239 | $Hashes = @() 240 | $VTResults = @() 241 | if($Export){ 242 | $CurrentFolder = Get-ChildItem -Path . 243 | $CurrentFolder | % {$Hashes += (Get-FileHash $_.Name).Hash} 244 | foreach ($Hash in $Hashes){ 245 | $Results = (Get-VTScore -Hash $Hash -VTAPI $VTAPI -ReturnPositive).Hash 246 | if($Results -ne $null){ 247 | $VTResults += $Results 248 | } 249 | 250 | } 251 | } 252 | else{ 253 | $FileHash = Get-FileHash -Path $RelativeFilePath -Algorithm SHA256 | Select-Object -ExpandProperty Hash 254 | $Results = (Get-VTScore -Hash $FileHash -VTAPI $VTAPI -ReturnPositive).Hash 255 | if($Results -ne $null){ 256 | $VTResults += $Results 257 | } 258 | } 259 | } 260 | 261 | if($GetTTPs){ 262 | $TTPs = (Get-TTPs -FilePath $RelativeFilePath) 263 | } 264 | 265 | [PSCustomObject] @{ 266 | PEFilePath = $RelativeFilePath.Path 267 | MagicValueOffset = $MagicValueOffset 268 | PEArch = $PEArch 269 | PEType = $PEType 270 | FileSizeBytes = (Get-Item -LiteralPath $RelativeFilePath).Length 271 | NumberofSections = $numberOfSections 272 | Sha256 = (Get-FileHash -LiteralPath $RelativeFilePath -Algorithm SHA256).Hash 273 | ImportTableAddress = $ImportTableAddress 274 | ImportTableAddressOffset = $ImportTableAddressOffset 275 | IsDotNetBinary = $DotNetBinary 276 | NumberOfPEs = $numOfMzHeaders.numOfMz 277 | PEOffsets = $numOfMzHeaders.offsets 278 | PESizes = $PESize 279 | PEExported = $Export 280 | NewPEFilePath = $Exported 281 | VTPositiveResults = $VTResults 282 | TTPs = $TTPs 283 | Strings = (Get-Strings -FilePath $RelativeFilePath).Strings 284 | } 285 | } -------------------------------------------------------------------------------- /Parsers/Get-TTPs.ps1: -------------------------------------------------------------------------------- 1 | function Get-TTPs 2 | { 3 | <# 4 | .SYNOPSIS 5 | 6 | Pulls ASCII and Unicode strings and then parses to find functions known to be within a technique. 7 | 8 | The strings portion is altered from Matt Graeber's original Get-Strings cmdlet. The original can be found here: https://github.com/mattifestation/PowerShellArsenal/blob/9149c29e829455c763e211a2f9501ae6395360da/Misc/Get-Strings.ps1 9 | 10 | .DESCRIPTION 11 | Get-TTPs pulls ASCII and Unicode strings and then parses to find functions known to be within a technique. 12 | 13 | .PARAMETER FilePath 14 | The path to the PE file. 15 | 16 | .PARAMETER APIFilePath 17 | The path to the API.json file. 18 | 19 | .OUTPUTS 20 | A PSCustomObject with the following properties: 21 | * FilePath - The path to the PE file. 22 | * FileHash - The SHA256 hash of the PE file. 23 | * TA0002_CreateProcess - Whether or not the PE file has a function known to be within the Create Process technique. 24 | * T1055_ProcessInjection - Whether or not the PE file has a function known to be within the Process Injection technique. 25 | * T1055_012_ProcessHollowing - Whether or not the PE file has a function known to be within the Process Hollowing technique. 26 | * T1134_TokenImpersonation - Whether or not the PE file has a function known to be within the Token Impersonation technique. 27 | * T1543_003_ServiceCreation - Whether or not the PE file has a function known to be within the Service Creation technique. 28 | * T1569_002_ServiceExecution - Whether or not the PE file has a function known to be within the Service Execution technique. 29 | * T1003_001_LSASSDump - Whether or not the PE file has a function known to be within the LSASS Dump technique. 30 | * T1486_Encryption - Whether or not the PE file has a function known to be within the Encryption technique. 31 | * T1078_UserLogon - Whether or not the PE file has a function known to be within the User Logon technique. 32 | * T1497_AntiAnalysis - Whether or not the PE file has a function known to be within the Anti-Analysis technique. 33 | * TX_VulnerableDriver - Whether or not the PE file has a function known to be within the Vulnerable Driver technique. 34 | * TX_COMInitialization - Whether or not the PE file has a function known to be within the COM Initialization technique. 35 | * TX_NamedPipeCreation - Whether or not the PE file has a function known to be within the Named Pipe Creation technique. 36 | * TX_MailslotCreation - Whether or not the PE file has a function known to be within Mailslot creations. 37 | * TX_MiscAction - Whether or not the PE file has a function known to be within the Misc Action technique. 38 | * TX_CobaltStrikeAPI - Whether or not the PE file has a function known to be within the Cobalt Strike API. 39 | * T1024_002_CommandAndControl - Whether or not the PE file has a function known to be within the Command and Control technique. 40 | * TA0002_CreateProcess_APIs - The APIs found within the Create Process technique. 41 | * T1055_ProcessInjection_APIs - The APIs found within the Process Injection technique. 42 | * T1055_012_ProcessHollowing_APIs - The APIs found within the Process Hollowing technique. 43 | * T1134_TokenImpersonation_APIs - The APIs found within the Token Impersonation technique. 44 | * T1543_003_ServiceCreation_APIs - The APIs found within the Service Creation technique. 45 | * T1569_002_ServiceExecution_APIs - The APIs found within the Service Execution technique. 46 | * T1003_001_LSASSDump_APIs - The APIs found within the LSASS Dump technique. 47 | * T1486_Encryption_APIs - The APIs found within the Encryption technique. 48 | * T1078_UserLogon_APIs - The APIs found within the User Logon technique. 49 | * T1497_AntiAnalysis_APIs - The APIs found within the Anti-Analysis technique. 50 | * TX_VulnerableDriver_APIs - The APIs found within the Vulnerable Driver technique. 51 | * TX_COMInitialization_APIs - The APIs found within the COM Initialization technique. 52 | * TX_NamedPipeCreation_APIs - The APIs found within the Named Pipe Creation technique. 53 | * TX_MailslotCreation_APIs - The APIs found within mailslot creations. 54 | * TX_MiscAction_APIs - The APIs found within the Misc Action technique. 55 | * TX_CobaltStrikeAPIs - The APIs found within the Cobalt Strike API. 56 | * T1024_002_CommandAndControl_APIs - The APIs found within the Command and Control technique. 57 | * TX_EtwPatch - Whether or not the PE file has a function known to be within the ETW Patch technique. 58 | 59 | 60 | .EXAMPLE 61 | Get-TTPs -FilePath C:\Windows\System32\cmd.exe 62 | 63 | Gets TTPs for the cmd.exe file. 64 | 65 | .EXAMPLE 66 | Get-TTPs -FilePath C:\Windows\System32\cmd.exe -APIFilePath C:\Users\user\Desktop\APIs\APIs.json 67 | 68 | Gets TTPs for the cmd.exe file while specifying the API folder path. 69 | 70 | .EXAMPLE 71 | 72 | ls C:\Windows\System32\cmd.exe | Get-TTPs 73 | 74 | Gets TTPs for the cmd.exe file. 75 | 76 | #> 77 | 78 | param 79 | ( 80 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)] 81 | [String] 82 | [ValidateNotNullOrEmpty()] 83 | [Alias('FullName')] 84 | $FilePath, 85 | 86 | [String] 87 | $APIFilePath = "$PWD\APIs\APIs.json" 88 | 89 | ) 90 | 91 | $ResolvedFilePath = Resolve-Path -Path $FilePath 92 | $FileHash = Get-FileHash -Path $ResolvedFilePath.Path -Algorithm SHA256 93 | 94 | $MinimumLength = 4 95 | $Results = @() 96 | foreach ($File in $ResolvedFilePath) 97 | { 98 | #Pulling Unicode Strings 99 | $UnicodeFileContents = Get-Content -Encoding 'Unicode' $File 100 | $UnicodeRegex = [Regex] "[\u0020-\u007E]{$MinimumLength,}" 101 | $Results += $UnicodeRegex.Matches($UnicodeFileContents) 102 | 103 | #Pulling Ascii Strings 104 | $AsciiFileContents = Get-Content -Encoding 'UTF7' $File 105 | $AsciiRegex = [Regex] "[\x20-\x7E]{$MinimumLength,}" 106 | $Results += $AsciiRegex.Matches($AsciiFileContents) 107 | 108 | } 109 | 110 | $jsonPath = $APIFilePath 111 | $jsonContent = Get-Content $jsonPath -Raw 112 | $apiList = ConvertFrom-Json -InputObject $jsonContent 113 | 114 | 115 | $MiscListAPIs = @() 116 | $T1486_Encryption_APIs = @() 117 | $T1497_AntiAnalysis_APIs = @() 118 | $TX_NamedPipeCreation_APIs = @() 119 | $TX_MailslotCreation_APIs = @() 120 | $TX_COMInitialization_APIs = @() 121 | $T1569_002_ServiceExecution_APIs = @() 122 | $T1543_003_ServiceCreation_APIs = @() 123 | $T1134_TokenImpersonation_APIs = @() 124 | $T1003_001_LSASSDump_APIs = @() 125 | $T1055_012_ProcessHollowing_APIs = @() 126 | $T1055_ProcessInjection_APIs = @() 127 | $TA0002_CreateProcess_APIs = @() 128 | $TX_VulnerableDriver_APIs = @() 129 | $SectionMapping_APIs = @() 130 | $ThreadContinuation_APIs = @() 131 | $ThreadSet_APIs = @() 132 | $ProcessOpen_APIs = @() 133 | $DuplicateToken_APIs = @() 134 | $ThreadTokenSet_APIs = @() 135 | $ProcessRead_APIs = @() 136 | $ProcessInjection_Write_APIs = @() 137 | $ProcessInjection_Execute_APIs = @() 138 | $LogonUser_APIs = @() 139 | $CobaltStrike_APIs = @() 140 | $CommandAndControl_APIs = @() 141 | $MemoryCpy_APIs = @() 142 | $MemProtect_APIs = @() 143 | $EtwPatch_APIs = @() 144 | 145 | $MiscAction = $false 146 | $CreateProcess = $false 147 | $LSASSDump = $false 148 | $ProcessHollowing = $false 149 | $COMInitialization = $false 150 | $CreateNamedPipe = $false 151 | $CreateMailslot = $false 152 | $VulnerableDriver = $false 153 | $ServiceCreation = $false 154 | $ServiceExecution = $false 155 | $AntiAnalysisCheck = $false 156 | $TokenImpersonation = $false 157 | $ProcessInjection = $false 158 | $SectionMapping = $false 159 | $ThreadContinuation = $false 160 | $ThreadSet = $false 161 | $T1486_Encryption = $false 162 | $DuplicateToken = $false 163 | $ThreadTokenSet = $false 164 | $ProcessInjection_Write = $false 165 | $ProcessInjection_Execute = $false 166 | $ProcessRead = $false 167 | $ProcessOpen = $false 168 | $LogonUser = $false 169 | $CobaltStrike = $false 170 | $CommandAndControl = $false 171 | $MemoryCpy = $false 172 | $MemProtect = $false 173 | $EtwPatch = $false 174 | 175 | foreach ($api in $apiList.apis) { 176 | # Access API details 177 | $apiName = $api.name 178 | $apiTag = $api.tag 179 | 180 | # Perform your specific checks or actions here 181 | $matchResults = $Results.Value | Select-String -Pattern $apiName -AllMatches | ForEach-Object { $_.Matches } | ForEach-Object { $_.Value } 182 | 183 | if ($null -ne $matchResults) { 184 | 185 | # Check if the tag of the API matches and update the corresponding variable 186 | switch($apiTag){ 187 | "TX_MiscAction" 188 | { 189 | $MiscAction = $true 190 | $MiscListAPIs += $matchResults 191 | break 192 | } 193 | "TA0002_CreateProcess" 194 | { 195 | $CreateProcess = $true 196 | $TA0002_CreateProcess_APIs += $matchResults 197 | break 198 | } 199 | "TX_MemoryCpy" 200 | { 201 | $MemoryCpy = $true 202 | $MemoryCpy_APIs += $matchResults 203 | break 204 | } 205 | "TX_MemoryProtectionManipulation" 206 | { 207 | $MemProtect = $true 208 | $MemProtect_APIs += $matchResults 209 | break 210 | } 211 | "SectionMapping" 212 | { 213 | $SectionMapping = $true 214 | $SectionMapping_APIs += $matchResults 215 | break 216 | } 217 | "ThreadContinuation"{ 218 | $ThreadContinuation = $true 219 | $ThreadContinuation_APIs += $matchResults 220 | break 221 | } 222 | "ThreadSet" 223 | { 224 | $ThreadSet = $true 225 | $ThreadSet_APIs += $matchResults 226 | break 227 | } 228 | "TX_ProcessHandle" 229 | { 230 | $ProcessOpen = $true 231 | $ProcessOpen_APIs += $matchResults 232 | break 233 | } 234 | "ProcessRead" 235 | { 236 | $ProcessRead = $true 237 | $ProcessRead_APIs += $matchResults 238 | break 239 | } 240 | "TX_COMInitialization" 241 | { 242 | $COMInitialization = $true 243 | $TX_COMInitialization_APIs += $matchResults 244 | break 245 | } 246 | "TX_NamedPipeCreation" 247 | { 248 | $CreateNamedPipe = $true 249 | $TX_NamedPipeCreation_APIs += $matchResults 250 | break 251 | } 252 | "TX_MailslotCreation" 253 | { 254 | $CreateMailslot = $true 255 | $TX_MailslotCreation_APIs += $matchResults 256 | break 257 | } 258 | "DeviceCodeExecution" 259 | { 260 | $VulnerableDriver = $true 261 | $TX_VulnerableDriver_APIs += $matchResults 262 | break 263 | } 264 | "T1543_003_ServiceCreation" 265 | { 266 | $ServiceCreation = $true 267 | $T1543_003_ServiceCreation_APIs += $matchResults 268 | break 269 | } 270 | "T1569_002_ServiceExecution" 271 | { 272 | $ServiceExecution = $true 273 | $T1569_002_ServiceExecution_APIs += $matchResults 274 | break 275 | } 276 | "T1497_AntiAnalysis" 277 | { 278 | $AntiAnalysisCheck = $true 279 | $T1497_AntiAnalysis_APIs += $matchResults 280 | break 281 | } 282 | "T1134_TokenImpersonation" 283 | { 284 | $TokenImpersonation = $true 285 | $T1134_TokenImpersonation_APIs += $matchResults 286 | break 287 | } 288 | "ProcessInjection_Write" 289 | { 290 | $ProcessInjection_Write = $true 291 | $ProcessInjection_Write_APIs += $matchResults 292 | break 293 | } 294 | "ProcessInjection_Execute" 295 | { 296 | $ProcessInjection_Execute = $true 297 | $ProcessInjection_Execute_APIs += $matchResults 298 | break 299 | } 300 | "T1486_Encryption" 301 | { 302 | $T1486_Encryption = $true 303 | $T1486_Encryption_APIs += $matchResults 304 | break 305 | } 306 | "TokenDuplicate" 307 | { 308 | $DuplicateToken = $true 309 | $DuplicateToken_APIs += $matchResults 310 | break 311 | } 312 | "ThreadTokenSet" 313 | { 314 | $ThreadTokenSet = $true 315 | $ThreadTokenSet_APIs += $matchResults 316 | break 317 | } 318 | "UserLogon" 319 | { 320 | $LogonUser = $true 321 | $LogonUser_APIs += $matchResults 322 | break 323 | } 324 | "TX_CobaltStrikeAPI" 325 | { 326 | $CobaltStrike = $true 327 | $CobaltStrike_APIs += $matchResults 328 | break 329 | } 330 | "T1024_002_CommandAndControl" 331 | { 332 | $CommandAndControl = $true 333 | $CommandAndControl_APIs += $matchResults 334 | break 335 | } 336 | } 337 | } 338 | } 339 | if($MemoryCpy -eq $true -and $MemProtect -eq $true) 340 | { 341 | $EtwPatch = $true 342 | $EtwPatch_APIs = $MemoryCpy_APIs + $MemProtect_APIs 343 | } 344 | if($ProcessInjection_Execute -eq $true -and $ProcessInjection_Write -eq $true) 345 | { 346 | $ProcessInjection = $true 347 | $T1055_ProcessInjection_APIs = $ProcessInjection_Write_APIs + $ProcessInjection_Execute_APIs 348 | } 349 | 350 | if($SectionMapping -eq $true -and $CreateProcess -eq $true -and $ThreadContinuation -eq $true -and $ThreadSet -eq $true) 351 | { 352 | $ProcessHollowing = $true 353 | $T1055_012_ProcessHollowing_APIs = $SectionMapping_APIs + $TA0002_CreateProcess_APIs + $ThreadContinuation_APIs + $ThreadSet_APIs 354 | } 355 | 356 | if($TokenImpersonation -eq $false -and $DuplicateToken -eq $true -and $ThreadTokenSet -eq $true) 357 | { 358 | $TokenImpersonation = $true 359 | } 360 | if($ProcessRead -eq $true -and $ProcessOpen -eq $true) 361 | { 362 | $LSASSDump = $true 363 | $T1003_001_LSASSDump_APIs = $ProcessOpen_APIs + $ProcessRead_APIs 364 | } 365 | 366 | [PSCustomObject] @{ 367 | FilePath = $ResolvedFilePath.Path 368 | FileHash = $FileHash.Hash 369 | TA0002_CreateProcess = $CreateProcess 370 | T1055_ProcessInjection = $ProcessInjection 371 | T1055_012_ProcessHollowing = $ProcessHollowing 372 | T1134_TokenImpersonation = $TokenImpersonation 373 | T1543_003_ServiceCreation = $ServiceCreation 374 | T1569_002_ServiceExecution = $ServiceExecution 375 | T1003_001_LSASSDump = $LSASSDump 376 | T1486_Encryption = $T1486_Encryption 377 | T1078_UserLogon = $LogonUser 378 | T1497_AntiAnalysis = $AntiAnalysisCheck 379 | TX_VulnerableDriver = $VulnerableDriver 380 | TX_COMInitialization = $COMInitialization 381 | TX_NamedPipeCreation = $CreateNamedPipe 382 | TX_MailslotCreation = $CreateMailslot 383 | TX_MiscAction = $MiscAction 384 | TX_CobaltStrikeAPI = $CobaltStrike 385 | T1024_002_CommandAndControl = $CommandAndControl 386 | TX_EtwPatch = $EtwPatch 387 | TA0002_CreateProcess_APIs = $TA0002_CreateProcess_APIs | Select-Object -Unique 388 | T1055_ProcessInjection_APIs = $T1055_ProcessInjection_APIs | Select-Object -Unique 389 | T1055_012_ProcessHollowing_APIs = $T1055_012_ProcessHollowing_APIs | Select-Object -Unique 390 | T1134_TokenImpersonation_APIs = $T1134_TokenImpersonation_APIs | Select-Object -Unique 391 | T1543_003_ServiceCreation_APIs = $T1543_003_ServiceCreation_APIs | Select-Object -Unique 392 | T1569_002_ServiceExecution_APIs = $T1569_002_ServiceExecution_APIs | Select-Object -Unique 393 | T1003_001_LSASSDump_APIs = $T1003_001_LSASSDump_APIs | Select-Object -Unique 394 | T1486_Encryption_APIs = $T1486_Encryption_APIs | Select-Object -Unique 395 | T1078_UserLogon_APIs = $LogonUser_APIs | Select-Object -Unique 396 | TX_VulnerableDriver_APIs = $TX_VulnerableDriver_APIs | Select-Object -Unique 397 | T1497_AntiAnalysis_APIs = $T1497_AntiAnalysis_APIs | Select-Object -Unique 398 | TX_COMInitialization_APIs = $TX_COMInitialization_APIs | Select-Object -Unique 399 | TX_NamedPipeCreation_APIs = $TX_NamedPipeCreation_APIs | Select-Object -Unique 400 | TX_MailslotCreation_APIs = $TX_MailslotCreation_APIs | Select-Object -Unique 401 | TX_MiscAction_APIs = $MiscListAPIs 402 | TX_CobaltStrikeAPIs = $CobaltStrike_APIs | Select-Object -Unique 403 | T1024_002_CommandAndControl_APIs = $CommandAndControl_APIs | Select-Object -Unique 404 | TX_EtwPatch_APIs = $EtwPatch_APIs | Select-Object -Unique 405 | 406 | } 407 | 408 | } --------------------------------------------------------------------------------