Sql-Server

如何解密 MSSQL 表中的壓縮數據

  • May 1, 2022

我們正在嘗試從其他人的 MS SQL 數據庫導入(逆向工程)一些數據,而沒有任何供應商支持。

過去,數據以純文字或 RTF 格式儲存,因此很容易提取。但是這個數據庫有一些看起來“加密”的內容。如果數據採用這種格式,則還有另一列“zipped”= 1。我被告知他們正在壓縮數據以保持在 SQL Express 的 10GB 限制之下。

它看起來有點像這樣:

-Ëj„@D÷
þC}€7!2‹<Pɾí¾êÍôCn·ÿ~¦6UÅ©–F

關於如何解碼的任何想法?同一個表中還有其他行是純文字或 RTF,但很多都是這種格式。

這是數據庫的範例導出:

https://1drv.ms/u/s!Au6oldAhXo2M5Xt_bE9Q5iA0WdfF?e=IsuYdQ

其中包括它應該是什麼樣子的螢幕截圖。

數據未加密;它只是使用Deflate壓縮的,這在 TSQL 中不直接可用。TSQL COMPRESS使用 Gzip,它是類似的,但不嚴格兼容。所以在 C# 中是這樣的:

using System.Data.SqlClient;
using System.IO;
using System.IO.Compression;

using var con = new SqlConnection("server=.;database=spmcopy;integrated security=true;multipleactiveresultsets=true");
con.Open();

var cmd = new SqlCommand("select counter, cast(cast([text] as varchar(max)) as varbinary(max)) ZippedText from notescopy where Zipped=1 ", con);
var cmdWrite = new SqlCommand("update notescopy set [text] = cast(cast(@t as varchar(max)) as text), Zipped = 0 where counter = @c",con);
var ptext = cmdWrite.Parameters.Add(new SqlParameter("@t", System.Data.SqlDbType.VarBinary, -1));
var pCounter = cmdWrite.Parameters.Add(new SqlParameter("@c", System.Data.SqlDbType.Int));

using var reader = cmd.ExecuteReader();

while (reader.Read())
{
   pCounter.Value = reader.GetInt32(0);
   var compressedStream = reader.GetStream(1);

   var dest = new MemoryStream();
   var decompressedStream = new DeflateStream(compressedStream, CompressionMode.Decompress);
   decompressedStream.CopyTo(dest);
   dest.Position = 0;
   ptext.Value = dest.ToArray();

   cmdWrite.ExecuteNonQuery();
}

此外,看起來您可以在 Deflate 流中添加一個標準的 10 字節標頭以使其與 GZip 兼容,所以

select cast(decompress(cast(0x1F8B0800000000000400 as varbinary(max)) + cast(cast([text] as varchar(max)) as varbinary(max))) as varchar(max)) d
from notescopy

看起來 DECOMPRESS 會忽略 CRC32 和 ISIZE 尾欄位(如果它們不存在),這是合規的,但不是強制性的解壓縮器行為。

引用自:https://dba.stackexchange.com/questions/311495