Class: Ronin::Support::Binary::Stack

Inherits:
Object
  • Object
show all
Includes:
CTypes::Mixin
Defined in:
lib/ronin/support/binary/stack.rb

Overview

Represents a stack that can have binary data pushed to or popped from it.

Features

  • Supports configurable endianness and architecture.
  • Can dump out a formatting binary string for new a stack.
  • Can parse an existing stack dump string.
  • Supports negative indexing.

Examples

Creating a new stack:

stack = Binary::Stack.new
# => #<Ronin::Support::Binary::Stack: "">
stack.push 0x41414141
# => #<Ronin::Support::Binary::Stack: "AAAA\x00\x00\x00\x00">
stack.push 0x7fffffffdde0
# => #<Ronin::Support::Binary::Stack: "\xE0\xDD\xFF\xFF\xFF\x7F\x00\x00AAAA\x00\x00\x00\x00">
stack.push -1
# => #<Ronin::Support::Binary::Stack: "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\xDD\xFF\xFF\xFF\x7F\x00\x00AAAA\x00\x00\x00\x00">
stack.to_s
# => => "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\xDD\xFF\xFF\xFF\x7F\x00\x00AAAA\x00\x00\x00\x00"

Creating a stack from an existing String:

stack = Binary::Stack.new("\x41\x00\x00\x00\x00\x00\x00\x00\x42\x00\x00\x00\x00\x00\x00\x00")
stack[0]
# => 65
stack[8]
# => 66

Negative indexing within the stack:

stack.push(65)
stack.push(66)
stack[-8]
# => 65
stack[-16]
# => 66

Note: negative indexes are treated relative to the beginning of the stack, since stacks grow downward in the address space.

Since:

  • 1.0.0

Instance Attribute Summary collapse

Attributes included from CTypes::Mixin

#arch, #endian, #os, #type_resolver, #type_system

Instance Method Summary collapse

Methods included from CTypes::Mixin

#initialize_type_system

Constructor Details

#initialize(string = nil, **kwargs) ⇒ Stack

Initializes the stack.

The desired architecture for the values within the stack.

Parameters:

  • string (String, nil) (defaults to: nil)

    Optional existing stack contents.

  • kwargs (Hash{Symbol => Object})

    Additional keyword arguments.

Options Hash (**kwargs):

  • :endian (:little, :big, :net, nil)

    The desired endianness of the values within the stack.

  • :arch (:x86, :x86_64, :ppc, :ppc64, :mips, :mips_le, :mips_be, :mips64, :mips64_le, :mips64_be, :arm, :arm_le, :arm_be, :arm64, :arm64_le, :arm64_be)

Since:

  • 1.0.0



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/ronin/support/binary/stack.rb', line 118

def initialize(string=nil, **kwargs)
  initialize_type_system(**kwargs)

  @machine_word = @type_system::MACHINE_WORD

  if string
    @string = string
    @size   = @string.bytesize
    @length = @size / @machine_word.size
  else
    @string = String.new
    @size   = 0
    @length = 0
  end
end

Instance Attribute Details

#lengthInteger (readonly)

The number of machine words on the stack.

Returns:

Since:

  • 1.0.0



86
87
88
# File 'lib/ronin/support/binary/stack.rb', line 86

def length
  @length
end

#machine_wordCTypes::UInt32Type, CTypes::UInt64Type (readonly)

The "machine word" from the CTypes::Mixin#type_system.

Returns:

Since:

  • 1.0.0



81
82
83
# File 'lib/ronin/support/binary/stack.rb', line 81

def machine_word
  @machine_word
end

#sizeInteger (readonly)

The size of the stack in bytes.

Returns:

Since:

  • 1.0.0



91
92
93
# File 'lib/ronin/support/binary/stack.rb', line 91

def size
  @size
end

#stringString (readonly)

The underlying buffer for the stack.

Returns:

Since:

  • 1.0.0



96
97
98
# File 'lib/ronin/support/binary/stack.rb', line 96

def string
  @string
end

Instance Method Details

#[](index) ⇒ Integer

Note:

negative offsets are treated as relative to the bottom or the beginning of the stack, since stack grow downward in the address space.

Accesses a machine word at the given index within the stack.

Parameters:

  • index (Integer)

    The byte offset within the stack to read from.

Returns:

  • (Integer)

    The value at the index within the stack.

Raises:

  • (IndexError)

Since:

  • 1.0.0



150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/ronin/support/binary/stack.rb', line 150

def [](index)
  offset = if index < 0 then @size + index
           else              index
           end

  if (offset + @machine_word.size) > @size
    raise(IndexError,"index #{index} is out of bounds: 0...#{@size}")
  end

  data = @string[offset,@machine_word.size]
  return @machine_word.unpack(data)
end

#[]=(index, value) ⇒ Integer

Note:

negative offsets are treated as relative to the bottom or the beginning of the stack, since stacks grow downward in the address space.

Sets a machine word at the given index within the stack.

Parameters:

  • index (Integer)

    The byte offset within the stack to write to.

  • value (Integer)

    The value to write at the index within the stack.

Returns:

Raises:

  • (IndexError)

Since:

  • 1.0.0



182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/ronin/support/binary/stack.rb', line 182

def []=(index,value)
  offset = if index < 0 then @size + index
           else              index
           end

  if (offset + @machine_word.size) > @size
    raise(IndexError,"index #{index} is out of bounds: 0...#{@size}")
  end

  @string[offset,@machine_word.size] = @machine_word.pack(value)
  return value
end

#inspectString

Inspects the stack object.

Returns:

Since:

  • 1.0.0



248
249
250
# File 'lib/ronin/support/binary/stack.rb', line 248

def inspect
  "#<#{self.class}: #{@string.inspect}>"
end

#popInteger

Pops a value off the top of the stack (or to the end of the underlying buffer).

Returns:

  • (Integer)

    The value popped from the stack.

Since:

  • 1.0.0



220
221
222
223
224
225
226
227
228
229
# File 'lib/ronin/support/binary/stack.rb', line 220

def pop
  data  = @string.byteslice(0,@machine_word.size)
  value = @machine_word.unpack(data)

  @length -= 1
  @size   -= @machine_word.size

  @string = @string.byteslice(@machine_word.size,@size)
  return value
end

#push(value) ⇒ self

Pushes a value onto the top of the stack (or to the end of the underlying buffer).

Parameters:

  • value (Integer)

    The value to push onto the stack.

Returns:

  • (self)

Since:

  • 1.0.0



204
205
206
207
208
209
210
211
# File 'lib/ronin/support/binary/stack.rb', line 204

def push(value)
  data = @machine_word.pack(value)

  @string.insert(0,data)
  @length += 1
  @size   += @machine_word.size
  return self
end

#to_sString Also known as: to_str

Cnnverts the stack into a String.

Returns:

  • (String)

    The underlying buffer for the stack.

Since:

  • 1.0.0



237
238
239
# File 'lib/ronin/support/binary/stack.rb', line 237

def to_s
  @string
end