373 lines
17 KiB
HTML
373 lines
17 KiB
HTML
|
|
{% 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">← 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 %}
|