123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301(**************************************************************************)(* *)(* SPDX-License-Identifier LGPL-2.1 *)(* Copyright (C) *)(* CEA (Commissariat à l'énergie atomique et aux énergies alternatives) *)(* *)(**************************************************************************)openCil_typesopenCil_datatypeletwarnkindname=Options.warning~once:true"unobfuscated %s name `%s'"kindnameclassvisitor=objectinheritVisitor.frama_c_inplacevalvarinfos_visited=Varinfo.Hashtbl.create17vallogic_vars_visited=Logic_var.Hashtbl.create7valid_pred_visited=Identified_predicate.Hashtbl.create7method!vtypet=matcht.tnodewith|TFun(rt,args,variadic)->letargs'=matchargswith|None->None|Somel->Some(List.map(fun(s,t,a)->(Dictionary.freshObfuscator_kind.Formal_in_types,t,a))l)inCil.ChangeDoChildrenPost(Cil_const.mk_tfun~tattr:t.tattrrtargs'variadic,Fun.id)|_->Cil.DoChildrenmethod!vglob_aux=function|GType(ty,_)->ifnot(Cil.is_in_libc(Ast_types.get_attributesty.ttype))thenty.tname<-Dictionary.freshObfuscator_kind.Typety.tname;Cil.DoChildren|GVarDecl(v,_)|GVar(v,_,_)|GFun({svar=v},_)|GFunDecl(_,v,_)whenCil_builtins.is_unused_builtinv->Cil.SkipChildren|_->Cil.DoChildrenmethod!vcompinfoci=ci.cname<-Dictionary.freshObfuscator_kind.Typeci.cname;Cil.DoChildrenmethod!venuminfoei=ei.ename<-Dictionary.freshObfuscator_kind.Typeei.ename;Cil.DoChildrenmethod!vfieldinfofi=fi.fname<-Dictionary.freshObfuscator_kind.Fieldfi.fname;Cil.DoChildrenmethod!venumitemei=ei.einame<-Dictionary.freshObfuscator_kind.Enumei.einame;Cil.DoChildrenmethod!vvdecvi=(* Varinfo can be visited (and obfuscated) more than once:
functions for their declaration and definition, variables
as parts of the type of the function, and in the body of
the function declaration, etc. Thus we make sure that the
obfuscator does not visit them twice.
Moreover, string literals have their own special treatment.
*)ifVarinfo.Hashtbl.memvarinfos_visitedvi||Ast_info.is_string_literalvithenCil.SkipChildrenelsebeginifAst_types.is_funvi.vtypethenbeginifvi.vname<>"main"&¬(Cil_builtins.is_builtinvi)&¬(Cil.is_in_libcvi.vattr)thenvi.vname<-Dictionary.freshObfuscator_kind.Functionvi.vnameendelsebeginletadd=ifvi.vglobthenDictionary.freshObfuscator_kind.Global_varelseifvi.vformalthenDictionary.freshObfuscator_kind.Formal_varelseDictionary.freshObfuscator_kind.Local_varinvi.vname<-addvi.vname;end;Varinfo.Hashtbl.addvarinfos_visitedvi();Cil.DoChildrenendmethod!vlogic_var_decllvi=matchlvi.lv_kindwith|LVGlobal|LVFormal|LVQuant|LVLocal->ifLogic_var.Hashtbl.memlogic_vars_visitedlvithenCil.SkipChildrenelsebeginlvi.lv_name<-Dictionary.freshObfuscator_kind.Logic_varlvi.lv_name;Logic_var.Hashtbl.addlogic_vars_visitedlvi();Cil.DoChildrenend|LVC->Cil.SkipChildrenmethod!vstmt_auxstmt=letlabels=List.map(function|Label(s,loc,true)->(* only obfuscate user's labels, not Cil's ones *)lets'=Dictionary.freshObfuscator_kind.LabelsinLabel(s',loc,true)|Label(_,_,false)|Case_|Default_aslabel->label)stmt.labelsinstmt.labels<-labels;Cil.DoChildrenmethod!videntified_predicatep=ifIdentified_predicate.Hashtbl.memid_pred_visitedpthenCil.SkipChildrenelsebeginIdentified_predicate.Hashtbl.addid_pred_visitedp();let{tp_kind;tp_statement=pred}=p.ip_contentinletnames=pred.pred_nameinletnames'=List.map(Dictionary.freshObfuscator_kind.Predicate)namesinletpred'={predwithpred_name=names'}inletip_content=Logic_const.toplevel_predicate~kind:tp_kindpred'inletp'={pwithip_content}inCil.ChangeDoChildrenPost(p',Fun.id)endmethod!vtermt=List.iter(funs->warn"term"s)t.term_name;Cil.DoChildrenmethod!vannotation=function|Daxiomatic(str,globs,attrs,loc)->letstr'=Dictionary.freshObfuscator_kind.AxiomaticstrinCil.ChangeDoChildrenPost(Daxiomatic(str',globs,attrs,loc),Fun.id)|Dlemma(str,labs,typs,pred,attrs,loc)->letstr'=Dictionary.freshObfuscator_kind.LemmastrinCil.ChangeDoChildrenPost(Dlemma(str',labs,typs,pred,attrs,loc),Fun.id)|_->Cil.DoChildrenmethod!vmodel_infomi=warn"model"mi.mi_name;Cil.DoChildrenmethod!vlogic_type_info_decllti=ifnot(Logic_env.is_builtin_logic_typelti.lt_name)thenlti.lt_name<-Dictionary.freshObfuscator_kind.Logic_typelti.lt_name;Cil.DoChildrenmethod!vlogic_ctor_info_decllci=ifnot(Logic_env.is_builtin_logic_ctorlci.ctor_name)thenlci.ctor_name<-Dictionary.freshObfuscator_kind.Logic_constructorlci.ctor_name;Cil.DoChildrenmethod!vattr(str,_)=warn"attribute"str;Cil.DoChildrenmethod!vattrparamp=(matchpwith|AStrstr|ACons(str,_)|ADot(_,str)->warn"attribute parameter"str|_->());Cil.DoChildrenendletobfuscate_behaviors()=(* inheriting method vbehavior or vspec does not work since only a copy of the
piece of spec is provided. *)Globals.Functions.iter(funkf->leth=Datatype.String.Hashtbl.create7inAnnotations.iter_behaviors_by_emitter(funemitterb->ifEmitter.equalemitterEmitter.end_user&¬(Cil.is_default_behaviorb)thenbeginAnnotations.remove_behavior~force:trueemitterkfb;letnew_=Dictionary.freshObfuscator_kind.Behaviorb.b_nameinDatatype.String.Hashtbl.addhb.b_namenew_;b.b_name<-new_;Annotations.add_behaviorsemitterkf[b];end)kf;lethandle_bnamesiterremoveadd=iter(funemitterl->removeemitterkfl;addemitterkf(List.map(Datatype.String.Hashtbl.findh)l))kfinhandle_bnamesAnnotations.iter_complete(funekfl->Annotations.remove_completeekfl)(funekfl->Annotations.add_completeekfl);handle_bnamesAnnotations.iter_disjoint(funekfl->Annotations.remove_disjointekfl)(funekfl->Annotations.add_disjointekfl))letdefine_string_litfmtv=Format.fprintffmt"#define %s %a@\n"v.vnameCil_printer.pp_str_literal(Globals.Vars.get_string_literalv)moduleUpdatePrinter(X:Printer.PrinterClass)=struct(* obfuscated printer *)classprinter=object(self)inheritX.printerassupermethod!filefmtast=letliteral_strings=Globals.Vars.fold(funv_acc->ifAst_info.is_string_literalvthenCil_datatype.Varinfo.Set.addvaccelseacc)Cil_datatype.Varinfo.Set.emptyinifnot(Cil_datatype.Varinfo.Set.is_emptyliteral_strings)thenbeginletstring_fmt=ifOptions.String_literal.is_default()thenfmtelsebeginletfile=Options.String_literal.get()intryletcout=open_outfileinFormat.formatter_of_out_channelcoutwithSys_error_asexn->Options.error"@[cannot generate the literal string dictionary \
into file `%s':@ %s@]"file(Printexc.to_stringexn);fmtendinFormat.fprintfstring_fmt"\
/* *********************************************************** */@\n\
/* start of dictionary required to compile the obfuscated code */@\n\
/* *********************************************************** */@\n";Cil_datatype.Varinfo.Set.iter(define_string_litstring_fmt)literal_strings;Format.fprintfstring_fmt"\
/* ********************************************************* */@\n\
/* end of dictionary required to compile the obfuscated code */@\n\
/* ********************************************************* */@\n@\n";iffmt!=string_fmtthenbeginFormat.pp_print_flushstring_fmt();Format.fprintffmt"\
/* include the dictionary of literal strings */@\n\
@[#include \"%s\"@]@\n@\n"(Options.String_literal.get())endend;super#filefmtastmethod!lvalfmtlv=matchlvwith|Varv,(NoOffset|Index_aso)whenAst_info.is_string_literalv->Format.fprintffmt"%s%a"v.vnameself#offseto|_->super#lvalfmtlvmethod!term_lvalfmtlv=matchlvwith|TVar{lv_origin=Somev},(TNoOffset|TIndex_aso)whenAst_info.is_string_literalv->Format.fprintffmt"%s%a"v.vnameself#term_offseto|_->super#term_lvalfmtlvmethod!globalfmtg=matchgwith(* do not output literal string globals even with -print-as-is
(which makes little sense with -obfuscate anyways)
*)|GVarDecl(v,_)|GVar(v,_,_)whenAst_info.is_string_literalv->()|_->super#globalfmtgendendletobfuscate()=Dictionary.mark_as_computed();obfuscate_behaviors();Visitor.visitFramacFile(newvisitor:>Visitor.frama_c_visitor)(Ast.get());Printer.update_printer(moduleUpdatePrinter:Printer.PrinterExtension)