Skip to content

Commit bd200de

Browse files
committed
Improved pickling types parser APIs.
1 parent 390da79 commit bd200de

3 files changed

Lines changed: 162 additions & 9 deletions

File tree

NtApiDotNet/Ndr/NdrParser.cs

Lines changed: 87 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -203,16 +203,21 @@ private static IEnumerable<NdrProcedureDefinition> ReadProcs(IMemoryReader reade
203203
return procs.AsReadOnly();
204204
}
205205

206-
private void ReadTypes(IntPtr midl_type_pickling_info_ptr, IntPtr midl_stub_desc_ptr, IEnumerable<int> fmt_offsets)
206+
private void ReadTypes(IntPtr midl_type_pickling_info_ptr, IntPtr midl_stub_desc_ptr, bool deref_stub_desc, Func<IMemoryReader, IntPtr, IEnumerable<int>> get_offsets)
207207
{
208208
if (midl_type_pickling_info_ptr == IntPtr.Zero)
209209
{
210-
throw new ArgumentException("Must specify the MIDL_TYPE_PICKLING_INFO pointer");
210+
throw new ArgumentException("Must specify a MIDL_TYPE_PICKLING_INFO pointer");
211211
}
212212

213213
if (midl_stub_desc_ptr == IntPtr.Zero)
214214
{
215-
throw new ArgumentException("Must specify the MIDL_STUB_DESC pointer");
215+
throw new ArgumentException($"Must specify a {(deref_stub_desc ? "MIDL_STUBLESS_PROXY_INFO" : "MIDL_STUB_DESC")} pointer");
216+
}
217+
218+
if (deref_stub_desc)
219+
{
220+
midl_stub_desc_ptr = _reader.ReadIntPtr(midl_stub_desc_ptr);
216221
}
217222

218223
var pickle_info = _reader.ReadStruct<MIDL_TYPE_PICKLING_INFO>(midl_type_pickling_info_ptr);
@@ -225,7 +230,7 @@ private void ReadTypes(IntPtr midl_type_pickling_info_ptr, IntPtr midl_stub_desc
225230
MIDL_STUB_DESC stub_desc = _reader.ReadStruct<MIDL_STUB_DESC>(midl_stub_desc_ptr);
226231
NdrParseContext context = new NdrParseContext(_type_cache, null, stub_desc, stub_desc.pFormatTypes, stub_desc.GetExprDesc(_reader),
227232
flags, _reader, NdrParserFlags.IgnoreUserMarshal);
228-
foreach (var i in fmt_offsets)
233+
foreach (var i in get_offsets(_reader, stub_desc.pFormatTypes))
229234
{
230235
NdrBaseTypeReference.Read(context, i);
231236
}
@@ -407,6 +412,19 @@ private static IMemoryReader CreateReader(NtProcess process)
407412
}
408413
}
409414

415+
private static IEnumerable<NdrComplexTypeReference> ReadPicklingComplexTypes(NdrParserFlags parser_flags, NtProcess process, IntPtr midl_type_pickling_info, IntPtr midl_stub_desc, bool deref_stub_desc, Func<IMemoryReader, IntPtr, IEnumerable<int>> get_offsets)
416+
{
417+
NdrParser parser = new NdrParser(process, null, parser_flags);
418+
RunWithAccessCatch(() => parser.ReadTypes(midl_type_pickling_info, midl_stub_desc, deref_stub_desc, get_offsets));
419+
return parser.ComplexTypes;
420+
}
421+
422+
private static IEnumerable<int> GetPicklingTableOffsets(IMemoryReader reader, IntPtr type_pickling_offset_table, IEnumerable<int> type_index)
423+
{
424+
var table = reader.ReadIntPtr(type_pickling_offset_table);
425+
return type_index.Select(i => reader.ReadInt32(table + i * 4));
426+
}
427+
410428
#endregion
411429

412430
#region Internal Members
@@ -644,26 +662,87 @@ public IEnumerable<NdrBaseTypeReference> Types
644662
#endregion
645663

646664
#region Static Methods
665+
666+
/// <summary>
667+
/// Parse NDR complex type information from a pickling structure. Used to extract explicit Encode/Decode method information.
668+
/// </summary>
669+
/// <param name="process">The process to read from.</param>
670+
/// <param name="midl_type_pickling_info">Pointer to the MIDL_TYPE_PICKLING_INFO structure.</param>
671+
/// <param name="midl_stub_desc">The pointer to the MIDL_STUB_DESC structure.</param>
672+
/// <param name="type_offsets">Pointers to the the format string to the start of the types.</param>
673+
/// <param name="parser_flags">Specify additional parser flags.</param>
674+
/// <returns>The list of complex types.</returns>
675+
/// <remarks>This function is used to extract type information for calls to NdrMesTypeDecode2. MIDL_TYPE_PICKLING_INFO is the second parameter,
676+
/// MIDL_STUB_DESC is the third, the Type Offsets is the fourth parameter.</remarks>
677+
public static IEnumerable<NdrComplexTypeReference> ReadPicklingComplexTypes(NtProcess process, IntPtr midl_type_pickling_info, IntPtr midl_stub_desc, IntPtr[] type_offsets, NdrParserFlags parser_flags)
678+
{
679+
if (type_offsets.Length == 0)
680+
{
681+
return new NdrComplexTypeReference[0];
682+
}
683+
684+
return ReadPicklingComplexTypes(parser_flags, process, midl_type_pickling_info, midl_stub_desc, false, (r, f) => type_offsets.Select(p => (int)(p.ToInt64() - f.ToInt64())));
685+
}
686+
687+
/// <summary>
688+
/// Parse NDR complex type information from a pickling structure. Used to extract explicit Encode/Decode method information.
689+
/// </summary>
690+
/// <param name="process">The process to read from.</param>
691+
/// <param name="midl_type_pickling_info">Pointer to the MIDL_TYPE_PICKLING_INFO structure.</param>
692+
/// <param name="midl_stubless_proxy">The pointer to the MIDL_STUBLESS_PROXY_INFO structure.</param>
693+
/// <param name="type_pickling_offset_table">Pointer to the type pickling offset table.</param>
694+
/// <param name="type_index">Index into type_pickling_offset_table array.</param>
695+
/// <param name="parser_flags">Specify additional parser flags.</param>
696+
/// <returns>The list of complex types.</returns>
697+
/// <remarks>This function is used to extract type information for calls to NdrMesTypeDecode3. MIDL_TYPE_PICKLING_INFO is the second parameter,
698+
/// MIDL_STUBLESS_PROXY_INFO is the third, the type pickling offset table is the fourth and the type index is the fifth.</remarks>
699+
public static IEnumerable<NdrComplexTypeReference> ReadPicklingComplexTypes(NtProcess process, IntPtr midl_type_pickling_info,
700+
IntPtr midl_stubless_proxy, IntPtr type_pickling_offset_table, int[] type_index, NdrParserFlags parser_flags)
701+
{
702+
if (type_index.Length == 0)
703+
{
704+
return new NdrComplexTypeReference[0];
705+
}
706+
707+
return ReadPicklingComplexTypes(parser_flags, process, midl_type_pickling_info, midl_stubless_proxy, true, (r, f) => GetPicklingTableOffsets(r, type_pickling_offset_table, type_index));
708+
}
709+
647710
/// <summary>
648711
/// Parse NDR complex type information from a pickling structure. Used to extract explicit Encode/Decode method information.
649712
/// </summary>
650713
/// <param name="process">The process to read from.</param>
651714
/// <param name="midl_type_pickling_info">Pointer to the MIDL_TYPE_PICKLING_INFO structure.</param>
652715
/// <param name="midl_stub_desc">The pointer to the MIDL_STUB_DESC structure.</param>
653716
/// <param name="start_offsets">Offsets into the format string to the start of the types.</param>
717+
/// <param name="parser_flags">Specify additional parser flags.</param>
654718
/// <returns>The list of complex types.</returns>
655719
/// <remarks>This function is used to extract type information for calls to NdrMesTypeDecode2. MIDL_TYPE_PICKLING_INFO is the second parameter,
656720
/// MIDL_STUB_DESC is the third (minus the offset).</remarks>
657-
public static IEnumerable<NdrComplexTypeReference> ReadPicklingComplexTypes(NtProcess process, IntPtr midl_type_pickling_info, IntPtr midl_stub_desc, params int[] start_offsets)
721+
public static IEnumerable<NdrComplexTypeReference> ReadPicklingComplexTypes(NtProcess process,
722+
IntPtr midl_type_pickling_info, IntPtr midl_stub_desc, int[] start_offsets, NdrParserFlags parser_flags)
658723
{
659724
if (start_offsets.Length == 0)
660725
{
661726
return new NdrComplexTypeReference[0];
662727
}
663728

664-
NdrParser parser = new NdrParser(process, null, NdrParserFlags.IgnoreUserMarshal);
665-
RunWithAccessCatch(() => parser.ReadTypes(midl_type_pickling_info, midl_stub_desc, start_offsets));
666-
return parser.ComplexTypes;
729+
return ReadPicklingComplexTypes(parser_flags, process, midl_type_pickling_info, midl_stub_desc, false, (r, f) => start_offsets);
730+
}
731+
732+
/// <summary>
733+
/// Parse NDR complex type information from a pickling structure. Used to extract explicit Encode/Decode method information.
734+
/// </summary>
735+
/// <param name="process">The process to read from.</param>
736+
/// <param name="midl_type_pickling_info">Pointer to the MIDL_TYPE_PICKLING_INFO structure.</param>
737+
/// <param name="midl_stub_desc">The pointer to the MIDL_STUB_DESC structure.</param>
738+
/// <param name="start_offsets">Offsets into the format string to the start of the types.</param>
739+
/// <returns>The list of complex types.</returns>
740+
/// <remarks>This function is used to extract type information for calls to NdrMesTypeDecode2. MIDL_TYPE_PICKLING_INFO is the second parameter,
741+
/// MIDL_STUB_DESC is the third (minus the offset).</remarks>
742+
public static IEnumerable<NdrComplexTypeReference> ReadPicklingComplexTypes(NtProcess process, IntPtr midl_type_pickling_info,
743+
IntPtr midl_stub_desc, params int[] start_offsets)
744+
{
745+
return ReadPicklingComplexTypes(process, midl_type_pickling_info, midl_stub_desc, start_offsets, NdrParserFlags.IgnoreUserMarshal);
667746
}
668747

