配置文件中的數據庫鏈接串加密了,你覺得我就挖不出來嗎?

一:背景

1. 講故事

前幾天在調試物聯櫃終端上的一個bug時發現 app.config 中的數據庫鏈接串是加密的,由於調試中要切換數據庫,我須要將密文放到專門的小工具上解密,改完鏈接串上的數據庫名,還得再加密貼到 app.config 中,煩的要死,內容以下:web

<appSettings>
    <!-- 數據庫鏈接字符串 -->
    <add key="OLEDBConnStr" value="XfES27am6Muw48iB1GlMVqvUbq7/Pp9n4XbZJsDu19YDr/Zdb3m7KT6haD7f9HLj/ZEvIiZbmSU4O5L9g03Y5IUB6KLCZI7s3nDLwTIC+bXLf5quu/r8ZAI+rgNnsNZdwoDfquRLQy5Cf2X8/MFDOcMNaZYMpTYeHsZoEERU/TP9t3n5QllJTihrmDFbiGHLqe1kfN3uB3g1kgs0oobIEfNPr09kQ/pFgzZi/kZCrK10PLZZ0pFj1YU5ReFqBsdBlecV3D2Zl3lx1Ibls24t7w==" />
  </appSettings>

改完bug以後,我就想這玩意能防的了誰呢? 私覺得搞這麼麻煩也就防防君子,像我這樣的 曉人,加不加密都是等於沒加密,照樣給你脫庫。。。😄😄😄算法

二:使用 ILSpy 去脫庫

1. 從DAL/Repository層去反編譯代碼

要想獲得明文的數據庫鏈接串,能夠從代碼中反推,好比從 DAL 或者 Repository 中找鏈接串字段 ConnectionString,我這邊的終端程序是用 wpf 寫的,採用的是經典的三層架構,因此在 bin 下能夠輕鬆找到,以下圖:sql

接下來用 ILSPy 反編譯這個 dll。數據庫

從上圖中能夠看出,鏈接串的明文是存放在: OleDbHelper.ConnectionString 中的,而後能夠看到,程序中定義了一個 Decrypt 方法專門用來解密鏈接串,哈哈,有了這個算法,是否是就能夠脫庫啦??? 以下代碼所示:api

class Program
    {
        static void Main(string[] args)
        {
            var str = "XfES27am6Muw48iB1GlMVqvUbq7/Pp9n4XbZJsDu19YDr/Zdb3m7KT6haD7f9HLj/ZEvIiZbmSU4O5L9g03Y5IUB6KLCZI7s3nDLwTIC+bXLf5quu/r8ZAI+rgNnsNZdwoDfquRLQy5Cf2X8/MFDOcMNaZYMpTYeHsZoEERU/TP9t3n5QllJTihrmDFbiGHLqe1kfN3uB3g1kgs0oobIEfNPr09kQ/pFgzZi/kZCrK10PLZZ0pFj1YU5ReFqBsdBlecV3D2Zl3lx1Ibls24t7w==";
            
            Console.WriteLine(Decrypt(str));
        }

        public static string Decrypt(string str)
        {
            if (!string.IsNullOrEmpty(str))
            {
                DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();
                byte[] key = Encoding.Unicode.GetBytes("Oyea");
                byte[] data = Convert.FromBase64String(str);
                MemoryStream MStream = new MemoryStream();
                CryptoStream CStream = new CryptoStream(MStream, descsp.CreateDecryptor(key, key), CryptoStreamMode.Write);
                CStream.Write(data, 0, data.Length);
                CStream.FlushFinalBlock();
                return Encoding.Unicode.GetString(MStream.ToArray());
            }
            return "";
        }
    }

不過還好,數據庫也是在客戶那邊獨立部署的,不存在走外網的狀況,否則就玩大了。。。 接下來咱們來看看如何去防範。架構

2. 加殼/混淆/加密狗

如今市面上商業版和免費版都提供了給C#代碼進行加密和混淆,不過我沒用過,我想最多在反編譯代碼後閱讀性上增長了一些障礙,這也不過是時間問題罷了,畢竟SqlConnection,SqlCommand 這些FCL的類你是無法混淆的,我從這些類上反推能夠很輕鬆的就能找到明文的 ConnectionString ,因此這條路我以爲是走不通的。app

