Skip to content

Instantly share code, notes, and snippets.

@IlluminatiFish
Last active June 5, 2021 03:34
Show Gist options
  • Save IlluminatiFish/ede8df9362a6c72a57bb6a93cea198f3 to your computer and use it in GitHub Desktop.
Save IlluminatiFish/ede8df9362a6c72a57bb6a93cea198f3 to your computer and use it in GitHub Desktop.
A quick python class, to find and identify a favicon for a given URL and calculating the favicon's murmur3 hash, which can be later used for favicon hash matching via services like Shodan
#
# This program is a utility used by myself that I have released
# to the public under the GPLv3 license
#
# Copyright (c) 2021 IlluminatiFish.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/.
#
import base64, mmh3, requests
from bs4 import BeautifulSoup
# Guess the refined method didn't work had to adjust and revert to a different method
def index(array, item):
try:
index_element = array.index(item)
return index_element
except ValueError:
return -1
class Centauri:
def __init__(self, url):
self.url = url
self.headers = {
'User-Agent': 'Centauri/0.1-BETA',
'Accept': '*/*'
}
def get_url(self):
possible_icon_locations = []
favicon_root_url = 'favicon.ico' if self.url.endswith('/') else '/favicon.ico'
root = requests.get(self.url + favicon_root_url, headers=self.headers)
if root.status_code == 200:
possible_icon_locations.append(self.url + favicon_root_url)
return possible_icon_locations[0]
response = requests.get(self.url, headers=self.headers)
soup = BeautifulSoup(response.text, 'html.parser')
for link_tag in soup.find_all('link'):
relational_link_sub_tag = link_tag.get('rel')
icon_exists = True
if index(relational_link_sub_tag, 'icon') == -1:
icon_exists = False
if not icon_exists:
continue
icon_check = relational_link_sub_tag[index(relational_link_sub_tag, 'icon')] == 'icon'
if 'icon' in relational_link_sub_tag and icon_check:
href_link_sub_tag = link_tag.get('href')
if href_link_sub_tag:
if href_link_sub_tag.startswith('//'):
location = self.url.split('//')[0] + href_link_sub_tag
elif href_link_sub_tag.startswith('/'):
if self.url.endswith('/'):
location = self.url[:-1] + '/' + href_link_sub_tag.split('/', 1)[1]
else:
location = self.url + '/' + href_link_sub_tag.split('/', 1)[1]
elif '/' in href_link_sub_tag:
if href_link_sub_tag.startswith('http://') or href_link_sub_tag.startswith('https://'):
location = href_link_sub_tag
else:
if self.url.endswith('/'):
location = self.url[:-1] + '/' + href_link_sub_tag
else:
location = self.url + '/' + href_link_sub_tag
possible_icon_locations.append(location)
if len(possible_icon_locations) > 0:
print('Possible Icons:', possible_icon_locations)
return list(set(possible_icon_locations))[0]
def get_hash(self, url):
if not url:
return None
response = requests.get(url, headers=self.headers)
favicon_b64_bytes = base64.encodebytes(response.content)
favicon_murmur3_hash = mmh3.hash(favicon_b64_bytes)
return favicon_murmur3_hash
url = ''
centauri = Centauri(url)
centauri_url = centauri.get_url()
print(centauri_url)
centauri_hash = centauri.get_hash(centauri_url)
print(centauri_hash)
# Amazon: 1941681276
# Facebook: -1321378357
# Twitter: -1831547740
# Microsoft: -2057558656
# Instagram: 1991136554
# Apple: -1498185948
# Paypal: 309020573
# Discord: -11132817
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment