1: Background
1. Tell a story
A bug was found on the app.com cabinet a few days before debugging The database connection string in config is encrypted. To switch the database during debugging, I need to decrypt the ciphertext on a special gadget. After changing the database name on the connection string, I have to encrypt and paste it to app In config, I'm bored to death. The contents are as follows:
<appSettings> <!-- Database connection string --> <add key="OLEDBConnStr" value="XfES27am6Muw48iB1GlMVqvUbq7/Pp9n4XbZJsDu19YDr/Zdb3m7KT6haD7f9HLj/ZEvIiZbmSU4O5L9g03Y5IUB6KLCZI7s3nDLwTIC+bXLf5quu/r8ZAI+rgNnsNZdwoDfquRLQy5Cf2X8/MFDOcMNaZYMpTYeHsZoEERU/TP9t3n5QllJTihrmDFbiGHLqe1kfN3uB3g1kgs0oobIEfNPr09kQ/pFgzZi/kZCrK10PLZZ0pFj1YU5ReFqBsdBlecV3D2Zl3lx1Ibls24t7w==" /> </appSettings>
After fixing the bug, I thought this thing could be prevented. Who? I think it's just a gentleman to prevent such trouble. For a knowledgeable person like me, adding or not encrypting is equal to not encrypting, so I'll take you out of the database... 😄😄😄
2: Use ILSpy to take off the library
1. Decompile code from DAL/Repository layer
To get the database connection string in plaintext, you can deduce it from the code. For example, you can find the connection string field ConnectionString from DAL or Repository. My terminal program is written in wpf and adopts the classic three-tier architecture, so it can be easily found under bin, as shown in the following figure:
Next, decompile the dll with ILSPy.
As can be seen from the above figure, the plaintext of the connection string is stored in: oledbhelper In connectionstring, then you can see that a Decrypt method is defined in the program to Decrypt the connection string. Ha ha, with this algorithm, can we get rid of the library??? The following code is shown:
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 ""; } }
However, fortunately, the database is also deployed independently on the customer's side. There is no external network, otherwise it will play a big game... Next, let's see how to prevent it.
2. Shelling / confusion / dongle
Now both commercial and free versions on the market provide C# code encryption and confusion, but I haven't used it. I think it's only a matter of time to add some obstacles to the readability after decompilating the code. After all, SqlConnection and SqlCommand FCL classes can't be confused. I can easily find plaintext ConnectionString from these classes, So I think this road is impassable.
3. Put the decryption algorithm on the server side
Since the decryption algorithm is buried in the client, you can dig it out. Can't you just put it on the server? When the program starts, call webapi to decrypt, so you have no choice??? Ha ha, you can use your brain to think about whether this method is feasible or not? It is true that the decryption algorithm has been removed, and it is meaningless to dig with ILSpy, but there is an important breakthrough here. No matter what form of decryption is used, the final connection string plaintext is stored in oledbhelper Connectionstring is a static variable, right! The next question is whether there is a way to dig out this static variable in the process? You're right. Grab the dump file of the program and dig it with windbg.
3: Use windbg to remove the library
1. Ideas
To dig out oledbhelper Connectionstring, in fact, is also very simple. In the fourth chapter of CLR via C# the interpretation of object types and type objects has such a picture, which is very classic.
As can be seen from the above figure, the static fields are in the Manager type object and the instance fields are in the Manager object. Compared with this figure, I only need to find the OleDbHelper type object through windbg, that is, the so-called EEClass.
2. windbg mining practice
- use! name2ee found Decrypt method descriptor (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
The above MethodDesc: 08ed83b0 is the address of the method descriptor.
- use! dumpmd exports the details of the method descriptor and finds the EEClass address of the OleDbHelper type object
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
The above class: 08ecab30 is the memory address of the OleDbHelper type object on the heap.
- use! dumpclass exports Class: 08ecab30 to find the static field of OleDbHelper class
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
From the above exported information, you can see that there are two static fields in the OleDbHelper class: ConnectionString and SecurityConnectionString.
- use! do prints out two static fields
See, the two purple boxes in the figure above are plaintext ConnectionString. Ha, how about it? 🐂 no 🐂.
4: Summary
When you realize the above two ways to remove the database, you should be able to think that in fact, it is a mistake for you to connect the database in the program. The operating system can pirate for you, not to mention your little software? Personally, I think the way to completely eliminate it should be to destroy the local SQL server and make all data acquisition provided by the remote webapi. Of course, this is divorced from business chat technology! 😄😄😄