Method: Pwnlib::Util::Packing.unpack

Defined in:
lib/pwnlib/util/packing.rb

.unpack(data, bits: nil, endian: nil, signed: nil) ⇒ Integer

Unpack packed string back to integer.

bits indicates number of bits that should be used from input data.

bits can also be the string ‘all’, indicating that all bytes from input should be used.

Examples:

unpack('4', bits: 8) #=> 52
unpack("\x3F", bits: 6, signed: false) #=> 63
unpack("\x3F", bits: 6, signed: true) #=> -1

Parameters:

  • data (String)

    String to be unpacked.

  • bits (Integer, 'all') (defaults to: nil)

    Number of bits to be used from data, or ???all??? for all bits. Default to context.bits

  • endian (String) (defaults to: nil)

    Endian to use when unpacking. Can be any value accepted by context (See Context::ContextType). Default to context.endian.

  • signed (Boolean, String) (defaults to: nil)

    Whether the output number should be signed. Can be any value accepted by context (See Context::ContextType). Default to context.signed.

Returns:

  • (Integer)

    The unpacked number.

Raises:

  • (ArgumentError)

    When data.size doesn???t match bits.



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/pwnlib/util/packing.rb', line 130

def unpack(data, bits: nil, endian: nil, signed: nil)
  bits = data.size * 8 if bits == 'all'

  context.local(bits: bits, endian: endian, signed: signed) do
    bits = context.bits
    endian = context.endian
    signed = context.signed
    bytes = (bits + 7) / 8

    raise ArgumentError, "data.size=#{data.size} does not match with bits=#{bits}" unless data.size == bytes

    data = data.reverse if endian == 'little'
    data = data.unpack('C*')
    number = 0
    data.each { |c| number = (number << 8) + c }
    number &= (1 << bits) - 1
    if signed
      signbit = number & (1 << (bits - 1))
      number -= 2 * signbit
    end
    number
  end
end