Class: Pwnlib::Context::ContextType

Inherits:
Object
  • Object
show all
Defined in:
lib/pwnlib/context.rb

Overview

The type for context. User should never need to initialize one by themself.

Constant Summary collapse

DEFAULT =
{
  arch: 'i386',
  bits: 32,
  endian: 'little',
  log_level: Logger::INFO,
  newline: "\n",
  os: 'linux',
  signed: false,
  timeout: :forever
}.freeze
OSES =
%w(linux freebsd windows).sort
BIG_32 =
{ endian: 'big', bits: 32 }.freeze
BIG_64 =
{ endian: 'big', bits: 64 }.freeze
LITTLE_8 =
{ endian: 'little', bits: 8 }.freeze
LITTLE_16 =
{ endian: 'little', bits: 16 }.freeze
LITTLE_32 =
{ endian: 'little', bits: 32 }.freeze
LITTLE_64 =
{ endian: 'little', bits: 64 }.freeze
ARCHS =
longest(
  'aarch64' => LITTLE_64,
  'alpha' => LITTLE_64,
  'avr' => LITTLE_8,
  'amd64' => LITTLE_64,
  'arm' => LITTLE_32,
  'cris' => LITTLE_32,
  'i386' => LITTLE_32,
  'ia64' => BIG_64,
  'm68k' => BIG_32,
  'mips' => LITTLE_32,
  'mips64' => LITTLE_64,
  'msp430' => LITTLE_16,
  'powerpc' => BIG_32,
  'powerpc64' => BIG_64,
  's390' => BIG_32,
  'sparc' => BIG_32,
  'sparc64' => BIG_64,
  'thumb' => LITTLE_32,
  'vax' => LITTLE_32
)
ENDIANNESSES =
longest(
  'be' => 'big',
  'eb' => 'big',
  'big' => 'big',
  'le' => 'little',
  'el' => 'little',
  'little' => 'little'
)
SIGNEDNESSES =
{
  'unsigned' => false,
  'no' => false,
  'yes' => true,
  'signed' => true
}.freeze
VALID_SIGNED =
SIGNEDNESSES.keys
LOG_LEVELS =

We use Logger#const_defined for pwnlib logger.

%w(DEBUG INFO WARN ERROR FATAL UNKNOWN).freeze

Instance Method Summary collapse

Constructor Details

#initialize(**kwargs) ⇒ ContextType

Instantiate a Pwnlib::Context::ContextType object.



85
86
87
88
# File 'lib/pwnlib/context.rb', line 85

def initialize(**kwargs)
  @attrs = DEFAULT.dup
  update(**kwargs)
end

Instance Method Details

#arch=(arch) ⇒ Object

Set the architecture of the target binary.

Parameters:

  • arch (String, Symbol)

    The architecture. Only values in ARCHS are available.

Raises:

  • (ArgumentError)

Difference with Python pwntools:

  • We always change bits and endian field whether user have already changed them.



185
186
187
188
189
190
191
192
# File 'lib/pwnlib/context.rb', line 185

def arch=(arch)
  arch = arch.to_s.downcase.gsub(/[[:punct:]]/, '')
  defaults = ARCHS[arch]
  raise ArgumentError, "arch must be one of #{ARCHS.keys.sort.inspect}" unless defaults

  defaults.each { |k, v| @attrs[k] = v }
  @attrs[:arch] = arch
end

#bits=(bits) ⇒ Object

Set the word size of the target machine in bits (i.e. the size of general purpose registers).

Parameters:

  • bits (Integer)

    The word size.

Raises:

  • (ArgumentError)


198
199
200
201
202
# File 'lib/pwnlib/context.rb', line 198

def bits=(bits)
  raise ArgumentError, "bits must be > 0 (#{bits} given)" unless bits.positive?

  @attrs[:bits] = bits
end

#bytesObject

The word size of the target machine.



205
206
207
# File 'lib/pwnlib/context.rb', line 205

def bytes
  bits / 8
end

#bytes=(bytes) ⇒ Object

Set the word size of the target machine in bytes (i.e. the size of general purpose registers).

Parameters:

  • bytes (Integer)

    The word size.



213
214
215
# File 'lib/pwnlib/context.rb', line 213

def bytes=(bytes)
  self.bits = bytes * 8
end

#clearObject

Clear the contents of the context, which will set all values to their defaults.

Examples:

context.arch = 'amd64'
context.clear
context.bits == 32
#=> true


148
149
150
# File 'lib/pwnlib/context.rb', line 148

def clear
  @attrs = DEFAULT.dup
end

#endian=(endian) ⇒ Object

The endianness of the target machine.

Examples:

