Today we are releasing MS09-026 which fixes a vulnerability in the Microsoft Windows RPC (Remote Procedure Call) NDR20 marshalling engine. This component is responsible for preparing data to be sent over the network and then translating it back to what the server or client application uses. NDR20 is specific to 32-bit applications that use RPC to transfer data. RPC's NDR64 marshalling engine is used for 64-bit applications.
This bug in NDR20 only impacts applications which utilize a specific style of structure when defining the RPC interface they use to communicate. The specific style of structure is a non-conformant varying array. More information can be found at http://msdn.microsoft.com/en-us/library/aa373542(VS.85).aspx. Note that this style of structure is uncommon. It is not used by any RPC interface that ships with any supported version of Windows. However, we are still providing a fix as it is a supported style of structure and may be in use somewhere.
So how can a developer know if an RPC interface is affected? The bulletin's FAQ states the following.
These code definitions, FC_SMVARRAY, FC_LGVARRAY, FC_VARIABLE_REPEAT, and FC_VARIABLE_OFFSET, are used in the RPC client and server stubs that are generated at compile time when midl.exe compiles the RPC interface's IDL file, specifically when using the /Oicf switch (http://msdn.microsoft.com/en-us/library/aa367352(VS.85).aspx). Other switches, which are defined in the previous link, also exist. These will generate different formats for the stubs so if in doubt make sure you are using the /Oicf switch.
Using what the bulletin has stated, a developer can examine the *_c.c or *_s.c stubs generated from the IDL with the following steps:
Here is an example MIDL_TYPE_FORMAT_STRING that would be affected by this issue.
static const repro_MIDL_TYPE_FORMAT_STRING repro__MIDL_TypeFormatString = { 0, { NdrFcShort( 0x0 ), /* 0 */ /* 2 */ 0x12, 0x8, /* FC_UP [simple_pointer] */ /* 4 */ 0x8, /* FC_LONG */ 0x5c, /* FC_PAD */ /* 6 */ 0x16, /* FC_PSTRUCT */ … 0x1f, /* FC_SMVARRAY */ 0x3, /* 3 */ /* 40 */ NdrFcShort( 0x3c ), /* 60 */ /* 42 */ NdrFcShort( 0x5 ), /* 5 */ /* 44 */ NdrFcShort( 0xc ), /* 12 */ /* 46 */ 0x28, /* Corr desc: parameter, FC_LONG */ 0x0, /* */ /* 48 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ /* 50 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ /* 52 */ 0x4b, /* FC_PP */ 0x5c, /* FC_PAD */ /* 54 */ 0x48, /* FC_VARIABLE_REPEAT */ 0x4a, /* FC_VARIABLE_OFFSET */ /* 56 */ NdrFcShort( 0xc ), /* 12 */ /* 58 */ NdrFcShort( 0x0 ), /* 0 */ … /* 74 */ 0x12, 0x10, /* FC_UP [pointer_deref] */ /* 76 */ NdrFcShort( 0xffb6 ), /* Offset= -74 (2) */ /* 78 */ 0x5b, /* FC_END */
Additionally, developers can examine their IDL directly and get an idea if their interface is affected. For affected interfaces, a definition like below will exist, where an array of non-fixed sized structures, shown in blue below, is passed. Notice that the array in green is a varying array (http://msdn.microsoft.com/en-us/library/aa379375(VS.85).aspx) because of it's fixed size but varying number elements contained within.
interface foo { typedef struct { int a; int **pp; char *buf; } test; void bar([in] int count, [out, length_is(count)] test r[7]); }
Developers with affected RPC interfaces should strongly encourage their customers to install this patch, especially if the RPC interface is anonymous.
- Nick Finco and Bruce Dang, MSRC Engineering