That’s so Swish !

SwishDbgExt is a Microsoft WinDbg debugging extension that expands the set of available commands by Microsoft WinDbg, but also fixes and improves existing commands.


This extension has been developed by Matt Suiche (@msuiche) – feel free to reach out on Twitter (even better, on the mailing list) to ask for more features, offer to contribute and/or report bugs.

Mailing-List:!forum/dfir-list or

SwishDbgExt aims at making life easier for kernel developers, troubleshooters and security experts with a series of debugging, incident response and memory forensics commands.

Because SwishDbgExt is a WinDbg debugging extension, it means it can be used on local or remote kernel debugging session, live sessions generated by Microsoft LiveKd, but also on Microsoft crash dumps generated to a Blue Screen of Death or hybrid utilities such as MoonSols DumpIt.



I personally don’t have enough time to proceed to a full in-depth testing of all the commands on every of Windows, that’s is why I would like to thank few people who assisted me during with the testing of the private beta and their contributions. Now that the extension is public, I’m sure more bugs will be found – and as said above, feedback are highly appreciated and the mailing list is the most efficient way to share it :-)

Thanks to Frank Boldewin for his feedback and sharing his shellcode scanning techniques (!ms_malscore).

Thanks to Benjamin Delpy for his feedback and writing mimikatz (!ms_credentials).


Current version is: v0.5.20140716 (16 July 2014)

La French Tech : Cyber-Security – Where is the money ?

Most of you probably already know the Cyber Fast Track (CFT) program from DARPA, formely led by Peiter Zatko (congrats again!), that provides fast access to grants to U.S. cyber security researchers.

In July 2013, France tried to launch a similar project (but obviously applications are more complex and bureaucratic) called “Investissements d’avenir pour la securite numerique”, the official press release can be found here.

The initiative had been launched by the ministers Arnaud Montebourg, Fleur Pellerin, and Louis Gallois, former CEO of Airbus (ex-EADS), as Commissaire général à l’investissement for the “Grand Emprunt“. Grand Emprunt is a 35 billions loan issued by France in 2010 as part of its innovation strategy to stimulate R&D in different fields. Unfortunately, the coordinator of the projects were not communicated.

July 2013′s press release announced a EUR 150 millions (USD 200M+ USD) fund, for cyber security projects. I have always been curious to know, who was the commission and jury in charge of reviewing the submissions, and when will the list of accepted contestants and projects be published. The cyber-security call-for-projects closed on the 29th November 2013. So I assume something must have happened since then.

I know a lot of potential candidates didn’t submit anything because they were afraid the funds would go to multi-billions dollars French defense companies, so I offered to check by myself on their behalf. Therefore, I tried to contact individuals and generic contact information available at for the above information, but I unfortunately never got I answer back.

Nonetheless, I thought it was a great initiative that was poorly communicated, I was myself very impressed and glad to see that the French government was supporting sovereign projects related to cyber-security.

Has any contestants, journalists or member of the “French Tech” heard of anything ?

Hives & Trust issues

Some of you may have ever used RtlQueryRegistryValues, and probably wondered what Microsoft meant by saying:

Starting with Windows 8, if an RtlQueryRegistryValues call accesses an untrusted hive, and the caller sets the RTL_QUERY_REGISTRY_DIRECT flag for this call, the caller must additionally set the RTL_QUERY_REGISTRY_TYPECHECK flag.

A hive is marked as untrusted using the 0×1 flag in CMHIVE.Flags. This applies to any hives loaded using ZwLoadKey() such as third party hives, and as you can see below all USER hives and the Boot Configuration Data (BCD).


This can be an easy & quick way to recognize non-system hives. Moreover, another thing that people tend to forget is the presence of a hive specific function table within the HHIVE data structure. This function table has slightly changed between Windows 7 and Windows 8.

The 2 functions marked in the following data structure snippet, ReleaseCellRoutine(), FileSetSize() and FileFlush() have been removed from Windows 8 data structure.

  1. kd> dt nt!_HHIVE
  2.    +0×000 Signature        : Uint4B
  3.    +0×004 GetCellRoutine   : Ptr32     _CELL_DATA*
  4.    +0×008 ReleaseCellRoutine : Ptr32     void // Removed in Windows 8
  5.    +0x00c Allocate         : Ptr32     void*
  6.    +0×010 Free             : Ptr32     void
  7.    +0×014 FileSetSize      : Ptr32     unsigned char // Removed in Windows 8
  8.    +0×018 FileWrite        : Ptr32     unsigned char
  9.    +0x01c FileRead         : Ptr32     unsigned char
  10.    +0×020 FileFlush        : Ptr32     unsigned char // Removed in Windows 8
  11.    +0×024 HiveLoadFailure  : Ptr32 Void
  12.    +0×028 BaseBlock        : Ptr32 _HBASE_BLOCK
  13.    +0x02c DirtyVector      : _RTL_BITMAP

