upload successful

之前经常帮客户写一些需要特殊权限执行程序或者是访问指定资源的脚本,这种情况下,通常需要在脚本中包含敏感的账号信息或执行命令,这就存在很严重的敏感信息泄漏的风险

因此,我必须确保即使某些用户在拥有正常权限查看这些脚本的情况下,也无法正常获取到明文的账号信息或是敏感的操作

这里以一个简单的访问 Windows 共享的脚本作为加密混淆案例,我只演示混淆 $username$password 这两行敏感数据,当然,你也可以针对整个脚本进行混淆,混淆的方法都是通用的,需要灵活搭配使用,1+1 远远大于 2

l
# 定义共享路径、用户名和密码
$sharePath = "\\192.168.80.129\ISO"
$username = "bob"
$password = "P@ssw0rd"
# 将密码转换为安全字符串
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
# 创建凭据对象
$credential = New-Object System.Management.Automation.PSCredential($username, $securePassword)
# 使用凭据连接到共享
New-PSDrive -Name "P" -PSProvider FileSystem -Root $sharePath -Credential $credential -Persist

目前 Powershell 网上出现混淆的方法有很多,我只简单介绍我自己比较常用的几种方式

# base64 编码

我看网上有很多人说 base64 是一种加密方式,实际上 base64 算不上加密,只是一种编码算法,并且该算法是公开可逆的,只能达到混淆的效果,任何情况下都不应该使用 base64 作为敏感数据的加密手段

在这个示例中,我们将需要用户名和密码的转化成 base64 , 然后通过 [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String 命令解码,即可正常执行脚本

upload successful

# unicode 编码

unicode 编码需要在 powershell 6.0 以上版本才支持,将需要加密字符转化成 unicode ,用 "`u {unicode}" 便可以解码,由于 ISE 不支持 6.0 以上版本,所以我直接在命令行中演示

upload successful

# ASCII 编码

ASCIIUnicode 的编码原理一样,只是 ASCII 默认使用的是十进制,而 Unicode 默认使用的是十六进制ASCII 解码命令为 [char]ASCII ,例如字母 b[char]98 , 如果需要解码多个字符,可以用 -joinForEach-Object 将字符拼接

upload successful

# 字符串拼接

我们将变量中的字符串拆分成 N 段,然后再对变量字符进行拼接,也可以起到混淆的效果,当然,最终还是要配合编码混淆,不然意义不大

upload successful

另外还可以对字符进行替换和分割,字符串的操作方法可太多了,希望感兴趣的小伙伴自行百度,这里就不多叙说了

# 字母大小写和特殊字符混淆

Windows 操作系统中,通常命令行中的命令和以及操作系统中的文件名字母是不区分大小写的,还有一些具有特殊含义的符号,这些机制我们都可以利用起来混淆代码,从而增加代码阅读难度让别人不能一眼就看出我们代码的原貌

下面对一些特殊符号及其含义进行简单的说明,并以命令 Write-Host "hello" 为混淆示例,混淆后命令依然可以正常执行

符号名 作用 混淆示例
单引号 ' 创建一个文字字符串,字符串中的内容以原样输出,不解析变量 W'r'ite-'Host' "hello"
调用操作符 & 用于运行命令或脚本 &Write-Host "hello"
反引号 ` 反引号有多种用法,一般主要用于行续接和转义字符 `n`r`b`t`a`f`v, 其它没有特殊意义的字符系统会自动忽略反引号 Wr`it`e-H`ost "h`el`lo"
大括号 {} {} 是脚本块,用于定义一段可以延迟执行或多次调用的代码,可以配合 & 执行脚本块中的命令 &{Write-Host "hello"}
空格 空格一般作为参数的分割副,正常情况下只需要一个空格,多个空格会系统会自动忽略 Write-Host "hello"
小括号 () 小括号可以用于改变运算符优先级和参数传递,也可以用于创建子表达式 Write-Host ((("hello")))

upload successful

基础的混淆方法就写这么多吧,我也不想浪费大家时间看这些没有太大意义的基础教程,毕竟现在开源的混淆脚本一大堆,不管是混淆的效果还是效率都远比自己动手要好

# Invoke-Obfuscation

Invoke-ObfuscationGithub 上的一个开源的 Powershell 加密混淆脚本,也是我目前最常用的加密混淆脚本

使用方法也灰常简单,下载项目压缩包到本地并解压,从终端命令行进入到解压目录

Import-Module 命令导入 Invoke-Obfuscation.psd1 脚本模块后,执行 Invoke-Obfuscation 便可使用

upload successful

输入 tutorial 可以查看脚本使用说明

upload successful

Invoke-Obfuscation 的混淆方式有很多,这里我只简单的介绍 ENCODING 的方法,还是以开头的脚本为例,加密 $username$password 这两行敏感数据

l
set scriptblock $username = "bob"  		# 设置你需要混淆的命令
encoding						  		 # 混淆模式我这边选择 encoding
4								  		 # 选择二进制编码混淆
copy							  		 # 复制混淆后的命令到剪切板
set scriptblock $password = "P@ssw0rd"  # 设置你需要混淆的命令
encoding						   		# 混淆模式我这边选择 encoding
3								   		# 选择十进制编码混淆
copy							  		 # 复制混淆后的命令到剪切板

upload successful

最后看看执行效果吧

upload successful

可以看到混淆后脚本依然可以正常执行,如果你想了解更多 Invoke-Obfuscation 的用法,可以到 github 查看源项目

Invoke-Obfuscation 项目地址:https://github.com/danielbohannon/Invoke-Obfuscation

写这篇文章的初衷并非是为了绕过某些安全防护,只是之前在工作上无法避免需要经常帮客户写一些相关的脚本,在这里分享一下自己的方法思路而已