context.endian = :big

Parameters:

  • endian (String, Symbol)

    The endianness. Only values in ENDIANNESSES are available.

Raises:

  • (ArgumentError)


224
225
226
227
228
229
# File 'lib/pwnlib/context.rb', line 224

def endian=(endian)
  endian = ENDIANNESSES[endian.to_s.downcase]
  raise ArgumentError, "endian must be one of #{ENDIANNESSES.sort.inspect}" if endian.nil?

  @attrs[:endian] = endian
end

#local(**kwargs) ⇒ Object

Create a context manager for a block.

Examples:

context.local(arch: 'amd64') { puts context.endian }
# little

Parameters:

  • kwargs (Hash)

    Variables to be assigned in the environment.

Returns:

  • This would return what the block returned.

Raises:

  • (ArgumentError)


126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/pwnlib/context.rb', line 126

def local(**kwargs)
  raise ArgumentError, "Need a block for #{self.class}##{__callee__}" unless block_given?

  # XXX(Darkpi):
  #   improve performance for this if this is too slow, since we use this in many places that has argument
  #   endian / signed / ...
  old_attrs = @attrs.dup
  begin
    update(**kwargs)
    yield
  ensure
    @attrs = old_attrs
  end
end

#log_level=(value) ⇒ Object

Set the verbosity of the logger in Pwnlib.

Examples:

context.log_level = :debug

Parameters:

  • value (String, Symbol)

    The verbosity. Only values in LOG_LEVELS are available.

Raises:

  • (ArgumentError)


238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/pwnlib/context.rb', line 238

def log_level=(value)
  log_level = nil
  case value
  when String, Symbol
    value = value.to_s.upcase
    log_level = Logger.const_get(value) if LOG_LEVELS.include?(value)
  when Integer
    log_level = value
  end
  raise ArgumentError, "log_level must be an integer or one of #{LOG_LEVELS.inspect}" unless log_level

  @attrs[:log_level] = log_level
end

#newline=(newline) ⇒ Object

Set the newline.

Examples:

context.newline = "\r\n"

Parameters:

  • newline (String)

    The newline.



164
165
166
# File 'lib/pwnlib/context.rb', line 164

def newline=(newline)
  @attrs[:newline] = newline
end

#os=(os) ⇒ Object

Set the operating system of the target machine.

Examples:

context.os = :windows

Parameters:

  • os (String, Symbol)

    The name of the os. Only values in OSES are available.

Raises:

  • (ArgumentError)


259
260
261
262
263
264
# File 'lib/pwnlib/context.rb', line 259

def os=(os)
  os = os.to_s.downcase
  raise ArgumentError, "os must be one of #{OSES.sort.inspect}" unless OSES.include?(os)

  @attrs[:os] = os
end

#signed=(value) ⇒ Object

Set the signedness for packing opreation.

Examples:

context.signed == false
#=> true
context.signed = 'signed'
context.signed == true
#=> true

Parameters:

  • value (String, Symbol, true, false)

    The signedness. Only values in SIGNEDNESSES are available.

Raises:

  • (ArgumentError)


277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/pwnlib/context.rb', line 277

def signed=(value)
  signed = nil
  case value
  when String, Symbol
    signed = SIGNEDNESSES[value.to_s.downcase]
  when true, false
    signed = value
  end
  raise ArgumentError, "signed must be boolean or one of #{SIGNEDNESSES.keys.sort.inspect}" if signed.nil?

  @attrs[:signed] = signed
end

#timeout=(timeout) ⇒ Object

Set the default amount of time to wait for a blocking operation before it times out.

Examples:

context.timeout = 5.14

Parameters:

  • timeout (Float, :forever)

    Any positive floating number, indicates timeout in seconds.



175
176
177
# File 'lib/pwnlib/context.rb', line 175

def timeout=(timeout)
  @attrs[:timeout] = timeout
end

#to_sObject

Create a string representation of self.



110
111
112
113
# File 'lib/pwnlib/context.rb', line 110

def to_s
  vals = @attrs.map { |k, v| "#{k} = #{v.inspect}" }
  "#{self.class}(#{vals.join(', ')})"
end

#update(**kwargs) ⇒ Object Also known as: [], call

Convenience function, which is shorthand for setting multiple variables at once.

Examples:

context.update(arch: 'amd64', os: :linux)

Parameters:

  • kwargs (Hash)

    Variables to be assigned in the environment.



97
98
99
100
101
102
103
104
# File 'lib/pwnlib/context.rb', line 97

def update(**kwargs)
  kwargs.each do |k, v|
    next if v.nil?

    public_send("#{k}=", v)
  end
  self
end