class Rex::Nop::Opty2

This class provides an interface to generating multi-byte NOP sleds for x86. Optyx and spoonm get the creds!

Constants

Table

Public Class Methods

new(badchars = '', save_registers = nil) click to toggle source
# File lib/rex/nop/opty2.rb, line 17
def initialize(badchars = '', save_registers = nil)
  self.badchars       = badchars
  self.save_registers = (save_registers || []) | [ 'esp', 'ebp']
end

Public Instance Methods

generate_sled(length) click to toggle source

Generates the Opty2 multi-byte NOP sled.

# File lib/rex/nop/opty2.rb, line 25
def generate_sled(length)
  return '' if (length <= 0)

  # Initialize the sled buffer, the previous state, and the current stream
  # length.
  sled = ''
  prev = 256
  slen = 0

  # Initialize the byte count array
  counts = []

  256.times { |idx| counts[idx] = 0 }

  # Initialize the bad register mask
  mask = 0

  save_registers.each { |reg|
    mask |= 1 << (Rex::Arch::X86.reg_number(reg))
  }
  mask = mask << 16

  # Initialize the bad byte lookup table
  bad_bytes = []
  (badchars || '').each_byte { |byte|
    bad_bytes[byte] = 1
  }

  # Build the sled
  while (length > 0)
    low  = -1
    lows = []

    Table[prev].each { |nt|
      nt.each { |e|
        # Skip it if it's masked off or too large
        next if ((e & mask) != 0)
        next if (((e >> 8) & 0xff) > slen)

        byte = e & 0xff

        # Skip it if it's a bad byte
        next if (bad_bytes[byte] == 1)

        # Use it if it's a better value
        if ((low == -1) or (low > counts[byte]))
          low  = counts[byte]
          lows = [byte]
        # Otherwise, if it's just as good..
        elsif (low == counts[byte])
          lows << byte
        end
      }
    }

    # If we didn't find at least one byte possibility, then we're stuck.
    # Abort.
    if (low == -1)
      raise RuntimeError, "Failed to find a valid byte."
    end

    # Pick a random character for the possiblities
    prev = lows[rand(lows.length)]

    # Increment its used count
    counts[prev] += 1

    # Prepend the byte to the sled
    sled = prev.chr + sled

    # Increment the sled length
    slen   += 1
    length -= 1
  end

  # Return the sled
  sled
end