Class: Rex::Poly::LogicalBlock

Inherits:
Object
  • Object
show all
Defined in:
lib/rex/poly/block.rb

Overview

This class represents a logical block which is defined as a concise portion of code that may have one or more functionally equivalent implementations. A logical block should serve a very specific purpose, and any permutations beyond the first should result in exactly the same functionality without any adverse side effects to other blocks.

Like blocks of code, LogicalBlock’s can depend on one another in terms of ordering and precedence. By marking blocks as dependent on another, a hierarchy begins to form. This is a block dependency graph.

To add permutations to a LogicalBlock, they can either be passed in as a list of arguments to the constructor following the blocks name or can be added on the fly by calling the add_perm method. To get a random permutation, the rand_perm method can be called.

To mark one block as depending on another, the depends_on method can be called with zero or more LogicalBlock instances as parameters.

Direct Known Subclasses

SymbolicBlock::End

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, *perms) ⇒ LogicalBlock

Initializes the logical block’s name along with zero or more specific blocks.



75
76
77
78
79
80
81
# File 'lib/rex/poly/block.rb', line 75

def initialize(name, *perms)
	@name  = name

	reset

	add_perm(*perms)
end

Instance Attribute Details

#generatedObject

Whether or not this block has currently been generated for a given iteration.



312
313
314
# File 'lib/rex/poly/block.rb', line 312

def generated
  @generated
end

#offsetObject

This attributes contains the currently assigned offset of the permutation associated with this block into the polymorphic buffer that is being generated.



306
307
308
# File 'lib/rex/poly/block.rb', line 306

def offset
  @offset
end

Instance Method Details

#add_perm(*perms) ⇒ Object

Adds zero or more specific permutations that may be represented either as strings or as Proc’s to be called at evaluation time.



150
151
152
# File 'lib/rex/poly/block.rb', line 150

def add_perm(*perms)
	@perms.concat(perms)
end

#clobbers(*registers) ⇒ Object

Defines the list of zero or more LogicalRegister’s that this block clobbers.



217
218
219
# File 'lib/rex/poly/block.rb', line 217

def clobbers(*registers)
	@clobbers = registers
end

#depends_on(*depends) ⇒ Object

Sets the blocks that this block instance depends on.



198
199
200
201
202
203
# File 'lib/rex/poly/block.rb', line 198

def depends_on(*depends)
	@depends = depends.dup

	# Increment dependent references
	@depends.each { |b| b.ref }
end

#derefObject

Increments the number of blocks that have completed their dependency pass on this block. This number should never become higher than the



135
136
137
# File 'lib/rex/poly/block.rb', line 135

def deref
	@used_references += 1
end

#each_clobbers(&block) ⇒ Object

Enumerates each register instance that is clobbered by this block.



224
225
226
# File 'lib/rex/poly/block.rb', line 224

def each_clobbers(&block)
	@clobbers.each(&block)
end

#generate(save_registers = nil, state = nil, badchars = nil) ⇒ Object

Generates the polymorphic buffer that results from this block and any of the blocks that it either directly or indirectly depends on. A list of register numbers to be saved can be passed in as an argument.

This method is not thread safe. To call this method on a single block instance from within multiple threads, be sure to encapsulate the calls inside a locked context.



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/rex/poly/block.rb', line 237

def generate(save_registers = nil, state = nil, badchars = nil)
	# Create a localized state instance if one was not supplied.
	state = Rex::Poly::State.new if (state == nil)
	buf   = nil
	cnt   = 0

	# This is a lame way of doing this.  We just try to generate at most 128
	# times until we don't have badchars.  The reason we have to do it this
	# way is because of the fact that badchars can be introduced through
	# block offsetting and register number selection which can't be readily
	# predicted or detected during the generation phase.  In the future we
	# can make this better, but for now this will have to do.
	begin
		buf = do_generate(save_registers, state, badchars)

		if (buf and 
		    (badchars.nil? or Rex::Text.badchar_index(buf, badchars).nil?))
			break
		end
	end while ((cnt += 1) < 128)

	# If we passed 128 tries, then we can't succeed.
	buf = nil if (cnt >= 128)

	buf
