hex_editor

    Terminal hex editor & binary analysis toolkit: 20 format parsers, wildcard search, entropy analysis, steganography detection, Base64/URL/Unicode/Hex codecs. Cross-platform (Windows/Linux), dual-target (Native + Wasm-GC).

    hex
    editor
    binary
    tui
    parser
    forensics
    entropy
    steganography
    Download zip
    Author
    Version
    0.1.3
    License
    Apache-2.0
    Last updated
    2 days ago
    Downloads
    33

    Dependencies

    #R00TK17/hex_editor

    CI

    Terminal hex editor and binary file analysis toolkit written in MoonBit.

    #Features

    • Hex Editor TUI — interactive terminal UI with gap-buffer O(1) editing, undo/redo, clipboard
    • 20 Format Parsers — JPEG, PNG, GIF, BMP, WAV, FLAC, MP3, OGG, AVI, MP4, WebM/MKV, ZIP, RAR, TAR, ZLIB, GZip, 7z, BZip2, PE, ELF
    • Wildcard Search — BMH exact, Shift-Or bit-parallel (??), greedy segment (*, *N)
    • Signature Scanner — Aho-Corasick multi-pattern matching with 18 per-format validators
    • Entropy Analysis — Shannon entropy on 256-byte blocks (precomputed lookup table)
    • Hash / Checksum — MD5, SHA1, SHA224, SHA256, SM3 (pure MoonBit, no FFI)
    • Codecs — Base64, URL percent-encoding, Unicode escape, Hex encode/decode
    • Strings Extraction — printable ASCII sequences ≥ 4 chars
    • File Browser — UTF-8 path support, multi-file switching, persistent bookmarks
    • Steganography Detection — embedded file extraction, trailing data detection

    #Quick Start

    # Clone and setup (auto-installs MoonBit, GCC, builds, tests) git clone https://github.com/R00TK17/moonbit-HexEditor.git cd moonbit-HexEditor chmod +x setup.sh && ./setup.sh # Linux # .\setup.ps1 # Windows # CLI usage moon run cmd/main -- struct file.bin moon run cmd/main -- scan file.bin moon run cmd/main -- entropy file.bin moon run cmd/main -- hash file.bin # TUI mode moon run cmd/main -- file.bin

    #Usage as a Library

    // Parse binary file structure

    ///|
    let fields = @R00TK17/hex_editor.parse_structure(bytes)

    // Scan for embedded file signatures

    ///|
    let matches = @R00TK17/hex_editor.scan_signatures(bytes)

    // Shannon entropy analysis (256-byte blocks)

    ///|
    let blocks = @R00TK17/hex_editor.entropy_scan(bytes)

    // Search with wildcards

    ///|
    let result = @R00TK17/hex_editor.find_hex_pattern(bytes, "FF ?? ?? EE")

    ///|
    let result = @R00TK17/hex_editor.find_text_pattern(bytes, "He*ld")

    // Codecs

    ///|
    let b64 = @R00TK17/hex_editor.base64_encode(bytes)

    ///|
    let decoded = @R00TK17/hex_editor.base64_decode(b64)

    // Hash / checksum (MD5, SHA1, SHA224, SHA256, SM3)

    ///|
    let md5 : String = @R00TK17/hex_editor.md5_hex(bytes)

    ///|
    let results : Array[@R00TK17/hex_editor.HashResult] = @R00TK17/hex_editor.hash_all(
    bytes,
    )

    #Platform Support

    PlatformNativeWasm-GC
    Windows✓ TUI + CLIN/A
    Linux✓ TUI + CLIN/A
    Browser✓ CLI only

    EntropyBlock

    pub struct EntropyBlock {
    start : Int
    end : Int
    entropy : Double
    } derive(
    Debug
    )

    HashResult

    pub struct HashResult {
    name : String
    value : String
    } derive(
    Debug
    )

    HexBuffer

    type HexBuffer

    A mutable buffer for hex editing with Gap Buffer optimization.

    Physical layout: [bytes | gap | bytes]
    • gap_start: first index of the gap
    • gap_end: first index after the gap
    • len: logical byte count (excluding gap)

    The gap moves to the edit cursor on insert/delete. Consecutive edits at the same position are O(1).

    HexBuffer::byte_at

    fn HexBuffer::byte_at(self : HexBuffer, idx : Int) -> Byte

    Fast byte read for rendering (no bounds check, no Option). Caller must ensure idx < self.len.

    HexBuffer::data_ref

    fn HexBuffer::data_ref(self : HexBuffer) -> FixedArray[Byte]

    Returns internal data array (includes gap). Use byte_at() for correct access.

    HexBuffer::delete_byte

    fn HexBuffer::delete_byte(self : HexBuffer, offset : Int) -> Bool

    Delete byte at logical offset. O(1) if gap is already at offset.
    1. Move gap to offset
    2. Expand gap_end by 1 (the byte at gap_end is "deleted")

    HexBuffer::from_bytes

    fn HexBuffer::from_bytes(bytes : Bytes) -> HexBuffer

    Creates a HexBuffer from bytes. Gap is placed at the end. Layout: [file_bytes | gap]

    HexBuffer::from_file

    fn HexBuffer::from_file(path : String) -> HexBuffer raise

    HexBuffer::get_byte

    fn HexBuffer::get_byte(self : HexBuffer, offset : Int) -> Byte?

    Safe byte read with bounds check.

    HexBuffer::get_file_path

    fn HexBuffer::get_file_path(self : HexBuffer) -> String?

    HexBuffer::insert_byte

    fn HexBuffer::insert_byte(self : HexBuffer, offset : Int, value : Byte) -> Bool

    Insert a byte at logical offset. O(1) if gap is already at offset.
    1. Grow gap if exhausted
    2. Move gap to offset
    3. Write byte into gap_start, advance gap_start

    HexBuffer::is_empty

    fn HexBuffer::is_empty(self : HexBuffer) -> Bool

    HexBuffer::is_modified

    fn HexBuffer::is_modified(self : HexBuffer) -> Bool

    HexBuffer::length

    fn HexBuffer::length(self : HexBuffer) -> Int

    HexBuffer::new

    fn HexBuffer::new() -> HexBuffer

    Creates a new empty HexBuffer with 256-byte initial gap.

    HexBuffer::save

    fn HexBuffer::save(self : HexBuffer, path? : String) -> Unit raise

    HexBuffer::set_byte

    fn HexBuffer::set_byte(self : HexBuffer, offset : Int, value : Byte) -> Bool

    Set byte at logical offset. Returns false if out of bounds.

    HexBuffer::set_file_path

    fn HexBuffer::set_file_path(self : HexBuffer, path : String) -> Unit

    HexBuffer::to_bytes

    fn HexBuffer::to_bytes(self : HexBuffer) -> Bytes

    Compact copy of logical bytes (no gap).

    HexBuffer::to_fixedarray

    fn HexBuffer::to_fixedarray(self : HexBuffer) -> FixedArray[Byte]

    HexViewConfig

    type HexViewConfig

    Configuration for hex dump display formatting.

    HexViewConfig::default

    fn HexViewConfig::default() -> HexViewConfig

    Creates a default HexViewConfig.

    HexViewConfig::with_ascii

    fn HexViewConfig::with_ascii(self : HexViewConfig, show : Bool) -> HexViewConfig

    Creates a HexViewConfig with custom show_ascii setting.

    HexViewConfig::with_bytes_per_row

    fn HexViewConfig::with_bytes_per_row(self : HexViewConfig, bpr : Int) -> HexViewConfig

    Creates a HexViewConfig with custom bytes per row.

    HexViewConfig::with_uppercase

    fn HexViewConfig::with_uppercase(self : HexViewConfig, upper : Bool) -> HexViewConfig

    Creates a HexViewConfig with custom uppercase_hex setting.

    ScanMatch

    pub struct ScanMatch {
    offset : Int
    name : String
    size : Int
    confidence : Int
    } derive(
    Debug
    )

    StringMatch

    pub struct StringMatch {
    offset : Int
    text : String
    } derive(
    Debug
    )

    StructField

    type StructField derive(
    Debug
    )

    A parsed field from a file structure.

    base64_decode

    fn base64_decode(text : String) -> Bytes?

    Decode Base64 string to bytes.

    base64_encode

    fn base64_encode(data : Bytes) -> String

    Encode bytes to Base64 string.

    entropy_scan

    fn entropy_scan(bytes : Bytes) -> Array[EntropyBlock]

    Scan bytes in 256-byte blocks, compute Shannon entropy per block. Full blocks use precomputed table (pure lookup, no log2 calls).

    extract_region

    fn extract_region(bytes : Bytes, start : Int, name : String, base_path : String) -> String

    find_all_bytes

    fn find_all_bytes(data : Bytes, pattern : Bytes) -> Array[Int]

    Boyer-Moore-Horspool search — all occurrences.

    find_hex_pattern

    fn find_hex_pattern(data : Bytes, pattern : String) -> (Array[Int], Array[Int])?

    Search data for a hex pattern with ?? and * wildcards. Returns Some((offsets, match_lengths)) or None if pattern is invalid.

    find_strings

    fn find_strings(bytes : Bytes) -> Array[StringMatch]

    Scan bytes for printable ASCII strings of length >= 4.

    find_text_pattern

    fn find_text_pattern(data : Bytes, pattern : String) -> (Array[Int], Array[Int])?

    Search data for a text pattern with ?, *, *N wildcards and \ escape. Returns Some((offsets, match_lengths)) or None if pattern is invalid.

    format_ascii

    fn format_ascii(byte : Byte) -> Char

    Converts a byte to its ASCII representation for the text column. Printable ASCII characters (0x20-0x7E) are shown as-is. Non-printable bytes are shown as '.'.

    format_buffer_info

    fn format_buffer_info(buffer : HexBuffer) -> String

    Returns a brief summary of a HexBuffer.

    format_byte_hex

    fn format_byte_hex(byte : Byte, uppercase? : Bool) -> String

    Converts a byte to a 2-character hex string.

    format_hex_dump

    fn format_hex_dump(buffer : HexBuffer, start_offset? : Int, length? : Int, config? : HexViewConfig) -> String

    Formats a complete hex dump from a HexBuffer.

    format_hex_row

    fn format_hex_row(data : FixedArray[Byte], start : Int, length : Int, base_offset : Int, config : HexViewConfig) -> String

    Formats a single row of a hex dump.

    format_offset

    fn format_offset(offset : Int, width? : Int, uppercase? : Bool) -> String

    Formats an integer offset as a hex address string.

    format_size

    fn format_size(len : Int) -> String

    Formats a byte count in human-readable form.

    format_strings_export

    fn format_strings_export(matches : Array[StringMatch]) -> String

    Format strings matches as plain text for export.

    format_structure

    fn format_structure(fields : Array[StructField]) -> String

    Display parsed structure as readable text.

    format_structure_json

    fn format_structure_json(fields : Array[StructField]) -> String

    Format StructField array as JSON string.

    hash_all

    fn hash_all(data : Bytes) -> Array[HashResult]

    Compute all supported digests at once.

    hex_decode

    fn hex_decode(text : String) -> Bytes?

    Hex decode: space-separated hex values → bytes. Example: "48 65 6C" → b"\x48\x65\x6C"

    hex_encode

    fn hex_encode(data : Bytes) -> String

    Hex encode: bytes → space-separated hex values. Example: b"\x48\x65" → "48 65"

    md5_hex

    fn md5_hex(data : Bytes) -> String

    MD5 digest (hex, lowercase). MD5 is cryptographically broken — prefer SHA-256.

    parse_hex_string

    fn parse_hex_string(hex_str : String) -> Bytes?

    Parses a hex string like "FF 00 AB" into a Bytes sequence.

    parse_structure

    fn parse_structure(bytes : Bytes) -> Array[StructField]

    Parse structure of file bytes. Returns top-level fields or empty array.

    scan_signatures

    fn scan_signatures(bytes : Bytes) -> Array[ScanMatch]

    sha1_hex

    fn sha1_hex(data : Bytes) -> String

    SHA-1 digest (hex, lowercase). SHA-1 is cryptographically broken — prefer SHA-256.

    sha224_hex

    fn sha224_hex(data : Bytes) -> String

    SHA-224 digest (hex, lowercase).

    sha256_hex

    fn sha256_hex(data : Bytes) -> String

    SHA-256 digest (hex, lowercase).

    sm3_hex

    fn sm3_hex(data : Bytes) -> String

    SM3 digest (Chinese national standard, hex, lowercase).

    to_hex_string

    fn to_hex_string(n : Int, width? : Int) -> String

    Converts a number to a fixed-width hex string (useful for UI).

    unicode_decode

    fn unicode_decode(text : String) -> Bytes?

    Unicode decode: parse \uXXXX sequences to bytes. Plain ASCII characters are kept as-is. Codepoints <= 0x7F → 1 byte, <= 0x7FF → 2 bytes, else → 3 bytes (UTF-8). Returns None on invalid input.

    unicode_encode

    fn unicode_encode(data : Bytes) -> String

    Unicode encode: each byte → \u00XX notation.

    url_decode

    fn url_decode(text : String) -> Bytes?

    URL percent-decode a string to bytes. %XX is decoded, + is decoded as space. Returns None on invalid input.

    url_encode

    fn url_encode(data : Bytes) -> String

    URL percent-encode bytes. Unreserved characters (A-Z, a-z, 0-9, -, _, ., ~) pass through, all others become %XX.