3. 將解密算法放在 server 端

既然 解密算法 埋在客戶端你都能挖出來,那把它放在 server 端不就能夠啦? 在程序啓動的時候,調用一下 webapi 進行解密,這樣你總沒轍了吧 ??? 哈哈,你們能夠開動腦子想想,這種方法可行不可行?誠然,解密算法搬走了,再用 ILSpy 去挖已經沒有任何意義了,但這裏有一個重要突破點,無論是用什麼形式解密的,最後的鏈接串明文都是存放在 OleDbHelper.ConnectionString 這個靜態變量中,對吧!接下來的問題就是有沒有辦法把進程中的這個靜態變量給挖出來? 你說的對,就是抓程序的 dump文件 用 windbg 去挖。ide

三:使用 windbg 去脫庫

1. 思路

要想挖出 OleDbHelper.ConnectionString,其實也很簡單,在 CLR via C# 第四章中關於對象類型和類型對象的解讀有這麼一張圖,很經典。工具

從上圖中能夠看到,靜態字段是在 Manager 類型對象 中,實例字段都是在 Manager 對象 中,對照這張圖,我只須要經過 windbg 找到 OleDbHelper 類型對象,也就是所謂的 EEClasssqlserver

2. windbg 挖礦實戰

  • 使用 !name2ee 找到 Decrypt 方法描述符(MethodDesc)
0:000>  !name2ee xxx.Utilities.dll xxx.Utilities.Database.OleDbHelper.Decrypt
Module:      08ed7cdc
Assembly:    xxx.Utilities.dll
Token:       060002aa
MethodDesc:  08ed83b0
Name:        xxx.Utilities.Database.OleDbHelper.Decrypt(System.String)
JITTED Code Address: 048b6af0

上面的 MethodDesc: 08ed83b0 就是方法描述符的地址。

  • 使用 !dumpmd 導出方法描述符的詳細信息,找到 OleDbHelper類型對象 的 EEClass 地址
0:000> !dumpmd 08ed83b0
Method Name:  xxx.Utilities.Database.OleDbHelper.Decrypt(System.String)
Class:        08ecab30
MethodTable:  08ed8468
mdToken:      060002aa
Module:       08ed7cdc
IsJitted:     yes
CodeAddr:     048b6af0
Transparency: Critical

上面的 Class: 08ecab30 就是 OleDbHelper類型對象 在堆上的內存地址。

  • 使用 !dumpclass 導出 Class: 08ecab30 ,從而找到 OleDbHelper類的靜態字段
0:000> !dumpclass 08ecab30
Class Name:      xxx.Utilities.Database.OleDbHelper
mdToken:         02000033
File:            D:\code\A18001\Source\Main\TunnelClient\bin\Debug\xxx.Utilities.dll
Parent Class:    795115b0
Module:          08ed7cdc
Method Table:    08ed8468
Vtable Slots:    4
Total Method Slots:  6
Class Attributes:    100081  Abstract, 
Transparency:        Critical
NumInstanceFields:   0
NumStaticFields:     2
      MT    Field   Offset                 Type VT     Attr    Value Name
799bfd60  4000152       74        System.String  0   static 04c28270 ConnectionString
799bfd60  4000153       78        System.String  0   static 04c299e8 SecurityConnectionString

從上面導出信息中能夠看到 OleDbHelper類中 有兩個靜態字段: ConnectionStringSecurityConnectionString

  • 使用 !do 打印出兩個靜態字段

看到沒有,上圖中的兩個紫色框框就是明文的 ConnectionString 哈,怎麼樣? 🐂不🐂。

四: 總結

當認識到上面的兩種脫庫方式,你應該就能想到,其實你在程序中鏈接數據庫,這自己就是一種錯,操做系統都能給你盜版,況且你這區區一個小軟件? 我的以爲徹底杜絕的方式那應該就是:滅掉本地的sqlserver,讓全部的數據獲取都由遠端的 webapi 提供,固然這又是在脫離業務聊技術啦!😄😄😄

如您有更多問題與我互動,掃描下方進來吧~

圖片名稱
相關文章
相關標籤/搜索