Binary File Hex Dump Viewer & Annotator

Binary File Hex Dump Viewer & Annotator

Paste raw hex data to visualize the dump and log forensic annotations.

1. Raw Hexadecimal Input

Note: Input must be a continuous hex sequence (0-9, A-F).

2. Add Annotation

Paste raw hex data above to visualize the dump.

'; return; } const bytesPerLine = 16; const totalLength = rawHex.length; // Render Title outputDiv.innerHTML += `
Hex Dump Visualization
`; // Sort annotations by offset annotations.sort((a, b) => a.offset - b.offset); let nextAnnotationIndex = 0; for (let offset = 0; offset < totalLength; offset += bytesPerLine * 2) { const lineHex = rawHex.substring(offset, offset + bytesPerLine * 2); if (lineHex.length === 0) break; const lineAscii = hexToAscii(lineHex); const address = '0x' + offset.toString(16).padStart(8, '0'); let hexFormatted = ''; for (let i = 0; i < lineHex.length; i += 2) { hexFormatted += lineHex.substring(i, i + 2) + ' '; } const lineDiv = document.createElement('div'); lineDiv.className = 'bhdva-hex-line'; lineDiv.innerHTML = ` ${address} ${hexFormatted} ${lineAscii} `; outputDiv.appendChild(lineDiv); // Inject annotations if they fall on this line while (nextAnnotationIndex < annotations.length) { const currentAnno = annotations[nextAnnotationIndex]; if (currentAnno.offset >= offset && currentAnno.offset < offset + bytesPerLine * 2) { // Annotation belongs to this line const relativeOffset = currentAnno.offset - offset; const annoDiv = document.createElement('div'); annoDiv.className = 'bhdva-hex-line'; annoDiv.innerHTML = ` â””> (${currentAnno.offset.toString(16).padStart(4, '0')}) ${escapeHtml(currentAnno.text)} `; outputDiv.appendChild(annoDiv); nextAnnotationIndex++; } else if (currentAnno.offset >= offset + bytesPerLine * 2) { // Annotation belongs to a later line break; } else { // Annotation was skipped or is misplaced nextAnnotationIndex++; } } } }; // --- Annotation Management --- window.bhdvaAddAnnotation = function() { const offsetInput = document.getElementById('bhdva-annotation-offset').value.trim(); const text = document.getElementById('bhdva-annotation-text').value.trim(); if (!offsetInput || !text) { alert("Please provide both a Hex Offset and Annotation Text."); return; } // Parse hex address to integer offset const offset = parseInt(offsetInput.toLowerCase().startsWith('0x') ? offsetInput : '0x' + offsetInput, 16); if (isNaN(offset)) { alert("Invalid Hex Offset format. Use 0x1A or 1A."); return; } annotations.push({ offset, text }); // Clear input document.getElementById('bhdva-annotation-offset').value = '0x'; document.getElementById('bhdva-annotation-text').value = ''; bhdvaGenerateDump(); // Regenerate display bhdvaRenderAnnotationList(); // Update management list }; window.bhdvaRemoveAnnotation = function(offset) { annotations = annotations.filter(a => a.offset !== offset); bhdvaGenerateDump(); bhdvaRenderAnnotationList(); }; function bhdvaRenderAnnotationList() { const list = document.getElementById('bhdva-annotation-list'); list.innerHTML = ''; if (annotations.length === 0) { list.innerHTML = '

No annotations logged.

'; return; } // Sort by offset for display annotations.sort((a, b) => a.offset - b.offset); annotations.forEach(a => { const item = document.createElement('div'); item.className = 'flex justify-between items-center bg-gray-50 p-2 rounded'; item.innerHTML = ` 0x${a.offset.toString(16).padStart(4, '0')} ${escapeHtml(a.text)} `; list.appendChild(item); }); } // --- PDF Download --- window.bhdvaDownloadPDF = function() { // Ensure dump is generated before downloading bhdvaGenerateDump(); const element = document.getElementById('bhdva-viewer-output'); document.body.classList.add('bhdva-generating-pdf'); const opt = { margin: [0.5, 0.5], filename: `Binary_Hex_Dump_Annotated.pdf`, image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2, useCORS: true }, jsPDF: { unit: 'in', format: 'letter', orientation: 'landscape' } }; html2pdf().set(opt).from(element).save().then(() => { document.body.classList.remove('bhdva-generating-pdf'); }); }; // Utility: HTML Escape function escapeHtml(text) { if (!text) return ''; return text.replace(/[&<>"']/g, function(m) { switch (m) { case '&': return '&'; case '<': return '<'; case '>': return '>'; case '"': return '"'; case "'": return '''; default: return m; } }); }
Scroll to Top