假设所有基于脚本的语言(例如 VBscript 和 Powershell)每次都将整个代码“嵌入”在客户机器上,我是否应该假设该代码是“开放的”?我的意思是,有一些方法可以保护基于脚本的代码阅读(并因此写作)?
4 回答
有一些工具可以将 VBScript 转换为可执行文件,例如vbs2exe、vbsedit和scriptcryptor。通过 PowerShell 创建可执行文件也可以通过自己在 .net中使用 PowerGUI Pro或ps2exe 来完成。
使用这些工具,您可以使您的脚本“关闭”。与(几乎)所有客户端站点代码一样,它仍然可能被黑客入侵,但这需要更多的工具和知识,而不仅仅是在记事本中打开 vbs 文件并查看脚本。
我不相信有任何完整的证明方法,混淆和最小化是试图保护代码的方法(并且在最小化的情况下减少存储/传输大小)但最终有足够时间的人可以进行逆向工程或观看通过调试/反汇编工具执行程序。我认为你是最安全的假设客户端机器上的任何东西都可以被玩弄,并且保护代码或信息的最佳选择是将其存储/执行在具有适当安全性的服务器上,并不断更新安全漏洞补丁。
是的!您可以为此使用我的模板。并且不要忘记将密码从“qweasd”更改为其他密码!
函数全局:解密字符串 {
参数($Encrypted,$Passphrase,$salt,$init)
if ($Encrypted -is [字符串]) {
$Encrypted = [转换]::FromBase64String($Encrypted)
}
$r = 新对象 System.Security.Cryptography.RijndaelManaged
$pass = [System.Text.Encoding]::UTF8.GetBytes($Passphrase)
$salt = [System.Text.Encoding]::UTF8.GetBytes($salt)
$r.Key = (New-Object Security.Cryptography.PasswordDeriveBytes $pass,$salt,"SHA256",5).GetBytes(256/8)
$r.IV = (New-Object Security.Cryptography.SHA1Managed).ComputeHash([Text.Encoding]::UTF8.GetBytes($init))[0..15]
$d = $r.CreateDecryptor()
$ms = 新对象 IO.MemoryStream @(,$Encrypted)
$cs = 新对象 Security.Cryptography.CryptoStream $ms,$d,"Read"
$sr = 新对象 IO.StreamReader $cs
写输出 $sr.ReadToEnd()
$sr.Close()
$cs.Close()
$ms.Close()
$r.清除()
}
函数全局:运行解密([字符串]$加密){
$private:pass = Read-Host "输入密码以解码脚本代码" -AsSecureString
$private:BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($private:pass)
$private:UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($private:BSTR)
$block = (global:Decrypt-String -Encrypted $encrypted -Passphrase $private:UnsecurePassword -salt "d35104f3-dcd0-4cd7-80bb-5e66388e6ede" -init "3982c1d2-04da-4883-9a46-4b860794084e")
返回$块
}
函数全局:保存解密([字符串]$加密){
尝试 {
$answer = Read-Host "保存解码后的脚本版本?(y/n)"
开关($答案){
是{}
N {返回}
默认 {return}
}
$decrypted = 运行解密 $encrypted
$p = (Read-Host "输入新文件的路径")
if (-Not (Is-ValidPath $p)) { return }
if ($host.version -ne "2.0") {
$offset = $global:secure.StartPosition.Start + 1
} 别的 {
$offset = $global:secure.StartPosition.Start
}
(Get-Content $global:secure.File | Out-String).Remove($offset,$global:secure.ToString().Length).Insert($offset, $decrypted) | 输出文件 -FilePath $p -NoClobber
' Write-Host '解码文件成功保存。'
} 抓住 {
Write-Host '保存文件时出错。'
写主机 $error[0]
}
}
函数全局:Is-ValidPath([string]$path) {
if ($path -eq '') {
Write-Host '没有路径。创建文件失败。'; 返回 $false
} elseif (-not (Test-Path (Split-Path $path -Parent))) {
Write-Host '路径不存在。创建文件失败。'; 返回 $false
} elseif (测试路径 $path) {
Write-Host '文件已经存在。创建文件失败。'; 返回 $false
}
返回 $true;
}
$全球:安全= {
函数全局:加密字符串 {
参数($String,$Passphrase,$salt,$init,[switch]$arrayOutput)
$r = 新对象 System.Security.Cryptography.RijndaelManaged
$pass = [Text.Encoding]::UTF8.GetBytes($Passphrase)
$salt = [Text.Encoding]::UTF8.GetBytes($salt)
$r.Key = (New-Object Security.Cryptography.PasswordDeriveBytes $pass,$salt,"SHA256",5).GetBytes(256/8)
$r.IV = (New-Object Security.Cryptography.SHA1Managed).ComputeHash([Text.Encoding]::UTF8.GetBytes($init))[0..15]
$c = $r.CreateEncryptor()
$ms = 新对象 IO.MemoryStream
$cs = 新对象 Security.Cryptography.CryptoStream $ms,$c,"Write"
$sw = 新对象 IO.StreamWriter $cs
$sw.Write($String)
$sw.Close()
$cs.Close()
$ms.Close()
$r.清除()
[字节[]]$result = $ms.ToArray()
if ($arrayOutput) {
返回$结果
} 别的 {
返回 [转换]::ToBase64String($result)
}
}
函数全局:保存加密(){
$answer = Read-Host "`n保存此脚本的编码版本?(y/n)"
开关($答案){
是{}
N {返回}
默认 {return}
}
尝试 {
$path = (Read-Host "输入编码文件的路径").Trim("`"'")
if (-Not (Is-ValidPath $path)) {return}
运行加密 | 输出文件 -FilePath $path -NoClobber
' Write-Host '编码文件已成功保存。'
} 抓住 {
Write-Host '保存文件时出错。'
写主机 $error[0]
}
}
函数全局:运行加密(){
参数(
$pass = "qweasd",
$salt = "d35104f3-dcd0-4cd7-80bb-5e66388e6ede",
$init = "3982c1d2-04da-4883-9a46-4b860794084e"
)
$encrypted = global:Encrypt-String -String $global:secure -Passphrase $pass -salt $salt -init $init
if ($host.version -ne "2.0") {
$offset = $global:secure.StartPosition.Start + 1
} 别的 {
$offset = $global:secure.StartPosition.Start
}
$block = (Get-Content $global:secure.File | Out-String).Remove($offset, $global:secure.ToString().Length).Insert($offset, "New-Object -TypeName System.String '$加密'")
返回$块
}
#程序从这里开始
写主机“Hello World!”
#程序到此结束
}
尝试 {
$null = $global:secure.GetSteppablePipeline() #dirty hack
写警告“脚本编码!”
尝试 {
Invoke-Command -ScriptBlock ([Scriptblock]::Create((Run-Decrypt $global:secure.Invoke())))
} 最后 {
保存解密 $global:secure.Invoke()
}
} 抓住 {
尝试 {
调用命令 -ScriptBlock $global:secure
} 最后 {
找工作 | 移除作业强制
保存加密
}
}
我对可执行的方法并不满意,因为我发现复杂的脚本不容易编译(而且通常根本编译不了),而且最终很难使用。正如许多人所指出的,对于有决心的人来说,可执行文件不是障碍。我决定一个更好的方法是简单地使人类可读的脚本更难更改,然后简单地要求原始开发人员进行更改。
我编写了obfuscate-powershell来更改变量和函数名称、删除注释和更改空格,只是为了降低代码的可读性和可理解性。它仍然不安全,但总比什么都不做要好。