end

#last_reference?Boolean

Returns true if there is only one block reference remaining.

Returns:

  • (Boolean)


142
143
144
# File 'lib/rex/poly/block.rb', line 142

def last_reference?
	(@references - @used_references <= 0)
end

#nameObject

Returns the block’s name.



102
103
104
# File 'lib/rex/poly/block.rb', line 102

def name
	@name
end

#next_blocks(*blocks) ⇒ Object

Defines the next blocks, but not in a dependency fashion but rather in a linking of separate block contexts.



209
210
211
# File 'lib/rex/poly/block.rb', line 209

def next_blocks(*blocks)
	@next_blocks = blocks.dup
end

#offset_of(lblock) ⇒ Object

Returns the offset of a block. If the active state for this instance is operating in the first phase, then zero is always returned. Otherwise, the correct offset for the supplied block is returned.



269
270
271
272
273
274
275
276
277
278
279
# File 'lib/rex/poly/block.rb', line 269

def offset_of(lblock)
	if (@state.first_phase) 
		0 
	else
		if (lblock.kind_of?(SymbolicBlock::End))
			@state.curr_offset
		else
			lblock.offset
		end
	end
end

#onceObject

Returns true if this block is a ‘once’ block. That is, this block is dependend upon by multiple blocks but should only be generated once.



119
120
121
# File 'lib/rex/poly/block.rb', line 119

def once
	@once
end

#once=(tf) ⇒ Object

Flags whether or not the block should only be generated once. This can be used to mark a blog as being depended upon by multiple blocks, but making it such that it is only generated once.



111
112
113
# File 'lib/rex/poly/block.rb', line 111

def once=(tf)
	@once = tf
end

#rand_permObject

Returns a random permutation that is encapsulated in a Permutation class instance.



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/rex/poly/block.rb', line 158

def rand_perm
	perm = nil

	if (@state.badchars)
		perm = rand_perm_badchars
	else
		perm = Permutation.new(@perms[rand(@perms.length)], self)
	end

	if (perm.nil?)
		raise RuntimeError, "Failed to locate a valid permutation."
	end

	perm
end

#rand_perm_badcharsObject

Returns a random permutation that passes any necessary bad character checks.



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/rex/poly/block.rb', line 178

def rand_perm_badchars
	idx = rand(@perms.length)
	off = 0

	while (off < @perms.length)
		p = @perms[(idx + off) % @perms.length]

		if (p.kind_of?(Proc) or
		    @state.badchars.nil? or 
		    Rex::Text.badchar_index(p, @state.badchars).nil?)
			return Permutation.new(p, self)
		end

		off += 1
	end
end

#refObject

Increments the number of blocks that depend on this block.



126
127
128
# File 'lib/rex/poly/block.rb', line 126

def ref
	@references += 1
end

#regnum_of(reg) ⇒ Object

Returns the register number associated with the supplied LogicalRegister instance. If the active state for this instance is operating in the first phase, then zero is always returned. Otherwise, the correct register number is returned based on what is currently assigned to the supplied LogicalRegister instance, if anything.



288
289
290
# File 'lib/rex/poly/block.rb', line 288

def regnum_of(reg)
	(@state.first_phase) ? 0 : reg.regnum
end

#resetObject

Resets the block back to its starting point.



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/rex/poly/block.rb', line 86

def reset
	@perms           = []
	@depends         = []
	@next_blocks     = []
	@clobbers        = []
	@offset          = nil
	@state           = nil
	@once            = false
	@references      = 0
	@used_references = 0
	@generated       = false
end

#size_of(lblock) ⇒ Object



292
293
294
295
296
297
298
299
# File 'lib/rex/poly/block.rb', line 292

def size_of(lblock)
	@state.block_list.map { |b, p|
		if b == lblock
			return p.length
		end
	}
	0
end