diff --git a/rip-vault.py b/rip-vault.py new file mode 100644 index 0000000..a3b389c --- /dev/null +++ b/rip-vault.py @@ -0,0 +1,60 @@ +import requests +session = requests.Session() +session.headers.update({"User-Agent": "unshackle v4.0.0"}) +api_session_id = None + +def get_key(host: str, token: str, kid: str, service: str) -> str | None: + global api_session_id + params = {"kid": kid, "service": service.lower()} + if api_session_id: + params["session_id"] = api_session_id + r = session.post(host, json={"method": "GetKey", "params": params, "token": token}) + res = r.json() + if isinstance(res.get("message"), dict): + if sid := res["message"].get("session_id"): + api_session_id = sid + keys = res["message"].get("keys", []) + for entry in keys: + if isinstance(entry, str) and ":" in entry: + return entry.split(":", 1)[1] + elif isinstance(entry, dict): + return entry.get("key") + return None + +print("Vault Ripper\n") + +host = input("Vault host: ").strip() +token = input("Token: ").strip() +service = input("Service: ").strip() +kids_file = input("KIDs file path: ").strip() +output = input("Output file: ").strip() or "found_keys.txt" + +kids = [] +with open(kids_file, encoding="utf-8") as f: + for line in f: + line = line.strip() + if not line: + continue + kid = line.split(":")[0].strip().lower() + if len(kid) == 32: + kids.append(kid) + else: + print(f"Bad KID: {kid}") + +print(f"\nLoaded {len(kids)} KID(s), querying service '{service}'...\n") + +found = [] +for kid in kids: + key = get_key(host, token, kid, service) + if key: + print(f"HIT {kid}:{key}") + found.append(f"{kid}:{key}") + else: + print(f"MISS {kid}") + +if found: + with open(output, "w") as f: + f.write("\n".join(found)) + print(f"\nSaved {len(found)}/{len(kids)} keys to {output}") +else: + print("\nNo keys found.") \ No newline at end of file