Volatile/Get-InjectedThread.ps1

function Get-InjectedThread {
    <#
 
    .SYNOPSIS
 
    Looks for threads that were created as a result of code injection.
 
    .DESCRIPTION
 
    Memory resident malware (fileless malware) often uses a form of memory injection to get code execution. Get-InjectedThread looks at each running thread to determine if it is the result of memory injection.
 
    Common memory injection techniques that *can* be caught using this method include:
    - Classic Injection (OpenProcess, VirtualAllocEx, WriteProcessMemory, CreateRemoteThread)
    - Reflective DLL Injection
    - Process Hollowing
 
    NOTE: Nothing in security is a silver bullet. An attacker could modify their tactics to avoid detection using this methodology.
 
    .NOTES
 
    Author - Jared Atkinson (@jaredcatkinson)
 
    .EXAMPLE
 
    PS > Get-InjectedThread
 
    ProcessName : ThreadStart.exe
    ProcessId : 7784
    Path : C:\Users\tester\Desktop\ThreadStart.exe
    KernelPath : C:\Users\tester\Desktop\ThreadStart.exe
    CommandLine : "C:\Users\tester\Desktop\ThreadStart.exe"
    PathMismatch : False
    ThreadId : 14512
    AllocatedMemoryProtection : PAGE_EXECUTE_READWRITE
    MemoryProtection : PAGE_EXECUTE_READWRITE
    MemoryState : MEM_COMMIT
    MemoryType : MEM_PRIVATE
    BasePriority : 8
    IsUniqueThreadToken : False
    Integrity : MEDIUM_MANDATORY_LEVEL
    Privilege : SeChangeNotifyPrivilege
    LogonId : 999
    SecurityIdentifier : S-1-5-21-386661145-2656271985-3844047388-1001
    UserName : DESKTOP-HMTGQ0R\SYSTEM
    LogonSessionStartTime : 3/15/2017 5:45:38 PM
    LogonType : System
    AuthenticationPackage : NTLM
    BaseAddress : 4390912
    Size : 4096
    Bytes : {144, 195, 0, 0...}
 
    #>


    [CmdletBinding()]
    param ()

    $hSnapshot = CreateToolhelp32Snapshot -ProcessId 0 -Flags 4

    $Thread = Thread32First -SnapshotHandle $hSnapshot
    do {
        $proc = Get-Process -Id $Thread.th32OwnerProcessId

        if($Thread.th32OwnerProcessId -ne 0 -and $Thread.th32OwnerProcessId -ne 4) {
            $hThread = OpenThread -ThreadId $Thread.th32ThreadID -DesiredAccess $THREAD_ALL_ACCESS -InheritHandle $false
            if($hThread -ne 0) {
                $BaseAddress = NtQueryInformationThread -ThreadHandle $hThread
                $hProcess = OpenProcess -ProcessId $Thread.th32OwnerProcessID -DesiredAccess $PROCESS_ALL_ACCESS -InheritHandle $false

                if($hProcess -ne 0) {
                    $memory_basic_info = VirtualQueryEx -ProcessHandle $hProcess -BaseAddress $BaseAddress
                    $AllocatedMemoryProtection = $memory_basic_info.AllocationProtect -as $MemProtection
                    $MemoryProtection = $memory_basic_info.Protect -as $MemProtection
                    $MemoryState = $memory_basic_info.State -as $MemState
                    $MemoryType = $memory_basic_info.Type -as $MemType

                    if($MemoryState -eq $MemState::MEM_COMMIT -and $MemoryType -ne $MemType::MEM_IMAGE) {
                        $buf = ReadProcessMemory -ProcessHandle $hProcess -BaseAddress $BaseAddress -Size 100
                        $proc = Get-WmiObject Win32_Process -Filter "ProcessId = '$($Thread.th32OwnerProcessID)'"
                        $KernelPath = QueryFullProcessImageName -ProcessHandle $hProcess
                        $PathMismatch = $proc.Path.ToLower() -ne $KernelPath.ToLower()

                        # check if thread has unique token
                        try {
                            $hThreadToken = OpenThreadToken -ThreadHandle $hThread -DesiredAccess $TOKEN_ALL_ACCESS
                            $SID = GetTokenInformation -TokenHandle $hThreadToken -TokenInformationClass 1
                            $Privs = GetTokenInformation -TokenHandle $hThreadToken -TokenInformationClass 3
                            $LogonSession = GetTokenInformation -TokenHandle $hThreadToken -TokenInformationClass 17
                            $Integrity = GetTokenInformation -TokenHandle $hThreadToken -TokenInformationClass 25
                            $IsUniqueThreadToken = $true
                        } catch {
                            $hProcessToken = OpenProcessToken -ProcessHandle $hProcess -DesiredAccess $TOKEN_ALL_ACCESS
                            $SID = GetTokenInformation -TokenHandle $hProcessToken -TokenInformationClass 1
                            $Privs = GetTokenInformation -TokenHandle $hProcessToken -TokenInformationClass 3
                            $LogonSession = GetTokenInformation -TokenHandle $hProcessToken -TokenInformationClass 17
                            $Integrity = GetTokenInformation -TokenHandle $hProcessToken -TokenInformationClass 25
                            $IsUniqueThreadToken = $false
                        }

                        $ThreadDetail = New-Object PSObject
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name ProcessName -Value $proc.Name
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name ProcessId -Value $proc.ProcessId
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name Path -Value $proc.Path
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name KernelPath -Value $KernelPath
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name CommandLine -Value $proc.CommandLine
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name PathMismatch -Value $PathMismatch
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name ThreadId -Value $Thread.th32ThreadId
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name AllocatedMemoryProtection -Value $AllocatedMemoryProtection
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name MemoryProtection -Value $MemoryProtection
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name MemoryState -Value $MemoryState
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name MemoryType -Value $MemoryType
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name BasePriority -Value $Thread.tpBasePri
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name IsUniqueThreadToken -Value $IsUniqueThreadToken
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name Integrity -Value $Integrity
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name Privilege -Value $Privs
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name LogonId -Value $LogonSession.LogonId
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name SecurityIdentifier -Value $SID
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name UserName -Value "$($LogonSession.Domain)\$($LogonSession.UserName)"
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name LogonSessionStartTime -Value $LogonSession.StartTime
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name LogonType -Value $LogonSession.LogonType
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name AuthenticationPackage -Value $LogonSession.AuthenticationPackage
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name BaseAddress -Value $BaseAddress
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name Size -Value $memory_basic_info.RegionSize
                        $ThreadDetail | Add-Member -MemberType Noteproperty -Name Bytes -Value $buf
                        Write-Output $ThreadDetail
                    }
                    CloseHandle($hProcess)
                }
            }
            CloseHandle($hThread)
        }
    } while($Kernel32::Thread32Next($hSnapshot, [ref]$Thread))
    CloseHandle($hSnapshot)
}