Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file binsec_sse_stake.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2026 *)(* 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). *)(* *)(**************************************************************************)moduleStrMap=Basic_types.String.MapopenTypesopenIr(* --- Expr utils --- *)letrecpp_dba_rec?(flag=0)(_:unit)(ppf:Format.formatter)=function|Dba.Expr.Var{size;name;_}->if2landflag=0thenFormat.fprintfppf"%s"nameelseFormat.fprintfppf"%s<%d>"namesize|Dba.Expr.Load(size,_,e,_)->Format.fprintfppf"%@[%a,%d]"(pp_parenthesis~flag())esize|Dba.Expr.Cstbit->if1landflag=0thenFormat.fprintfppf"%a"Bitvector.pp_hex_or_binbitelse(* remove ambiguity on bitvector size in some cases *)Format.fprintfppf"%a<%d>"Bitvector.pp_hex_or_binbit(Bitvector.size_ofbit)|Dba.Expr.Unary(op,e)->Format.fprintfppf"%a"(pp_dba_uop~flage)op|Dba.Expr.Binary(op,e,e')->Format.fprintfppf"%a"(pp_dba_bop~flagee')op|Dba.Expr.Ite(e,e',e'')->Format.fprintfppf"%a ? %a : %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'(pp_parenthesis~flag())e''andpp_parenthesis?(flag=0)(_:unit)(ppf:Format.formatter)=function|e->(matchewith|Dba.Expr.Var_|Dba.Expr.Load_|Dba.Expr.Cst_->pp_dba_rec~flag()ppfe|e->Format.fprintfppf"(%a)"(pp_dba_rec~flag())e)andpp_dba_uop?(flag=0)(e:Dba.Expr.t)(ppf:Format.formatter)=function|Dba.Unary_op.Not->Format.fprintfppf"! %a"(pp_parenthesis~flag())e|Dba.Unary_op.Sextsize->Format.fprintfppf"sext%d %a"size(pp_parenthesis~flag())e|Dba.Unary_op.Uextsize->Format.fprintfppf"uext%d %a"size(pp_parenthesis~flag())e|Dba.Unary_op.Restrictinter->Format.fprintfppf"%a{%d..%d}"(pp_parenthesis~flag())einter.hiinter.lo|Dba.Unary_op.UMinus->Format.fprintfppf"- %a"(pp_parenthesis~flag())eandpp_dba_bop?(flag=0)(e:Dba.Expr.t)(e':Dba.Expr.t)(ppf:Format.formatter)=function|Plus->Format.fprintfppf"%a + %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|Minus->Format.fprintfppf"%a - %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|Mult->Format.fprintfppf"%a * %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|DivU->Format.fprintfppf"%a /u %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|RemU->Format.fprintfppf"%a %%u %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|DivS->Format.fprintfppf"%a /s %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|RemS->Format.fprintfppf"%a %%s %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|Or->Format.fprintfppf"%a | %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|And->Format.fprintfppf"%a & %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|Xor->Format.fprintfppf"%a ^ %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|Concat->Format.fprintfppf"%a :: %a"(pp_parenthesis~flag())e(pp_parenthesis~flag:0())e'|LShift->Format.fprintfppf"%a lsl %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|RShiftU->Format.fprintfppf"%a lsr %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|RShiftS->Format.fprintfppf"%a asr %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|LeftRotate->Format.fprintfppf"%a rol %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|RightRotate->Format.fprintfppf"%a ror %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|Eq->Format.fprintfppf"%a = %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|Diff->Format.fprintfppf"%a <> %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|LeqU->Format.fprintfppf"%a <=u %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|LtU->Format.fprintfppf"%a <u %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|GeqU->Format.fprintfppf"%a >=u %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|GtU->Format.fprintfppf"%a >u %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|LeqS->Format.fprintfppf"%a <=s %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|LtS->Format.fprintfppf"%a <s %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|GeqS->Format.fprintfppf"%a >=s %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'|GtS->Format.fprintfppf"%a >s %a"(pp_parenthesis~flag())e(pp_parenthesis~flag())e'letpp_dba=pp_dba_rec()letshortname="stake"moduleLogger=Logger.Sub(structletname=shortnameend)typewatchpoint=Rvalue|Load|Address|Test|TargetmoduleWatchpoint=structtypet=watchpointletto_string=function|Rvalue->"rvalue"|Load->"load"|Address->"address"|Test->"test"|Target->"jump-target"letof_string=function|"rvalue"->Rvalue|"load"->Load|"address"->Address|"test"->Test|"jump-target"->Target|_->raise(Invalid_argument"of_string")letppppft=Format.pp_print_stringppf(to_stringt)endtypemode=Ignore|Fix|CheckmoduletypeOPTIONS=sigvalrval:modevalload:modevaladdr:modevaltest:modevaltarget:modevalreg_init:boolvalmem_init:boolendmoduleBuiltin(O:OPTIONS)(E:ENGINEwithtypePath.value=Symbolic.Default.Expr.t):EXTENSIONSwithtypepath=E.Path.t=structmodulePath=E.PathmoduleValue=Path.Valuetypepath=Path.ttypeloc=VarofDba.Var.t|Memofint*Machine.endianness*Dba.Expr.ttypebuiltin+=|Initofloc|FixofDba.Expr.t*watchpoint|CheckofDba.Expr.t*watchpointletinstrumentation_routine:Revision.t->unit=letvisit_expr:Revision.t->Revision.vertex->Dba.Expr.t->unit=fungraphvertexexpr->ifO.reg_initthenDba_types.Var.Set.iter(fun({info;_}asvar)->matchinfowith|Register|Flag->Revision.insert_beforegraphvertex(Builtin(Init(Varvar)))|_->())(Dba_types.Expr.collect_variablesexprDba_types.Var.Set.empty)inletinstrument:Revision.t->Revision.vertex->Dba.Expr.t->watchpoint->unit=fungraphvertexexprwatchpoint->letopt=matchwatchpointwith|Rvalue->O.rval|Load->O.load|Address->O.addr|Test->O.test|Target->O.targetinmatchoptwith|Ignore->()|Fix->Revision.insert_beforegraphvertex(Builtin(Fix(expr,watchpoint)))|Check->Revision.insert_beforegraphvertex(Builtin(Check(expr,watchpoint)))infungraph->Revision.iter_new_vertex(funvertex->matchRevision.nodegraphvertexwith|Fallthrough{kind=Assign{rval;_};_}->visit_exprgraphvertexrval;instrumentgraphvertexrvalRvalue|Fallthrough{kind=Load{var={size;_};dir;addr;_};_}->visit_exprgraphvertexaddr;instrumentgraphvertexaddrAddress;ifO.mem_initthenRevision.insert_beforegraphvertex(Builtin(Init(Mem(size/8,dir,addr))));letload=Dba.Expr.load(Size.Byte.create(size/8))diraddrininstrumentgraphvertexloadLoad|Fallthrough{kind=Store{addr;rval;_};_}->visit_exprgraphvertexrval;visit_exprgraphvertexaddr;instrumentgraphvertexrvalRvalue;instrumentgraphvertexaddrAddress|Fallthrough{kind=Assumetest;_}|Fallthrough{kind=Asserttest;_}|Branch{test;_}->visit_exprgraphvertextest;instrumentgraphvertextestTest|Terminator{kind=Jump{target;_};_}->visit_exprgraphvertextarget;instrumentgraphvertextargetTarget|_->())graphletwordsize=Machine.ISA.word_sizeE.isaletfull_mask:unitZmap.t=Zmap.singleton~lo:Z.zero~hi:(Z.extractZ.minus_one0wordsize)()letslice:Bitvector.t->int->Image.bufferZmap.t=funaddrsize->letlo=Bitvector.value_ofaddrinlethi=Z.addlo(Z.of_int(size-1))inletview=Zmap.singleton~lo~hiImage.ZeroinZmap.union_left(Zmap.substract~crop:Image.crop_bufferE.image.content(Zmap.substractfull_maskview))viewletread:int->Machine.endianness->Bitvector.t->Bitvector.t=funsizeendiannessaddr->letreader=Image.content_reader(Virtual_address.of_bitvectoraddr)(Z.of_intsize)~endianness(sliceaddrsize)inReader.Read.readreadersizelethard_patch:Path.t->Image.bufferZmap.t->unit=funpathcontent->Zmap.iter(fun(Item{lo;hi;elt})->letcst=Bitvector.createlowordsizeinletaddr=Value.constantcstinmatch(elt:Image.buffer)with|Zero->Logger.debug~level:1"%a: Zeroing addresses [%a .. %a]"Virtual_address.pp(Path.pcpath)Bitvector.pp_hex_or_bincstBitvector.pp_hex_or_bin(Bitvector.createhiwordsize);Path.memcpy_vpathNone~addr(Z.to_int(Z.subhilo)+1)(Bigarray.Array1.createBigarray.int8_unsignedC_layout0)|Data{offset;len;value}->Logger.debug~level:1"%a: Loading addresses [%a .. %a] from file"Virtual_address.pp(Path.pcpath)Bitvector.pp_hex_or_bincstBitvector.pp_hex_or_bin(Bitvector.createhiwordsize);Path.memcpy_vpathNone~addrlen(Bigarray.Array1.subvalueoffsetlen))contentletsoft_patch:int->Machine.endianness->Bitvector.t->path->Symbolic.Default.Memory.symbol->unit=funsizeendiannessaddrpath(Symbol_asroot)->letvalue=readsizeendiannessaddrinletload=Symbolic.Default.Expr.loadsizeendianness(Value.constantaddr)rootinLogger.debug~level:1"%a: Soft patching %a with %a"Virtual_address.pp(Path.pcpath)Bitvector.pp_hex_or_binaddrBitvector.pp_hex_or_binvalue;matchPath.assume_vpath(Value.binaryEqload(Value.constantvalue))with|Some_->()|None->Logger.warning"%a: Soft patching %a with %a failed."Virtual_address.pp(Path.pcpath)Bitvector.pp_hex_or_binaddrBitvector.pp_hex_or_binvalue|exceptionSymbolic.State.Unknown->Logger.warning"%a: Soft patching %a with %a timed out."Virtual_address.pp(Path.pcpath)Bitvector.pp_hex_or_binaddrBitvector.pp_hex_or_binvalueletrecpatch:int->Machine.endianness->Bitvector.t->path->unit=funsizeendiannessaddrpath->matchPath.read_vpathNone~addr:(Value.constantaddr)sizeendiannesswith|Cst_->()|Load{label=Symbol_;_}->hard_patchpath(sliceaddrsize)|Load{label;_}->soft_patchsizeendiannessaddrpath(Symbolic.Default.Memory.baselabel)|_->if1<sizethensplit_patchsizeendiannessaddrpathandsplit_patch:int->Machine.endianness->Bitvector.t->path->unit=funsizeendiannessaddrpath->patch1endiannessaddrpath;if1<sizethensplit_patch(size-1)endianness(Bitvector.succaddr)pathletinit:Dba.Var.t->path->unit=fun({name;size;_}asvar)path->matchPath.State.lookupvar(Path.statepath)with|exceptionSymbolic.State.Undefined_->Logger.warning"%a: Initializing register %s to zero"Virtual_address.pp(Path.pcpath)name;Path.assign_vpathvar(Value.constant(Bitvector.zerossize))|_->()letfetch:int->Machine.endianness->Dba.Expr.t->path->unit=funsizediraddrpath->letvalue=Path.get_valuepathaddrinifPath.is_symbolic_vpathvaluethenLogger.warning"%a: Failed to ensure %a is initialized"Virtual_address.pp(Path.pcpath)pp_dba(Dba.Expr.load(Size.Byte.createsize)diraddr)elseletcst=Path.eval_vpathvalueinpatchsizedircstpathletfix:Dba.Expr.t->watchpoint->path->unit=funexprwatchpointpath->letvalue=Path.get_valuepathexprinifPath.is_symbolic_vpathvaluethen(letcst=Path.eval_vpathvalueinLogger.warning"%a: Enforce %a = %a (%a)"Virtual_address.pp(Path.pcpath)pp_dbaexprBitvector.pp_hex_or_bincstWatchpoint.ppwatchpoint;ignore(Path.assume_vpath(Value.binaryEqvalue(Value.constantcst))))letcheck:Dba.Expr.t->watchpoint->path->pathcontinuation=funexprwatchpointpath->letvalue=Path.get_valuepathexprinlett1=Unix.gettimeofday()inLogger.debug~level:3"Checking %a (%a)"pp_dbaexprWatchpoint.ppwatchpoint;letwitness:trilean=matchPath.check_sat_assuming_vpath(Value.binaryDiffvalue(Value.constant(Path.eval_vpathvalue)))with|exceptionSymbolic.State.Unknown->Unknown|None->True|Some_->Falseinlett2=Unix.gettimeofday()inLogger.debug~level:3"checked (time %fs)"(t2-.t1);matchwitnesswith|True->Return|Unknown->Logger.error"%a: Potential non-deterministic expression %a (%a)"Virtual_address.pp(Path.pcpath)pp_dbaexprWatchpoint.ppwatchpoint;SignalUnresolved_formula|False->Logger.error"%a: Non-deterministic expression %a (%a)"Virtual_address.pp(Path.pcpath)pp_dbaexprWatchpoint.ppwatchpoint;SignalUnsatisfiable_assumptionletlist=[Instrumentation_routineinstrumentation_routine;Builtin_resolver(function|Init(Varvar)->Apply(initvar)|Init(Mem(size,dir,addr))->Apply(fetchsizediraddr)|Fix(expr,info)->Apply(fixexprinfo)|Check(expr,info)->Call(checkexprinfo)|_->Unknown);Builtin_printer(funppfbuiltin->matchbuiltinwith|Init(Var{name;_})->Format.fprintfppf"ensure init %s"name;true|Init(Mem(size,dir,addr))->Format.fprintfppf"ensure init %a"pp_dba(Dba.Expr.load(Size.Byte.createsize)diraddr);true|Fix(expr,info)->Format.fprintfppf"fix %a (%a)"pp_dbaexprWatchpoint.ppinfo;true|Check(expr,info)->Format.fprintfppf"check %a (%a)"pp_dbaexprWatchpoint.ppinfo;true|_->false);]endmodulePlugin(O:OPTIONS):PLUGIN=structletname=shortnameletfields_=[]letextensions:typea.(moduleENGINEwithtypePath.t=a)->aextensionlist=funengine->letmoduleEngine=(valengine)inmatchEngine.Path.State.moreSymbolic.State.ValueKindwith|SomeSymbolic.Default.Term->letmoduleExtensions=Builtin(O)(Engine)inExtensions.list|_->Logger.fatal"unable to use '%s' within the current symbolic engine"shortnameend