669748
/// <summary>

NtObjectManager/NtObjectManager.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ FunctionsToExport = 'Get-AccessibleAlpcPort', 'Set-NtTokenPrivilege',
8989
'Get-NtAccountRight', 'Get-NtAccountRightSid', 'Get-NtConsoleSession', 'Get-ServicePrincipalName',
9090
'Get-NtTokenId', 'Get-AuthCredential', 'Export-AuthToken', 'Import-AuthToken', 'Get-MD4Hash',
9191
'Format-ASN1DER', 'Import-KerberosKeyTab', 'Export-KerberosKeyTab', 'New-KerberosKey', 'Get-KerberosKey',
92-
'Unprotect-AuthToken', 'Get-KerberosTicket'
92+
'Unprotect-AuthToken', 'Get-KerberosTicket', 'Get-NdrComplexType'
9393

9494
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
9595
CmdletsToExport = 'Add-NtKeyHive', 'Get-NtDirectory', 'Get-NtEvent', 'Get-NtFile',

NtObjectManager/NtObjectManager.psm1

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9352,4 +9352,78 @@ function Get-KerberosTicket {
93529352
}
93539353
}
93549354
}
9355+
}
9356+
9357+
<#
9358+
.SYNOPSIS
9359+
Get NDR complex types from memory.
9360+
.DESCRIPTION
9361+
This cmdlet parses NDR complex type information from a location in memory.
9362+
.PARAMETER PicklingInfo
9363+
Specify pointer to the MIDL_TYPE_PICKLING_INFO structure.
9364+
.PARAMETER StubDesc
9365+
Specify pointer to the MIDL_STUB_DESC structure.
9366+
.PARAMETER StublessProxy
9367+
Specify pointer to the MIDL_STUBLESS_PROXY_INFO structure.
9368+
.PARAMETER OffsetTable
9369+
Specify pointer to type offset table.
9370+
.PARAMETER TypeIndex
9371+
Specify list of type index into type offset table.
9372+
.PARAMETER TypeFormat
9373+
Specify list of type format string addresses for the types.
9374+
.PARAMETER TypeOffset
9375+
Specify list of type offsets into the format string for the types.
9376+
.PARAMETER Process
9377+
Specify optional process which contains the types.
9378+
.PARAMETER Module
9379+
Specify optional module base address for the types. If set all pointers
9380+
are relative offsets from the module address.
9381+
.INPUTS
9382+
None
9383+
.OUTPUTS
9384+
NdrComplexTypeReference[]
9385+
#>
9386+
function Get-NdrComplexType {
9387+
[CmdletBinding(DefaultParameterSetName="FromDecode3")]
9388+
Param(
9389+
[Parameter(Mandatory)]
9390+
[long]$PicklingInfo,
9391+
[Parameter(Mandatory, ParameterSetName = "FromDecode2")]
9392+
[Parameter(Mandatory, ParameterSetName = "FromDecode2Offset")]
9393+
[long]$StubDesc,
9394+
[Parameter(Mandatory, ParameterSetName = "FromDecode2")]
9395+
[long[]]$TypeFormat,
9396+
[Parameter(Mandatory, ParameterSetName = "FromDecode2Offset")]
9397+
[int[]]$TypeOffset,
9398+
[Parameter(Mandatory, ParameterSetName = "FromDecode3")]
9399+
[long]$StublessProxy,
9400+
[Parameter(Mandatory, ParameterSetName = "FromDecode3")]
9401+
[long]$OffsetTable,
9402+
[Parameter(Mandatory, ParameterSetName = "FromDecode3")]
9403+
[int[]]$TypeIndex,
9404+
[NtApiDotNet.Win32.SafeLoadLibraryHandle]$Module,
9405+
[NtApiDotNet.NtProcess]$Process,
9406+
[NtApiDotNet.Ndr.NdrParserFlags]$Flags = "IgnoreUserMarshal"
9407+
)
9408+
9409+
$base_address = 0
9410+
if ($null -ne $Module) {
9411+
$base_address = $Module.DangerousGetHandle().ToInt64()
9412+
}
9413+
9414+
switch($PSCmdlet.ParameterSetName) {
9415+
"FromDecode2" {
9416+
$type_offset = $TypeFormat | % { $_ + $base_address }
9417+
[NtApiDotNet.Ndr.NdrParser]::ReadPicklingComplexTypes($Process, $PicklingInfo+$base_address,`
9418+
$StubDesc+$base_address, $type_offset, $Flags) | Write-Output
9419+
}
9420+
"FromDecode2Offset" {
9421+
[NtApiDotNet.Ndr.NdrParser]::ReadPicklingComplexTypes($Process, $PicklingInfo+$base_address,`
9422+
$StubDesc+$base_address, $TypeOffset, $Flags) | Write-Output
9423+
}
9424+
"FromDecode3" {
9425+
[NtApiDotNet.Ndr.NdrParser]::ReadPicklingComplexTypes($Process, $PicklingInfo+$base_address,`
9426+
$StublessProxy+$base_address, $OffsetTable+$base_address, $TypeIndex, $Flags) | Write-Output
9427+
}
9428+
}
93559429
}

0 commit comments

Comments
 (0)