Skip to content

Commit

Permalink
Merge pull request #144 from khast3x/2.5.6
Browse files Browse the repository at this point in the history
2.5.6
  • Loading branch information
khast3x authored Jun 25, 2022
2 parents 0a371eb + 5668ba7 commit ee31c8f
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 53 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@
| [HaveIBeenPwned Pastes(v3)](https://haveibeenpwned.com/Pastes) | URLs of text files mentioning targets | :white_check_mark: :key: |
| [Hunter.io](https://hunter.io/) - Public | Number of related emails | :white_check_mark: |
| [Hunter.io](https://hunter.io/) - Service (free tier) | Cleartext related emails, Chasing | :white_check_mark: :key: |
| [Snusbase](https://snusbase.com/) - Service | Cleartext passwords, hashs and salts, usernames, IPs - Fast :zap: | :white_check_mark: :key: |
| [Snusbase](https://api.snusbase.com/admin/purchase) - Service | Cleartext passwords, hashs and salts, usernames, IPs - Fast :zap: | :white_check_mark: :key: |
| [Leak-Lookup](https://leak-lookup.com/) - Public | Number of search-able breach results | :white_check_mark: (:key:) |
| [Leak-Lookup](https://leak-lookup.com/) - Service | Cleartext passwords, hashs and salts, usernames, IPs, domain | :white_check_mark: :key: |
| [Emailrep.io](https://emailrep.io/) - Service (free) | Last seen in breaches, social media profiles | :white_check_mark: :key: |
| [scylla.so](https://scylla.so/) - Service (free) | Cleartext passwords, hashs and salts, usernames, IPs, domain | :construction: |
| [Dehashed.com](https://dehashed.com/) - Service | Cleartext passwords, hashs and salts, usernames, IPs, domain | :white_check_mark: :key: |
| [IntelX.io](https://intelx.io/signup) - Service (free trial) | Cleartext passwords, hashs and salts, usernames, IPs, domain, Bitcoin Wallets, IBAN | :white_check_mark: :key: |
| :new: [Breachdirectory.tk](https://breachdirectory.tk) - Service (free) | Cleartext passwords, hashs and salts, usernames, domain | :white_check_mark: :key: |
| :new: [Breachdirectory.org](https://breachdirectory.org) - Service (free) | Cleartext passwords, hashs and salts, usernames, domain | :construction: :key: |

*:key: - API key required*

Expand Down
54 changes: 54 additions & 0 deletions h8mail/utils/breachcompilation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,67 @@
import re
import stat
from string import printable
from .localsearch import local_search

def check_shell():
shell = os.environ['SHELL']
print("SHELL IS " + shell)
if "bash" not in shell:
c.info_news("If you're having issues or not results, be sure to launch h8mail using bash for this operation.")
c.info_news("OSX users should read this https://khast3x.club/posts/2021-02-17-h8mail-with-COMB/#targeting-emails\n")


def clean_targets(targets):
"""
This function is necessary since local_search performs a loose search.
We'll double check results to ensure ONLY target email is present is results
"""
for t in targets:
cleaned_data = []
for d in t.data:
if d:
found_email = re.split("[;:]",d[1])[0]
if found_email == t.target:
# We rebuild the expected data array ["BC_PASS", "password"]
new_data = [d[0], re.split("[;:]",d[1])[-1]]
cleaned_data.append(new_data)
else:
c.info_news("Removing " + d[1] + " (cleaning function)")
t.data = cleaned_data

return targets

def breachcomp_check(targets, breachcomp_path):
breachcomp_path = os.path.join(breachcomp_path, "data")
for t in targets:
if len(t.target):
for i in range(len(t.target)):
if t.target[i].isalnum():
next_dir_to_test = os.path.join(breachcomp_path, t.target[i])
else:
next_dir_to_test = os.path.join(breachcomp_path, "symbols")
if os.path.isdir(next_dir_to_test):
breachcomp_path = next_dir_to_test
else:
if os.path.isfile(next_dir_to_test):
found_list = local_search([next_dir_to_test], [t.target])
for f in found_list:
t.pwned += 1
t.data.append(("BC_PASS", f.content.strip()))
else:
c.bad_news(next_dir_to_test + " is neither a file or directory")

break

targets = clean_targets(targets)
return targets

def old_breachcomp_check(targets, breachcomp_path):
# https://gist.github.com/scottlinux/9a3b11257ac575e4f71de811322ce6b3
try:
import subprocess

check_shell()
query_bin = os.path.join(breachcomp_path, "query.sh")
st = os.stat(query_bin)
os.chmod(query_bin, st.st_mode | stat.S_IEXEC)
Expand Down
109 changes: 62 additions & 47 deletions h8mail/utils/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,11 @@ def get_scylla(self, user_query="email"):
elif "ip" in field and k is not None:
self.data.append(("SCYLLA_LASTIP", k))
self.pwned += 1
elif "domain" in field and k is not None:
if "domain" in field and k is not None:
self.data.append(("SCYLLA_SOURCE", k))
self.pwned += 1
else:
self.data.append(("SCYLLA_SOURCE", "N/A"))
except Exception as ex:
c.bad_news("scylla.so error: " + self.target)
print(ex)
Expand Down Expand Up @@ -488,53 +490,61 @@ def get_snusbase(self, api_url, api_key, user_query):
try:
if user_query == "ip":
user_query = "lastip"
if user_query in ["domain"]:
c.bad_news(
f"Snusbase does not support {user_query} search (yet)"
)
return
if user_query == "domain":
payload = {"type": "email", "term": "%@" + self.target, "wildcard": "true"}
# elif user_query == "hash": If we want hash to search for password instead of reverse searching emails from the hash
# payload = {"hash": self.target}
# api_url = "https://api.snusbase.com/v3/hash"
else:
payload = {"type": user_query, "term": self.target}
c.info_news("[" + self.target + "]>[snusbase]")
url = api_url
self.headers.update({"Authorization": api_key})
payload = {"type": user_query, "term": self.target}
self.headers.update({"authorization": api_key})
# payload = {"type": user_query, "term": self.target}
req = self.make_request(url, meth="POST", data=payload)
self.headers.popitem()
response = req.json()
c.good_news(
"Found {num} entries for {target} using Snusbase".format(
num=len(response["result"]), target=self.target
if "error" in response:
c.bad_news("[snusbase]> " + response["error"])
c.bad_news("[snusbase]> " + response["reason"])
return 1
if "size" in response:
c.good_news(
"Found {num} entries for {target} using Snusbase".format(
num=response["size"], target=self.target
)
)
)
for result in response["result"]:
if result["email"] and self.not_exists(result["email"]):
self.data.append(("SNUS_RELATED", result["email"].strip()))
if result["username"]:
self.data.append(("SNUS_USERNAME", result["username"]))
self.pwned += 1
if result["password"]:
self.data.append(("SNUS_PASSWORD", result["password"]))
self.pwned += 1
if result["hash"]:
if result["salt"]:
self.data.append(
(
"SNUS_HASH_SALT",
result["hash"].strip() + " : " + result["salt"].strip(),
for result in response["results"]:
if "email" in result and self.not_exists(result["email"]):
self.data.append(("SNUS_RELATED", result["email"].strip()))
if "username" in result:
self.data.append(("SNUS_USERNAME", result["username"]))
self.pwned += 1
if "password" in result:
self.data.append(("SNUS_PASSWORD", result["password"]))
self.pwned += 1
if "hash" in result:
if "salt" in result:
self.data.append(
(
"SNUS_HASH_SALT",
result["hash"].strip() + " : " + result["salt"].strip(),
)
)
)
self.pwned += 1
else:
self.data.append(("SNUS_HASH", result["hash"]))
self.pwned += 1
if "lastip" in result:
self.data.append(("SNUS_LASTIP", result["lastip"]))
self.pwned += 1
else:
self.data.append(("SNUS_HASH", result["hash"]))
if "name" in result:
self.data.append(("SNUS_NAME", result["name"]))
self.pwned += 1
if result["lastip"]:
self.data.append(("SNUS_LASTIP", result["lastip"]))
self.pwned += 1
if result["name"]:
self.data.append(("SNUS_NAME", result["name"]))
self.pwned += 1
if result["tablenr"] and self.not_exists(result["tablenr"]):
self.data.append(("SNUS_SOURCE", result["tablenr"]))

if "db" in result and self.not_exists(result["db"]):
self.data.append(("SNUS_SOURCE", result["db"]))
else:
self.data.append(("SNUS_SOURCE", "N/A"))
except Exception as ex:
c.bad_news(f"Snusbase error with {self.target}")
print(ex)
Expand Down Expand Up @@ -699,6 +709,8 @@ def get_weleakinfo_priv(self, api_key, user_query):
self.pwned += 1
if "Database" in result and self.not_exists(result["Database"]):
self.data.append(("WLI_SOURCE", result["Database"]))
else:
self.data.append(("WLI_SOURCE", "N/A"))
except Exception as ex:
c.bad_news(
f"WeLeakInfo error with {self.target} (private)"
Expand Down Expand Up @@ -807,11 +819,12 @@ def get_dehashed(self, api_email, api_key, user_query):
result["obtained_from"]
):
self.data.append(("DHASHD_SOURCE", result["obtained_from"]))
if "database_name" in result and self.not_exists(
elif "database_name" in result and self.not_exists(
result["database_name"]
):
self.data.append(("DHASHD_SOURCE", result["database_name"]))

else:
self.data.append(("DHASHD_SOURCE", "N/A"))
if response["balance"] is not None:
self.data.append(
(
Expand All @@ -820,20 +833,20 @@ def get_dehashed(self, api_email, api_key, user_query):
)
)
else:
c.bad_news("Dehashed error: status code " + req.status_code)
c.bad_news("Dehashed error: status code " + str(req.status_code))
self.headers.popitem()
except Exception as ex:
c.bad_news(f"Dehashed error with {self.target}")
print(ex)

def get_breachdirectory(self, user, passw, user_query):
# Todo: implement password source search when email has answer
c.info_news("[" + self.target + "]>[breachdirectory.tk]")
c.info_news("[" + self.target + "]>[breachdirectory.org]")
if user_query not in ["email", "username", "password", "domain"]:
c.bad_news("Breachdirectory does not support this option")
exit(1)
mode = "pastes"
url = "https://breachdirectory.tk/api/index?username={user}&password={passw}&func={mode}&term={target}".format(user=user, passw=passw, mode=mode, target=self.target)
url = "https://breachdirectory.org/api/index?username={user}&password={passw}&func={mode}&term={target}".format(user=user, passw=passw, mode=mode, target=self.target)
try:
req = self.make_request(
url, timeout=60
Expand All @@ -851,8 +864,10 @@ def get_breachdirectory(self, user, passw, user_query):
if "source" in result:
self.data.append(("BREACHDR_SOURCE", result["source"]))
self.pwned += 1
else:
self.data.append(("BREACHDR_SOURCE", "N/A"))
# Follow up with an aggregated leak sources query
url_src = "https://breachdirectory.tk/api/index?username={user}&password={passw}&func={mode}&term={target}".format(user=user, passw=passw, mode="sources", target=self.target)
url_src = "https://breachdirectory.org/api/index?username={user}&password={passw}&func={mode}&term={target}".format(user=user, passw=passw, mode="sources", target=self.target)
req = self.make_request(
url_src, timeout=60
)
Expand All @@ -863,7 +878,7 @@ def get_breachdirectory(self, user, passw, user_query):
self.data.append(("BREACHDR_EXTSRC", result))
## If using the 'auto' mode instead of pastes
# c.good_news(
# "Found {num} entries for {target} using breachdirectory.tk".format(
# "Found {num} entries for {target} using breachdirectory.org".format(
# num=str(response["found"]), target=self.target
# )
# )
Expand All @@ -882,4 +897,4 @@ def get_breachdirectory(self, user, passw, user_query):
# self.pwned += 1
except Exception as ex:
c.bad_news(f"Breachdirectory error with {self.target}")
print(ex)
print(ex)
2 changes: 1 addition & 1 deletion h8mail/utils/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def print_banner(b_type="intro"):
print(
"\t",
c.fg.cyan,
"Version " + __version__ + ' - "ROCKSMASSON.5" ',
"Version " + __version__ + ' - "ROCKSMASSON.6" ',
c.reset,
)

Expand Down
2 changes: 1 addition & 1 deletion h8mail/utils/print_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def generate_source_arrays(pwned_data):
temp_array = []
for i in range(len(pwned_data)):
if len(pwned_data[i]) == 2:
temp_array.append(pwned_data[i][0] + ":" + pwned_data[i][1])
temp_array.append(pwned_data[i][0] + ":" + str(pwned_data[i][1]))
no_src += 1
if "SOURCE" in pwned_data[i][0]:
data_array.append(temp_array)
Expand Down
2 changes: 1 addition & 1 deletion h8mail/utils/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def target_factory(targets, user_args):
if "snusbase_url" in api_keys:
snusbase_url = api_keys["snusbase_url"]
else:
snusbase_url = "http://api.snusbase.com/v2/search"
snusbase_url = "http://api.snusbase.com/v3/search"
current_target.get_snusbase(
snusbase_url, api_keys["snusbase_token"], query
)
Expand Down
2 changes: 1 addition & 1 deletion h8mail/utils/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.5.5"
__version__ = "2.5.6"

0 comments on commit ee31c8f

Please sign in to comment.