0

我有一百多个要解密的加密程序和函数(我正在尝试导出 bacpac 文件,但由于程序被加密而失败)。我尝试使用dbforge sql 解密器解密向导进行就地更改,但出现错误:

定义无效。找不到 CREATE 关键字。

当我尝试查看存储过程的 DDL 脚本(使用 dbforge sql 解密器)时,出现错误:

无法显示对象 dbo.pt_blocks 的定义,因为它已被第三方工具加密

我找不到解决办法。有没有可用的解决方案或其他工具?

编辑:我发现这个资源提到

获取源代码并发出不带加密选项的 ALTER 命令。只需获取源代码并删除 WITH ENCRYPTION

我怎么能做到这一点?

编辑:我启用了远程 DAC。我怎样才能解密一切?此问题的已接受答案的链接已断开。

编辑:问题已通过卸载创建加密程序的第三方工具得到解决。

4

1 回答 1

1

下面是一个 PowerShell 示例,该示例创建了一个包含所有加密对象的脚本文件,该示例来自 Paul White 的WITH ENCRYPTION文章的内部信息。将 2 个连接字符串中的数据源和初始目录更改为所需的服务器和数据库以及脚本文件路径。

DAC 连接用于从系统表中检索值,因此sysadmin需要服务器角色成员资格。remote admin connections如果远程运行,则必须启用SQL Server选项并允许 TCP 端口 1434 通过防火墙。

该脚本可以从 PowerShell ISE 或自定义后的命令提示符运行。命令行调用示例,假设脚本保存到文件“Decrypt-Objects.ps1”。

powershell -ExecutionPolicy RemoteSigned -File C:\PowershellScripts\Decrypt-Objects.ps1

PowerShell 脚本:

# PowerShell implementation of T-SQL code from https://sqlperformance.com/2016/05/sql-performance/the-internals-of-with-encryption

Function Get-DecryptedString($pwd, $data) {

    $key = [System.Array]::CreateInstance([int], 256)
    $box = [System.Array]::CreateInstance([int], 256)
    $cipher = [System.Array]::CreateInstance([byte], $data.Length)

    for ($i = 0; $i -lt 256; ++$i) {
      $key[$i] = $pwd[$i % $pwd.Length]
      $box[$i] = $i
    }

    for ($j = $i = 0; $i -lt 256; ++$i) {
      $j = ($j + $box[$i] + $key[$i]) % 256
      $tmp = $box[$i]
      $box[$i] = $box[$j]
      $box[$j] = $tmp
    }

    for ($a = $j = $i = 0; $i -lt $data.Length; ++$i) {
      ++$a
      $a %= 256
      $j += $box[$a]
      $j %= 256
      $tmp = $box[$a]
      $box[$a] = $box[$j]
      $box[$j] = $tmp
      $k = $box[(($box[$a] + $box[$j]) % 256)]
      $cipher[$i] = ($data[$i] -bxor $k)
    }

    $decryptedString = [System.Text.Encoding]::Unicode.GetString($cipher)

    return $decryptedString

}


Function Get-ClearObjectText($connectionString, $objectName) {

$getRc4KeyQuery = @"
DECLARE
    @objectid integer = OBJECT_ID(@ObjectName),
    @family_guid binary(16),
    @objid binary(4),
    @subobjid binary(2);
 
-- Find the database family GUID
SELECT @family_guid = CONVERT(binary(16), DRS.family_guid)
FROM sys.database_recovery_status AS DRS
WHERE DRS.database_id = DB_ID();
 
-- Convert object ID to little-endian binary(4)
SET @objid = CONVERT(binary(4), REVERSE(CONVERT(binary(4), @objectid)));
 
SELECT
    -- Read the encrypted value
    @imageval = SOV.imageval,
    -- Get the subobjid and convert to little-endian binary
    @subobjid = CONVERT(binary(2), REVERSE(CONVERT(binary(2), SOV.subobjid)))
FROM sys.sysobjvalues AS SOV
WHERE 
    SOV.[objid] = @objectid
    AND SOV.valclass = 1;
 
-- Compute the RC4 initialization key
SELECT @RC4key = HASHBYTES('SHA1', @family_guid + @objid + @subobjid);
"@

    $connection = New-Object System.Data.SqlClient.SqlConnection($dacConnectionString)
    $connection.Open()
    
    $command = New-Object System.Data.SqlClient.SqlCommand($getRc4KeyQuery, $connection)
    ($command.Parameters.Add("@ObjectName", [System.Data.SqlDbType]::NVarChar, 261)).Value = $objectName
    ($command.Parameters.Add("@imageval", [System.Data.SqlDbType]::VarBinary, -1)).Direction = [System.Data.ParameterDirection]::Output
    ($command.Parameters.Add("@RC4key", [System.Data.SqlDbType]::Binary, 20)).Direction = [System.Data.ParameterDirection]::Output
    [void]$command.ExecuteNonQuery()
    $imageval = $command.Parameters["@imageval"].Value
    $RC4key = $command.Parameters["@RC4key"].Value
    $connection.Close()

    $decryptedString = Get-DecryptedString -pwd $RC4key -data $imageval

    Return $decryptedString


}

# ############
# ### MAIN ###
# ############

# DAC connection string for decryption
$dacConnectionString = "Data Source=admin:YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI"

# normal connection string for encrypted object list
$connectionString = "Data Source=YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI"

# target file path for clear encrypted objects DDL
$scriptFilePath = "C:\Scripts\EncryptedObjects.sql"
[void](New-Item -Path "C:\Scripts\EncryptedObjects.sql" -ItemType file -Force) # create directory (if needed) and empty script file

$EncryptedObjectQuery = @"
SELECT
     QUOTENAME(OBJECT_SCHEMA_NAME(object_id)) + '.' + QUOTENAME(name) AS QualifiedObjectName
FROM sys.objects
WHERE OBJECTPROPERTY(object_id, 'IsEncrypted') = 1;
"@

try {

    $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
    $command = New-Object System.Data.SqlClient.SqlCommand($EncryptedObjectQuery, $connection)
    $connection.Open()

    $reader = $command.ExecuteReader()

    while ($reader.Read()) {

        $createObjectScript = Get-ClearObjectText -connectionString $dacConnectionString -objectName $reader["QualifiedObjectName"]

        $createObjectScript | Out-File -FilePath $scriptFilePath -Append
        "GO" | Out-File -FilePath $scriptFilePath -Append

    }

    $connection.Close()

}
catch {

    throw

}
于 2021-05-25T22:16:54.863 回答