def find_alpc_endpoints(targetiid, version=(1, 0), nb_response=1, sid=gdef.WinLocalSystemSid): """Ask the EPMapper for ALPC endpoints of ``targetiid:version`` (maximum of ``nb_response``) :param str targetiid: The IID of the requested interface :param (int,int) version: The version requested interface :param int nb_response: The maximum number of response :param WELL_KNOWN_SID_TYPE sid: The SID used to request the EPMapper :returns: [:class:`~windows.rpc.epmapper.UnpackTower`] -- A list of :class:`~windows.rpc.epmapper.UnpackTower` """ if isinstance(targetiid, basestring): targetiid = gdef.IID.from_string(targetiid) # Connect to epmapper client = windows.rpc.RPCClient(r"\RPC Control\epmapper") epmapperiid = client.bind("e1af8308-5d1f-11c9-91a4-08002b14a0fa", version=(3, 0)) # Compute request tower ## object rpc_object = gdef.RPC_IF_ID(targetiid, *version) ## Syntax syntax_iid = gdef.IID.from_string("8a885d04-1ceb-11c9-9fe8-08002b104860") rpc_syntax = gdef.RPC_IF_ID(syntax_iid, 2, 0) ## Forge tower tower_array_size, towerarray = construct_alpc_tower( rpc_object, rpc_syntax, "ncalrpc", b"", None) # parameters local_system_psid = windows.utils.get_known_sid(sid) context = (0, 0, 0, 0, 0) # Pack request fullreq = EptMapAuthParameters.pack([ bytearray(targetiid), (tower_array_size, towerarray), local_system_psid, context, nb_response ]) # RPC Call response = client.call(epmapperiid, 7, fullreq) # Unpack response stream = ndr.NdrStream(response) unpacked = EptMapAuthResults.unpack(stream) # Looks like there is a memory leak here (in stream.data) if nb_response > len(unpacked[2]) # Parse towers return [explode_alpc_tower(obj) for obj in unpacked[2]]
def _forge_bind_request(self, uuid, syntaxversion, requested_if_nb): version_major, version_minor = syntaxversion req = ALPC_RPC_BIND() req.request_type = gdef.RPC_REQUEST_TYPE_BIND req.target = gdef.RPC_IF_ID(uuid, *syntaxversion) req.flags = gdef.BIND_IF_SYNTAX_NDR32 req.if_nb_ndr32 = requested_if_nb req.if_nb_ndr64 = 0 req.if_nb_unkn = 0 req.register_multiple_syntax = False req.some_context_id = 0xB00B00B return buffer(req)[:]
def explode_alpc_tower(tower): stream = ndr.NdrStream(bytearray(tower)) size = stream.partial_unpack("<I")[0] if size != len(stream.data): raise ValueError( "Invalid tower size: indicate {0}, tower size {1}".format( size, len(stream.data))) floor_count = stream.partial_unpack("<H")[0] if floor_count != 4: raise ValueError( "ALPC Tower are expected to have 4 floors ({0} instead)".format( floor_count)) # Floor 0 lhs, rhs = parse_floor(stream) if not (lhs[0] == 0xd): raise ValueError("Floor 0: IID expected") iid = gdef.IID.from_buffer_copy(lhs[1:17]) object = gdef.RPC_IF_ID(iid, lhs[17], lhs[18]) # Floor 1 lhs, rhs = parse_floor(stream) if not (lhs[0] == 0xd): raise ValueError("Floor 0: IID expected") iid = gdef.IID.from_buffer_copy(lhs[1:17]) syntax = gdef.RPC_IF_ID(iid, lhs[17], lhs[18]) # Floor 2 lhs, rhs = parse_floor(stream) if (len(lhs) != 1 or lhs[0] != 0x0c): raise ValueError( "Alpc Tower expects 0xc as Floor2 LHS (got {0:#x})".format(lhs[0])) lhs, rhs = parse_floor(stream) if not (rhs[-1] == 0): rhs = rhs[:rhs.find("\x00")] # raise ValueError("ALPC Port name doest not end by \\x00") return UnpackTower("ncalrpc", bytes(rhs[:-1]), None, object, syntax)