假设所有基于脚本的语言(例如 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来更改变量和函数名称、删除注释和更改空格,只是为了降低代码的可读性和可理解性。它仍然不安全,但总比什么都不做要好。