A: background

1. Tell a story

Wx on the day before yesterday a friend gave me a dump, let me help me to identify the sensitive information in memory is also encrypted, data security is very important now, not only the information in the database encryption, data is also required after pouring into memory ciphertext storage, along with it, strive for the maximum safety 😄, this as the background, the next is I acutely, How am I supposed to judge that? 😂 😂 😂

Two: how to identify

1. Think about

After a few seconds, I calm down and think there is a certain solution. Let me simplify the problem.

  • Check if there are any plaintext characters in memory with strings of three, four, or five.

  • Check whether the md5 in plaintext exists in the memory.

A search of the above two points will almost certainly determine whether sensitive information is encrypted.

A managed language like C# has the advantage that all managed objects are stored on the managed heap, which means strings are also on the managed heap, so the next problem is how to retrieve strings on the heap for string= 3.

The problem comes, many times the managed heap of string is massive, I have seen up to tens of millions of string boundless, when can I find my most beautiful baby 😤😤😤, the end of the theoretical time, the next start to fight monsters.

2. Case demonstration

To keep the conversation going, let me use a simple example to show you how to search for string= Joe with human flesh. Look at the code first.


    class Program
    {
        static List<string> strList = new List<string> ();static void Main(string[] args)
        {
            strList.Add("fake");
            strList.Add("Zhang"); Console.ReadLine(); }}Copy the code

Next comes Windbg.

  • with! dumpheap -type System.String -min 8 -max 15Find all the10-15byteA string of ranges.

0:000> !dumpheap  -type System.String -min 8 -max 15
 Address       MT     Size
026f1228 652224e4       14     
026f164c 652224e4       16     
026f230c 65222d74       12. Statistics: MT Count TotalSize Class Name65225468        1           12 System.Collections.Generic.GenericEqualityComparer`1[[System.String, mscorlib]]
65222d74       10          156 System.String[]
652224e4       65         1168 System.String
Total 76 objects

Copy the code

From the output, we can see that there are 1168 strings in the current size range. We also find that this size is not particularly accurate. Let alone, although there are a lot of strings, it can still be human. Do XXX Check one by one.


0:000>!do 026f2354
Name:        System.String
MethodTable: 652224e4
EEClass:     65327690
Size:        18(0x12) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4. 0_4. 0. 0. 0__b77a5C561934e089 \mscorlib. DLL String: d3fields: MT Field Offset Type VT Attr Value Name652242a8  4000283        4         System.Int32  1 instance        2 m_stringLength
65222c9c  4000284        8          System.Char  1 instance     5f20 m_firstChar
652224e4  4000288       70        System.String  0   shared   static Empty
    >> Domain:Value  00a22530:NotInit  <<

Copy the code

See, the above String: zhang SAN is the result I want, plaintext store real hammer.

🙃🙃🙃, that is too no actual combat experience, just said, many times after the screening of string may be as high as tens of thousands of thousands, and then human flesh that is impossible…

Is there a script to replace human flesh? 😜😜😜, heh heh, there really is…

Three: Use automated scripts

Windbg Preview now supports Javacript as a script extension. Next, I’m going to write the human steps into a script, which looks like a professional name called Playbook.


"use strict";

function RunCommands() {

    var ctl = host.namespace.Debugger.Utility.Control;
    var str_address_list = ctl.ExecuteCommand(! "" dumpheap -type System.String -min 8 -max 15 -short");

    for (var str_address of str_address_list) {

        var str_dump = ctl.ExecuteCommand(! "" do -nofields " + str_address);

        var str = str_dump.Last();

        var isContains = str.indexOf("Zhang") > 0;

        if(isContains) host.diagnostics.debugLog(str+""+str_address +"\n"); }}Copy the code

If there is a string, print it with the address address. Once the script is saved, run the RunCommands() function with dx.


0:000> dx Debugger. State. Scripts. RunCommands. Contents. RunCommands (String) : zhang SAN026f2354
Debugger.State.Scripts.RunCommands.Contents.RunCommands()

Copy the code

See, the clear text is shown in three, if you don’t believe me, I cut a picture, to prove that I did not cheat you 🤭🤭🤭.

Four:

In this case the final use of JS script easy to fix, it can be seen that the script gave WinDBG unlimited mining possibilities, really is too powerful, interested words can refer to MSDN: docs.microsoft.com/en-us/windo…