Checking the integrity of this function table, is an important step to prevent from threats that are avoiding to call CmRegisterCallbackEx() to register their registry callback functions.


Developing WinDbg ExtEngCpp Extension in C++ – Symbols – Part 4

As part of my previous series of articles on developping WinDbg ExtEngCpp extension, I will cover through two examples how to use symbols efficiently while writing your extension.

In the past, I tried several times to report issues (e.g. “!reg subkeylist”), but I never had a response from the WinDbg team. Same thing when I attempted to reach them for some questions related to the WinDbg SDK, which is the reason I assume there is no team (retired ?) anymore at Microsoft to maintain WinDbg and decided to convert my frustration in my own extension replacing most of the broken or improvable functions from WinDbg as you can at the end of the article. If anyone is interested in beta-testing my extension, contact me over email.


You can find below an example of using ExtRemoteTyped. The function below computes the cellindex using the benefit ExtRemoteTyped format and functions.

  2. EXT_COMMAND(ms_cellindex,
  3.     "Compute cell index",
  4.     "{;ed;hive;Key hive}{;ed;index;Cell index}")
  5. {
  6.     ULONG64 KeyHiveAddr = GetUnnamedArgU64(0);
  7.     ULONG CellIndex = (ULONG)GetUnnamedArgU64(1);
  9.     ExtRemoteTyped KeyHive("(nt!_HHIVE *)@$extin", KeyHiveAddr);
  10.     ULONG64 CellAddr = RegGetCellPaged(KeyHive, CellIndex);
  11. ()
  12. }
  14. ULONG64
  15. RegGetCellPaged(
  16.     ExtRemoteTyped KeyHive,
  17.     ULONG CellIndex
  18. )
  19. {
  20.     ULONG Type, Table, Block, Offset;
  21.     ULONG64 CellAddr;
  23.     Type = ((ULONG)((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT));
  24.     Table = (ULONG)((CellIndex & HCELL_TABLE_MASK) >> HCELL_TABLE_SHIFT);
  25.     Block = (ULONG)((CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT);
  26.     Offset = (ULONG)(CellIndex & HCELL_OFFSET_MASK);
  28.     // g_Ext->Dml("Hive: %I64X, CellIndex = %x, Type = %x, Table = %x, Block = %x, Offset = %x\n",
  29.     //    KeyHive.GetPtr(), CellIndex, Type, Table, Block, Offset);
  31.     ExtRemoteTyped DirMap = KeyHive.Field("Storage").ArrayElement(Type).Field("Map");
  32.     ExtRemoteTyped MapTable = DirMap.Field("Directory").ArrayElement(Table);
  33.     CellAddr = MapTable.Field("Table").ArrayElement(Block).Field("BlockAddress").GetPtr();
  35.     CellAddr += Offset;
  36.     if (KeyHive.Field("Version").GetUlong() == 1) CellAddr += sizeof(LONG)+sizeof(ULONG);
  37.     else CellAddr += sizeof(LONG);
  39.     return CellAddr;
  40. }


There are two functions that can be used for symbols name resolution, GetOffsetByName() and GetNameByOffset()

  1.     if (g_Ext->m_Symbols->GetOffsetByName("nt!KeServiceDescriptorTable", &KeServiceDescriptorTable) != S_OK) goto Exit;
  2.     if (g_Ext->m_Symbols->GetOffsetByName("nt!KiServiceLimit", &KiServiceLimit) != S_OK) goto Exit;
  3.     if (g_Ext->m_Data->ReadPointersVirtual(1, KeServiceDescriptorTable, &ServiceTableBase) != S_OK) goto Exit;
  4.     if (g_Ext->m_Data->ReadVirtual(KiServiceLimit, &Limit, sizeof(ULONG), NULL) != S_OK) goto Exit;
  5. ()
  6.         g_Ext->m_Symbols->GetNameByOffset(SIGN_EXTEND(Address), (PSTR)Name, _countof(Name), NULL, NULL);
  8.         Dml("[%3d] 0x%I64X %-64s (Hooked: %3s) (Inline: %3s)\n",
  9.             Entry.Index, Entry.Address, Name,
  10.             Entry.PatchedEntry ? "Yes" : "No", Entry.InlineHooking ? "Yes" : "No");



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