示例#1
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="process">Process to parse from.</param>
        /// <param name="symbol_resolver">Specify a symbol resolver to use for looking up symbols.</param>
        /// <param name="parser_flags">Flags which affect the parsing operation.</param>
        public NdrParser(NtProcess process, ISymbolResolver symbol_resolver, NdrParserFlags parser_flags)
        {
            CheckSymbolResolver(process, symbol_resolver);
            if (process == null || process.ProcessId == NtProcess.Current.ProcessId)
            {
                _reader = new CurrentProcessMemoryReader();
            }
            else
            {
                if (!Environment.Is64BitProcess && process.Is64Bit)
                {
                    throw new ArgumentException("Do not support 32 to 64 bit reading.");
                }

                if (Environment.Is64BitProcess != process.Is64Bit)
                {
                    _reader = new CrossBitnessProcessMemoryReader(process);
                }
                else
                {
                    _reader = new ProcessMemoryReader(process);
                }
            }
            _symbol_resolver = symbol_resolver;
            _type_cache      = new NdrTypeCache();
            _parser_flags    = parser_flags;
        }
示例#2
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="reader">Memory reader to parse from.</param>
 /// <param name="process">Process to read from.</param>
 /// <param name="symbol_resolver">Specify a symbol resolver to use for looking up symbols.</param>
 /// <param name="parser_flags">Flags which affect the parsing operation.</param>
 internal NdrParser(IMemoryReader reader, NtProcess process, ISymbolResolver symbol_resolver, NdrParserFlags parser_flags)
 {
     CheckSymbolResolver(process, symbol_resolver);
     _reader          = reader;
     _symbol_resolver = symbol_resolver;
     _type_cache      = new NdrTypeCache();
     _parser_flags    = parser_flags;
 }
示例#3
0
 internal NdrParseContext(NdrTypeCache type_cache, ISymbolResolver symbol_resolver,
                          MIDL_STUB_DESC stub_desc, IntPtr type_desc, int desc_size, IMemoryReader reader,
                          NdrParserFlags parser_flags)
 {
     TypeCache      = type_cache;
     SymbolResolver = symbol_resolver;
     StubDesc       = stub_desc;
     TypeDesc       = type_desc;
     CorrDescSize   = desc_size;
     Reader         = reader;
     Flags          = parser_flags;
 }
示例#4
0
 internal NdrParseContext(NdrTypeCache type_cache, ISymbolResolver symbol_resolver,
                          MIDL_STUB_DESC stub_desc, IntPtr type_desc, NDR_EXPR_DESC expr_desc,
                          NdrInterpreterOptFlags2 opt_flags, IMemoryReader reader, NdrParserFlags parser_flags)
 {
     TypeCache      = type_cache;
     SymbolResolver = symbol_resolver;
     StubDesc       = stub_desc;
     TypeDesc       = type_desc;
     ExprDesc       = expr_desc;
     OptFlags       = opt_flags;
     Reader         = reader;
     Flags          = parser_flags;
 }
