I am trying to follow a webpage in creating a visual network tracker using google maps, wireshark and python. I understand how it all works but my code seems to only be printing the header and footer.
I am guessing the code is not reading the pcap file correctly but do not see where to fix it. Any help would be greatly appreciated.
The website I was following is https://medium.com/vinsloev-academy/python-cybersecurity-network-tracking-using-wireshark-and-google-maps-2adf3e497a93
My code can be seen below;
import dpkt
import socket
import pygeoip
def plotIPs(pcap):
kmlPts = ''
for (ts, buf) in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
src = socket.inet_ntoa(ip.src)
dst = socket.inet_ntoa(ip.dst)
KML = retKML(dst, src)
kmlPts = kmlPts + KML
except:
pass
return kmlPts
def retKML(dstip, srcip):
dst = gi.record_by_name(dstip)
src = gi.record_by_name('x.xxx.xxx.xxx')
try:
dstlongitude = dst['longitude']
dstlatitude = dst['latitude']
srclongitude = src['longitude']
srclatitude = src['latitude']
kml = (
'<Placemark>\n'
'<name>%s</name>\n'
'<extrude>1</extrude>\n'
'<tessellate>1</tessellate>\n'
'<styleUrl>#transBluePoly</styleUrl>\n'
'<LineString>\n'
'<coordinates>%6f,%6f\n%6f,%6f</coordinates>\n'
'</LineString>\n'
'</Placemark>\n'
)%(dstip, dstlongitude, dstlatitude, srclongitude, srclatitude)
return kml
except:
return ''
def main():
f = open('DataCapture.pcap', 'rb')
pcap = dpkt.pcap.Reader(f)
kmlheader = '<?xml version="1.0" encoding="UTF-8"?> \n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>\n'\
'<Style id="transBluePoly">' \
'<LineStyle>' \
'<width>1.5</width>' \
'<color>501400E6</color>' \
'</LineStyle>' \
'</Style>'
kmlfooter = '</Document>\n</kml>\n'
kmldoc=kmlheader+plotIPs(pcap)+kmlfooter
print(kmldoc)
if __name__ == '__main__':
main()
Firstly, you are not using the full power of exception handling to see your errors, you are just using pass or return ''. So you don't know what is going on. Try printing the exception at least or a traceback.
Then you are missing the line in your example:
gi = pygeoip.GeoIP('GeoLiteCity.dat')
And you must have GeoLiteCity.dat in your path.
You are returning strings from your function calls, this is not a good idea and that is where I think your code is failing.
Then you are manipulating strings to create an XML document. This is not the best practice but I know the tutorial you used did it. I'm using minidom in this example:
import traceback
import dpkt
import socket
import pygeoip
from xml.dom import minidom
gi = pygeoip.GeoIP('GeoLiteCity.dat')
def plot_ips(pcap) -> list:
kml_pts = []
for (ts, buf) in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
src = socket.inet_ntoa(ip.src)
dst = socket.inet_ntoa(ip.dst)
kml = ret_kml(dst, src)
kml_pts.append(kml)
except Exception as ex:
print(str(ex))
traceback.print_exc()
return kml_pts
def ret_kml(dst_ip, src_ip) -> dict:
dst = gi.record_by_name(dst_ip)
src = gi.record_by_name(src_ip)
# print(dst)
# print(src)
try:
return {
"dst_ip": dst_ip,
"src_ip": src_ip,
"dst_longitude": dst['longitude'],
"dst_latitude": dst['latitude'],
"src_longitude": src['longitude'],
"src_latitude": src['latitude']
}
except KeyError as ex:
print(f"KeyError {ex}")
traceback.print_exc()
return {}
def main():
f = open('DataCapture.pcap', 'rb')
pcap = dpkt.pcap.Reader(f)
root = minidom.Document()
kml = root.createElement('kml')
kml.setAttribute('xmlns', "http://www.opengis.net/kml/2.2")
root.appendChild(kml)
document = root.createElement('Document')
kml.appendChild(document)
style = root.createElement('Style')
style.setAttribute("id", "transBluePoly")
document.appendChild(style)
line_style = root.createElement("LineStyle")
style.appendChild(line_style)
width = root.createElement("width")
width_text = root.createTextNode("1.5")
width.appendChild(width_text)
line_style.appendChild(width)
color = root.createElement("color")
color_text = root.createTextNode("501400E6")
color.appendChild(color_text)
line_style.appendChild(color)
try:
for record in plot_ips(pcap):
# print(record)
place_mark = root.createElement('Placemark')
name = root.createElement('name')
name_text = root.createTextNode(record.get('dst_ip'))
name.appendChild(name_text)
place_mark.appendChild(name)
extrude = root.createElement('extrude')
extrude_text = root.createTextNode('1')
extrude.appendChild(extrude_text)
place_mark.appendChild(extrude)
tessellate = root.createElement('tessellate')
tessellate_text = root.createTextNode('1')
tessellate.appendChild(tessellate_text)
place_mark.appendChild(tessellate)
style_url = root.createElement('styleUrl')
style_url_text = root.createTextNode('#transBluePoly')
style_url.appendChild(style_url_text)
place_mark.appendChild(style_url)
line_string = root.createElement('LineString')
coordinates = root.createElement('coordinates')
coordinates_text = root.createTextNode(
f"{record.get('dst_ip')},{record.get('dst_longitude')},{record.get('dst_latitude')},"
f"{record.get('src_longitude')},{record.get('src_latitude')}"
)
coordinates.appendChild(coordinates_text)
line_string.appendChild(coordinates)
place_mark.appendChild(line_string)
document.appendChild(place_mark)
print(root.toprettyxml())
except Exception as ex:
print(str(ex))
traceback.print_exc()
if __name__ == '__main__':
main()
Using the file from https://wiki.wireshark.org/uploads/__moin_import__/attachments/SampleCaptures/ipv4frags.pcap renamed to DataCapture.pcap my code produces the following output:
<?xml version="1.0" ?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Style id="transBluePoly">
<LineStyle>
<width>1.5</width>
<color>501400E6</color>
</LineStyle>
</Style>
<Placemark>
<name>2.1.1.1</name>
<extrude>1</extrude>
<tessellate>1</tessellate>
<styleUrl>#transBluePoly</styleUrl>
<LineString>
<coordinates>2.1.1.1,2.3386999999999887,48.85820000000001,2.3386999999999887,48.85820000000001</coordinates>
</LineString>
</Placemark>
<Placemark>
<name>2.1.1.1</name>
<extrude>1</extrude>
<tessellate>1</tessellate>
<styleUrl>#transBluePoly</styleUrl>
<LineString>
<coordinates>2.1.1.1,2.3386999999999887,48.85820000000001,2.3386999999999887,48.85820000000001</coordinates>
</LineString>
</Placemark>
<Placemark>
<name>2.1.1.2</name>
<extrude>1</extrude>
<tessellate>1</tessellate>
<styleUrl>#transBluePoly</styleUrl>
<LineString>
<coordinates>2.1.1.2,2.3386999999999887,48.85820000000001,2.3386999999999887,48.85820000000001</coordinates>
</LineString>
</Placemark>
</Document>
</kml>
I have not checked the syntax for Google Maps so it may need some tweaking.