draugr~ single ELF file analysis tool |
| git clone https://github.com/djnnvx/draugr.git |
| log | files | refs | archive | README |
entropy.odin (1511B)
1 package analysis 2 3 import "core:fmt" 4 import "core:math" 5 import "core:os" 6 7 calculate_entropy :: proc(data: []u8) -> f64 { 8 if len(data) == 0 { 9 return 0.0 10 } 11 12 freq: [256]f64 13 for b in data { 14 freq[b] += 1.0 15 } 16 17 total := f64(len(data)) 18 entropy := 0.0 19 for i := 0; i < len(freq); i += 1 { 20 f := freq[i] 21 if f > 0 { 22 p := f / total 23 entropy -= p * math.log_f64(p, 2) 24 } 25 } 26 27 return entropy 28 } 29 30 entropy_output :: proc(data: []u8, out_path: string) -> string { 31 f, err := open_out(out_path) 32 if err != "" { 33 return err 34 } 35 defer close_out(f, out_path) 36 37 block_size := 256 38 fmt.fprintf(f, "Entropy Analysis (block size: %d bytes)\n", block_size) 39 fmt.fprintf(f, "%-12s %-6s %s\n", "Offset", "Size", "Entropy") 40 fmt.fprintf(f, "%s\n", "----------------------------------------") 41 42 for i := 0; i < len(data); i += block_size { 43 end := i + block_size 44 if end > len(data) { 45 end = len(data) 46 } 47 48 block := data[i:end] 49 entropy := calculate_entropy(block) 50 51 // Odin's fmt zero-fills numeric widths, so pad via a string for alignment. 52 fmt.fprintf(f, "0x%08x %-6s %.4f\n", i, fmt.tprintf("%d", len(block)), entropy) 53 } 54 55 overall := calculate_entropy(data) 56 fmt.fprintf(f, "\nOverall entropy: %.4f bits/byte\n", overall) 57 58 if overall < 4.0 { 59 fmt.fprintf(f, "Classification: Low entropy (text/code)\n") 60 } else if overall < 7.0 { 61 fmt.fprintf(f, "Classification: Medium entropy (mixed)\n") 62 } else { 63 fmt.fprintf(f, "Classification: High entropy (compressed/encrypted)\n") 64 } 65 66 return "" 67 }