Есть какой-то способ защитить коды скриптов?
Предполагая, что все основанные на сценариях языки (такие как VBscript и Powershell) каждый раз идут со всем кодом, "встроенным" на клиентском компьютере, должен ли я считать, что этот код "открыт"? Я имею в виду, есть какой-то способ защитить основанные на сценариях коды для чтения (и, следовательно, для записи)?
3 ответа
Есть некоторые инструменты, которые могут конвертировать VBScript в исполняемые файлы, такие как vbs2exe, vbsedit и scriptcryptor. Создание исполняемого файла через PowerShell также возможно, выполняя его самостоятельно в.net, используя PowerGUI Pro или ps2exe.
С помощью этих инструментов вы можете сделать ваши скрипты "закрытыми". Как и в случае (почти) всего клиентского кода сайта, он все еще может быть взломан, но для этого нужно гораздо больше инструментов и знаний, чем просто открыть ваш файл VBS в блокноте и заглянуть в ваш скрипт.
Я не верю, что существует какой-либо способ полного доказательства, запутывание и минимизация - это метод, предназначенный для попытки защитить код (а в случае минимизации уменьшить объем хранилища / объем передаваемых данных), но в конечном итоге тот, у кого достаточно времени, может проанализировать или посмотреть выполнение программы с помощью средств отладки / разборки. Я думаю, что вам безопаснее всего предполагать, что на клиентском компьютере можно поиграть с чем-либо, и ваш лучший вариант для защиты кода или информации - хранить / выполнять его на сервере с надлежащей защитой и постоянным обновлением в отношении исправлений безопасности.
Да! Вы можете использовать для этого мой шаблон. И не забудьте сменить пароль с "qweasd" на другой!
function global: Decrypt-String { param($Encrypted, $ Passphrase, $ salt, $ init) if ($Encrypted -is [строка]) { $ Encrypted = [Конвертировать]::FromBase64String($Encrypted) } $ r = New-Object 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 = New-Object Security.Cryptography.CryptoStream $ ms, $ d, "Прочитать" $ sr = Новый объект IO.StreamReader $cs Запись-вывод $ sr.ReadToEnd () $ sr.Close () $ cs.Close() $ ms.Close() $ r.Clear() } function global: Run-Decrypt ([строка]$encrypted) { $ private: pass = Read-Host "Введите пароль для декодирования кода скрипта" -AsSecureString $ private:BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($private: пройти) $ 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") вернуть $ block } function global:Save-Decrypt ([строка]$encrypted) { пытаться { $ answer = Read-Host "Сохранить версию декодированного скрипта? (да / нет)" switch ($answer) { Г {} N {return} По умолчанию {return} } $ decrypted = Выполнить-расшифровать $ зашифровано $p = (Read-Host "Введите путь для нового файла") if (-Not (Is-ValidPath $p)) {return} if ($host.version -ne "2.0") { $ offset = $global:secure.StartPosition.Start + 1 } else { $ offset = $global:secure.StartPosition.Start } (Get-Content $global:secure.File | Out-String).Remove($offset, $ global:secure.ToString().Length).Insert($offset, $decrypted) | Out-File -FilePath $p -NoClobber Write-Host 'Декодированный файл успешно сохранен.' } ловить { Write-Host 'Ошибка при сохранении файла.' Ошибка Write-Host $[0] } } глобальная функция:Is-ValidPath([строка] $ path) { if ($path -eq '') { Write-Host 'Нет пути. Не удалось создать файл.'; вернуть $ false } elseif (-not (Test-Path (Split-Path $path -Parent))) { Путь Write-Host не существует. Не удалось создать файл.'; вернуть $ false } elseif (Test-Path $path) { Файл Write-Host уже существует. Не удалось создать файл.'; вернуть $ false } return $ true; } $ global: secure = { function global: Encrypt-String { param($String, $ Passphrase, $ salt, $ init,[переключатель] $ arrayOutput) $ r = New-Object 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 = New-Object Security.Cryptography.CryptoStream $ ms, $ c, "Запись" $ sw = Новый объект IO.StreamWriter $ cs $ sw.Write($String) $ sw.Close() $ cs.Close() $ ms.Close() $ r.Clear() [byte[]] $ result = $ms.ToArray() if ($arrayOutput) { вернуть $ результат } else { return [Convert]::ToBase64String($result) } } function global:Save-Encrypt () { $ answer = Read-Host "` n Сохранить закодированную версию этого скрипта? (да / нет) " switch ($answer) { Г {} N {return} По умолчанию {return} } пытаться { $ path = (Read-Host "Введите путь для закодированного файла").Trim("`"'") if (-Not (Is-ValidPath $path)) {return} Run-Encrypt | Out-File -FilePath $path -NoClobber Write-Host 'Закодированный файл успешно сохранен.' } ловить { Write-Host 'Ошибка при сохранении файла.' Ошибка Write-Host $[0] } } function global:Run-Encrypt () { парам ( $ 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 } else { $ 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 '$ зашифровано'") вернуть $ block } # программа начинается здесь Write-Host "Hello World!" # программа заканчивается здесь } пытаться { $ null = $ global: secure.GetSteppablePipeline() # грязный взлом Запись-Предупреждение "Скрипт закодирован!" пытаться { Invoke-Command -ScriptBlock ([Scriptblock]::Create((Run-Decrypt $global:secure.Invoke()))) } наконец-то { Сохранить-расшифровать $ global: secure.Invoke() } } ловить { пытаться { Invoke-Command -ScriptBlock $global:secure } наконец-то { Get-Job | Remove-Job -Force Сохранить-зашифровать } }
Я не был действительно удовлетворен подходом к исполняемым файлам, поскольку я обнаружил, что сложные сценарии компилируются нелегко (и часто вообще не компилируются) и, в конце концов, слишком сложны для работы. Как указывалось многими, для решительного человека исполняемый файл не является препятствием. Я решил, что лучший способ - просто сделать читаемый человеком сценарий более трудным для изменения, чем просто запросить изменения, которые должны быть сделаны первоначальными разработчиками.
Я написал obfuscate-powershell для изменения имен переменных и функций, удаления комментариев и изменения пробелов, чтобы сделать код менее читаемым и понятным. Это все еще никоим образом не безопасно, но это лучше, чем вообще ничего не делать.