def __bytes__(self) -> bytes: variable_chunk = b'' binary_path_name_ndr = ConformantVaryingString(representation=self.binary_path_name) load_order_group_ndr = ConformantVaryingString(representation=self.load_order_group) dependencies_ndr = ConformantVaryingString(representation='\x00'.join(self.dependencies)) service_start_name_ndr = ConformantVaryingString(representation=self.service_start_name) display_name_ndr = ConformantVaryingString(representation=self.display_name) ndr_strings = ( binary_path_name_ndr, load_order_group_ndr, dependencies_ndr, service_start_name_ndr, display_name_ndr ) for ndr_string in ndr_strings: variable_chunk += bytes(ndr_string) variable_chunk += ((4 - (len(variable_chunk) % 4)) % 4) * b'\x00' return b''.join([ struct_pack('<I', self.service_type.value), struct_pack('<I', self.start_type.value), struct_pack('<I', self.error_control.value), struct_pack('<I', Pointer(representation=b'').referent_id), struct_pack('<I', Pointer(representation=b'').referent_id), struct_pack('<I', self.tag_id), struct_pack('<I', Pointer(representation=b'').referent_id), struct_pack('<I', Pointer(representation=b'').referent_id), struct_pack('<I', Pointer(representation=b'').referent_id), variable_chunk ])
def from_bytes(cls, data: bytes) -> ROpenSCManagerWRequest: machine_name = ConformantVaryingString.from_bytes(data=Pointer.from_bytes(data=data).representation) machine_name_len: int = len(machine_name) offset = Pointer.structure_size + machine_name_len + ((4 - (machine_name_len % 4)) % 4) database_name = ConformantVaryingString.from_bytes(data=Pointer.from_bytes(data=data[offset:]).representation) database_name_len: int = len(database_name) offset += Pointer.structure_size + database_name_len + ((4 - (database_name_len % 4)) % 4) return cls( machine_name=machine_name.representation, desired_access=SCManagerAccessFlagMask.from_int(struct_unpack('<I', data[offset:offset + 4])[0]), database_name=DatabaseName(database_name.representation) if database_name else None )
def __bytes__(self) -> bytes: return b''.join([ self.key_handle, ndr_pad(bytes(RRPUnicodeString(representation=self.sub_key_name))), ndr_pad(bytes(RRPUnicodeString(representation=self.class_name))), self._OPTIONS_STRUCT.pack(int(self.options)), self._SAM_DESIRED_STRUCT.pack(int(self.sam_desired)), ndr_pad( bytes( Pointer(representation=bytes(self.security_attributes)))), bytes( Pointer(representation=self._DISPOSITION_STRUCT.pack( self.disposition))) ])
def from_bytes(cls, data: bytes) -> Tuple[ShareInfo1Container, int]: entries_read: int = struct_unpack('<I', data[:4])[0] pointer_data = Pointer.from_bytes(data[4:]).representation max_count = struct_unpack('<I', pointer_data[:4])[0] offset = 4 entry_share_type_list: List[ShareType] = [] for _ in range(entries_read): entry_share_type_list.append( ShareType.from_int(struct_unpack('<I', pointer_data[offset+4:offset+8])[0]) ) offset += 12 entries: List[ShareInfo1] = [] for i in range(entries_read): netname_cvs = ConformantVaryingString.from_bytes(data=pointer_data[offset:]) offset += calculate_pad_length(len(netname_cvs)) remark_cvs = ConformantVaryingString.from_bytes(pointer_data[offset:]) offset += calculate_pad_length(len(remark_cvs)) entries.append( ShareInfo1( netname=netname_cvs.representation, share_type=entry_share_type_list[i], remark=remark_cvs.representation ) ) return cls(entries=tuple(entries)), 8 + offset
def __bytes__(self) -> bytes: server_name_bytes = bytes( Pointer(representation=ConformantVaryingString( representation=self.server_name or ''))) return b''.join([ ndr_pad(server_name_bytes), bytes( ShareEnumStruct( share_info=ShareInfoContainer.from_level_and_params( level=self.level))), struct_pack('<i', self.preferred_maximum_length), bytes( Pointer(representation=self.resume_handle) if self. resume_handle else NullPointer()) ])
def __bytes__(self) -> bytes: return b''.join([ self.service_handle, struct_pack('<I', self.argc), bytes( Pointer(representation=b''.join([ struct_pack('<I', len(self.argv)), b''.join( struct_pack('<I', Pointer(representation=b'').referent_id) for _ in self.argv), b''.join( ndr_pad(data=bytes( ConformantVaryingString( representation=argument_string))) for argument_string in self.argv) ])) if self.argv else NullPointer()) ])
def from_bytes(cls, data: ByteString, base_offset: int = 0, strict: bool = False) -> BaseRegCreateKeyRequest: data = memoryview(data)[base_offset:] offset = 0 key_handle: bytes = cls._KEY_HANDLE_STRUCT.unpack_from( buffer=data, offset=offset)[0] offset += cls._KEY_HANDLE_STRUCT.size ndr_sub_key_name = RRPUnicodeString.from_bytes(data=data[offset:]) offset += calculate_pad_length(len(ndr_sub_key_name)) ndr_class_name = RRPUnicodeString.from_bytes(data=data[offset:]) offset += calculate_pad_length(len(ndr_class_name)) options = RegOptions.from_int(value=cls._OPTIONS_STRUCT.unpack_from( buffer=data, offset=offset)[0]) offset += cls._OPTIONS_STRUCT.size sam_desired = Regsam.from_int( value=cls._SAM_DESIRED_STRUCT.unpack_from(buffer=data, offset=offset)[0]) offset += cls._SAM_DESIRED_STRUCT.size security_attributes_pointer = Pointer.from_bytes(data=data, base_offset=offset) offset += Pointer.structure_size security_attributes = RPCSecurityAttributes.from_bytes( data=security_attributes_pointer.representation) offset += calculate_pad_length(len(security_attributes)) disposition_pointer = Pointer.from_bytes(data=data, base_offset=offset) offset += Pointer.structure_size disposition = Disposition( cls._DISPOSITION_STRUCT.unpack_from( buffer=disposition_pointer.representation)[0]) return cls(key_handle=key_handle, sub_key_name=ndr_sub_key_name.representation, class_name=ndr_class_name.representation, options=options, sam_desired=sam_desired, security_attributes=security_attributes, disposition=disposition)
def __bytes__(self) -> bytes: dependencies_ndr = Pointer( representation=UnidimensionalConformantArray(representation=tuple( bytes([byte]) for byte in '\x00'.join(self.dependencies).encode( encoding='utf-16-le')))) if len( self.dependencies) != 0 else NullPointer() password_ndr = Pointer(representation=UnidimensionalConformantArray( representation=tuple( bytes([byte]) for byte in (self.password + '\x00').encode(encoding='utf-16-le') ))) if self.password is not None else NullPointer() return b''.join([ self.scm_handle, ndr_pad(data=bytes( ConformantVaryingString(representation=self.service_name))), ndr_pad(data=bytes( Pointer(representation=ConformantVaryingString( representation=self.display_name)))), struct_pack('<I', int(self.desired_access)), struct_pack('<I', self.service_type.value), struct_pack('<I', self.start_type.value), struct_pack('<I', self.error_control.value), ndr_pad(data=bytes( ConformantVaryingString( representation=self.binary_path_name))), ndr_pad(data=bytes( Pointer(representation=ConformantVaryingString( representation=self.load_order_group)) if self. load_order_group is not None else NullPointer())), struct_pack('<I', self.tag_id), ndr_pad(data=bytes(dependencies_ndr)), struct_pack('<I', (0 if isinstance(dependencies_ndr, NullPointer) else len(dependencies_ndr.representation) - UnidimensionalConformantArray.STRUCTURE_SIZE)), ndr_pad(data=bytes( Pointer(representation=ConformantVaryingString( representation=self.service_start_name)) if self. service_start_name is not None else NullPointer())), ndr_pad(data=bytes(password_ndr)), struct_pack('<I', (0 if isinstance(password_ndr, NullPointer) else len(password_ndr.representation) - UnidimensionalConformantArray.STRUCTURE_SIZE)) ])
def __bytes__(self) -> bytes: return b''.join([ self.key_handle, bytes( Pointer(representation=self._DISPOSITION_STRUCT.pack( self.disposition))), self._RETURN_CODE_STRUCT.pack(self.return_code) ])
def __bytes__(self) -> bytes: security_descriptor_len = self.in_security_descriptor return b''.join([ bytes( Pointer(representation=bytes(self.security_descriptor)) if self.security_descriptor is not None else NullPointer()), self._IN_SECURITY_DESCRIPTOR_STRUCT.pack(security_descriptor_len), self._OUT_SECURITY_DESCRIPTOR_STRUCT.pack(security_descriptor_len) ])
def __bytes__(self) -> bytes: machine_name_bytes = bytes( Pointer(representation=ConformantVaryingString(representation=self.machine_name or '')) ) database_name_bytes = bytes( Pointer( representation=ConformantVaryingString( representation=self.database_name.value if self.database_name else '' ) ) ) return b''.join([ ndr_pad(machine_name_bytes), ndr_pad(database_name_bytes), struct_pack('<I', int(self.desired_access)) ])
def __bytes__(self) -> bytes: if len(self.representation) == 0: pointer = NullPointer() string_len = 0 else: pointer = Pointer(representation=ConformantVaryingString( representation=self.representation)) string_len = len(self.representation_bytes) return b''.join( [pack('<H', string_len), pack('<H', string_len), bytes(pointer)])
def __bytes__(self) -> bytes: fixed_part: bytes = b'' variable_part: bytes = b'' for entry in self.entries: netname_pointer = Pointer(representation=ConformantVaryingString(representation=entry.netname)) remark_pointer = Pointer(representation=ConformantVaryingString(representation=entry.remark)) fixed_part += b''.join([ struct_pack('<I', netname_pointer.referent_id), struct_pack('<I', int(entry.share_type)), struct_pack('<I', remark_pointer.referent_id) ]) variable_part += b''.join([ ndr_pad(bytes(netname_pointer.representation)), ndr_pad(bytes(remark_pointer.representation)) ]) return b''.join([ struct_pack('<I', self.entries_read), b''.join([fixed_part, variable_part]) or b'\x00\x00\x00\x00' ])
def unpack_structure(data: ByteString, structure: dict[str, tuple[Type, ...]], offset: int = 0) -> dict[str, Any]: data = memoryview(data)[offset:] offset = 0 structure_values: dict[str, Any] = {} for value_name, item_types in structure.items(): item_data = data[offset:] item_types_deque: Deque[Type] = deque(item_types) while True: try: item_type = item_types_deque.popleft() except IndexError: break if item_type in {LPDWORD, LPBYTE, LPBYTE_VAR}: item_types_deque.extendleft(reversed(get_args(item_type))) elif item_type in {DWORD}: struct = CTYPE_TO_STRUCT[item_type.__supertype__] item_data = struct.unpack_from(buffer=item_data)[0] offset += struct.size elif item_type is Pointer: pointer = Pointer.from_bytes(data=item_data) item_data = pointer.representation offset += Pointer.structure_size else: if isinstance(item_data, (ByteString, memoryview)): item_data = item_type.from_bytes(item_data) if issubclass(item_type, NDRType): offset += calculate_pad_length( length_unpadded=len(item_data)) else: offset += len(item_data) if hasattr(item_data, 'representation'): item_data = item_data.representation else: item_data = item_type(item_data) structure_values[value_name] = item_data return structure_values
def from_bytes(cls, data: ByteString, base_offset: int = 0) -> RPCSecurityDescriptor: data = memoryview(data)[base_offset:] offset = 0 security_descriptor_pointer = Pointer.from_bytes(data=data, base_offset=offset) security_descriptor = SecurityDescriptor.from_bytes( data=security_descriptor_pointer.representation) if not isinstance( security_descriptor_pointer, NullPointer) else None # TODO: Parse `cbInSecurityDescriptor` and `cbOutSecurityDescriptor`? return cls(security_descriptor=security_descriptor)
def from_bytes(cls, data: bytes) -> RChangeServiceConfigWRequest: offset = cls.STRUCTURE_SIZE attribute_name_class_pair = ( ('binary_path_name', ConformantVaryingString), ('load_order_group', ConformantVaryingString), ('dependencies', UnidimensionalConformantArray), ('service_start_name', ConformantVaryingString), ('password', UnidimensionalConformantArray), ('display_name', ConformantVaryingString) ) kwargs = {} for attribute_name, attribute_class in attribute_name_class_pair: # Skip attributes in between variable ones. if attribute_name in {'dependencies', 'service_start_name', 'display_name'}: offset += 4 attribute_pointer = Pointer.from_bytes(data=data[offset:]) attribute_ndr = ( attribute_class.from_bytes(data=attribute_pointer.representation) if not isinstance(attribute_pointer, NullPointer) else None ) attribute_len = len(attribute_ndr) if attribute_ndr is not None else 0 if attribute_name == 'dependencies': kwargs[attribute_name] = tuple( b''.join(attribute_ndr.representation).decode(encoding='utf-16-le').split('\x00') ) if attribute_ndr else tuple() elif attribute_name == 'password': kwargs[attribute_name] = b''.join(attribute_ndr.representation).decode(encoding='utf-16-le').rstrip('\x00') else: kwargs[attribute_name] = attribute_ndr.representation if attribute_ndr is not None else None offset += calculate_pad_length(length_unpadded=attribute_pointer.structure_size+attribute_len, multiple=4) service_type_int_val: int = struct_unpack('<I', data[20:24])[0] start_type_int_val: int = struct_unpack('<I', data[24:28])[0] error_control_int_val: int = struct_unpack('<I', data[28:32])[0] return cls( service_handle=data[:20], service_type=ServiceType(service_type_int_val) if service_type_int_val != SERVICE_NO_CHANGE else None, start_type=StartType(start_type_int_val) if start_type_int_val != SERVICE_NO_CHANGE else None, error_control=ErrorControl(error_control_int_val) if error_control_int_val != SERVICE_NO_CHANGE else None, **kwargs )
def from_bytes(cls, data: bytes) -> RStartServiceWRequest: argc = struct_unpack('<I', data[20:24]) argv_ndr_representation = Pointer.from_bytes( data=data[24:]).representation num_argv: int = struct_unpack('<I', argv_ndr_representation[:4])[0] offset = 4 + num_argv * Pointer.structure_size argv_list: List[str] = [] for _ in range(num_argv): argv_ndr_string = ConformantVaryingString.from_bytes( data=argv_ndr_representation[offset:]) argv_list.append(argv_ndr_string.representation) offset += calculate_pad_length( length_unpadded=len(argv_ndr_string), multiple=4) return cls(service_handle=data[:20], argv=tuple(argv_list))
def from_bytes(cls, data: bytes) -> NetrShareEnumResponse: # TODO: Make this more concise. info_struct, num_info_struct_bytes = ShareEnumStruct.from_bytes( data=data) offset = num_info_struct_bytes total_entries = struct_unpack('<I', data[offset:offset + 4])[0] offset += 4 resume_handle = Pointer.from_bytes(data=data[offset:offset + 8]).representation offset += len(resume_handle) return cls(info_struct=info_struct, total_entries=total_entries, resume_handle=resume_handle, return_code=Win32ErrorCode( struct_unpack('<I', data[offset:offset + 4])[0]))
def from_bytes(cls, data: ByteString, base_offset: int = 0) -> BaseRegSaveKeyRequest: data = memoryview(data)[base_offset:] offset = 0 key_handle: bytes = cls._KEY_HANDLE_STRUCT.unpack_from(buffer=data, offset=base_offset)[0] offset += cls._KEY_HANDLE_STRUCT.size ndr_save_path = RRPUnicodeString.from_bytes(data=data, base_offset=offset) offset += calculate_pad_length(length_unpadded=len(ndr_save_path)) security_attributes_ndr_pointer = Pointer.from_bytes(data=data, base_offset=offset) offset += Pointer.structure_size security_attributes = RPCSecurityAttributes.from_bytes(data=security_attributes_ndr_pointer.representation) offset += calculate_pad_length(length_unpadded=len(security_attributes)) return cls( key_handle=key_handle, save_path=ndr_save_path.representation, security_attributes=security_attributes )
def from_bytes(cls, data: ByteString, base_offset: int = 0) -> BaseRegCreateKeyResponse: data = memoryview(data)[base_offset:] offset = 0 key_handle: bytes = cls._KEY_HANDLE_STRUCT.unpack_from( buffer=data, offset=offset)[0] offset += cls._KEY_HANDLE_STRUCT.size disposition = Disposition( cls._DISPOSITION_STRUCT.unpack_from( Pointer.from_bytes(data=data, base_offset=offset).representation)[0]) offset += Pointer.structure_size + cls._DISPOSITION_STRUCT.size return_code = Win32ErrorCode( cls._RETURN_CODE_STRUCT.unpack_from(buffer=data, offset=offset)[0]) return cls(key_handle=key_handle, disposition=disposition, return_code=return_code)
def __bytes__(self) -> bytes: return b''.join([ self.key_handle, ndr_pad(bytes(RRPUnicodeString(representation=str(self.save_path)))), bytes(Pointer(representation=bytes(self.security_attributes))) ])
def from_bytes(cls, data: bytes) -> RCreateServiceWRequest: attribute_name_class_pair = (('service_name', ConformantVaryingString), ('display_name', ConformantVaryingString), ('desired_access', ServiceAccessFlagMask.from_int), ('service_type', ServiceType), ('start_type', StartType), ('error_control', ErrorControl), ('binary_path_name', ConformantVaryingString), ('load_order_group', ConformantVaryingString), ('tag_id', None), ('dependencies', UnidimensionalConformantArray), ('_depen_size', None), ('service_start_name', ConformantVaryingString), ('password', UnidimensionalConformantArray), ('_pw_size', None)) kwargs = {} offset = 20 for attribute_name, attribute_class in attribute_name_class_pair: if attribute_name in {'_depen_size', '_pw_size'}: offset += 4 continue if attribute_name in {'service_name', 'binary_path_name'}: ndr_string = attribute_class.from_bytes(data=data[offset:]) kwargs[attribute_name] = ndr_string.representation offset += calculate_pad_length(length_unpadded=len(ndr_string)) elif attribute_name in { 'service_type', 'start_type', 'error_control', 'desired_access' }: kwargs[attribute_name] = attribute_class( struct_unpack('<I', data[offset:offset + 4])[0]) offset += 4 elif attribute_name == 'tag_id': kwargs[attribute_name] = struct_unpack( '<I', data[offset:offset + 4])[0] offset += 4 else: attribute_pointer = Pointer.from_bytes(data=data[offset:]) attribute_ndr = (attribute_class.from_bytes( data=attribute_pointer.representation) if not isinstance(attribute_pointer, NullPointer) else None) attribute_len = len( attribute_ndr) if attribute_ndr is not None else 0 if attribute_name == 'dependencies': kwargs[attribute_name] = tuple(b''.join( attribute_ndr.representation).decode( encoding='utf-16-le').split( '\x00')) if attribute_ndr else tuple() elif attribute_name == 'password' and attribute_ndr is not None: kwargs[attribute_name] = b''.join( attribute_ndr.representation).decode( encoding='utf-16-le').rstrip('\x00') else: kwargs[ attribute_name] = attribute_ndr.representation if attribute_ndr is not None else None offset += calculate_pad_length( length_unpadded=attribute_pointer.structure_size + attribute_len) return cls(scm_handle=data[:20], **kwargs)