Skip to content

Instantly share code, notes, and snippets.

@0xNDI
Created October 5, 2025 07:39
Show Gist options
  • Select an option

  • Save 0xNDI/d82f491ac4e6fa205dfb3475ca5d4fbb to your computer and use it in GitHub Desktop.

Select an option

Save 0xNDI/d82f491ac4e6fa205dfb3475ca5d4fbb to your computer and use it in GitHub Desktop.
Fix rusthound zip so it imports to latest BH CE
#!/usr/bin/env python3
import json
import sys
import zipfile
import tempfile
import os
import shutil
def main():
if len(sys.argv) != 2:
print("Usage: python fix-rusthound.py <zip_file>")
sys.exit(1)
zip_file = sys.argv[1]
if not os.path.exists(zip_file):
print(f"Error: File '{zip_file}' not found")
sys.exit(1)
if not zipfile.is_zipfile(zip_file):
print(f"Error: '{zip_file}' is not a valid zip file")
sys.exit(1)
domains_file = None
with zipfile.ZipFile(zip_file, 'r') as zf:
for filename in zf.namelist():
if filename.endswith('domains.json'):
domains_file = filename
break
if not domains_file:
print("Error: No file ending with 'domains.json' found in the zip")
sys.exit(1)
print(f"Found domains file: {domains_file}")
try:
with zipfile.ZipFile(zip_file, 'r') as zf:
with zf.open(domains_file) as f:
data = json.load(f)
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON in {domains_file} - {e}")
sys.exit(1)
if not isinstance(data, dict) or 'data' not in data:
print("Error: JSON must have a top-level 'data' key containing an array")
sys.exit(1)
if not isinstance(data['data'], list):
print("Error: The 'data' key must contain an array")
sys.exit(1)
original_count = len(data['data'])
data['data'] = [
item for item in data['data']
if isinstance(item, dict) and
item.get('ObjectIdentifier', '').strip() != ''
]
new_count = len(data['data'])
try:
zip_dir = os.path.dirname(os.path.abspath(zip_file))
with tempfile.NamedTemporaryFile(delete=False, dir=zip_dir, suffix='.tmp') as temp_zip:
temp_zip_path = temp_zip.name
with zipfile.ZipFile(zip_file, 'r') as original_zip, \
zipfile.ZipFile(temp_zip_path, 'w', zipfile.ZIP_DEFLATED) as new_zip:
for item in original_zip.infolist():
if item.filename != domains_file:
new_zip.writestr(item, original_zip.read(item.filename))
cleaned_json = json.dumps(data, indent=2, ensure_ascii=False) + '\n'
new_zip.writestr(domains_file, cleaned_json.encode('utf-8'))
shutil.move(temp_zip_path, zip_file)
except PermissionError:
print(f"Error: Permission denied writing to '{zip_file}'")
if 'temp_zip_path' in locals() and os.path.exists(temp_zip_path):
os.unlink(temp_zip_path)
sys.exit(1)
except Exception as e:
print(f"Error: Failed to update zip file - {e}")
if 'temp_zip_path' in locals() and os.path.exists(temp_zip_path):
os.unlink(temp_zip_path)
sys.exit(1)
print(f"Cleaned {domains_file} in {zip_file}: {original_count} -> {new_count} entries")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment