draugr.git


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 }