UNPKG

@hashangit/breachhound

Version:

An efficient OSINT tool for uncovering digital footprints associated with a username. TypeScript port of GoSearch.

239 lines 11.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.VERSION = exports.ASCII_ART = void 0; exports.printHeader = printHeader; exports.appendToFile = appendToFile; exports.deleteOldFile = deleteOldFile; exports.displayResults = displayResults; const chalk_1 = __importDefault(require("chalk")); const fs = __importStar(require("fs/promises")); exports.ASCII_ART = `...`; // Your ASCII art exports.VERSION = '1.0.0'; // Keep version consistent or read from package.json function printHeader(username, siteCount, options) { console.clear(); console.log(chalk_1.default.blue(exports.ASCII_ART)); console.log(`BreachHound ${exports.VERSION} - TypeScript Port`); console.log(chalk_1.default.grey('⎯'.repeat(60))); console.log(`:: Target Username : ${chalk_1.default.cyan(username)}`); console.log(`:: Websites to Check : ${siteCount}`); if (options.hideFalsePositives) console.log(`:: Hide Uncertain : ${chalk_1.default.yellow('Yes')}`); if (options.breachDirectoryEnabled) console.log(`:: BreachDirectory : ${chalk_1.default.green('Enabled')}`); console.log(chalk_1.default.grey('⎯'.repeat(60))); if (!options.hideFalsePositives) { console.log(chalk_1.default.yellow('[!] Yellow [?] links indicate uncertainty about the profile\'s existence.\n')); } } async function appendToFile(targetUsername, content) { // ... (implementation as before) ... const filePath = `${targetUsername}.txt`; try { await fs.appendFile(filePath, content + '\n', 'utf8'); } catch (error) { console.error(chalk_1.default.red(`[-] Error writing to file ${filePath}: ${error}`)); } } async function deleteOldFile(targetUsername) { // ... (implementation as before) ... const filePath = `${targetUsername}.txt`; try { await fs.unlink(filePath); // console.log(chalk.grey(`[*] Deleted old results file: ${filePath}`)); // Optional: log deletion } catch (error) { if (error.code !== 'ENOENT') { // Ignore error if file doesn't exist console.error(chalk_1.default.red(`[-] Error deleting old results file ${filePath}: ${error}`)); } } } async function displayResults(results, username, hideFalsePositives) { // --- Website Results --- console.log(chalk_1.default.yellow(`\n[*] Website Scan Results:`)); results.websiteResults.forEach(res => { if (res.status === 'found') { const line = `[+] ${res.siteName}: ${res.profileUrl}`; console.log(chalk_1.default.green(line)); appendToFile(username, line); } else if (res.status === 'uncertain' && !hideFalsePositives) { const line = `[?] ${res.siteName}: ${res.profileUrl}`; console.log(chalk_1.default.yellow(line)); appendToFile(username, `[?] ${line}`); // Add prefix to file too } else if (res.status === 'error') { // Optional: log errors verbosely if needed // console.error(chalk.red(`[-] Error checking ${res.siteName}: ${res.error}`)); } }); // --- API Results --- await displayApiResult(results.hudsonRockResult, username); await displayApiResult(results.breachDirectoryResult, username); await displayApiResult(results.proxyNovaResult, username); await displayApiResult(results.domainCheckResult, username); // --- Summary --- console.log(chalk_1.default.grey('⎯'.repeat(60))); const summaryLines = [ `:: Profiles Found / Uncertain : ${results.summary.profilesFound}`, `:: Total Time Taken : ${results.summary.durationSeconds} seconds`, `:: Report saved to : ${username}.txt` ]; summaryLines.forEach(line => console.log(line)); await appendToFile(username, '\n' + chalk_1.default.grey('⎯'.repeat(60)) + '\n' + summaryLines.join('\n')); console.log(chalk_1.default.grey('⎯'.repeat(60))); } // Helper to display formatted API results async function displayApiResult(result, username) { console.log(chalk_1.default.grey('⎯'.repeat(60))); console.log(chalk_1.default.yellow(`[*] ${result.service} Results:`)); if (result.status === 'skipped') { const msg = `:: ${result.service} check skipped (API key may be missing).`; console.log(chalk_1.default.grey(msg)); await appendToFile(username, `\n--- ${result.service} Check ---`); await appendToFile(username, msg); return; } await appendToFile(username, `\n--- ${result.service} Check ---`); if (result.status === 'error') { const msg = `:: Error querying ${result.service}: ${result.error}`; console.error(chalk_1.default.red(msg)); await appendToFile(username, msg); return; } // Add specific formatting based on result.service and result.details // Example for HudsonRock: if (result.service === 'HudsonRock') { const data = result.details; // Use any for now, define specific type later if (result.found && data?.stealers) { // ... (detailed printing logic for stealers as before) ... const msg = ":: This username is associated with a computer infected by an info-stealer."; console.log(chalk_1.default.red(msg)); await appendToFile(username, msg); // ... loop through stealers, print details ... } else { const msg = ":: This username is not associated with a computer infected by an info-stealer."; console.log(chalk_1.default.green(msg)); await appendToFile(username, msg); } } // Formatting for BreachDirectory: else if (result.service === 'BreachDirectory') { if (result.found && result.details?.breaches?.length > 0) { const count = result.details.foundCount || result.details.breaches.length; const msg = `[+] Found ${count} breach entries:`; console.log(chalk_1.default.green(msg)); await appendToFile(username, msg); // Loop through breach entries and print details for (const entry of result.details.breaches) { let passMsg = ''; if (entry.crackedPassword) { passMsg = `[+] Password (Cracked): ${entry.crackedPassword}`; } else if (entry.password) { passMsg = `[+] Password: ${entry.password}`; } else { passMsg = `[?] Password: Not Available`; } console.log(chalk_1.default.green(passMsg)); await appendToFile(username, passMsg); if (entry.email) { const emailMsg = `[+] Email: ${entry.email}`; console.log(chalk_1.default.green(emailMsg)); await appendToFile(username, emailMsg); } if (entry.hash) { const hashMsg = `[+] Hash: ${entry.hash}`; console.log(chalk_1.default.grey(hashMsg)); // Use grey for hash await appendToFile(username, hashMsg); } if (entry.sha1) { const sha1Msg = `[+] SHA1: ${entry.sha1}`; console.log(chalk_1.default.grey(sha1Msg)); // Use grey for hash await appendToFile(username, sha1Msg); } if (entry.source) { const sourceMsg = `[+] Source: ${entry.source}`; console.log(chalk_1.default.green(sourceMsg)); await appendToFile(username, sourceMsg); } console.log(''); // Add a blank line between entries await appendToFile(username, ''); } } else { const msg = `[-] No breaches found.`; console.log(chalk_1.default.red(msg)); // Use red for "not found" await appendToFile(username, msg); } } // Formatting for ProxyNova else if (result.service === 'ProxyNova') { if (result.found && result.details) { // Assuming details contains info like count or entries const count = result.details.found || (Array.isArray(result.details.entries) ? result.details.entries.length : 0); const msg = `[+] Found ${count} potential credential leak(s) in Comb DB.`; console.log(chalk_1.default.green(msg)); await appendToFile(username, msg); // Optionally loop through result.details.entries if they exist and print them } else { const msg = `[-] No potential credential leaks found in Comb DB.`; console.log(chalk_1.default.red(msg)); await appendToFile(username, msg); } } // Formatting for DomainCheck else if (result.service === 'DomainCheck') { if (result.found && result.details?.found?.length > 0) { const foundDomains = result.details.found.join(', '); const msg = `[+] Found potentially available domains: ${foundDomains}`; console.log(chalk_1.default.green(msg)); await appendToFile(username, msg); } else { const msg = `[-] No potentially available domains found matching the username.`; console.log(chalk_1.default.red(msg)); await appendToFile(username, msg); } } } //# sourceMappingURL=ui.js.map