Generating IDA Type Information Libraries from Windows Type Libraries
When working with IDA, a commonly leveraged feature are type information libraries (TIL).
These libraries contain high-level type information such as function prototypes, type definitions, standard structures or enums; enabling IDA to convert statements such as movsxd rbx, dword ptr [r12+3Ch]
into, for example, the more human-readable counterpart movsxd rbx, [r12+IMAGE_DOS_HEADER.e_lfanew]
.
On Windows, a similar concept called type libraries (TLB) exists to describe COM (Component Object Model) objects. In a nutshell, COM provides a language-independent interface to objects, abstracting how they have been implemented themselves.
In this quick-post, we’ll explore how to convert Windows type libraries (TLB) into IDA type information libraries (TIL).
In particular, we’ll generate the necessary type information library to analyze .NET injection into unmanaged processes using mscoree.dll
and mscorlib.dll
(e.g., through _AppDomain
).
In a hurry? Grab the .NET type information library directly!
Abstract
Achieving TLB-to-TIL conversion can be done through an intermediary C++ conversion:
- First, the MSVC (Microsoft Visual C++) compiler can be leveraged to convert TLBs into their respective C++ header files.
- Once the C++ header files generated, IDAClang can be used to convert these into TILs.
Requirements
To achieve TLB-to-TIL conversion, this article requires the following tools:
- The MSVC (Microsoft Visual C++) compiler installed through Visual Studio*.
- The IDAClang command-line utility.
* For our example, we’ll be generating a type information library targeting the .NET Framework, hence also requiring header files part of the .NET Framework Developer Pack (a.k.a. SDK). The .NET Framework Developer Pack can be installed through Visual Studio.
Given both MSVC and IDAClang rely on a properly configured developer environment (e.g., a configured INCLUDE
environment variable), this article assumes all commands are issued within a Visual Studio Developer Command Prompt such as the “x64 Native Tools Command Prompt”.
Converting Microsoft Type Libraries to C++ Headers
Windows type libraries are a Windows-specific feature which integrates seamlessly with the MSVC compiler through the #import
statement.
#import
creates two header files that reconstruct the type library contents in C++ source code. The primary header file is similar to the one produced by the Microsoft Interface Definition Language (MIDL) compiler, but with additional compiler-generated code and data. The primary header file has the same base name as the type library, plus a.TLH
extension.Source: learn.microsoft.com
As such, creating a C++ file to import a type library will generate its C++ header.
Given we wish to convert mscorlib.tlb
into C++ headers, we can create the following C++ file named, for example, til.cpp
.
#import "mscorlib.tlb" raw_interfaces_only auto_rename
Once the C++ file has been created, we can rely on the MSVC compiler to generate the necessary headers.
The beneath command will generate the mscorlib.tlh
file.
CL.exe /c /D NDEBUG /D _CONSOLE /D _UNICODE /D UNICODE /permissive- /TP til.cpp
Converting C++ Headers to IDA Type Information Libraries
With the C++ headers generated, we can now proceed to create the IDA type information library.
To do so, we can create a new C++ header file that will reference any standard headers (e.g., those from the .NET Framework Developer Pack) and generated headers (i.e., the previously generated mscorlib.tlh
) we wish to use in IDA.
The following is our example til.h
.
// Include standard headers
// Example: Microsoft .NET Framework Developer Pack
#include <alink.h>
#include <clrdata.h>
#include <cordebug.h>
#include <corhlpr.h>
#include <corprof.h>
#include <corpub.h>
#include <corsym.h>
#include <fusion.h>
#include <gchost.h>
#include <ICeeFileGen.h>
#include <isolation.h>
#include <ivalidator.h>
#include <ivehandler.h>
#include <metahost.h>
#include <mscoree.h>
#include <openum.h>
#include <StrongName.h>
#include <tlbref.h>
#include <VerError.h>
// Include generated headers
// Example: Microsoft Common Language Runtime Class Library
// The mscorlib.h generated from mscorlib.tlb
#include "mscorlib.tlh"
Once the C++ header file created, we can rely on IDAClang to generate the TIL.
idaclang.exe -x c++ -target x86_64-pc-windows -ferror-limit=0 --idaclang-tildesc "Example" --idaclang-tilname "example.til" til.h
MSVC and Clang (used in IDAClang) are two different C++ compilers. While they can mostly agree, compiling MSVC-generated C++ code using Clang is bound to generate non-fatal errors. While IDAClang may generate quite some errors as shown below, the TIL conversion should succeed after a moment.
IDACLANG: nonfatal: ./mscorlib.tlh:10774:1: error: enumeration previously declared with fixed underlying type
IDACLANG: nonfatal: ./mscorlib.tlh:11509:64: error: expected ';' after struct
IDACLANG: nonfatal: ./mscorlib.tlh:11509:1: error: declaration of anonymous struct must be a definition
IDACLANG: nonfatal: ./mscorlib.tlh:11510:11: error: expected unqualified-id
As an example, we published our .NET type information library mscoru.til
.
Using the IDA Type Information Library
Once the TIL generated, we can proceed to make it available to IDA.
To do so, copy the TIL to the appropriate folder which, in our example, could be the C:\Program Files\IDA Pro 8.3\til\pc
directory.
Once the TIL staged, IDA should display the new type information library and allow it to be loaded.
With the TIL loaded, we can now instruct IDA to import the new structures such as ICLRMetaHost
and its ICLRMetaHost_vtbl
virtual function table.
Once our structures imported, we can leverage IDA’s structure offsets to make raw offsets human-readable.
In our .NET injection analysis, this enables us to identify where the raw .NET assembly is loaded. Such information in turn allows us to identify from where it originates and where we could best intercept it for further analysis.
Conclusions & Lessons Learned
While tools such as OLEViewer alongside MIDL could in theory generate C++ code as well, we found these to be unreliable. Instead, working with MSVC and IDAClang provides a quick (and clean) approach to convert TLBs into TILs.
The above described process can be extended to other abused COM objects such as the Windows Script Host Object Model (with TLB %SystemRoot%\System32\wshom.ocx
) or the Microsoft Management Console (with TLB %SystemRoot%\System32\mmc.exe
).
By creating IDA type information libraries matching libraries used by adversaries we gain the capability to properly understand their tooling, how to analyze further stages and how to best defend against them.