A collection of cybersecurity content.

System EXEs and DLLs: Collecting Evidence

Intro

It is critical for incident response teams to have a complete understanding of any incident. Gathering information on the signature statuses, sizes, hashes and other attributes of key files is a crucial component in achieving enough data to help paint a full picture during an incident and to give pivoting points to extend and use across the environment.

Why Collect This Information?

Security teams thoroughly examine all relevant details during investigations to identify potential anomalies, signs of compromise, and any elements that can be incorporated into the analysis tools utilized by the security operations team. Understanding what to look for across all systems is key in detecting impacted systems. Effective evidence collection minimizes incident response times and strengthens an organization’s security posture by detecting malicious activity.

A single minute detail can make a significant impact in uncovering the full scope of a threat, preventing it from becoming a prolonged and complex investigation. Failing to pay attention to small details could result in missing crucial information for the attack that might have been otherwise halted early.

Scripts

This script on the left will collect information about executables on the system and save the output to a csv at C:\temp\exe_info_and_their_signatures.csv. There are baked in exclusions that can be customized for your environment.

This script on the right will collect information about dynamic link libraries on the system and save the output to a csv at C:\temp\dll_info_and_their_signatures.csv. There are baked in exclusions that can be customized for your environment.

Both of these scripts will output properties related to FileName, FileSize, Status, IsOSBinary, StatusMessage, CreationTime, LastWriteTime, LastAccessTime, SignerCertificate, TimeStamperCertificate, SHA256.

The IsOSBinary property is interesting because it gives a Boolean value of whether the file is part of the operating system.

# Collects exe information

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# Function to make file size outputs pretty
Function Get-FormattedByteSize {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline=$true)]
        [double]$ByteSize
    )

    $SizeUnits = @("bytes", "KB", "MB", "GB", "TB", "PB")
    $ByteSize | ForEach-Object {
        $UnitIndex = 0
        $Size = [math]::Round($_, 2)
        while ($Size -ge 1KB) {
            $Size = $Size / 1KB
            $UnitIndex++
        }
        "{0:N2} {1}" -f $Size, $SizeUnits[$UnitIndex]
    }
}

$exe_exclusionPaths = @("C:\ExclusionPath1_zzzzzz", "C:\ExclusionPath2_zzzzzz")

$exes = Get-ChildItem -Path "C:\" -Recurse -Include *.exe -File -ErrorAction SilentlyContinue | Where-Object {$exe_exclusionPaths -notcontains $_.DirectoryName}

$results = foreach ($exe in $exes) {
    $signature = Get-AuthenticodeSignature -FilePath $exe.FullName -ErrorAction SilentlyContinue
    $sha256 = (Get-FileHash $exe.FullName -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash
    $fileSize = Get-FormattedByteSize -ByteSize $exe.Length -ErrorAction SilentlyContinue

    $props = @{
        FileName = $exe.FullName
        FileSize = $fileSize
        Status = $signature.Status
        IsOSBinary = $signature.IsOSBinary
        StatusMessage = $signature.StatusMessage
        CreationTime = $exe.CreationTime
        LastWriteTime = $exe.LastWriteTime
        LastAccessTime = $exe.LastAccessTime
        SignerCertificate = $signature.SignerCertificate
        TimeStamperCertificate = $signature.TimeStamperCertificate
        SHA256 = $sha256
    }

    New-Object PSObject -Property $props
}

$results | Select-Object FileName, FileSize, Status, IsOSBinary, StatusMessage, CreationTime, LastWriteTime, LastAccessTime, SignerCertificate, TimeStamperCertificate, SHA256 | Sort-Object CreationTime -Descending | Export-Csv -Path "C:\temp\exe_info_and_their_signatures.csv" -NoTypeInformation
# Collects dll information

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# Function to make file size outputs pretty
Function Get-FormattedByteSize {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline=$true)]
        [double]$ByteSize
    )

    $SizeUnits = @("bytes", "KB", "MB", "GB", "TB", "PB")
    $ByteSize | ForEach-Object {
        $UnitIndex = 0
        $Size = [math]::Round($_, 2)
        while ($Size -ge 1KB) {
            $Size = $Size / 1KB
            $UnitIndex++
        }
        "{0:N2} {1}" -f $Size, $SizeUnits[$UnitIndex]
    }
}

$dll_exclusionPaths = @("C:\ExclusionPath1_zzzzzz", "C:\ExclusionPath2_zzzzzz")

$dlls = Get-ChildItem -Path "C:\" -Recurse -Include *.dll -File -ErrorAction SilentlyContinue | Where-Object {$dll_exclusionPaths -notcontains $_.DirectoryName}

$results = foreach ($dll in $dlls) {
    $signature = Get-AuthenticodeSignature -FilePath $dll.FullName -ErrorAction SilentlyContinue
    $sha256 = (Get-FileHash $dll.FullName -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash
    $fileSize = Get-FormattedByteSize -ByteSize $dll.Length -ErrorAction SilentlyContinue

    $props = @{
        FileName = $dll.FullName
        FileSize = $fileSize
        Status = $signature.Status
        IsOSBinary = $signature.IsOSBinary
        StatusMessage = $signature.StatusMessage
        CreationTime = $dll.CreationTime
        LastWriteTime = $dll.LastWriteTime
        LastAccessTime = $dll.LastAccessTime
        SignerCertificate = $signature.SignerCertificate
        TimeStamperCertificate = $signature.TimeStamperCertificate
        SHA256 = $sha256
    }

    New-Object PSObject -Property $props
}

$results | Select-Object FileName, FileSize, Status, IsOSBinary, StatusMessage, CreationTime, LastWriteTime, LastAccessTime, SignerCertificate, TimeStamperCertificate, SHA256 | Sort-Object CreationTime -Descending | Export-Csv -Path "C:\temp\dll_info_and_their_signatures.csv" -NoTypeInformation
Conclusion

Efficient methods of collecting information on hosts are essential in reducing response and investigation times, allowing the security team to swiftly identify correlations in the data. Attaining this goal heavily relies on the compilation of key file signatures, names, sizes, and hashes.