ronin-rb/ronin-exploits

View on GitHub
lib/ronin/exploits/mixins/stack_overflow.rb

Summary

Maintainability
A
1 hr
Test Coverage
# frozen_string_literal: true
#
# ronin-exploits - A Ruby library for ronin-rb that provides exploitation and
# payload crafting functionality.
#
# Copyright (c) 2007-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
#
# ronin-exploits is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ronin-exploits is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with ronin-exploits.  If not, see <https://www.gnu.org/licenses/>.
#

require 'ronin/exploits/mixins/binary'
require 'ronin/exploits/mixins/nops'
require 'ronin/exploits/mixins/text'

module Ronin
  module Exploits
    module Mixins
      #
      # Methods for building Stack Overflow buffers.
      #
      # ## Example
      #
      #     include Mixins::StackOverflow
      #
      #     def build
      #       ebp = 0x06eb9090
      #       eip = 0x1001ae86
      #
      #       buffer = buffer_overflow(length: 1024, nops: 16, payload: payload, bp: ebp, ip: eip)
      #       # ...
      #     end
      #
      # If you want more control over how the buffer is constructed:
      #
      #     include Mixins::StackOverflow
      #
      #     def build
      #       ebp = 0x06eb9090
      #       eip = 0x1001ae86
      #
      #       buffer = junk(1024) + nops(16) + payload + stack_frame(ebp,eip)
      #       # ...
      #     end
      #
      # @api public
      #
      # @since 1.0.0
      #
      module StackOverflow
        include Binary
        include NOPS
        include Text

        #
        # Creates a new stack frame.
        #
        # @param [Integer] bp
        #   The stack base pointer address.
        #
        # @param [Integer] ip
        #   The instruction pointer address.
        #
        # @return [String]
        #   The new stack frame.
        #
        def stack_frame(bp,ip)
          pack(:machine_word,bp) + pack(:machine_word,ip)
        end

        #
        # Builds the stack overflow buffer containing the payload, nops, and a
        # stack frame.
        #
        # @param [Integer] length
        #   The desired total length of the buffer.
        #
        # @param [Integer, nil] nops
        #   The amount of NOP padding before the payload.
        #
        # @param [#to_s] payload
        #   The payload to add to the buffer.
        #
        # @param [Integer] bp
        #   The stack base pointer address.
        #
        # @param [Integer] ip
        #   The instruction pointer address.
        #
        # @return [String]
        #   The built buffer.
        #
        # @example
        #   ebp = 0x06eb9090 # short jump 6 bytes
        #   eip = 0x1001ae86 # pop pop ret 1001AE86 SSLEAY32.DLL
        #
        #   buffer = buffer_overflow(length: 1024, nops: 16, payload: payload, bp: ebp, ip: eip)
        #
        def buffer_overflow(length: , nops: nil, payload: , bp: , ip: )
          payload = payload.to_s
          payload = self.nops(nops) + payload if nops

          stack_frame = self.stack_frame(bp,ip)

          buffer = String.new(encoding: Encoding::ASCII_8BIT)
          buffer << junk(length - payload.bytesize - stack_frame.bytesize)
          buffer << payload
          buffer << stack_frame

          return buffer
        end
      end
    end
  end
end