Developing WinDbg ExtEngCpp Extension in C++ – Memory & Debugger Markup Language (DML) – Part 3

In the previous articles, we have seen the basics of the functionalities and architecture of writing a WinDbg ExtEngCpp extension. We are now going move forward with additional functionalities.

Debugger Data Values

A useful function is IDebugDataSpaces::ReadDebuggerData which retrieves data from the KDDEBUGGER_DATA64 structure (nt!KdDebuggerDataBlock).

  1.        if (g_Ext->m_Data->ReadDebuggerData(DEBUG_DATA_KernBase, &Data, sizeof(Data), NULL) == S_OK)
  2.         {
  3.             g_Ext->Dml("ReadDebuggerData(DEBUG_DATA_KernBase) = 0x%I64X\n", Data);
  4.         }

Another alternative is to use ExtNtOsInformation::GetNtDebuggerData() (from exengcpp.cpp) which internally use both g_Ext->m_Data->ReadDebuggerData() and g_Ext->m_Symbols->GetOffsetByName() to query symbols if the first call failed. Here is a good blogpost explaining how to use GetOffsetByName.

Fixed-size values

ExtRemoteData contains a bunch of functions to retrieve small-sized (inferior or equal to sizeof(ULONG64)) data such as GetChar(), GetUchar(), GetBoolean(), GetUshort(), GetUlong(), GetUlong64() or as we have seen previously GetPtr().

The sample below illustrates an example of using GetUlong() against a ExtRemoteData member.

  1. NtHeader32 = (PIMAGE_NT_HEADERS32)((PUCHAR)Header + BaseImage.Field("e_lfanew").GetUlong());
Memory buffer

Another thing you are most likely to do is to read large buffer, or even multiple pages in memory when trying to read an executable for instance. But, as you know, the way executables are mapped in memory is not necessary linear especially because of the different sections. IDebugDataSpaces::ReadVirtual method always you to read linear mapped memory, the example below shows you how to use ReadVirtual to read non-linear memory using the same method.

  1. HRESULT
  2. WINAPI
  3. ReadVirtual(
  4.     IN ULONG64 BaseAddress,
  5.     OUT PVOID Buffer,
  6.     IN ULONG BufferSize,
  7.     OUT PULONG OutBytesRead
  8. )
  9. {
  10.     HRESULT Result;
  11.  
  12.     ULONG Index = 0;
  13.  
  14.     ULONG SumBytesRead = 0;
  15.     ULONG BytesRead = 0;
  16.     ULONG BytesToRead;
  17.  
  18.     RtlZeroMemory(Buffer, BufferSize);
  19.  
  20.     for (Index = 0; SumBytesRead < BufferSize; Index += 1)
  21.     {
  22.         BytesToRead = (BufferSize – (Index * PAGE_SIZE));
  23.         if (BytesToRead > PAGE_SIZE) BytesToRead = PAGE_SIZE;
  24.  
  25.         Result = g_Ext->m_Data->ReadVirtual(BaseAddress + (Index * PAGE_SIZE),
  26.                                             (PUCHAR)Buffer + (Index * PAGE_SIZE),
  27.                                             BytesToRead,
  28.                                             &BytesRead);
  29.         if (Result != S_OK)
  30.         {
  31.             //
  32.             // Check if base address is valid or not.
  33.             //
  34.             if (Index == 0) goto CleanUp;
  35.  
  36.             // g_Ext->Dml("Error: [%d] Can’t read 0x%I64x bytes at %I64x.\n",
  37.             //     Index, BytesToRead, BaseAddress + (Index * PAGE_SIZE));
  38.             // goto CleanUp;
  39.         }
  40.  
  41.         SumBytesRead += BytesToRead ;
  42.     }
  43.  
  44. CleanUp:
  45.     if (SumBytesRead == BufferSize) Result = S_OK;
  46.  
  47.     *OutBytesRead = SumBytesRead;
  48.  
  49.     return Result;
  50. }
Debugger Markup Language (DML)

WinDbg has its own markup language, the two most interesting tags are that you can create links to other commands using “link” tag, but also use colors with the help of “col” tag. Unfortunately, you can’t use custom colors but only predefined colors for the debugger.

The colors can be defined as the following: <col fg=”name” bg=”name”/></col>. DML can also be used in script using the .printf /D command, which can also be a fast way to try different colors.
Here is the list of the current color names (defaults only apply to windbg):

  • wbg and wfg – Default window background and foreground colors. Default to system colors for window and window text.
  • clbg and clfg – Current line background and foreground colors. Default to system colors for highlight and highlight text.
  • changed – Used for data that has changed since a previous stop point, such as changed registers in windbg. Defaults to red.
  • srcnum, srcchar, srcstr, srcid, srckw, srcpair, srccmnt, srcdrct, srcspid, srcannot – Source element colors. Defaults can be seen in windbg.
  • empbg and emphfg – Emphasized text. Defaults to light blue.
  • subbg and subfg – Subdued text. Default to system color for inactive caption text and inactive captions.
  • normbg, normfg, warnbg, warnfg, errbg, errfg, verbbg, verbfg – Output level colors. Defaults can be seen in windbg.

In the example below we are using the colors “changed” and “emphfg” to emphasized keywords before printing details of each process.

  1.        Dml("\n<col fg=\"changed\"/>Process: <link cmd=\"!process %p 1\"/>%s (PID=0x%x)\n",
  2.             ProcObj.m_CcProcessObject.ProcessObjectPtr, ProcObj.m_CcProcessObject.ImageFileName, ProcObj.m_CcProcessObject.ProcessId);
  3.         if (wcslen(ProcObj.m_CcProcessObject.FullPath)) Dml("<col fg=\"emphfg\"/>Path: %S\n", ProcObj.m_CcProcessObject.FullPath);
  4.         if (wcslen(ProcObj.m_CcProcessObject.CompanyName)) Dml("<col fg=\"emphfg\"/>Vendor: %S\n", ProcObj.m_CcProcessObject.CompanyName);
  5.         if (wcslen(ProcObj.m_CcProcessObject.FileVersion)) Dml("<col fg=\"emphfg\"/>Version: %S\n", ProcObj.m_CcProcessObject.FileVersion);
  6.         if (wcslen(ProcObj.m_CcProcessObject.FileDescription)) Dml("<col fg=\"emphfg\"/>Description: %S\n", ProcObj.m_CcProcessObject.FileDescription);

The code above give us the following output. As you can see, it’s much clearer and nicer for the eyes.
sample-windbg

Related articles:

- Developing WinDbg ExtEngCpp Extension in C++ – Introduction – Part 1
- Developing WinDbg ExtEngCpp Extension in C++ – COM Interface – Part 2
- Developing WinDbg ExtEngCpp Extension in C++ – Memory & Debugger Markup Language (DML) – Part 3
- Developing WinDbg ExtEngCpp Extension in C++ – Symbols – Part 4

2 thoughts on “Developing WinDbg ExtEngCpp Extension in C++ – Memory & Debugger Markup Language (DML) – Part 3

Comments are closed.