示例#5
0
        /// <summary>
        /// Parse all RPC servers from a PE file.
        /// </summary>
        /// <param name="file">The PE file to parse.</param>
        /// <param name="dbghelp_path">Path to a DBGHELP DLL to resolve symbols.</param>
        /// <param name="symbol_path">Symbol path for DBGHELP</param>
        /// <param name="flags">Flags for the RPC parser.</param>
        /// <remarks>This only works for PE files with the same bitness as the current process.</remarks>
        /// <returns>A list of parsed RPC server.</returns>
        public static IEnumerable <RpcServer> ParsePeFile(string file, string dbghelp_path, string symbol_path, RpcServerParserFlags flags)
        {
            List <RpcServer> servers = new List <RpcServer>();

            using (var result = SafeLoadLibraryHandle.LoadLibrary(file, LoadLibraryFlags.DontResolveDllReferences, false))
            {
                if (!result.IsSuccess)
                {
                    return(servers.AsReadOnly());
                }

                var lib      = result.Result;
                var sections = lib.GetImageSections();
                var offsets  = sections.SelectMany(s => FindRpcServerInterfaces(s, flags.HasFlagSet(RpcServerParserFlags.ParseClients)));
                if (offsets.Any())
                {
                    SymbolResolverFlags symbol_flags = flags.HasFlagSet(RpcServerParserFlags.SymSrvFallback) ? SymbolResolverFlags.SymSrvFallback : SymbolResolverFlags.None;

                    using (var sym_resolver = !flags.HasFlagSet(RpcServerParserFlags.IgnoreSymbols) ? SymbolResolver.Create(NtProcess.Current,
                                                                                                                            dbghelp_path, symbol_path, symbol_flags, null) : null)
                    {
                        NdrParserFlags parser_flags = NdrParserFlags.IgnoreUserMarshal;
                        if (flags.HasFlagSet(RpcServerParserFlags.ResolveStructureNames))
                        {
                            parser_flags |= NdrParserFlags.ResolveStructureNames;
                        }

                        foreach (var offset in offsets)
                        {
                            IMemoryReader reader = new CurrentProcessMemoryReader(sections.Select(s => Tuple.Create(s.Data.DangerousGetHandle().ToInt64(), (int)s.Data.ByteLength)));
                            NdrParser     parser = new NdrParser(reader, NtProcess.Current,
                                                                 sym_resolver, parser_flags);
                            IntPtr ifspec = lib.DangerousGetHandle() + (int)offset.Offset;
                            try
                            {
                                var rpc = parser.ReadFromRpcServerInterface(ifspec, lib.DangerousGetHandle());
                                servers.Add(new RpcServer(rpc, parser.ComplexTypes, file, offset.Offset, offset.Client));
                            }
                            catch (NdrParserException)
                            {
                            }
                        }
                    }
                }
            }

            return(servers.AsReadOnly());
        }
        private static void FixupStructureNames(List <NdrProcedureDefinition> procs,
                                                ISymbolResolver symbol_resolver, NdrParserFlags parser_flags)
        {
            if (!parser_flags.HasFlagSet(NdrParserFlags.ResolveStructureNames) || !(symbol_resolver is ISymbolTypeResolver type_resolver))
            {
                return;
            }

            var complex_types = new Dictionary <NdrComplexTypeReference, UserDefinedTypeInformation>();

            foreach (var proc in procs)
            {
                if (!(type_resolver.GetTypeForSymbolByAddress(proc.DispatchFunction) is FunctionTypeInformation func_type))
                {
                    continue;
                }

                if (func_type.Parameters.Count != proc.Params.Count)
                {
                    continue;
                }

                for (int i = 0; i < func_type.Parameters.Count; ++i)
                {
                    proc.Params[i].Name = func_type.Parameters[i].Name;
                    UpdateComplexTypes(complex_types, func_type.Parameters[i].ParameterType, proc.Params[i].Type);
                }

                if (proc.ReturnValue != null && func_type.ReturnType != null)
                {
                    UpdateComplexTypes(complex_types, func_type.ReturnType, proc.ReturnValue.Type);
                }
            }

            HashSet <NdrComplexTypeReference> fixup_set = new HashSet <NdrComplexTypeReference>();

            foreach (var pair in complex_types)
            {
                FixupComplexType(fixup_set, pair.Key, pair.Value);
            }
        }
示例#7
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="process">Process to parse from.</param>
 /// <param name="symbol_resolver">Specify a symbol resolver to use for looking up symbols.</param>
 /// <param name="parser_flags">Flags which affect the parsing operation.</param>
 public NdrParser(NtProcess process, ISymbolResolver symbol_resolver, NdrParserFlags parser_flags)
     : this(CreateReader(process), process, symbol_resolver, parser_flags)
 {
 }
