Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
initial push of beta code
  • Loading branch information
dmille6 authored Jul 24, 2024
1 parent 54ddb01 commit 89e68f9
Show file tree
Hide file tree
Showing 9 changed files with 513 additions and 0 deletions.
4 changes: 4 additions & 0 deletions config.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
shodan_api: '<put shodan API here>'
shodan_query: <common shodan query>
data_retention: 90 #days
scan_interval: 30 #days
Binary file not shown.
Binary file added library/__pycache__/shodan_lib.cpython-312.pyc
Binary file not shown.
141 changes: 141 additions & 0 deletions library/jsonDataStore_lib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import os
import json
from datetime import datetime, timedelta, timezone
from colorama import Fore, Back, Style, init

##############################################################################
# jsonDataStore Class
# Description: VERY basic way of storing information in a json formatted text file.
# Long term probably need to convert this to something else.. sql-lite? i dunno.
##############################################################################
class jsonDataStore:
dataStore={}
datestoreFilename=''
logger=''


# Creation Method: Nothing really going on here other than creating object
def __init__(self, filename, logger):
self.logger=logger
init(autoreset=True)
print (Fore.GREEN + f' [*]: Data Store Object Created')
self.logger.debug(" [*]: Data Store Object Created")
self.datestoreFilename=filename

#self.getDataStore(filename)

# getDataStore Method: returns data stored in class/method
def getDataStore(self):
return self.dataStore.copy()

# readDataStoreFromFile: reads json datastore master file
def readDataStoreFromFile(self, file_path):
file_path=self.datestoreFilename
self.check_file_exists(file_path)

try:
# Open and read the JSON file
with open(file_path, 'r') as file:
data = json.load(file)
self.logger.debug(" [+]: reading data from file.")
self.dataStore=data.copy()
return data
except FileNotFoundError:
print(Fore.RED + f" [+]: The file {file_path} does not exist.")
self.logger.debug("[+]: The file does not exist.")
except json.JSONDecodeError as e:
print(Fore.RED + f" [-]: Invalid JSON in file: {file_path}. Error: {e}")
self.logger.debug(f"[-]: Invalid JSON in file: {file_path}. Error: {e}")
except Exception as e:
print(Fore.RED + f"An error occurred: {e}")
self.logger.debug(f"[-]: An error occurred: {e}")
return None

# addDataToStore: adds new shodan data to datestore.
def addDataToStore(self, data_key, data_to_store):
if self.dataStore.get(data_key): #already in DB
dataFromDictionary=self.dataStore.get(data_key)

# converts text timestamp to datetime stamp so you can compare
firstseen_timestamp = self.convertStrTimeStamptoDateTime(self.dataStore[data_key]['first_seen'])
lastseen_timestamp = self.convertStrTimeStamptoDateTime(self.dataStore[data_key]['last_seen'])

# converts text timestamp from new entry to datetime stamp so you can compare
data_to_store_timestamp = self.convertStrTimeStamptoDateTime(data_to_store['timestamp'])

# Because python reads files in a random order not alphabetically or by date, you gotta compare dates with
# each item read. (only applies to reading old data files)
if firstseen_timestamp > data_to_store_timestamp:
dataFromDictionary['first_seen']=data_to_store['timestamp']

if lastseen_timestamp < data_to_store_timestamp:
dataFromDictionary['last_seen']=data_to_store['timestamp']

dataFromDictionary['seen_count']+=1
self.dataStore[data_key]=dataFromDictionary.copy()
self.logger.info(f" [+]: Updated Entry: {data_key}")

else: # new entry
self.dataStore[data_key] = {}

data_to_store['first_seen'] = data_to_store['timestamp']
data_to_store['last_seen'] = data_to_store['timestamp']
data_to_store['last_scan'] = 0
data_to_store['seen_count'] = 1
data_to_store['vulnerability_count']: len(data_to_store['vulns'])

self.dataStore[data_key] = data_to_store.copy()
self.logger.info(f" [+]: New Entry: {data_key}")
data = {}

# deleteFromDataStore: delete entry in data store by key. used for pruning
# old entries in the database
def deleteFromDataStore(self, key):
print (f'deleting from store {key}')
self.logger.info(f' [+]: Deleting from store {key}')

# countRecords: returns number of records in data store
def countRecords(self):
return len(self.dataStore)

