Есть какой-то способ защитить коды скриптов?

Предполагая, что все основанные на сценариях языки (такие как 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 для изменения имен переменных и функций, удаления комментариев и изменения пробелов, чтобы сделать код менее читаемым и понятным. Это все еще никоим образом не безопасно, но это лучше, чем вообще ничего не делать.

Другие вопросы по тегам