示例#8
0
        private static IEnumerable <NdrProcedureDefinition> ReadProcs(IMemoryReader reader, MIDL_SERVER_INFO server_info, int start_offset,
                                                                      int dispatch_count, NdrTypeCache type_cache, ISymbolResolver symbol_resolver, IList <string> names, NdrParserFlags parser_flags)
        {
            RPC_SYNTAX_IDENTIFIER transfer_syntax = server_info.GetTransferSyntax(reader);

            IntPtr proc_str    = IntPtr.Zero;
            IntPtr fmt_str_ofs = IntPtr.Zero;

            if (transfer_syntax.SyntaxGUID != NdrNativeUtils.DCE_TransferSyntax)
            {
                MIDL_SYNTAX_INFO[] syntax_info = server_info.GetSyntaxInfo(reader);
                if (!syntax_info.Any(s => s.TransferSyntax.SyntaxGUID == NdrNativeUtils.DCE_TransferSyntax))
                {
                    throw new NdrParserException("Can't parse NDR64 syntax data");
                }
                MIDL_SYNTAX_INFO dce_syntax_info = syntax_info.First(s => s.TransferSyntax.SyntaxGUID == NdrNativeUtils.DCE_TransferSyntax);
                proc_str    = dce_syntax_info.ProcString;
                fmt_str_ofs = dce_syntax_info.FmtStringOffset;
            }
            else
            {
                proc_str    = server_info.ProcString;
                fmt_str_ofs = server_info.FmtStringOffset;
            }

            IntPtr[]       dispatch_funcs       = server_info.GetDispatchTable(reader, dispatch_count);
            MIDL_STUB_DESC stub_desc            = server_info.GetStubDesc(reader);
            IntPtr         type_desc            = stub_desc.pFormatTypes;
            NDR_EXPR_DESC  expr_desc            = stub_desc.GetExprDesc(reader);
            List <NdrProcedureDefinition> procs = new List <NdrProcedureDefinition>();

            if (fmt_str_ofs != IntPtr.Zero)
            {
                for (int i = start_offset; i < dispatch_count; ++i)
                {
                    int fmt_ofs = reader.ReadInt16(fmt_str_ofs + i * 2);
                    if (fmt_ofs >= 0)
                    {
                        string name = null;
                        if (names != null)
                        {
                            name = names[i - start_offset];
                        }
                        procs.Add(new NdrProcedureDefinition(reader, type_cache, symbol_resolver,
                                                             stub_desc, proc_str + fmt_ofs, type_desc, expr_desc, dispatch_funcs[i], name, parser_flags));
                    }
                }
            }
            return(procs.AsReadOnly());
        }
示例#9
0
        private static NdrRpcServerInterface ReadRpcServerInterface(IMemoryReader reader, RPC_SERVER_INTERFACE server_interface,
                                                                    NdrTypeCache type_cache, ISymbolResolver symbol_resolver, NdrParserFlags parser_flags)
        {
            RPC_DISPATCH_TABLE dispatch_table = server_interface.GetDispatchTable(reader);
            var procs = ReadProcs(reader, server_interface.GetServerInfo(reader), 0,
                                  dispatch_table.DispatchTableCount, type_cache, symbol_resolver, null, parser_flags);

            return(new NdrRpcServerInterface(server_interface.InterfaceId, server_interface.TransferSyntax, procs,
                                             server_interface.GetProtSeq(reader).Select(s => new NdrProtocolSequenceEndpoint(s, reader))));
        }
