class Rex::Proto::ACPP::Message

Attributes

password[RW]

@return [String] the password to attempt to authenticate with

payload[RW]

@return [String] the optional message payload

status[RW]

@return [Integer] the status of this message

type[RW]

@return [Integer] the type of this message

Public Class Methods

decode(data, validate_checksum = true) click to toggle source

Decodes the provided data into a Message

@param data [String] the data to parse as a Message @param validate_checksum [Boolean] true to validate the message and

payload checksums, false to not.  Defaults to true.

@return [Message] the decoded Message

# File lib/rex/proto/acpp/message.rb, line 125
def self.decode(data, validate_checksum = true)
  data = data.dup
  fail "Incorrect ACPP message size #{data.size} -- must be 128" unless data.size == 128
  fail 'Unexpected header' unless 'acpp' == data.slice!(0, 4)
  _unknown1 = data.slice!(0, 4)
  read_message_checksum = data.slice!(0, 4).unpack('N').first
  read_payload_checksum = data.slice!(0, 4).unpack('N').first
  _read_payload_size = data.slice!(0, 4).unpack('N').first
  _unknown2 = data.slice!(0, 8)
  type = data.slice!(0, 4).unpack('N').first
  status = data.slice!(0, 4).unpack('N').first
  _unknown3 = data.slice!(0, 12)
  password = Rex::Encoding::Xor::Generic.encode(data.slice!(0, 32), XOR_KEY).first.strip
  _unknown4 = data.slice!(0, 48)
  payload = data
  m = new
  m.type = type
  m.password = password
  m.status = status
  m.payload = payload

  # we can now validate the checksums if desired
  if validate_checksum
    actual_message_checksum = Zlib.adler32(m.with_checksum(0))
    if actual_message_checksum != read_message_checksum
      fail "Invalid message checksum (expected #{read_message_checksum}, calculated #{actual_message_checksum})"
    end
    # I'm not sure this can ever happen -- if the payload checksum is wrong, then the
    # message checksum will also be wrong.  So, either I misunderstand the protocol
    # or having two checksums is useless
    actual_payload_checksum = Zlib.adler32(payload)
    if actual_payload_checksum != read_payload_checksum
      fail "Invalid payload checksum (expected #{read_payload_checksum}, calculated #{actual_payload_checksum})"
    end
  end
  m
end
new() click to toggle source
# File lib/rex/proto/acpp/message.rb, line 83
def initialize
  @payload = ''
  @type = 0
  @status = 0
  @password = ''
  @unknown1 = 1
  @unknown2 = ''
  @unknown3 = ''
  @unknown4 = ''
end

Public Instance Methods

==(other) click to toggle source

Compares this Message and another Message for equality

@param other [Message] the Message to compare @return [Boolean] true iff the two messages are equal, false otherwise

# File lib/rex/proto/acpp/message.rb, line 112
def ==(other)
  other.type == @type &&
    other.status == @status &&
    other.password == @password &&
    other.payload == @payload
end
successful?() click to toggle source

Determines if this message has a successful status code

@return [Boolean] true iff @status is 0, false otherwise

# File lib/rex/proto/acpp/message.rb, line 97
def successful?
  @status == 0
end
to_s() click to toggle source

Get this Message as a String

@return [String] the string representation of this Message

# File lib/rex/proto/acpp/message.rb, line 104
def to_s
  with_checksum(Zlib.adler32(with_checksum(0)))
end
with_checksum(message_checksum) click to toggle source
# File lib/rex/proto/acpp/message.rb, line 163
def with_checksum(message_checksum)
  [
    'acpp',
    @unknown1,
    message_checksum,
    Zlib.adler32(@payload),
    @payload.size,
    @unknown2,
    @type,
    @status,
    @unknown3,
    Rex::Encoding::Xor::Generic.encode([@password].pack('a32').slice(0, 32), XOR_KEY).first,
    @unknown4,
    payload
  ].pack('a4NNNNa8NNa12a32a48a*')
end