@@ -606,6 +606,78 @@ def jotai(
606606 except Exception as exc :
607607 logger .error ("Jotai benchmark failed: %s" , exc )
608608 raise typer .Exit (code = 1 )
609+
610+ @app .command ()
611+ def headers (
612+ input_file : Path = typer .Argument (..., help = "C/C++ source file to obfuscate" ),
613+ output : Optional [Path ] = typer .Option (None , "--output" , "-o" , help = "Output file (default: input_obfuscated.c)" ),
614+ stdlib_only : bool = typer .Option (False , "--stdlib-only" , help = "Obfuscate only standard library functions" ),
615+ custom_only : bool = typer .Option (False , "--custom-only" , help = "Obfuscate only custom functions" ),
616+ dry_run : bool = typer .Option (False , "--dry-run" , help = "Show what would be obfuscated without writing output" ),
617+ verbose : bool = typer .Option (False , "--verbose" , "-v" , help = "Show function pointer mapping" ),
618+ ):
619+ """Obfuscate function calls in a C/C++ source file using indirect calls via function pointers."""
620+
621+ from core .indirect_call_obfuscator import obfuscate_indirect_calls
622+
623+ if not input_file .exists ():
624+ typer .echo (f"Error: Input file not found: { input_file } " , err = True )
625+ raise typer .Exit (code = 1 )
626+
627+ output_file = output or input_file .parent / f"{ input_file .stem } _obfuscated{ input_file .suffix } "
628+
629+ if stdlib_only :
630+ obfuscate_stdlib = True
631+ obfuscate_custom = False
632+ elif custom_only :
633+ obfuscate_stdlib = False
634+ obfuscate_custom = True
635+ else :
636+ obfuscate_stdlib = True
637+ obfuscate_custom = True
638+
639+ typer .echo (f"📄 Reading: { input_file } " )
640+ source_code = input_file .read_text (encoding = "utf-8" , errors = "replace" )
641+
642+ typer .echo ("🔒 Obfuscating function calls..." )
643+ typer .echo (f" - Standard library: { 'Yes' if obfuscate_stdlib else 'No' } " )
644+ typer .echo (f" - Custom functions: { 'Yes' if obfuscate_custom else 'No' } " )
645+
646+ try :
647+ transformed_code , metadata = obfuscate_indirect_calls (
648+ source_code ,
649+ input_file ,
650+ obfuscate_stdlib = obfuscate_stdlib ,
651+ obfuscate_custom = obfuscate_custom ,
652+ )
653+
654+ typer .echo ("\n ✅ Obfuscation complete:" )
655+ typer .echo (f" - Standard library functions: { metadata ['obfuscated_stdlib_functions' ]} " )
656+ typer .echo (f" - Custom functions: { metadata ['obfuscated_custom_functions' ]} " )
657+ typer .echo (f" - Total obfuscated: { metadata ['total_obfuscated' ]} " )
658+
659+ if verbose :
660+ typer .echo ("\n 📋 Function pointers created:" )
661+ for func , ptr in sorted (metadata ["function_pointers" ].items ()):
662+ typer .echo (f" { func } → { ptr } " )
663+
664+ if dry_run :
665+ typer .echo ("\n Dry run mode - no file written" )
666+ typer .echo ("\n Preview (first 50 lines):" )
667+ typer .echo ("=" * 60 )
668+ for i , line in enumerate (transformed_code .split ("\n " )[:50 ], 1 ):
669+ typer .echo (f"{ i :3} : { line } " )
670+ typer .echo ("=" * 60 )
671+ else :
672+ output_file .write_text (transformed_code , encoding = "utf-8" )
673+ typer .echo (f"\n 💾 Output written to: { output_file } " )
674+
675+ except Exception as exc :
676+ typer .echo (f"\n ❌ Error during obfuscation: { exc } " , err = True )
677+ if verbose :
678+ import traceback
679+ traceback .print_exc ()
680+ raise typer .Exit (code = 1 )
609681
610682
611683if __name__ == "__main__" :
0 commit comments