1: Background
1. Tell a story
A few days ago, when debugging a bug on the IOT cabinet terminal, I found that the database connection string in app.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 in app.config. It's annoying. 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 a gentleman to prevent such trouble, like me Xiaoren, whether you add encryption or not is equal to no encryption. I'll take you off the database anyway... 😄😄😄
2: Use ILSpy to take off the library
1. Decompile code from DAL/Repository layer
To get the plaintext database connection string, you can deduce it from the code, such as from DAL perhaps Repository Connection string field not found in ConnectionString, the terminal program on my side is written in wpf and adopts the classic three-tier architecture, so bin It can be easily found in the following figure:
Next use ILSPy Decompile this dll.
As can be seen from the above figure, the plaintext of the connection string is stored in: OleDbHelper.ConnectionString Then you can see that one is defined in the program Decrypt This method is specially used to decrypt the connection string. Ha ha, with this algorithm, can we get rid of the database??? 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. Shell / confuse / encrypt dog
Both the commercial version and the free version on the market now provide C# code encryption and confusion, but I haven't used it. I think it's only a matter of time. After all, you can't confuse the FCL classes such as SqlConnection and SqlCommand, I can easily find the plaintext ConnectionString by extrapolating from these classes, so I think this road is impassable.
3. Put the decryption algorithm on the server side
since Decryption algorithm You can dig it out on the client, so 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 In this 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 database
1. Ideas
To dig out OleDbHelper.ConnectionString is also very simple. In CLR via C# In the fourth chapter, there is such a picture about object types and the interpretation of type objects, which is very classic.
As can be seen from the above figure, the static field is in the Manager type object In, instance fields are in Manager object In this figure, I just need to find it through windbg OleDbHelper type object, 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
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
above Class: 08ecab30 Is the memory address of the OleDbHelper type object on the heap.
-
use! dumpclass export Class: 08ecab30 , To find the static field of the 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 exported information above, 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, huh? 🐂 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? 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! 😄😄😄