Autarch/web/templates/hash_detection.html

373 lines
17 KiB
HTML
Raw Normal View History

{% extends "base.html" %}
{% block title %}Hash Toolkit - AUTARCH{% endblock %}
{% block content %}
<div class="page-header" style="display:flex;align-items:center;gap:1rem;flex-wrap:wrap">
<div>
<h1>Hash Toolkit</h1>
<p style="margin:0;font-size:0.85rem;color:var(--text-secondary)">
Identify unknown hashes, compute file/text digests, and look up threat intelligence.
</p>
</div>
<a href="{{ url_for('analyze.index') }}" class="btn btn-sm" style="margin-left:auto">&larr; Analyze</a>
</div>
<!-- Tab Bar -->
<div class="tab-bar">
<button class="tab active" data-tab-group="hashtool" data-tab="identify" onclick="showTab('hashtool','identify')">Identify</button>
<button class="tab" data-tab-group="hashtool" data-tab="filehash" onclick="showTab('hashtool','filehash')">File Hash</button>
<button class="tab" data-tab-group="hashtool" data-tab="texthash" onclick="showTab('hashtool','texthash')">Text Hash</button>
<button class="tab" data-tab-group="hashtool" data-tab="mutate" onclick="showTab('hashtool','mutate')">Mutate</button>
<button class="tab" data-tab-group="hashtool" data-tab="generate" onclick="showTab('hashtool','generate')">Generate</button>
<button class="tab" data-tab-group="hashtool" data-tab="reference" onclick="showTab('hashtool','reference')">Reference</button>
</div>
<!-- ══ Identify Tab ══ -->
<div class="tab-content active" data-tab-group="hashtool" data-tab="identify">
<div class="section">
<h2>Hash Algorithm Detection</h2>
<p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
Paste an unknown hash to identify possible algorithms (supports 40+ hash types).
</p>
<div class="input-row">
<input type="text" id="ht-identify-input" placeholder="Paste hash string here..." style="font-family:monospace">
<button id="btn-ht-identify" class="btn btn-primary" onclick="htIdentify()">Identify</button>
</div>
<pre class="output-panel scrollable" id="ht-identify-output"></pre>
<div id="ht-threat-links" style="margin-top:8px;display:none">
<h3 style="font-size:0.85rem;color:var(--text-secondary);margin-bottom:6px">Threat Intelligence Lookups</h3>
<div id="ht-links-container" style="display:flex;flex-wrap:wrap;gap:6px"></div>
</div>
</div>
</div>
<!-- ══ File Hash Tab ══ -->
<div class="tab-content" data-tab-group="hashtool" data-tab="filehash">
<div class="section">
<h2>File Hashing</h2>
<p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
Compute CRC32, MD5, SHA1, SHA256, and SHA512 digests for any file.
</p>
<div class="input-row">
<input type="text" id="ht-file-path" placeholder="File path (e.g., /usr/bin/ls)">
<button id="btn-ht-file" class="btn btn-primary" onclick="htHashFile()">Hash File</button>
</div>
<pre class="output-panel scrollable" id="ht-file-output"></pre>
</div>
</div>
<!-- ══ Text Hash Tab ══ -->
<div class="tab-content" data-tab-group="hashtool" data-tab="texthash">
<div class="section">
<h2>Text / String Hashing</h2>
<div class="form-group" style="margin-bottom:0.75rem">
<textarea id="ht-text-input" rows="4" placeholder="Enter text to hash..." style="width:100%;font-family:monospace"></textarea>
</div>
<div class="input-row">
<select id="ht-text-algo">
<option value="md5">MD5</option>
<option value="sha1">SHA-1</option>
<option value="sha224">SHA-224</option>
<option value="sha256" selected>SHA-256</option>
<option value="sha384">SHA-384</option>
<option value="sha512">SHA-512</option>
<option value="sha3-256">SHA3-256</option>
<option value="sha3-512">SHA3-512</option>
<option value="blake2b">BLAKE2b</option>
<option value="blake2s">BLAKE2s</option>
<option value="crc32">CRC32</option>
<option value="all">ALL algorithms</option>
</select>
<button id="btn-ht-text" class="btn btn-primary" onclick="htHashText()">Hash</button>
</div>
<pre class="output-panel scrollable" id="ht-text-output"></pre>
</div>
</div>
<!-- ══ Mutate Tab ══ -->
<div class="tab-content" data-tab-group="hashtool" data-tab="mutate">
<div class="section">
<h2>Change File Hash</h2>
<p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
Append bytes to a copy of a file to change its hash. Original file is not modified.
</p>
<div class="input-row">
<input type="text" id="ht-mutate-path" placeholder="File path to mutate">
<select id="ht-mutate-method" style="max-width:140px">
<option value="random">Random bytes</option>
<option value="null">Null bytes</option>
<option value="space">Spaces</option>
<option value="newline">Newlines</option>
</select>
<input type="number" id="ht-mutate-bytes" value="4" min="1" max="1024" style="max-width:80px" title="Bytes to append">
<button id="btn-ht-mutate" class="btn btn-primary" onclick="htMutate()">Mutate</button>
</div>
<pre class="output-panel scrollable" id="ht-mutate-output"></pre>
</div>
</div>
<!-- ══ Generate Tab ══ -->
<div class="tab-content" data-tab-group="hashtool" data-tab="generate">
<div class="section">
<h2>Create Dummy Hash Files</h2>
<p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
Generate test files with known content for hash verification and testing.
</p>
<div class="input-row">
<input type="text" id="ht-gen-dir" placeholder="Output directory (e.g., /tmp)" value="/tmp">
<input type="text" id="ht-gen-name" placeholder="Filename" value="hashtest.bin" style="max-width:180px">
</div>
<div class="input-row" style="margin-top:6px">
<select id="ht-gen-type">
<option value="random">Random data</option>
<option value="zeros">All zeros (0x00)</option>
<option value="ones">All ones (0xFF)</option>
<option value="pattern">Repeating pattern (ABCDEF...)</option>
<option value="text">Custom text (repeated)</option>
</select>
<input type="number" id="ht-gen-size" value="1024" min="1" max="10485760" style="max-width:120px" title="Size in bytes">
<button id="btn-ht-gen" class="btn btn-primary" onclick="htGenerate()">Generate</button>
</div>
<div id="ht-gen-custom-row" class="input-row" style="margin-top:6px;display:none">
<input type="text" id="ht-gen-custom" placeholder="Custom text to repeat...">
</div>
<pre class="output-panel scrollable" id="ht-gen-output"></pre>
</div>
</div>
<!-- ══ Reference Tab ══ -->
<div class="tab-content" data-tab-group="hashtool" data-tab="reference">
<div class="section">
<h2>Hash Type Reference</h2>
<p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
Common hash types, output lengths, and hashcat mode numbers.
</p>
<div id="ht-reference-table" style="overflow-x:auto"></div>
</div>
</div>
<script>
/* ── Hash Toolkit ─────────────────────────────────────────────────── */
function htIdentify() {
var hash = document.getElementById('ht-identify-input').value.trim();
if (!hash) return;
var btn = document.getElementById('btn-ht-identify');
setLoading(btn, true);
postJSON('/analyze/hash-detection/identify', {hash: hash}).then(function(data) {
setLoading(btn, false);
if (data.error) { renderOutput('ht-identify-output', 'Error: ' + data.error); return; }
var lines = [];
lines.push('Input: ' + data.hash);
lines.push('Length: ' + data.length + ' characters');
lines.push('');
if (data.matches && data.matches.length) {
lines.push('Possible Algorithms (' + data.matches.length + ' match' + (data.matches.length > 1 ? 'es' : '') + '):');
lines.push('');
data.matches.forEach(function(m, i) {
var hc = m.hashcat !== null ? ' [hashcat: ' + m.hashcat + ']' : '';
lines.push(' ' + (i + 1) + '. ' + m.name + hc);
lines.push(' ' + m.description);
});
} else {
lines.push(data.message || 'No matching hash algorithms found.');
}
renderOutput('ht-identify-output', lines.join('\n'));
// Show threat intel links for hex hashes of typical lengths
var linksDiv = document.getElementById('ht-threat-links');
var container = document.getElementById('ht-links-container');
var hexLens = [32, 40, 64, 128];
if (/^[a-fA-F0-9]+$/.test(hash) && hexLens.indexOf(hash.length) !== -1) {
container.innerHTML = '';
htGetThreatLinks(hash).forEach(function(link) {
var a = document.createElement('a');
a.href = link.url;
a.target = '_blank';
a.rel = 'noopener';
a.className = 'btn btn-sm';
a.textContent = link.name;
a.style.fontSize = '0.8rem';
container.appendChild(a);
});
linksDiv.style.display = '';
} else {
linksDiv.style.display = 'none';
}
}).catch(function() { setLoading(btn, false); });
}
function htGetThreatLinks(hash) {
return [
{name: 'VirusTotal', url: 'https://www.virustotal.com/gui/file/' + hash},
{name: 'Hybrid Analysis', url: 'https://www.hybrid-analysis.com/search?query=' + hash},
{name: 'MalwareBazaar', url: 'https://bazaar.abuse.ch/browse.php?search=' + hash},
{name: 'AlienVault OTX', url: 'https://otx.alienvault.com/indicator/file/' + hash},
{name: 'Shodan', url: 'https://www.shodan.io/search?query=' + hash},
];
}
function htHashFile() {
var filepath = document.getElementById('ht-file-path').value.trim();
if (!filepath) return;
var btn = document.getElementById('btn-ht-file');
setLoading(btn, true);
postJSON('/analyze/hash-detection/file', {filepath: filepath}).then(function(data) {
setLoading(btn, false);
if (data.error) { renderOutput('ht-file-output', 'Error: ' + data.error); return; }
var lines = [];
lines.push('File: ' + data.path);
lines.push('Size: ' + data.size + ' bytes');
lines.push('');
lines.push('Digests:');
if (data.hashes) {
lines.push(' CRC32: ' + (data.hashes.crc32 || ''));
lines.push(' MD5: ' + (data.hashes.md5 || ''));
lines.push(' SHA1: ' + (data.hashes.sha1 || ''));
lines.push(' SHA256: ' + (data.hashes.sha256 || ''));
lines.push(' SHA512: ' + (data.hashes.sha512 || ''));
}
renderOutput('ht-file-output', lines.join('\n'));
}).catch(function() { setLoading(btn, false); });
}
function htHashText() {
var text = document.getElementById('ht-text-input').value;
if (!text) return;
var algo = document.getElementById('ht-text-algo').value;
var btn = document.getElementById('btn-ht-text');
setLoading(btn, true);
postJSON('/analyze/hash-detection/text', {text: text, algorithm: algo}).then(function(data) {
setLoading(btn, false);
if (data.error) { renderOutput('ht-text-output', 'Error: ' + data.error); return; }
var lines = [];
lines.push('Input length: ' + data.text_length + ' characters');
lines.push('');
if (data.algorithm === 'all' && data.hashes) {
lines.push('All Digests:');
Object.keys(data.hashes).sort().forEach(function(name) {
var pad = ' '.slice(0, 10 - name.length);
lines.push(' ' + name + ':' + pad + data.hashes[name]);
});
} else {
lines.push('Algorithm: ' + data.algorithm.toUpperCase());
lines.push('Hash: ' + data.hash);
}
renderOutput('ht-text-output', lines.join('\n'));
}).catch(function() { setLoading(btn, false); });
}
function htMutate() {
var filepath = document.getElementById('ht-mutate-path').value.trim();
if (!filepath) return;
var method = document.getElementById('ht-mutate-method').value;
var numBytes = document.getElementById('ht-mutate-bytes').value || '4';
var btn = document.getElementById('btn-ht-mutate');
setLoading(btn, true);
postJSON('/analyze/hash-detection/mutate', {filepath: filepath, method: method, num_bytes: numBytes}).then(function(data) {
setLoading(btn, false);
if (data.error) { renderOutput('ht-mutate-output', 'Error: ' + data.error); return; }
var lines = [];
lines.push('Original: ' + data.original_path + ' (' + data.original_size + ' bytes)');
lines.push('Mutated: ' + data.mutated_path + ' (' + data.mutated_size + ' bytes)');
lines.push('Method: ' + data.method + ' (' + data.bytes_appended + ' bytes appended)');
lines.push('');
lines.push('Before:');
lines.push(' MD5: ' + data.original_hashes.md5);
lines.push(' SHA256: ' + data.original_hashes.sha256);
lines.push('');
lines.push('After:');
lines.push(' MD5: ' + data.new_hashes.md5);
lines.push(' SHA256: ' + data.new_hashes.sha256);
renderOutput('ht-mutate-output', lines.join('\n'));
}).catch(function() { setLoading(btn, false); });
}
function htGenerate() {
var dir = document.getElementById('ht-gen-dir').value.trim();
var name = document.getElementById('ht-gen-name').value.trim();
var type = document.getElementById('ht-gen-type').value;
var size = document.getElementById('ht-gen-size').value || '1024';
var custom = document.getElementById('ht-gen-custom').value;
if (!dir || !name) return;
var btn = document.getElementById('btn-ht-gen');
setLoading(btn, true);
postJSON('/analyze/hash-detection/generate', {
output_dir: dir, filename: name, content_type: type, size: size, custom_text: custom
}).then(function(data) {
setLoading(btn, false);
if (data.error) { renderOutput('ht-gen-output', 'Error: ' + data.error); return; }
var lines = [];
lines.push('Created: ' + data.path);
lines.push('Size: ' + data.size + ' bytes');
lines.push('Content: ' + data.content_type);
lines.push('');
lines.push('Digests:');
if (data.hashes) {
lines.push(' CRC32: ' + (data.hashes.crc32 || ''));
lines.push(' MD5: ' + (data.hashes.md5 || ''));
lines.push(' SHA1: ' + (data.hashes.sha1 || ''));
lines.push(' SHA256: ' + (data.hashes.sha256 || ''));
lines.push(' SHA512: ' + (data.hashes.sha512 || ''));
}
renderOutput('ht-gen-output', lines.join('\n'));
}).catch(function() { setLoading(btn, false); });
}
/* Show/hide custom text input when content type changes */
document.getElementById('ht-gen-type').addEventListener('change', function() {
document.getElementById('ht-gen-custom-row').style.display = this.value === 'text' ? '' : 'none';
});
/* Build static reference table */
(function() {
var el = document.getElementById('ht-reference-table');
if (!el) return;
var ref = [
['CRC32', '8', 'Hex', '11500'],
['MD4', '32', 'Hex', '900'],
['MD5', '32', 'Hex', '0'],
['NTLM', '32', 'Hex', '1000'],
['LM', '32', 'Hex', '3000'],
['MySQL323', '16', 'Hex', '200'],
['MySQL41', '41', '*Hex', '300'],
['RIPEMD-160', '40', 'Hex', '6000'],
['SHA-1', '40', 'Hex', '100'],
['Tiger-192', '48', 'Hex', '10000'],
['SHA-224', '56', 'Hex', '--'],
['SHA-256', '64', 'Hex', '1400'],
['SHA-384', '96', 'Hex', '10800'],
['SHA-512', '128', 'Hex', '1700'],
['SHA3-256', '64', 'Hex', '17400'],
['SHA3-512', '128', 'Hex', '17600'],
['BLAKE2b', '128', 'Hex', '600'],
['BLAKE2s', '64', 'Hex', '--'],
['Whirlpool', '128', 'Hex', '6100'],
['bcrypt', '60', '$2a$...', '3200'],
['MD5 crypt', '34', '$1$...', '500'],
['SHA-256 crypt', '63', '$5$...', '7400'],
['SHA-512 crypt', '98', '$6$...', '1800'],
['Argon2', 'var', '$argon2...', '--'],
['PBKDF2', 'var', '$pbkdf2...', '10900'],
['WordPress', '34', '$P$...', '400'],
['Drupal7', '55', '$S$...', '7900'],
];
var html = '<table style="width:100%;font-size:0.82rem;border-collapse:collapse">';
html += '<thead><tr style="border-bottom:2px solid var(--border);text-align:left">';
html += '<th style="padding:6px 10px">Algorithm</th>';
html += '<th style="padding:6px 10px">Length</th>';
html += '<th style="padding:6px 10px">Format</th>';
html += '<th style="padding:6px 10px">Hashcat Mode</th></tr></thead><tbody>';
ref.forEach(function(r) {
html += '<tr style="border-bottom:1px solid var(--border)">';
r.forEach(function(c) { html += '<td style="padding:5px 10px;font-family:monospace">' + c + '</td>'; });
html += '</tr>';
});
html += '</tbody></table>';
el.innerHTML = html;
})();
</script>
{% endblock %}