示例#10
0
 public bool HasFlag(NdrParserFlags flags)
 {
     return((Flags & flags) == flags);
 }
        internal NdrProcedureDefinition(IMemoryReader mem_reader, NdrTypeCache type_cache,
                                        ISymbolResolver symbol_resolver, MIDL_STUB_DESC stub_desc,
                                        IntPtr proc_desc, IntPtr type_desc, NDR_EXPR_DESC expr_desc, IntPtr dispatch_func,
                                        string name, NdrParserFlags parser_flags)
        {
            BinaryReader        reader       = mem_reader.GetReader(proc_desc);
            NdrFormatCharacter  handle_type  = (NdrFormatCharacter)reader.ReadByte();
            NdrInterpreterFlags old_oi_flags = (NdrInterpreterFlags)reader.ReadByte();

            if ((old_oi_flags & NdrInterpreterFlags.HasRpcFlags) == NdrInterpreterFlags.HasRpcFlags)
            {
                RpcFlags = reader.ReadUInt32();
            }

            ProcNum = reader.ReadUInt16();

            if (string.IsNullOrWhiteSpace(name))
            {
                if (symbol_resolver != null && dispatch_func != IntPtr.Zero)
                {
                    Name = symbol_resolver.GetSymbolForAddress(dispatch_func, false, true);
                }

                Name = Name ?? $"Proc{ProcNum}";
            }
            else
            {
                Name = name;
            }

            StackSize = reader.ReadUInt16();
            if (handle_type == 0)
            {
                // read out handle type.
                handle_type = (NdrFormatCharacter)reader.ReadByte();
                NdrHandleParamFlags flags      = (NdrHandleParamFlags)reader.ReadByte();
                ushort handle_offset           = reader.ReadUInt16();
                NdrBaseTypeReference base_type = new NdrSimpleTypeReference(handle_type);
                if (handle_type == NdrFormatCharacter.FC_BIND_PRIMITIVE)
                {
                    flags = flags != 0 ? NdrHandleParamFlags.HANDLE_PARAM_IS_VIA_PTR : 0;
                }
                else if (handle_type == NdrFormatCharacter.FC_BIND_GENERIC)
                {
                    // Remove the size field, we might do something with this later.
                    flags = (NdrHandleParamFlags)((byte)flags & 0xF0);
                    // Read out the remaining data.
                    reader.ReadByte();
                    reader.ReadByte();
                }
                else if (handle_type == NdrFormatCharacter.FC_BIND_CONTEXT)
                {
                    // Read out the remaining data.
                    reader.ReadByte();
                    reader.ReadByte();
                }
                else
                {
                    throw new ArgumentException($"Unsupported explicit handle type {handle_type}");
                }
                Handle = new NdrProcedureHandleParameter(0,
                                                         (flags & NdrHandleParamFlags.HANDLE_PARAM_IS_VIA_PTR) != 0 ? new NdrPointerTypeReference(base_type)
                            : base_type, handle_offset, true, flags, handle_type == NdrFormatCharacter.FC_BIND_GENERIC);
            }
            else
            {
                Handle = new NdrProcedureHandleParameter(0, new NdrSimpleTypeReference(handle_type), 0, false, 0, false);
            }

            ushort constant_client_buffer_size = reader.ReadUInt16();
            ushort constant_server_buffer_size = reader.ReadUInt16();

            InterpreterFlags = (NdrInterpreterOptFlags)reader.ReadByte();
            int number_of_params = reader.ReadByte();

            NdrProcHeaderExts exts = new NdrProcHeaderExts();

            if ((InterpreterFlags & NdrInterpreterOptFlags.HasExtensions) == NdrInterpreterOptFlags.HasExtensions)
            {
                int ext_size = reader.ReadByte();
                reader.BaseStream.Position -= 1;
                // Read out extension bytes.
                byte[] extension = reader.ReadAll(ext_size);
                if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(NdrProcHeaderExts)) <= ext_size)
                {
                    using (var buffer = new SafeStructureInOutBuffer <NdrProcHeaderExts>(ext_size, false))
                    {
                        buffer.WriteArray(0, extension, 0, ext_size);
                        exts = buffer.Result;
                    }
                }
            }

            NdrParseContext context         = new NdrParseContext(type_cache, symbol_resolver, stub_desc, type_desc, expr_desc, exts.Flags2, mem_reader, parser_flags);
            List <NdrProcedureParameter> ps = new List <NdrProcedureParameter>();

            bool has_return  = InterpreterFlags.HasFlag(NdrInterpreterOptFlags.HasReturn);
            int  param_count = has_return ? number_of_params - 1 : number_of_params;

            for (int param = 0; param < param_count; ++param)
            {
                ps.Add(new NdrProcedureParameter(context, reader, $"p{param}"));
            }

            if (Handle.Explicit && !Handle.Generic)
            {
                // Insert handle into parameter list at the best location.
                int index = 0;
                while (index < ps.Count)
                {
                    if (ps[index].Offset > Handle.Offset)
                    {
                        ps.Insert(index, Handle);
                        break;
                    }
                    index++;
                }
            }

            Params = ps.AsReadOnly();
            if (has_return)
            {
                ReturnValue = new NdrProcedureParameter(context, reader, "retval");
            }
            DispatchFunction = dispatch_func;
        }
        /// <summary>
        /// Parse NDR complex type information from a pickling structure. Used to extract explicit Encode/Decode method information.
        /// </summary>
        /// <param name="process">The process to read from.</param>
        /// <param name="midl_type_pickling_info">Pointer to the MIDL_TYPE_PICKLING_INFO structure.</param>
        /// <param name="midl_stub_desc">The pointer to the MIDL_STUB_DESC structure.</param>
        /// <param name="start_offsets">Offsets into the format string to the start of the types.</param>
        /// <param name="parser_flags">Specify additional parser flags.</param>
        /// <returns>The list of complex types.</returns>
        /// <remarks>This function is used to extract type information for calls to NdrMesTypeDecode2. MIDL_TYPE_PICKLING_INFO is the second parameter,
        /// MIDL_STUB_DESC is the third (minus the offset).</remarks>
        public static IEnumerable <NdrComplexTypeReference> ReadPicklingComplexTypes(NtProcess process,
                                                                                     IntPtr midl_type_pickling_info, IntPtr midl_stub_desc, int[] start_offsets, NdrParserFlags parser_flags)
        {
            if (start_offsets.Length == 0)
            {
                return(new NdrComplexTypeReference[0]);
            }

            return(ReadPicklingComplexTypes(parser_flags, process, midl_type_pickling_info, midl_stub_desc, false, (r, f) => start_offsets));
        }
        /// <summary>
        /// Parse NDR complex type information from a pickling structure. Used to extract explicit Encode/Decode method information.
        /// </summary>
        /// <param name="process">The process to read from.</param>
        /// <param name="midl_type_pickling_info">Pointer to the MIDL_TYPE_PICKLING_INFO structure.</param>
        /// <param name="midl_stubless_proxy">The pointer to the MIDL_STUBLESS_PROXY_INFO structure.</param>
        /// <param name="type_pickling_offset_table">Pointer to the type pickling offset table.</param>
        /// <param name="type_index">Index into type_pickling_offset_table array.</param>
        /// <param name="parser_flags">Specify additional parser flags.</param>
        /// <returns>The list of complex types.</returns>
        /// <remarks>This function is used to extract type information for calls to NdrMesTypeDecode3. MIDL_TYPE_PICKLING_INFO is the second parameter,
        /// MIDL_STUBLESS_PROXY_INFO is the third, the type pickling offset table is the fourth and the type index is the fifth.</remarks>
        public static IEnumerable <NdrComplexTypeReference> ReadPicklingComplexTypes(NtProcess process, IntPtr midl_type_pickling_info,
                                                                                     IntPtr midl_stubless_proxy, IntPtr type_pickling_offset_table, int[] type_index, NdrParserFlags parser_flags)
        {
            if (type_index.Length == 0)
            {
                return(new NdrComplexTypeReference[0]);
            }

            return(ReadPicklingComplexTypes(parser_flags, process, midl_type_pickling_info, midl_stubless_proxy, true, (r, f) => GetPicklingTableOffsets(r, type_pickling_offset_table, type_index)));
        }
        /// <summary>
        /// Parse NDR complex type information from a pickling structure. Used to extract explicit Encode/Decode method information.
        /// </summary>
        /// <param name="process">The process to read from.</param>
        /// <param name="midl_type_pickling_info">Pointer to the MIDL_TYPE_PICKLING_INFO structure.</param>
        /// <param name="midl_stub_desc">The pointer to the MIDL_STUB_DESC structure.</param>
        /// <param name="type_offsets">Pointers to the the format string to the start of the types.</param>
        /// <param name="parser_flags">Specify additional parser flags.</param>
        /// <returns>The list of complex types.</returns>
        /// <remarks>This function is used to extract type information for calls to NdrMesTypeDecode2. MIDL_TYPE_PICKLING_INFO is the second parameter,
        /// MIDL_STUB_DESC is the third, the Type Offsets is the fourth parameter.</remarks>
        public static IEnumerable <NdrComplexTypeReference> ReadPicklingComplexTypes(NtProcess process, IntPtr midl_type_pickling_info, IntPtr midl_stub_desc, IntPtr[] type_offsets, NdrParserFlags parser_flags)
        {
            if (type_offsets.Length == 0)
            {
                return(new NdrComplexTypeReference[0]);
            }

            return(ReadPicklingComplexTypes(parser_flags, process, midl_type_pickling_info, midl_stub_desc, false, (r, f) => type_offsets.Select(p => (int)(p.ToInt64() - f.ToInt64()))));
        }
        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)
        {
            NdrParser parser = new NdrParser(process, null, parser_flags);

            RunWithAccessCatch(() => parser.ReadTypes(midl_type_pickling_info, midl_stub_desc, deref_stub_desc, get_offsets));
            return(parser.ComplexTypes);
        }