ronin-rb/ronin-exploits

View on GitHub
lib/ronin/exploits/mixins/seh.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/text'
require 'ronin/exploits/mixins/binary'
require 'ronin/exploits/mixins/nops'

module Ronin
  module Exploits
    module Mixins
      #
      # Methods for building Structured Exception Handler (SEH) buffer
      # overflows.
      #
      # ## Example
      #
      #     include Mixins::SEH
      #
      #     def build
      #       nseh = 0x06eb9090 # short jump 6 bytes
      #       seh  = 0x1001ae86 # pop pop ret 1001AE86 SSLEAY32.DLL
      #
      #       buffer = seh_buffer_overflow(length: 1024, nops: 16, payload: payload, nseh: nseh, seh: seh)
      #       # ...
      #     end
      #
      # If you want more control over how the buffer is constructed:
      #
      #     include Mixins::SEH
      #
      #     def build
      #       nseh = 0x06eb9090 # short jump 6 bytes
      #       seh  = 0x1001ae86 # pop pop ret 1001AE86 SSLEAY32.DLL
      #
      #       buffer = junk(1024) + seh_record(nseh,seh) + nops(16) + payload
      #       # ...
      #     end
      #
      # @api public
      #
      # @since 1.0.0
      #
      module SEH
        include Text
        include Binary
        include NOPS

        #
        # Creates a SEH record.
        #
        # @param [Integer] nseh
        #   The address to the next SEH record.
        #
        # @param [Integer] seh
        #   The address to the SEH exception handler for the record that we
        #   want to call.
        #
        # @return [String]
        #   The SEH record.
        #
        # @example
        #   nseh = 0x06eb9090 # short jump 6 bytes
        #   seh  = 0x1001ae86 # pop pop ret 1001AE86 SSLEAY32.DLL
        #
        #   buffer = junk(1024) + seh_record(nseh,seh) + nops(16) + payload
        #
        # @api public
        #
        def seh_record(nseh,seh)
          pack(:machine_word,nseh) + pack(:machine_word,seh)
        end

        #
        # Builds a SEH buffer overflow.
        #
        # @param [Integer] length
        #   The desired length of the buffer.
        #
        # @param [Integer, nil] nops
        #   The optional amount of NOPs to add before the payload.
        #
        # @param [#to_s] payload
        #   The payload to add to the buffer.
        #
        # @param [Integer] nseh
        #   The address to the next SEH record.
        #
        # @param [Integer] seh
        #   The address to the SEH exception handler for the record that we
        #   want to call.
        #
        # @return [String]
        #   The SEH buffer overflow.
        #
        # @example
        #   nseh = 0x06eb9090 # short jump 6 bytes
        #   seh  = 0x1001ae86 # pop pop ret 1001AE86 SSLEAY32.DLL
        #
        #   buffer = seh_buffer_overflow(length: 1024, nops: 16, payload: payload, nseh: nseh, seh: seh)
        #
        # @api public
        #
        def seh_buffer_overflow(length: , nops: nil, payload: , nseh: , seh: )
          payload = payload.to_s
          payload = self.nops(nops) + payload if nops

          seh_record = self.seh_record(nseh,seh)

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

          return buffer
        end
      end
    end
  end
end