Ejemplo n.º 1
0
        private byte[] ProtectPDU(byte[] header, ref byte[] stub_data, int auth_padding_length)
        {
            List <SecurityBuffer> buffers = new List <SecurityBuffer>();

            if (_negotiated_auth_type != RpcAuthenticationType.Kerberos)
            {
                buffers.Add(new SecurityBufferInOut(SecurityBufferType.Data | SecurityBufferType.ReadOnlyWithChecksum, header));
            }
            var stub_data_buffer = new SecurityBufferInOut(SecurityBufferType.Data, stub_data);

            buffers.Add(stub_data_buffer);
            if (_negotiated_auth_type != RpcAuthenticationType.Kerberos)
            {
                buffers.Add(new SecurityBufferInOut(SecurityBufferType.Data | SecurityBufferType.ReadOnlyWithChecksum,
                                                    AuthData.ToArray(_transport_security, auth_padding_length, 0, new byte[0])));
            }

            byte[] signature;
            if (_transport_security.AuthenticationLevel == RpcAuthenticationLevel.PacketIntegrity)
            {
                signature = _auth_context.MakeSignature(buffers, _send_sequence_no);
            }
            else
            {
                signature = _auth_context.EncryptMessage(buffers, SecurityQualityOfProtectionFlags.None, _send_sequence_no);
                stub_data = stub_data_buffer.ToArray();
                RpcUtils.DumpBuffer(true, "Send Encrypted Data", stub_data);
            }

            RpcUtils.DumpBuffer(true, "Send Signature Data", signature);
            return(AuthData.ToArray(_transport_security, auth_padding_length, 0, signature));
        }
Ejemplo n.º 2
0
        private RpcClientResponse SendAndReceiveImmediate(int proc_num, Guid objuuid, byte[] ndr_buffer, IReadOnlyCollection <NtObject> handles)
        {
            LRPC_IMMEDIATE_REQUEST_MESSAGE req_msg = new LRPC_IMMEDIATE_REQUEST_MESSAGE()
            {
                Header    = new LRPC_HEADER(LRPC_MESSAGE_TYPE.lmtRequest),
                BindingId = 0,
                CallId    = CallId++,
                ProcNum   = proc_num,
            };

            if (objuuid != Guid.Empty)
            {
                req_msg.ObjectUuid = objuuid;
                req_msg.Flags     |= LRPC_REQUEST_MESSAGE_FLAGS.ObjectUuid;
            }

            AlpcMessageType <LRPC_IMMEDIATE_REQUEST_MESSAGE> send_msg = new AlpcMessageType <LRPC_IMMEDIATE_REQUEST_MESSAGE>(req_msg, ndr_buffer);
            AlpcMessageRaw            resp_msg  = new AlpcMessageRaw(0x1000);
            AlpcSendMessageAttributes send_attr = new AlpcSendMessageAttributes();

            if (handles.Count > 0)
            {
                send_attr.AddHandles(handles);
            }

            using (AlpcReceiveMessageAttributes recv_attr = new AlpcReceiveMessageAttributes())
            {
                RpcUtils.DumpBuffer(true, "ALPC Request Immediate", send_msg);
                _client.SendReceive(AlpcMessageFlags.SyncRequest, send_msg, send_attr, resp_msg, recv_attr, NtWaitTimeout.Infinite);
                RpcUtils.DumpBuffer(true, "ALPC Response Immediate", resp_msg);
                RpcClientResponse response = HandleResponse(resp_msg, recv_attr, req_msg.CallId);
                ClearAttributes(resp_msg, recv_attr);
                return(response);
            }
        }
