Go Reference Go Report Card License: MIT
Pure Go library and CLI tool for parsing Norton Ghost GHO disk image files.
No C dependencies. No CGo. Single binary.
- Parse GHO file/partition headers and record structure
- Decompress Fast LZ (Z1) compressed partitions
- Create GHO images from raw partition data
- Fixup GHO headers (ghofixup.exe equivalent — CD/span flag modification with PRNG cipher)
- Extract MBR/Track 0 data and partition table
- Stream decompression (constant memory, arbitrary image sizes)
- Supports Ghost 11.x–12.x format
# Library go get github.com/nyarime/gho # CLI tool go install github.com/nyarime/gho/cmd/gho@latest
# Show image info gho info disk.gho # Extract all partitions to a directory gho extract disk.gho output/ # Create a GHO image from a partition image (+ optional MBR) gho create output.gho partition.img mbr.bin # Modify header flags (ghofixup.exe equivalent) gho fixup disk.gho cd # Set spanned/CD bit gho fixup disk.gho cd- # Clear spanned/CD bit gho fixup disk.gho span # Toggle CD flag
Example output:
GHO Image Summary
File Type: 1 (1=single, 9=span)
Compression: 2 (Fast/Z1)
Image ID: 0x12345678
MBR Partitions: 1
P0: type=0x83 LBA=2016 size=102240 (49.9 MB)
Data Partitions: 1
Partition 0: 3 spans, 42816212 bytes compressed data
Decompressing partition 0...
Saved partition 0: output/partition-0.img (51.4 MB)
package main import ( "bytes" "fmt" "log" "github.com/nyarime/gho" ) func main() { img, err := gho.Open("disk.gho") if err != nil { log.Fatal(err) } defer img.Close() // Print summary fmt.Print(img.Summary()) // Access MBR partition table for i, p := range img.MBRPartitions() { fmt.Printf("Partition %d: type=%#x, LBA=%d, size=%d sectors\n", i, p.Type, p.LBAStart, p.LBASize) } // Decompress partition 0 to memory var buf bytes.Buffer if err := img.DecompressPartition(0, &buf); err != nil { log.Fatal(err) } fmt.Printf("Decompressed: %d bytes\n", buf.Len()) }
w, _ := gho.Create("output.gho", gho.CompressionNone) w.WriteTrack0(mbrData, 63) // MBR + boot sectors w.WritePartition(partFile) // raw partition data (io.Reader) w.Close()
// Set CD/spanned bit (like ghofixup.exe cd) gho.ModifyHeader("disk.gho", gho.FixupCD) // Toggle span flag gho.ModifyHeader("disk.gho", gho.FixupSpan)
Norton Ghost GHO files store disk/partition images with the following structure:
┌──────────────────────────────────────┐
│ File Header (512 bytes) │ Magic: FE EF, compression type, ID
├──────────────────────────────────────┤
│ Record: Track 0 (type 0x0006) │ 6-byte header + MBR + boot sectors
├──────────────────────────────────────┤
│ Record: Partition (type 0x0603) │ 20-byte partition descriptor
├──────────────────────────────────────┤
│ FEEF Partition Header (512 bytes) │ Per-partition compression settings
├──────────────────────────────────────┤
│ Compressed Blocks │ [2B len][block data]...
│ ├─ Block: 2B stored_len + data │ 32KB decompressed per block
│ ├─ Block: ... │
│ └─ Block: ... │
├──────────────────────────────────────┤
│ Record: Continuation (type 0x0703) │ Additional data spans
├──────────────────────────────────────┤
│ (optional FEEF + more blocks) │
├──────────────────────────────────────┤
│ Record: End (type 0x0023) │ End of image marker
└──────────────────────────────────────┘
Compression: Each block is 32KB decompressed. The first byte of block data indicates the type:
0x01→ Uncompressed (raw data at offset 4)- Other → Fast LZ compressed (custom LZ77 variant with 4096-entry hash table)
Records: Every record has a 10-byte header: [4B type][4B magic 0x012F18D8][2B body_len]
The Fast LZ decompressor was reverse-engineered from Norton Ghost 11.5.1. It's a custom LZ77 variant using:
- 16-bit control words (bit 0 = literal, bit 1 = match reference)
- 4096-entry hash table with the hash function:
h = ((-24993 * (b2 ^ (16 * (b1 ^ (16 * b0))))) >> 4) & 0xFFF - 2-byte match tokens encoding hash index + extra length
- Minimum match length of 3 bytes
| Ghost Version | Compression | Status |
|---|---|---|
| 11.x–12.x | None (Z0) | ✅ Read + Write |
| 11.x–12.x | Fast LZ (Z1) | |
| 11.x–12.x | High/zlib (Z3–Z9) | ✅ Read + Write |
| Encrypted images | CRC-16 cipher | ✅ Read + Write |
| Span files (.ghs) | Multi-file | ✅ Read |
Contributions welcome! Areas that need work:
- Span file writing: Creating multi-file (.ghs) span images
- Full disk images: Currently supports partition-level images; whole-disk with MBR rebuild is planned
MIT — see LICENSE.
Reverse-engineered from Norton Ghost 11.5.1 by Nyarime.
Part of the Nyarc firmware analysis toolkit.