123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)openCil_typesopenCil_datatypeletwarnkindname=Options.warning~once:true"unobfuscated %s name `%s'"kindnamelethas_literal_string=reffalseclassvisitor=objectinheritVisitor.frama_c_inplacevalvarinfos_visited=Varinfo.Hashtbl.create17vallogic_vars_visited=Logic_var.Hashtbl.create7valid_pred_visited=Identified_predicate.Hashtbl.create7method!vtype=function|TFun(t,args,variadic,attrs)->letargs'=matchargswith|None->None|Somel->Some(List.map(fun(s,t,a)->(Dictionary.freshObfuscator_kind.Formal_in_types,t,a))l)inCil.ChangeDoChildrenPost(TFun(t,args',variadic,attrs),Fun.id)|_->Cil.DoChildrenmethod!vglob_aux=function|GType(ty,_)->ifnot(Cil.is_in_libc(Cil.typeAttrsty.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!vexpre=matche.enodewith|Const(CStrstr)->has_literal_string:=true;(* ignore the result: will be handle by hacking the pretty printer *)(tryignore(Dictionary.id_of_literal_stringstr)withNot_found->ignore(Dictionary.freshObfuscator_kind.Literal_stringstr));Cil.SkipChildren|_->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 *)ifVarinfo.Hashtbl.memvarinfos_visitedvithenCil.SkipChildrenelsebeginifCil.isFunctionTypevi.vtypethenbeginifvi.vname<>"main"&¬(Cil_builtins.is_builtinvi)&¬(Cil_builtins.is_special_builtinvi.vname)&¬(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=function|Attr(str,_)|AttrAnnotstr->warn"attribute"str;Cil.DoChildrenmethod!vattrparamp=(matchpwith|AStrstr|ACons(str,_)|ADot(_,str)->warn"attribute parameter"str|_->());Cil.DoChildreninitializerhas_literal_string:=falseendletobfuscate_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(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))moduleUpdatePrinter(X:Printer.PrinterClass)=struct(* obfuscated printer *)classprinter=objectinheritX.printerassupermethod!constantfmt=function|CStrstr->Format.fprintffmt"%s"(Dictionary.id_of_literal_stringstr)|c->super#constantfmtcmethod!filefmtast=if!has_literal_stringthenbeginletstring_fmt=ifOptions.Literal_string.is_default()thenfmtelsebeginletfile=Options.Literal_string.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";Dictionary.pretty_kindstring_fmtObfuscator_kind.Literal_string;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.Literal_string.get())endend;super#filefmtastendendletobfuscate()=Dictionary.mark_as_computed();obfuscate_behaviors();Visitor.visitFramacFile(newvisitor:>Visitor.frama_c_visitor)(Ast.get());Printer.update_printer(moduleUpdatePrinter:Printer.PrinterExtension)(*
Local Variables:
compile-command: "make -C ../../.."
End:
*)