Ejemplo n.º 3
0
        internal byte[] ProtectPDU(byte[] header, ref byte[] stub_data, int auth_padding_length, int send_sequence_no)
        {
            List <SecurityBuffer> buffers = new List <SecurityBuffer>();

            buffers.Add(new SecurityBufferInOut(SecurityBufferType.Data | SecurityBufferType.ReadOnly, header));
            var stub_data_buffer = new SecurityBufferInOut(SecurityBufferType.Data, stub_data);

            buffers.Add(stub_data_buffer);
            buffers.Add(new SecurityBufferInOut(SecurityBufferType.Data | SecurityBufferType.ReadOnly,
                                                AuthData.ToArray(TransportSecurity, auth_padding_length, ContextId, new byte[0])));

            byte[] signature = new byte[0];
            if (TransportSecurity.AuthenticationLevel == RpcAuthenticationLevel.PacketIntegrity)
            {
                signature = AuthContext.MakeSignature(buffers, send_sequence_no);
            }
            else if (TransportSecurity.AuthenticationLevel == RpcAuthenticationLevel.PacketPrivacy)
            {
                signature = AuthContext.EncryptMessage(buffers, SecurityQualityOfProtectionFlags.None, send_sequence_no);
                stub_data = stub_data_buffer.ToArray();
                RpcUtils.DumpBuffer(true, "Send Encrypted Data", stub_data);
            }

            if (signature.Length > 0)
            {
                RpcUtils.DumpBuffer(true, "Send Signature Data", signature);
            }

            return(AuthData.ToArray(TransportSecurity, auth_padding_length, ContextId, signature));
        }
Ejemplo n.º 4
0
        private Tuple <PDUHeader, byte[]> ReadPDU(int frag_count)
        {
            byte[] buffer = _pipe.Read(_max_recv_fragment);
            RpcUtils.DumpBuffer(true, $"RPC Named Pipe Receive Buffer - Fragment {frag_count}", buffer);
            MemoryStream stm    = new MemoryStream(buffer);
            BinaryReader reader = new BinaryReader(stm);
            PDUHeader    header = PDUHeader.Read(reader);

            NdrUnmarshalBuffer.CheckDataRepresentation(header.DataRep);
            if (header.AuthLength != 0)
            {
                throw new NotSupportedException("Named pipe transport doesn't support authentication data.");
            }
            return(Tuple.Create(header, reader.ReadAllBytes(header.FragmentLength - PDUHeader.PDU_HEADER_SIZE)));
        }
Ejemplo n.º 5
0
        private RpcClientResponse SendAndReceiveLarge(int proc_num, Guid objuuid, byte[] ndr_buffer, IReadOnlyCollection <NtObject> handles)
        {
            LRPC_LARGE_REQUEST_MESSAGE req_msg = new LRPC_LARGE_REQUEST_MESSAGE()
            {
                Header        = new LRPC_HEADER(LRPC_MESSAGE_TYPE.lmtRequest),
                BindingId     = 0,
                CallId        = CallId++,
                ProcNum       = proc_num,
                LargeDataSize = ndr_buffer.Length,
                Flags         = LRPC_REQUEST_MESSAGE_FLAGS.ViewPresent
            };

            if (objuuid != Guid.Empty)
            {
                req_msg.ObjectUuid = objuuid;
                req_msg.Flags     |= LRPC_REQUEST_MESSAGE_FLAGS.ObjectUuid;
            }

            var send_msg  = new AlpcMessageType <LRPC_LARGE_REQUEST_MESSAGE>(req_msg);
            var recv_msg  = new AlpcMessageRaw(0x1000);
            var send_attr = new AlpcSendMessageAttributes();

            if (handles.Count > 0)
            {
                send_attr.AddHandles(handles);
            }

            using (var port_section = _client.CreatePortSection(AlpcCreatePortSectionFlags.Secure, ndr_buffer.Length))
            {
                using (var data_view = port_section.CreateSectionView(AlpcDataViewAttrFlags.Secure | AlpcDataViewAttrFlags.AutoRelease, ndr_buffer.Length))
                {
                    data_view.WriteBytes(ndr_buffer);
                    send_attr.Add(data_view.ToMessageAttribute());
                    using (var recv_attr = new AlpcReceiveMessageAttributes())
                    {
                        RpcUtils.DumpBuffer(true, "ALPC Request Large", send_msg);
                        _client.SendReceive(AlpcMessageFlags.SyncRequest, send_msg, send_attr, recv_msg, recv_attr, NtWaitTimeout.Infinite);
                        RpcUtils.DumpBuffer(true, "ALPC Response Large", recv_msg);
                        RpcClientResponse response = HandleResponse(recv_msg, recv_attr, req_msg.CallId);
                        ClearAttributes(recv_msg, recv_attr);
                        return(response);
                    }
                }
            }
        }
        private Tuple <PDUHeader, byte[], AuthData> ReadPDU(int frag_count)
        {
            byte[] buffer = ReadFragment(_max_recv_fragment);
            RpcUtils.DumpBuffer(true, $"{GetType().Name} Receive Buffer - Fragment {frag_count}", buffer);
            MemoryStream stm    = new MemoryStream(buffer);
            BinaryReader reader = new BinaryReader(stm);
            PDUHeader    header = PDUHeader.Read(reader);

            NdrUnmarshalBuffer.CheckDataRepresentation(header.DataRep);
            AuthData auth_data            = new AuthData();
            int      auth_trailing_length = header.AuthLength > 0 ? header.AuthLength + AuthData.PDU_AUTH_DATA_HEADER_SIZE : 0;

            byte[] data = reader.ReadAllBytes(header.FragmentLength - PDUHeader.PDU_HEADER_SIZE - auth_trailing_length);
            if (auth_trailing_length > 0)
            {
                stm.Seek(header.FragmentLength - auth_trailing_length, SeekOrigin.Begin);
                auth_data = AuthData.Read(reader, header.AuthLength);
            }
            return(Tuple.Create(header, data, auth_data));
        }