# saveDataStore: saves all data in data store to json file
def saveDataStore(self, filename):
data=self.dataStore
file_path=self.datestoreFilename
try:
# Open and write to the JSON file
with open(file_path, 'w') as file:
json.dump(self.dataStore, file, indent=4)
print(Fore.GREEN + f"[*]: Data successfully written to {file_path}.")
print (Fore.GREEN + f' [+]: Number of Records saved: {self.countRecords()}')
self.logger.debug(f" [*]: Data successfully written to {file_path}.")
self.logger.debug(f' [+]: Number of Records saved: {self.countRecords()}')

except Exception as e:
print(f"An error occurred: {e}")
self.logger.info(f"[-]: An error occurred: {e}")

# check_file_exists: just checks if the data store file exists, if not creates one
def check_file_exists(self, file_path):
# Check if the file exists
if not os.path.exists(file_path):
# Create the file
with open(file_path, 'w') as file:
# Optionally write initial content to the file
file.write('')
print(Fore.GREEN + f" [+]: DataStore {file_path} created.")
self.logger.debug(f" [+]: DataStore {file_path} created.")
else:
print(Fore.YELLOW + f" [+]: DataStore {file_path} already exists.")
self.logger.debug(f" [+]: DataStore {file_path} already exists.")

# convertStrTimeStamptoDateTime: datastore file saves date as text, this converts
# back to python datetime
def convertStrTimeStamptoDateTime(self, strTimeStamp):
datetime_obj = datetime.fromisoformat(strTimeStamp)

# Format the datetime object to the desired format
# For example, converting to 'YYYY-MM-DD HH:MM:SS' format
formatted_timestamp = datetime.strptime(strTimeStamp, '%Y-%m-%dT%H:%M:%S.%f')

return formatted_timestamp
59 changes: 59 additions & 0 deletions library/shodan_lib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from datetime import datetime, timedelta, timezone
import shodan
from colorama import Fore, Back, Style, init

'''
shodan_api_class: just a wrapper for shodan api
__init__ : takes in the shodan api and verifies communication
check_api : verifies communication with shodan
query_shodan : queries shodan with given query
'''
class shodan_api_class:
shodan_api_key=''
shodan_query=''
shodan_valid_key=False
shodan_obj=''
logger=''
def __init__(self, shodan_api_key, logger):
self.logger=logger
init(autoreset=True)
print (Fore.GREEN + "Initializing Shodan")
self.shodan_api_key=shodan_api_key
self.shodan_obj=shodan.Shodan(self.shodan_api_key)

self.shodan_valid_key=self.check_api(self)
print (Fore.YELLOW + f' [+]: Shodan Communication is: {self.shodan_valid_key}')

def check_api(self,shodan_obj):
try:
results = self.shodan_obj.info()

if results:
self.logger.debug(f" [+]: Shodan API is valid")
return True
else:
self.logger.debug(f" [-]: Shodan API is NOT valid")
return False
except shodan.APIError as e:
print(Fore.RED + f"Error: {e}")
self.logger.ERROR(f" [+]: Shodan API Error: {e}")
return False

def query_shodan(self, shodan_query):
print (Fore.CYAN + f' [+]: Querying: {shodan_query}')
self.logger.info(f' [+]: Querying Shodan: {shodan_query}')

# Define the query parameters

# Perform the search query
try:
results = self.shodan_obj.search(shodan_query)
# Print the results
print(Fore.GREEN + f" [+]: Results found: {results['total']}")
self.logger.info(f' [+]: Results found: {results['total']}')

return results.copy()
except shodan.APIError as e:
print(Fore.RED + f"Error: {e}")
self.logger.ERROR(f"Error: {e}")
21 changes: 21 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
art==6.2
certifi==2024.6.2
charset-normalizer==3.3.2
click==8.1.7
click-plugins==1.1.1
colorama==0.4.6
filelock==3.15.1
fire==0.6.0
idna==3.7
pyfiglet==1.0.2
PyYAML==6.0.1
requests==2.32.3
requests-file==2.1.0
shodan==1.31.0
six==1.16.0
tabulate==0.9.0
termcolor==2.4.0
text2art==0.2.0
tldextract==5.1.2
urllib3==2.2.1
XlsxWriter==3.2.0
1 change: 1 addition & 0 deletions shodanDataStore.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Loading

0 comments on commit 89e68f9

Please sign in to comment.