def parse_http_response(sessions): http_data = {} host_counter = 0 for session, pkt in sessions.items(): for packet in sessions[session]: response_headers = [] if packet.haslayer(http.HTTPResponse): http_layer = packet.getlayer(http.HTTPResponse) #Raw response headers = str(http_layer).split("\\r\\n\\r\\n") hdrs = headers[0] post_body = http_layer.payload http_data[f"Host{host_counter}"] = {} http_data[f"Host{host_counter}"]["Http_Version"] = str( http_layer.Http_Version) http_data[f"Host{host_counter}"]["Status_Code"] = str( http_layer.Status_Code) temp = hdrs.split("\\r\\n") for i in range(1, len(temp)): #Example: 'Content-Encoding: gzip' . Split it to get a list which contains ['Content-Encoding', 'gzip'] hdr = temp[i].split(": ") http_data[f"Host{host_counter}"][hdr[0]] = str(hdr[1]) http_data[f"Host{host_counter}"]["POST_Body"] = str(post_body) http_data[f"Host{host_counter}"]["Raw Request"] = str( http_layer) #Extract images from POST Body and write to them to disk if ('Content-Type' or 'content-type' or 'Content-type' or 'content-Type') in http_data[f"Host{host_counter}"]: if re.search( '[iI]mage\/', str(http_data[f"Host{host_counter}"].values())): print(f"[+]Writing image to the disk...") rand_num = str(random.randrange( 1000000, 9999999999999)) h = f"Host_{host_counter}" dr = create_host_dir(h, rand_num) filename = f"{dr}/{rand_num}" with open(filename, 'wb') as f: #Convert scapy.packet.raw object to bytes object and write to a binary file f.write(bytes(post_body)) else: pass #other content types else: #print(f"[-]Key not found or Content-Type is not Image: ") pass host_counter += 1 return http_data
def get_leap_data(self, packet, client): leap_fields = packet.getlayer('LEAP').fields identity = None if 'name' in leap_fields: identity = leap_fields['name'] client.add_identity(17, identity) if 'data' in leap_fields and len(leap_fields['data']) == 24: client.add_ms_chap_info(17, response=leap_fields['data'], identity=identity) del leap_fields, identity
def get_eap_data(self, packet, bssid, client_mac): cert_layer = None eap_layer = packet.getlayer(EAP).payload conn_string = bssid + ' ' + client_mac frag_flag, len_flag = {'EAP_TLS':(64, 128), 'EAP_TTLS':(8, 16), 'PEAP':(16, 32), 'EAP_Fast':(8, 16)}[eap_layer.name] if eap_layer.flags & frag_flag and eap_layer.flags & len_flag: self.fragment_buffer[conn_string] = [eap_layer] elif eap_layer.flags & frag_flag: if conn_string in self.fragment_buffer: self.fragment_buffer[conn_string].append(eap_layer.payload) elif eap_layer.flags == 0 and conn_string in self.fragment_buffer: eap_layer = eap_layer.__class__(''.join([x.do_build() for x in self.fragment_buffer[conn_string]]) + eap_layer.payload.do_build()) # Take that people trying to read my code! Spencer 1, you 0. del self.fragment_buffer[conn_string] if eap_layer.haslayer('TLSv1Certificate'): # At this point, if possible, we should have a fully assembled packet cert_layer = eap_layer.getlayer('TLSv1Certificate') del eap_layer, conn_string, frag_flag, len_flag return cert_layer
def parse_http_reqs(sessions): http_data = {} host_counter = 0 for session, pkt in sessions.items(): for packet in sessions[session]: if packet.haslayer(http.HTTPRequest): http_layer = packet.getlayer(http.HTTPRequest) raw_req = str(http_layer) headers = str(http_layer).split("\\r\\n") #Remove last two garbage elements from headers list headers.pop( -1 ) # Remove "'" caused by str(packet[TCP].payload).split("\\r\\n") headers.pop( -1 ) # Remove '' caused by str(packet[TCP].payload).split("\\r\\n") #Store all HTTP headers, Raw request etc for this host in a dict 'http_data' http_data[f"Host{host_counter}"] = {} http_data[f"Host{host_counter}"]["Method"] = str( http_layer.Method) http_data[f"Host{host_counter}"]["Path"] = str(http_layer.Path) http_data[f"Host{host_counter}"]["HTTP_Version"] = str( packet[TCP].Http_Version ) #Not sure as to why http_layer.HTTP_Version does not work http_data[f"Host{host_counter}"]["Host"] = str(http_layer.Host) #Start from Index 2 because we already captured a few headers above. for i in range(2, len(headers)): hdr = headers[i].split(": ") http_data[f"Host{host_counter}"][hdr[0]] = hdr[1] http_data[f"Host{host_counter}"]["Raw_Request"] = raw_req host_counter += 1 return http_data
def get_leap_from_ap_data(self, packet, client): leap_fields = packet.getlayer('LEAP').fields if 'data' in leap_fields and len(leap_fields['data']) == 8: client.add_ms_chap_info(17, challenge=leap_fields['data'], identity=leap_fields['name']) del leap_fields
def get_wps_data(self, packet, network): wpsData = parse_wps_data(packet.getlayer('WPS').data) if network.wpsData is None: network.wpsData = wpsData else: network.wpsData.update(wpsData)
def get_client_wps_data(self, packet, client): wpsData = parse_wps_data(packet.getlayer('WPS').data) if client.wpsData is None: client.wpsData = wpsData else: client.wpsData.update(wpsData)
def parse_wireless_packet(self, packet): """ This is the core packet parsing routine. It takes a Scapy style packet object as an argument. """ if packet.name == 'RadioTap dummy': packet = packet.payload # Offset it so we start with the Dot11 header shouldStop = False self.packetCounter += 1 # this section finds SSIDs in Bacons if packet.haslayer('Dot11Beacon') or packet.haslayer('Dot11ProbeResp') or packet.haslayer('Dot11AssoReq'): self.update_maps(packet) shouldStop = True if shouldStop: return # This section extracts useful EAP info cert_layer = None if 'EAP' in packet: fields = packet.getlayer('EAP').fields if fields['code'] not in [1, 2]: return eaptype = fields['type'] for x in range(1, 4): addr = 'addr' + str(x) if not addr in packet.fields: return bssid = get_bssid(packet) if not bssid: return if bssid and not bssid in self.BSSIDToSSIDMap: self.BSSIDToSSIDMap[bssid] = bssid self.OrphanedBSSIDs.append(bssid) self.KnownNetworks[bssid] = eapeak.networks.WirelessNetwork(UNKNOWN_SSID_NAME) self.KnownNetworks[bssid].add_BSSID(bssid) network = self.KnownNetworks[self.BSSIDToSSIDMap[bssid]] client_mac = get_source(packet) from_AP = False if client_mac == bssid: client_mac = get_destination(packet) from_AP = True if not bssid or not client_mac: return if network.has_client(client_mac): client = network.get_client(client_mac) else: client = eapeak.clients.WirelessClient(bssid, client_mac) if from_AP: network.addEapType(eaptype) elif eaptype > 4: client.addEapType(eaptype) elif eaptype == 3 and fields['code'] == 2: # Parses NAKs and attempts to harvest the desired EAP types, RFC 3748 self.get_client_eap_types(fields, client) if eaptype == 254 and packet.haslayer('EAP_Expanded'): network.add_expanded_vendor_id(packet.getlayer('EAP_Expanded').vendor_id) if from_AP: if packet.haslayer('LEAP'): self.get_leap_from_ap_data(packet, client) elif packet.getlayer(EAP).payload.name in ['EAP_TLS', 'EAP_TTLS', 'PEAP', 'EAP_Fast']: cert_layer = self.get_eap_data(packet, bssid, client_mac) elif packet.haslayer('EAP_Expanded') and packet.getlayer('EAP_Expanded').vendor_type == 1 and packet.haslayer('WPS') and packet.getlayer('WPS').opcode == 4: try: self.get_wps_data(packet, network) except: # pylint: disable=bare-except pass else: if eaptype == 1 and 'identity' in fields: client.add_identity(1, fields['identity']) if packet.haslayer('LEAP'): self.get_leap_data(packet, client) elif packet.haslayer('EAP_Expanded') and packet.getlayer('EAP_Expanded').vendor_type == 1 and packet.haslayer('WPS') and packet.getlayer('WPS').opcode == 4: try: self.get_client_wps_data(packet, client) except: # pylint: disable=bare-except pass # Data is corrupted network.add_client(client) if not cert_layer: shouldStop = True if shouldStop: return if cert_layer and 'certificate' in cert_layer.fields: self.get_cert_data(network, cert_layer) return
def parseWirelessPacket(self, packet): """ This is the core packet parsing routine. It takes a Scapy style packet object as an argument. """ if packet.name == 'RadioTap dummy': packet = packet.payload # offset it so we start with the Dot11 header shouldStop = False self.packetCounter += 1 # this section finds SSIDs in Bacons, I don't like this section, but I do like bacon if packet.haslayer('Dot11Beacon') or packet.haslayer('Dot11ProbeResp') or packet.haslayer('Dot11AssoReq'): tmp = packet for x in range(0, SSID_SEARCH_RECURSION): if 'ID' in tmp.fields and tmp.fields['ID'] == 0 and 'info' in tmp.fields: # this line verifies that we found an SSID if tmp.fields['info'] == '\x00': break # null SSIDs are useless if self.targetSSIDs and tmp.fields['info'] not in self.targetSSIDs: # Obi says: These are not the SSIDs you are looking for... break bssid = getBSSID(packet) if not bssid: return ssid = ''.join([c for c in tmp.fields['info'] if ((ord(c) > 31 or ord(c) == 9) and ord(c) < 128)]) if not ssid: return if bssid in self.OrphanedBSSIDs: # if this info is relating to a BSSID that was previously considered to be orphaned newNetwork = self.KnownNetworks[bssid] # retrieve the old one del self.KnownNetworks[bssid] # delete the old network's orphaned reference self.OrphanedBSSIDs.remove(bssid) self.BSSIDToSSIDMap[bssid] = ssid # this changes the map from BSSID -> BSSID (for orphans) to BSSID -> SSID newNetwork.updateSSID(ssid) if ssid in self.KnownNetworks: newNetwork = mergeWirelessNetworks(newNetwork, self.KnownNetworks[ssid]) elif bssid in self.BSSIDToSSIDMap: continue elif ssid in self.KnownNetworks: # this is a BSSID from a probe for an SSID we've seen before newNetwork = self.KnownNetworks[ssid] # so pick up where we left off by using the curent state of the WirelessNetwork object elif bssid: newNetwork = eapeak.networks.WirelessNetwork(ssid) self.BSSIDToSSIDMap[bssid] = ssid newNetwork.addBSSID(bssid) self.KnownNetworks[ssid] = newNetwork del bssid, ssid break tmp = tmp.payload if tmp is None: break shouldStop = True if shouldStop: return # this section extracts useful EAP info cert_layer = None if 'EAP' in packet: fields = packet.getlayer('EAP').fields if fields['code'] not in [1, 2]: # don't bother parsing through success and failures just yet. return eaptype = fields['type'] for x in range(1, 4): addr = 'addr' + str(x) # outputs addr1, addr2, addr3 if not addr in packet.fields: return bssid = getBSSID(packet) if not bssid: return if bssid and not bssid in self.BSSIDToSSIDMap: self.BSSIDToSSIDMap[bssid] = bssid self.OrphanedBSSIDs.append(bssid) self.KnownNetworks[bssid] = eapeak.networks.WirelessNetwork(UNKNOWN_SSID_NAME) self.KnownNetworks[bssid].addBSSID(bssid) network = self.KnownNetworks[self.BSSIDToSSIDMap[bssid]] # objects should be returned, network to client should affect the client object as still in the BSSIDMap bssid = getBSSID(packet) client_mac = getSource(packet) from_AP = False if client_mac == bssid: client_mac = getDestination(packet) from_AP = True if not bssid or not client_mac: return # something went wrong if network.hasClient(client_mac): client = network.getClient(client_mac) else: client = eapeak.clients.WirelessClient(bssid, client_mac) if from_AP: network.addEapType(eaptype) elif eaptype > 4: client.addEapType(eaptype) elif eaptype == 3 and fields['code'] == 2: # this parses NAKs and attempts to harvest the desired EAP types, RFC 3748 if 'eap_types' in fields: for eap in fields['eap_types']: client.addEapType(eap) del eap if eaptype == 254 and packet.haslayer(EAP_Expanded): network.addExpandedVendorID(packet.getlayer(EAP_Expanded).vendor_id) if from_AP: # from here on we look for things based on whether it's to or from the AP if packet.haslayer('LEAP'): leap_fields = packet.getlayer(LEAP).fields if 'data' in leap_fields and len(leap_fields['data']) == 8: client.addMSChapInfo(17, challenge=leap_fields['data'], identity=leap_fields['name']) del leap_fields elif packet.getlayer(EAP).payload.name in ['EAP_TLS', 'EAP_TTLS', 'PEAP', 'EAP_Fast']: eap_layer = packet.getlayer(EAP).payload conn_string = bssid + ' ' + client_mac frag_flag, len_flag = {'EAP_TLS':(64, 128), 'EAP_TTLS':(8, 16), 'PEAP':(16, 32), 'EAP_Fast':(8, 16)}[eap_layer.name] if eap_layer.flags & frag_flag and eap_layer.flags & len_flag: self.fragment_buffer[conn_string] = [eap_layer] elif eap_layer.flags & frag_flag: if conn_string in self.fragment_buffer: self.fragment_buffer[conn_string].append(eap_layer.payload) elif eap_layer.flags == 0 and conn_string in self.fragment_buffer: eap_layer = eap_layer.__class__(''.join([x.do_build() for x in self.fragment_buffer[conn_string]]) + eap_layer.payload.do_build()) # take that people trying to read my code! Spencer 1, you 0. del self.fragment_buffer[conn_string] if eap_layer.haslayer('TLSv1Certificate'): # at this point, if possible, we should have a fully assembled packet cert_layer = eap_layer.getlayer(TLSv1Certificate) del eap_layer, conn_string, frag_flag, len_flag elif packet.haslayer('EAP_Expanded') and packet.getlayer('EAP_Expanded').vendor_type == 1 and packet.haslayer('WPS') and packet.getlayer('WPS').opcode == 4: try: wpsData = parseWPSData(packet.getlayer('WPS').data) if network.wpsData is None: network.wpsData = wpsData else: network.wpsData.update(wpsData) except: # pylint: disable=bare-except pass else: if eaptype == 1 and 'identity' in fields: client.addIdentity(1, fields['identity']) if packet.haslayer('LEAP'): leap_fields = packet.getlayer(LEAP).fields identity = None if 'name' in leap_fields: identity = leap_fields['name'] client.addIdentity(17, identity) if 'data' in leap_fields and len(leap_fields['data']) == 24: client.addMSChapInfo(17, response=leap_fields['data'], identity=identity) del leap_fields, identity elif packet.haslayer('EAP_Expanded') and packet.getlayer('EAP_Expanded').vendor_type == 1 and packet.haslayer('WPS') and packet.getlayer('WPS').opcode == 4: try: wpsData = parseWPSData(packet.getlayer('WPS').data) if client.wpsData is None: client.wpsData = wpsData else: client.wpsData.update(wpsData) except: # pylint: disable=bare-except pass # data is corrupted network.addClient(client) if not cert_layer: shouldStop = True if shouldStop: return if cert_layer and 'certificate' in cert_layer.fields: cert_data = cert_layer.certificate[3:] tmp_certs = [] while cert_data: if len(cert_data) < 4: break # length and 1 byte are at least 4 bytes tmp_length = struct.unpack('!I', '\x00' + cert_data[:3])[0] cert_data = cert_data[3:] if len(cert_data) < tmp_length: break # I smell corruption tmp_certs.append(cert_data[:tmp_length]) cert_data = cert_data[tmp_length:] for certificate in tmp_certs: try: certificate = X509.load_cert_string(certificate, X509.FORMAT_DER) except X509.X509Error: pass network.addCertificate(certificate) return