Ejemplo n.º 7
0
        private void BindInterface(Guid interface_id, Version interface_version)
        {
            var bind_msg = new AlpcMessageType <LRPC_BIND_MESSAGE>(new LRPC_BIND_MESSAGE(interface_id, interface_version));

            RpcUtils.DumpBuffer(true, "ALPC BindInterface Send", bind_msg);
            var recv_msg = new AlpcMessageRaw(0x1000);

            using (var recv_attr = new AlpcReceiveMessageAttributes())
            {
                _client.SendReceive(AlpcMessageFlags.SyncRequest, bind_msg, null, recv_msg, recv_attr, NtWaitTimeout.Infinite);
                RpcUtils.DumpBuffer(true, "ALPC BindInterface Receive", recv_msg);
                using (var buffer = recv_msg.Data.ToBuffer())
                {
                    CheckForFault(buffer, LRPC_MESSAGE_TYPE.lmtBind);
                    var value = buffer.Read <LRPC_BIND_MESSAGE>(0);
                    if (value.RpcStatus != 0)
                    {
                        throw new NtException(NtObjectUtils.MapDosErrorToStatus(value.RpcStatus));
                    }
                }
            }
        }
Ejemplo n.º 8
0
        private PDUBase SendReceivePDU(PDUBase send_pdu)
        {
            try
            {
                CallId++;
                PDUHeader pdu_header = new PDUHeader()
                {
                    MajorVersion = PDUHeader.RPC_VERSION_MAJOR,
                    MinorVersion = PDUHeader.RPC_VERSION_MINOR,
                    DataRep      = _data_rep,
                    CallId       = CallId,
                    Type         = send_pdu.PDUType
                };

                List <byte[]> fragments = send_pdu.DoFragment(_max_send_fragment - PDUHeader.PDU_HEADER_SIZE);
                for (int i = 0; i < fragments.Count; ++i)
                {
                    pdu_header.Flags = send_pdu.GetFlags();
                    if (i == 0)
                    {
                        pdu_header.Flags |= PDUFlags.FirstFrag;
                    }
                    if (i == fragments.Count - 1)
                    {
                        pdu_header.Flags |= PDUFlags.LastFrag;
                    }

                    pdu_header.FragmentLength = (ushort)(fragments[i].Length + PDUHeader.PDU_HEADER_SIZE);
                    MemoryStream send_stm = new MemoryStream();
                    BinaryWriter writer   = new BinaryWriter(send_stm);
                    pdu_header.Write(writer);
                    writer.Write(fragments[i]);
                    byte[] fragment = send_stm.ToArray();
                    string name     = fragments.Count == 1 ? "RPC Named Pipe Send Buffer" : $"RPC Named Pipe Send Buffer - Fragment {i}";
                    RpcUtils.DumpBuffer(true, name, fragment);
                    if (_pipe.Write(fragment) != fragment.Length)
                    {
                        throw new RpcTransportException("Failed to write out PDU buffer.");
                    }
                }

                MemoryStream recv_stm    = new MemoryStream();
                PDUHeader    curr_header = new PDUHeader();
                int          frag_count  = 0;
                while ((curr_header.Flags & PDUFlags.LastFrag) == 0)
                {
                    var pdu = ReadPDU(frag_count++);
                    curr_header = pdu.Item1;
                    if (curr_header.CallId != CallId)
                    {
                        throw new RpcTransportException("Mismatching call ID.");
                    }
                    recv_stm.Write(pdu.Item2, 0, pdu.Item2.Length);
                }

                return(CheckFault(curr_header.ToPDU(recv_stm.ToArray())));
            }
            catch (EndOfStreamException)
            {
                throw new RpcTransportException("End of stream.");
            }
        }
        private byte[] SendReceiveRequestPDU(int proc_num, Guid objuuid, byte[] stub_data, RpcTransportSecurityContext security_context)
        {
            try
            {
                CallId++;
                PDURequest request_pdu = new PDURequest()
                {
                    OpNum      = (short)proc_num,
                    ObjectUUID = objuuid
                };

                int max_fragment     = _max_send_fragment - request_pdu.HeaderLength;
                int auth_data_length = 0;

                if (_auth_data_required)
                {
                    auth_data_length = security_context.AuthDataLength;
                    max_fragment    -= (auth_data_length + AuthData.PDU_AUTH_DATA_HEADER_SIZE);
                    max_fragment    &= ~0xF;
                }

                List <byte[]> fragments = PDURequest.DoFragment(stub_data, max_fragment);
                for (int i = 0; i < fragments.Count; ++i)
                {
                    PDUHeader pdu_header = new PDUHeader()
                    {
                        MajorVersion = PDUHeader.RPC_VERSION_MAJOR,
                        MinorVersion = PDUHeader.RPC_VERSION_MINOR,
                        DataRep      = _data_rep,
                        CallId       = CallId,
                        Type         = PDUType.Request
                    };

                    if (i == 0)
                    {
                        pdu_header.Flags |= PDUFlags.FirstFrag;
                    }
                    if (i == fragments.Count - 1)
                    {
                        pdu_header.Flags |= PDUFlags.LastFrag;
                    }

                    byte[] stub_fragment = fragments[i];
                    byte[] auth_data     = new byte[0];
                    byte[] header        = request_pdu.ToArray(pdu_header, stub_fragment.Length, 0);
                    if (_auth_data_required)
                    {
                        int auth_data_padding  = 0;
                        int auth_trailing_size = (header.Length + stub_fragment.Length + AuthData.PDU_AUTH_DATA_HEADER_SIZE) & 0xF;
                        if (auth_trailing_size != 0)
                        {
                            auth_data_padding = 16 - auth_trailing_size;
                            Array.Resize(ref stub_fragment, stub_fragment.Length + auth_data_padding);
                        }

                        header    = request_pdu.ToArray(pdu_header, stub_fragment.Length + AuthData.PDU_AUTH_DATA_HEADER_SIZE, auth_data_length);
                        auth_data = security_context.ProtectPDU(header, ref stub_fragment, auth_data_padding, _send_sequence_no);
                    }

                    MemoryStream send_stm = new MemoryStream();
                    BinaryWriter writer   = new BinaryWriter(send_stm);
                    writer.Write(header);
                    writer.Write(stub_fragment);
                    writer.Write(auth_data);
                    byte[] fragment = send_stm.ToArray();
                    string name     = fragments.Count == 1 ? $"{GetType().Name} Send Buffer" : $"{GetType().Name} Send Buffer - Fragment {i}";
                    RpcUtils.DumpBuffer(true, name, fragment);
                    if (!WriteFragment(fragment))
                    {
                        throw new RpcTransportException("Failed to write out PDU buffer.");
                    }
                    _send_sequence_no++;
                }

                MemoryStream recv_stm    = new MemoryStream();
                PDUHeader    curr_header = new PDUHeader();
                int          frag_count  = 0;
                while ((curr_header.Flags & PDUFlags.LastFrag) == 0)
                {
                    var pdu = ReadPDU(frag_count++);
                    curr_header = pdu.Item1;
                    AuthData auth_data = pdu.Item3;
                    if (curr_header.CallId != CallId)
                    {
                        throw new RpcTransportException($"Mismatching call ID - {curr_header.CallId} should be {CallId}.");
                    }

                    if (auth_data.ContextId != security_context.ContextId)
                    {
                        security_context = GetContext(auth_data.ContextId);
                    }

                    var recv_pdu = CheckFault(curr_header.ToPDU(pdu.Item2));
                    if (recv_pdu is PDUResponse resp_pdu)
                    {
                        byte[] resp_stub_data = _auth_data_required ? security_context.UnprotectPDU(resp_pdu.ToArray(curr_header),
                                                                                                    resp_pdu.StubData, auth_data, _recv_sequence_no) : resp_pdu.StubData;
                        _recv_sequence_no++;
                        recv_stm.Write(resp_stub_data, 0, resp_stub_data.Length);
                    }
                    else
                    {
                        throw new RpcTransportException($"Unexpected {recv_pdu.PDUType} PDU from server.");
                    }
                }

                return(recv_stm.ToArray());
            }
            catch (EndOfStreamException)
            {
                throw new RpcTransportException("End of stream.");
            }
        }
        private Tuple <PDUBase, AuthData> SendReceivePDU(int call_id, PDUBase send_pdu, byte[] auth_data,
                                                         bool receive_pdu, RpcTransportSecurityContext security_context)
        {
            try
            {
                int trailing_auth_length = auth_data.Length > 0 ? auth_data.Length + AuthData.PDU_AUTH_DATA_HEADER_SIZE : 0;

                PDUHeader pdu_header = new PDUHeader()
                {
                    MajorVersion = PDUHeader.RPC_VERSION_MAJOR,
                    MinorVersion = PDUHeader.RPC_VERSION_MINOR,
                    DataRep      = _data_rep,
                    CallId       = CallId,
                    Type         = send_pdu.PDUType,
                    Flags        = PDUFlags.LastFrag | PDUFlags.FirstFrag,
                    AuthLength   = checked ((ushort)auth_data.Length)
                };

                byte[] pdu_data        = send_pdu.ToArray();
                int    pdu_data_length = pdu_data.Length + PDUHeader.PDU_HEADER_SIZE;
                int    auth_padding    = 0;
                if (auth_data.Length > 0 && (pdu_data_length & 15) != 0 && send_pdu.PDUType != PDUType.Auth3)
                {
                    auth_padding = 16 - (pdu_data_length & 15);
                }

                pdu_header.FragmentLength = checked ((ushort)(pdu_data.Length + PDUHeader.PDU_HEADER_SIZE + trailing_auth_length + auth_padding));
                MemoryStream send_stm = new MemoryStream();
                BinaryWriter writer   = new BinaryWriter(send_stm);
                pdu_header.Write(writer);
                writer.Write(pdu_data);
                if (auth_data.Length > 0)
                {
                    writer.Write(new byte[auth_padding]);
                    new AuthData(security_context.TransportSecurity.AuthenticationType, security_context.TransportSecurity.AuthenticationLevel,
                                 auth_padding, security_context.ContextId, auth_data).Write(writer, auth_padding);
                }
                byte[] fragment = send_stm.ToArray();
                RpcUtils.DumpBuffer(true, $"{GetType().Name} Send Buffer", fragment);
                if (!WriteFragment(fragment))
                {
                    throw new RpcTransportException("Failed to write out PDU buffer.");
                }
                _send_sequence_no++;
                if (!receive_pdu)
                {
                    return(null);
                }

                var pdu         = ReadPDU(0);
                var curr_header = pdu.Item1;
                if (!curr_header.Flags.HasFlagAllSet(PDUFlags.LastFrag | PDUFlags.FirstFrag))
                {
                    throw new RpcTransportException($"Invalid PDU flags {curr_header.Flags}.");
                }

                if (curr_header.CallId != call_id)
                {
                    throw new RpcTransportException($"Mismatching call ID - {curr_header.CallId} should be {call_id}.");
                }

                if (pdu.Item3.ContextId != security_context.ContextId)
                {
                    throw new RpcTransportException($"Mismatching context ID - {pdu.Item3.ContextId} should be {security_context.ContextId}.");
                }

                _recv_sequence_no++;

                return(Tuple.Create(CheckFault(curr_header.ToPDU(pdu.Item2)), pdu.Item3));
            }
            catch (EndOfStreamException)
            {
                throw new RpcTransportException("End of stream.");
            }
        }