Created
November 25, 2017 06:18
-
-
Save achillean/7190d53841865a8c9978f59863669857 to your computer and use it in GitHub Desktop.
Timelapse GIF Creator using the Shodan API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# gifcreator.py | |
# | |
# Dependencies: | |
# - arrow | |
# - shodan | |
# | |
# Installation: | |
# sudo easy_install arrow shodan | |
# sudo apt-get install imagemagick | |
# | |
# Usage: | |
# 1. Download a json.gz file using the website or the Shodan command-line tool (https://cli.shodan.io). | |
# For example: | |
# shodan download --limit=100 screenshots.json.gz has_screenshot:true | |
# 2. Run the tool on the file: | |
# python gifcreator.py screenshots.json.gz | |
import arrow | |
import os | |
import shodan | |
import shodan.helpers as helpers | |
import sys | |
# Settings | |
API_KEY = '' | |
# The user has to provide at least 1 Shodan data file | |
if len(sys.argv) < 2: | |
print('Usage: {} <shodan-data.json.gz> ...'.format(sys.argv[0])) | |
sys.exit(1) | |
# GIFs are stored in the local "data" directory | |
os.mkdir('data') | |
# Setup the Shodan API object | |
api = shodan.Shodan(API_KEY) | |
# Loop over all of the Shodan data files the user provided | |
for banner in helpers.iterate_files(sys.argv[1:]): | |
# See whether the current banner has a screenshot, if it does then lets lookup | |
# more information about this IP | |
has_screenshot = helpers.get_screenshot(banner) | |
if has_screenshot: | |
ip = helpers.get_ip(banner) | |
print('Looking up {}'.format(ip)) | |
host = api.host(ip, history=True) | |
# Store all the historical screenshots for this IP | |
screenshots = [] | |
for tmp_banner in host['data']: | |
# Try to extract the image from the banner data | |
screenshot = helpers.get_screenshot(tmp_banner) | |
if screenshot: | |
# Sort the images by the time they were collected so the GIF will loop | |
# based on the local time regardless of which day the banner was taken. | |
timestamp = arrow.get(banner['timestamp']).time() | |
sort_key = timestamp.hour | |
# Add the screenshot to the list of screenshots which we'll use to create the timelapse | |
screenshots.append(( | |
sort_key, | |
screenshot['data'] | |
)) | |
# Extract the screenshots and turn them into a GIF if we've got more than a few images | |
if len(screenshots) >= 3: | |
# screenshots is a list where each item is a tuple of: | |
# (sort key, screenshot in base64 encoding) | |
# | |
# Lets sort that list based on the sort key and then use Python's enumerate | |
# to generate sequential numbers for the temporary image filenames | |
for (i, screenshot) in enumerate(sorted(screenshots, key=lambda x: x[0], reverse=True)): | |
# Create a temporary image file | |
# TODO: don't assume that all images are "jpg", use the mimetype instead | |
open('/tmp/gif-image-{}.jpg'.format(i), 'w').write(screenshot[1].decode('base64')) | |
# Create the actual GIF using the ImageMagick "convert" command | |
# The resulting GIFs are stored in the local data/ directory | |
os.system('convert -layers OptimizePlus -delay 5x10 /tmp/gif-image-*.jpg -loop 0 +dither -colors 256 -depth 8 data/{}.gif'.format(ip)) | |
# Clean up the temporary files | |
os.system('rm -f /tmp/gif-image-*.jpg') | |
# Show a progress indicator | |
print('GIF created for {}'.format(ip)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment