Semantics-Aware Malware Detection

【论文笔记】Malware Detection with Deep Neural Network Using Process Behavior 【论文笔记】Malware Detection with Deep Neural Network Using Process Behavior     会议:2016 IEEE 40th Annual Computer Software and Applications Conference (COMPSAC)    &nbs... 阅读详情
Notes from: "Semantics-Aware Malware Detection"
	    [Christodorescu, Jha, Seshia, Song, Bryant]
--------
Problem:
--------
 - old trend in malware: create a supervirus, infect millions with it

 - new trend in malware: create a virus, create several derivatives of
   that virus (each of which would require a distinct signature for AV
   scanners) which differ from the base virus only slightly, have each 
   derivative infect smaller numbers of (possibly just local) hosts

   --> so, how to make virus signatures for the main base virus that also
       "catch" these derivatives, rather than having to have a sample of each
       derivative and having to have even more bloated signature databases

------------------
malware detector : system which attempts to detect whether a program has
------------------ malicious intent

 - evade detection via obfuscating the malware

 - malware detectors use pattern matching are susceptible to obfuscation

   -- a purely syntactic approach

      - match some sequence of instructions (perhaps using regular expressions)

      - but not matching based on what code DOES, matching based on
        particular instruction sequences in code

----------------
Their approach :
----------------
 - malware detection algo incorporates instruction semantics : seeking to 
   match based on malicious program traits

 - so theoretically would catch derivative programs which have the same
   functionality as the original

========
I. Intro
========
malware instance : program that has malicious intent

 - e.g. viruses, trojans, worms

 - can classify malware w.r.t. its propagation method and goal

malware detector : system that attempts to identify malware

 - e.g. a virus scanner : uses sigs and other heuristics to identify malware

goal of malware writer : modify or morph malware so that it evades detection

 - ideally do this derivative/variant-generation automatically

 - e.g. evade detection via program obfuscation

   -- e.g. virus encrypts its malicious payload and decrypts it during exec

   -- e.g. polymorphism and metamorphism

   -- polymorphic virus : obfuscates decryption loop using transformations

      -- sample transformations :

	 -- nop insertion

	 -- code transposition (change order of instructions and put jumps
	    in in order to retain original semantics)

	 -- register reassignment (permute register allocation)

   -- metamorphic virus : obfuscate entire virus

      -- on replication, change code in variety of ways

	 -- e.g. code transposition, substitution of equivalent
            instruction sequences, change of conditional jumps,
	    register reassignment

 - another (obfuscation) technique : add new behaviors to existing malware

   -- by adding new behavior to base code, able to evade detection even though 
      base code would have been detected

   -- cf. Sobig.A through Sobig.F (worms), Netsky, Beagle (from 2004) to present

 - commercial malware detectors : use simple pattern matching approach

   -- match : program contains a sequence of instructions that is matched
	      by a regular expression

   -- basic deficiency : ignore SEMANTICs of these instructions

   -- not resilient to slight variations

      -- so must use different patterns for detecting two malware instances
         that are slight variations of each other

 - suppose program P transformed by a compiler phase to produce program P^t
   (maybe that compiler phase consisted of register allocation)

   - translation-validation problem :

     -- determine whether P^t simulates P

     -- used to prove that various compiler phases preserve semantics of P

   - view hacker obfuscations as compiler phases

     -- then malware detection problem seems similar to translation-validation 
	problem

	- after hacker obfuscation produces P' out of P (where P is a
          known bad program), does P' have same semantics as P?

     -- but hacker obfuscations will produce P' such that P' has *different*
        semantics than P (added functionality, e.g.)

	- so P and P' are not equivalent

     -- plus, translation-validation makes assumptions a/b transformed program :

	-- e.g. all branches in P' must match branches in P

	   - this does not necessarily hold for hacker transformations

     -- all the same, some useful ideas from translation-validation : 
	(1) modeling semantics of instructions, (2) use decision procedures
     
 - observe that certain malicious behaviors appear in all variants of a
   certain malware (e.g. the decryption loop in a polymorphic virus)
	
   -- but decryption loop, e.g., might appear in different form in variants

 - algo for discovering specified malicious behaviors in a given program

 - formal semantics : define problem of determining whether a program
		      exhibits a specified malicious behavior

   -- in general, undecidable

 - semantics-aware malware detection algo : 

   -- handle limited set of transformations

   -- detects multiple variants with single template

   -- more resilient than commercial AV scanners [claim]

==================================
II. Semantics of Malware Detection
==================================
(1) Specify malicious behavior : via templates

 Template T : instruction sequence (I_T) which uses variables (V_T) and constants (C_T)
 ----------------
 Sample template:
 ----------------
   (1)	A = const_addr1      // encrypted memory starts here
   (2)	B = const_addr2      // location to put decrypted memory
   (3)	condition(A)?	TRUE : goto (7), FALSE : goto (4)
   (4)	mem[B] = f(mem[A])
   (5)	A = A + c
   (6)	B = B + d
	goto (3)
   (7)	jump const_addr2

 variables, V_T : { A, B }

 symbolic constants, C_T : { const_addr1, const_addr2, c, d, f(x), p(x) }

  -- symbolic constants : either n-ary function, F(n), or n-ary predicate, P(n)
  -- actual constants (e.g. c, d) are 0-ary functions
  -- n-ary function : takes n arguments, returns a value
  -- n-ary predicate : takes n arguments, returns a boolean

  -- c : TAU	     <==>    the type of symbolic constant c is TAU

 ==> resilient to obfuscations : 
     -- register renaming (since use vars and constants)
     -- changing starting addy of a memory block (since use vars)

 ==> When does an instruction sequence contain a malicious behavior?
     -- if template and instruction sequence have the same effect on memory
     -- IOW, the malicious behavior specified by the template is
	demonstrated by the instruction sequence

 ==> also resilient to insertion of irrelevant instruction sequences

 -----------------------------------------------------------------
 Sample malware instance (instruction sequence) of above template:
 -----------------------------------------------------------------
   (1) eax = 0x403000
   (2) ebx = 0x400000
   (3) edx = eax + 3
   (4) eax >= 406000 ?	TRUE : goto (9), FALSE : goto (5)
   (5) mem[ebx] = mem[edx - 3] << 2 + 1
   (6) eax = eax + 4
   (7) edx = edx + 4
   (8) ebx = ebx + 4
       goto (4)
   (9) jump 0x400000

   - edx above is totally unnecessary, could have written :

   (1) eax =  0x403000
   (2) ebx =  0x400000
   (3) eax >= 0x406000 ?	TRUE : goto (7), FALSE : goto (4)
   (4) mem[ebx] = mem[eax] << 2 + 1
   (5) eax = eax + 4
   (6) ebx = ebx + 4
       goto (3)
   (7) jump 0x400000

   - but this second instance is a more obvious match to the given template

   - so provided first instance to illustrate that even when additional
     registers are included, that the first instance matches would be caught

     --> some resilience based on semantic matching to hacker obfuscation

 - execution context : an assignment of values (of appropriate types) to
		       the set of symbolic constants, C_T

   -- e.g. const_addr1  <-- 0x403000
	   const_addr2  <-- 0x400000
	   condition(X) <-- X >= 0x406000
	   f(X)         <-- X << 2 + 1
	   c	        <-- 4
	   d		<-- 4

   -- EC_T : execution context for a template T

      EC_T( c ) : where c is a constant, returns the value of that constant

   -- EC_T : is a function with domain C_T such that 

      for all c in C_T, the type of c and the type of EC_T(c) are the same

 - EC_T( T ) : the template obtained by replacing every constant c in C_T by EC_T(c)

 - state s^T for the template T is a 3-tuple denoted : ( val^T, pc^T, mem^T )

   -- val^T : V_T --> Values, is an assignment of values to the variables in V_T

   -- pc^T : value for the program counter

   -- mem^T : Addr --> Values, gives the memory content

 - a state for the instruction sequence I is a 3-tuple (val, pc, mem)

   -- val : Reg --> Values, is an assignment of values to the set of registers

   -- pc : a value for the PC

   -- mem : Addr --> Values, gives memory contents

 - S^T is state space for template; S is state space for instruction sequence

 - given EC_T for a template T and template is in state s^T

 - if execute instruction i from the template EC_T(T) in state s^T, we
   transition to a new state s_1^T and generate a system event e (event
   may be sys call or kernel trap, e.g.); denote this via :

   s^T ---[e]---> s_1^T

 - if an instruction i does NOT generate a system event, e(i) = null
   [it generates the null event]

 - for every initial template state, s_0^T, executing T in an execution
   context EC_T generates a sequence :

   SIGMA( T, EC_T, s_0^T ) = s_0^T ---[e_1^T]---> s_1^T ---[e_2^T]---> ...

   - for i  >= 1, 

     s_i^T == state after executing i'th instruction from the template EC_T(T) and 

     e_i^T == the event generated by the i'th instruction

     --> s_i^T ---> execute (i+1)-th instruction ---> generate event ---> s_(i+1)^T

   - if template doesn't terminate, sequence can be infinite

   SIGMA( I, s_0 ) == sequence when the instruction sequence I is executed
		      from the initial state s_0

   ==========================================================================
 - Definition 1 : "instruction sequence I contains a behavior specified by T"
   ==========================================================================
   an instruction sequence I contains a behavior specified by the template
   T if there exists a program state s_0, an execution context EC_T and a
   template state s_0^T such that mem( s_0^T ) == mem( s_0 ) and the two
   sequences SIGMA( T, EC_T, s_0^T ) and SIGMA( I, s_0 ) are finite and :

   -- note that the initial PCs don't have to be the same

   ------------------------------------
   requirements for the two sequences :
   ------------------------------------
   (1) SIGMA( T, EC_T, s_0^T ) 

       = s_0^T ---[e_1^T]---> s_1^T ---[e_2^T]---> ... ---[e_k^T]---> s_k^T

       SIGMA( I, s_0 ) 

       = s_0 ---[e_1]---> s_1 ---[e_2]---> ... ---[e_r]---> s_r

    Let affected( SIGMA( T, EC_T, s_0^T ) ) be the set of addresses such that :
    
      mem(s_0^T)[a] != mem(s_k^T)[a]

      (addresses whose contents before applying the template from the initial
       state are different than AFTER applying the template to completion)

    REQUIRED :	 mem( s_k^T )[a] == mem( s_r )[a] for all a in affected(...)

    for any memory address whose contents change when applying the template, 
    the value of those contents are the same as the value of those contents 
    when applying the instruction sequence from the init state to completion
   
    RECALL: the memory in the two starting states is identical
 
    THIS SAYS: call M the set of memory addresses whose content changes
    during the execution of the template. Then for every m in M,
    mem[m] at the end of execution of the template must equal mem[m] at
    the end of execution of the instruction sequence

    --> NOTE that this is NOT the same thing as saying that the contents
	of memory at the end of both must be identical

	we only care about the memory addresses whose content changed
	during execution of the template

	this means that there could be some memory address A and its
	contents could be changed during execution of the instruction
	sequence BUT NOT during execution of the template

	--> for example, edx in the given example
	--> edx could have value 0 at the beginning of both
	--> then edx could have value 0 at the end of the template but
	    have value 0x406000 at the end of the instruction sequence

	    ==> this is OK; edx as such is "extraneous"

    (2) ignoring null events, the event sequence < e_0^T, e_1^T, ..., e_k^T > 
	is a subsequence of < e_1, e_2, ..., e_r >

    two system events e_i^T and e_j MATCH if the arguments to each are the
    same and the return values from each are the same

    (3) if pc( s_k^T ) is in affected( SIGMA( T, EC_T, s_0^T ) )

        then pc( s_r ) is in affected( SIGMA( T, EC_T, s_0^T ) )

    - if the program counter at the end of applying the template is an
      address whose contents have changed (due to applying the template)
      then the program counter after issuing the instruction sequence
      must also have changed due to that instruction sequence

    [A problem is that affected(...) contains ADDRESSES whereas pc( s_i^T )
     refers to a VALUE or the *contents* of some address]

     - do we assume that the *address* of the program counter stays static?

    < Tangent re: condition 3; see cond_3_tangent.txt for details >

   ==============================================
 - Definition 2 : Template Matching Problem (TMP)
   ==============================================
   a program P satisfies a template T iff P contains an instruction
   sequence I such that I contains a behavior specified by T

     NOTATION : P |= T        (P satisfies template T)

   e.g. P is malware; T specifies decryption loop; if P contains *any*
   instruction sequence I which contains the behavior specified by T
   then P satisfies T (e.g. PGP should satisfy that T)

   ----------------
   Variant Family : 
   ----------------
    - Let T be a set of templates (e.g. T = { T_1, T_2, ..., T_l } and
      T_1 specifies decryption loop behavior, T_2 specifies email addy
      search behavior, ... )

    - The set T defines a variant family F : 

	  { P | for all T_i in T, P satisfies T_i }

      -- note that it is possible for some family members, f in F,
	 to have *additional* behavior than what is specified by T

	 -- so adding functionality to a family member will not cause that
            family member to be thrown out of the family

	 -- removing some functionality may result in booting the family
            member though

   ------------------------------
 - Theorem 1 : TMP is undecidable
   ------------------------------
   Let M be a Turing machine and P_M be a program that uses instructions
   and simulates M

   Assume there is some address sp_addr which P_M doesn't alter the contents of

   Before starting to simulate M, P_M sets mem[sp_addr] = 0
   After simulating M, P_M sets mem[sp_addr] = 1

   Consider template T_1 : mem[sp_addr] = 0
			   mem[sp_addr] = 1

   So P_M satisfies template T_1 if and only if M halts which implies a
   solution to the halting problem which is undecidable therefore...

------------------
A weaker semantics
------------------
Semantics from above may be too strict; imagine a template uses certain
memory locations to store temporary values then such mem locs should not
be checked for equality in comparing the executions of an instruction
sequence and a template.

core memory locations: core( SIGMA( T, EC_T, s_0^T ) ) is a subset of the
		       affected memory addresses

Then modified condition 1 :

 - for all a in core( SIGMA( T, EC_T, s_0^T ) ), 

   mem( s_k^T )[a] = mem( s_r )[a]

 - so we only check "core" memory locations for equality

How to define "core" memory locations?

 - label each instruction in I_T as "temp" or "persistent"

 - core memory locations = any address in affected( ... ) that is the
			   target of a PERSISTENT load or store

=======================================
III. Semantics-aware matching algorithm :
=======================================
 - Sound but not complete

   Sound : no false positives (anything that matches definitely matches)   
    --> every solution produced is indeed a solution

   Complete : no false negatives (catch everything that matches)
    --> produces all possible solutions

 - tool takes as input : template and a binary (for MSFT Windows on Intel
		         IA-32 (x86) platform)

 - tool outputs whether any fragment of the program contains the behavior 
   specified by the template

   -- describes the matched fragment of the program plus relates template
      vars to program registers and memory locations and lists irrelevant
      instruction sequences that are part of the matched program fragment

 - architecture : tool built on top of IDA Pro disassembler

   - binary comes in and is disassembled, create control flow graphs from
     it (one per program function), produce intermediate representation (IR)

     -- IR generated using library of x86 instruction transformers
     -- IR is architecture-independent
     -- IR can still contain library and sys calls that are platform specific
	--> remove this dependency by using summary functions expressed in IR
	    - not much info on this (how works exactly, examples, ...)

     ==> point of all this, though, is for IR to be platform- and
	 architecture-independent, so could conceivably use one template
	 to detect some virus with semantically identical variants
	 produced for Win32, Linux, ...

   - so malware detector algo takes Template and program IR, interacts with :
     - decision procedures, which include :
       -- nop library, random execution, simplify, UCLID
     and outputs YES or NO

     nop library : predefined patterns of irrelevant instructions
     randomized execution : randomized x86 interpreter
     simplify : theorem prover
     UCLID : decision procedure with bit-vector arithmetic

   ===============================================
 - algo description, malware detection algo : A_MD
   ===============================================
   - finds, for each template node, a matching node in the program

   - a template node is an expression; e.g. "A = const_addr1", "condition(A)?",

   - a program node is an expression; e.g. "eax = 0x403000", "eax >= 0x406000?"

   - two nodes, n_T (from the template) and n_P (from the program) match if
     there exists an assignment to vars from the n_T expression that unifies 
     it with n_P

   - once two matching nodes are found, check whether def-use relationships
     true b/n template nodes also hold true in the corresponding program

     -- def-use relationship : 

	two nodes n_1 and n_2 are related by a def-use relationship IF
	n_1's DEFinition of a var reaches n_2's USE of the same var

	e.g. n_1 = statement S_i and n_2 = statement S_j and 
	n_1 defines some variable X and n_2 *uses* that value of X
	(as set during statement S_i)

        [see def_use_rp.txt in this folder for slighly more in-depth
	 though still somewhat elementary explanation]

    - if all the nodes in the template have matching counterparts in the
      program that satisfy these conditions, then the algo has found a
      program fragment that satisfies the template and produces a proof of
      this relationship

 - formally, given a malicious code template T and a program P, 

   A_MD : is a predicate on pairs of programs and templates

     A_MD : Programs x Templates ---> { "yes", "don't know" }

   "don't know" == algo can't determine that prog satisfies the template

   such that A_MD( P, T ) returns "yes" when P satisfies T under the
   conditions below
----------------------
Simplified template T;  X^key == X (bit-vector XOR) key
----------------------
(1)   A = const_addr1					// b_1
(2)   B = const_addr2					// b_2
(3)   A > const_addr3 ?  TRUE: goto 7, FALSE: goto 4	// b_3
(4)   mem[B] = mem[A]^key				// b_4
(5)   A = A + c						// b_5
(6)   B = B + d						// b_6
      goto 3 // they have another typo here
(7)   jump const_addr2					// b_7
---------------------
Simplified program P:
---------------------
(1) eax = 0x403000					// a_1
(2) ebx = 0x400000					// a_2
(3) nop							// a_3
(4) ecx = eax + 1					// a_4
(5) ecx - 1 > 0x406000 ?  TRUE: goto 10, FALSE: goto 6	// a_5
(6) eax = ecx - 1					// a_6
(7) mem[ebx] = mem[eax]^5				// a_7
(8) eax = eax + 1					// a_8
(9) ebx = ebx + 2					// a_9
    goto 4    
(10) jump 0x400000					// a_10

===========================================================
For A_MD(P, T) = "yes", the following conditions must hold:
===========================================================
 -----------------------------------------------
 (1) matching of template nodes to program nodes
 -----------------------------------------------
 - each node n in T has to unify with a node m in P
 
 - call n_T : the set of template nodes and n_P the set of program nodes

 - IOW, there is an onto partial function f from the nodes of P to the
   nodes of T (there may exist nodes p in n_P such that f(p) = not defined;
   however for every node t in n_T, there exists some p in n_P such that
   f(p) = t)

   then f : { nodes in P }         ---> { nodes in T }
	    { n_P }		   ---> { n_T }
	    { a_1, a_2, ..., a_m } ---> { b_1, b_2, ..., b_n }

	    m >= n

   then:    f( a_i ) = b_j   for some i,j

	    and a_i and b_j are unifiable

   B( X, n, m ), where n = f( m ) 

      == the binding of variable X (where X is referred to in the template
	 instruction at node n) TO an expression referred to in the
	 program instruction at node m; 

   ==> So is it okay if more than one program node maps to the SAME
       template node? By the definition of f, this is allowed...

   e.g.  B(A,1,1) = eax		     also	B(B,2,1) = eax
	 B(A,2,2) = ebx				B(A,1,2) = ebx
	 B(A,3,5) = (ecx - 1)
	 B(A,5,8) = eax
	 B(B,6,9) = ebx

   ----------------------------------------------------------------------------------
   sample definition of f [there is more than one possible that satisfies this cond]:
   ----------------------------------------------------------------------------------
     a_1 -->    b_1
     a_2 -->	b_2
     a_3 -->	undefined
     a_4 -->	undefined
     a_5 -->	b_3
     a_6 -->	undefined
     a_7 -->	b_4
     a_8 -->	b_5
     a_9 -->	b_6
     a_10 -->   b_7

 ---------------------------------
 (2) preservation of def-use paths
 ---------------------------------
  - for each node n in T, define def(n) as the set of vars defined in n
  - for each node n in T, define use(n) as the set of vars USED in node n
    ----------	    ------	 ------
    nodes in T	    def(n)	 use(n)
    ----------	    ------	 ------
    b_1		    A		 none
    b_2		    B		 none
    b_3		    none	 A
    b_4		    none	 A, B
    b_5		    A		 A
    b_6		    B		 B
    b_7		    none	 none

  - nodes n_pre : predecessor to the template entry node
  - nodes n_post : successor to all template exit nodes
  - def( n_pre ) = use( n_post ) = V_T
  - so  def( n_pre ) = set of all nodes defined in the template?
  - and use( n_post ) = set of all nodes used in the template?
 
  - a def-use path is a sequence of nodes < n_1, n_2, ..., n_k > such that

    + for 1 <= i < k, there is an edge from n_i to n_(i+1) in T

      [i.e. < n_1, n_2, ..., n_k > is a valid path through template T ]

    + I( n_1 ) == the instruction at node n_1

      I( n_1 ) DEFines a variable that I( n_k ) USEs

      [i.e. def( n_1 ) INTERSECT use( n_k ) != {} ]

    + none of the instructions at the intermediate nodes redefine the
      value of the variables in def(n_1)

      [i.e. def(n_1) INTERSECT def(n_i) = {} for 1 < i < k ]

  - so from our template graph, 

    paths : n_1 --> n_2 --> n_3
	    n_3 --> n_4
	    n_3 --> n_7
	    n_4 --> n_5 --> n_6 --> n_3 

    def( A ) : { n_1, n_5 }	 use( A ) : { n_3, n_4, n_5 }
    def( B ) : { n_2, n_6 }	 use( B ) : { n_4, n_6 }

    ---------------------------------------------
    def-use relationships, denoted duse(n_1,n_2):
    ---------------------------------------------
    A : duse( n_1, n_3 ) path : n_1 --> n_2 --> n_3
    A : duse( n_1, n_4 ) path : n_1 --> n_2 --> n_3 --> n_4    
    A : duse( n_1, n_5 ) path : n_1 --> n_2 --> n_3 --> n_4 --> n_5
    A : duse( n_5, n_3 ) path : n_5 --> n_6 --> n_3
    A : duse( n_5, n_4 ) path : n_5 --> n_6 --> n_3 --> n_4
    A : duse( n_5, n_5 ) path : n_5 --> n_6 --> n_3 --> n_4 --> n_5

    B : duse( n_2, n_4 ) path : n_2 --> n_3 --> n_4
    B : duse( n_2, n_6 ) path : n_2 --> n_3 --> n_4 --> n_5 --> n_6
    B : duse( n_6, n_4 ) path : n_6 --> n_3 --> n_4
    B : duse( n_6, n_6 ) path : n_6 --> n_3 --> n_4 --> n_5 --> n_6

 - any def-use relationship in the template, e.g. between nodes n and n',
   must hold between nodes m and m' WHERE n = f(m) and n' = f(m')

 - consider two nodes n and n' in T that are def-use related

   - let nodes n and n' in T be matched to nodes m and m' in P
   
   - suppose X is a var that is defined in n and used in n'

     B( X, n, m )   = r	     "X is bound to expression r in node m"
     B( X, n', m' ) = r'     "X is bound to expression r' in node m'"

   - for example, n = n_1, n' = n_3, X = A
		  m = m_1, m' = m_5, X = A

     then B(X, n_1, m_1 ) = eax
	  B(X, n_3, m_5 ) = (ecx - 1)

     so r = eax and r' = (ecx - 1)

     then need to make sure that value of (eax) after "eax = 0x403000" (m_1)
     is equal to value of (ecx - 1) before "ecx - 1 > 0x406000" (m_5)
     *for every program path corresponding to the template path from n_1 to n_3*

     - in this case there is just one such program path

   - need to make sure that value of r AFTER executing I(m) is same as
     value of r' BEFORE executing I(m')

   - let's try another example: n_6 and n_4 are related by def-use r/p in T

     and n_6 corresponds to m_9 and n_4 corresponds to m_7

     B( B, n_6, m_9 ) = ebx
     B( B, n_4, m_7 ) = ebx

     condition is trivially satisfied

   ===========================================================
 - Theorem 2 : A_MD is sound with respect to the TMP semantics; 
   ===========================================================

	i.e. A_MD( P, T ) = "yes" ===> P |= T

 - sound but not complete
 - can show there exists a program P and a template T such that 

   P satisfies T but A_MD( P, T ) returns "don't know"

   template T				  program P
   ----------				  ---------
   for ( i = 0; i < 10; i++ )		  for ( i = 0; i < 10; i += 2 )
     a[i] = 0;				      a[i] = 0;
					  for ( i = 1; i < 10; i += 2 )
					      a[i] = 0;

   - A_MD won't catch this matching as the ordering of updates in the
     template loop is different than that of the program loops

   =================
 - Local unification
   =================
   -- produces an assignment to vars in an instruction at a template node
      such that this matches a program node instruction

   -- program node expressions contain ground terms only
   -- instantiate template vars with program expression

   -- template node 1 ( A = const_addr1 ) can be unified with

        program node 1 ( eax = 0x403000 ) OR
	program node 2 ( ebx = 0x400000 )

      but not with program node 8 ( eax = eax + 1 ) or 9 ( ebx = ebx + 2 )

   ++ so note that unification assigns to vars BUT ALSO to constants

   -- [ t_1, p_1 ] { A <-- eax, const_addr1 <-- 0x403000 }
      [ t_2, p_2 ] { B <-- ebx, const_addr2 <-- 0x400000 }
      [ t_3, p_5 ] { A <-- ecx - 1, const_addr3 <-- 0x406000 }
      [ t_4, p_7 ] { B <-- ebx, A <-- eax, key <-- 5 }
      [ t_5, p_8 ] { A <-- eax, c <-- 1 }
      [ t_6, p_9 ] { B <-- ebx, d <-- 2 }
      [ t_7, p_10 ] { const_addr2 <-- 0x400000 }

      --> B is only assigned ebx so we don't have to worry about B
      --> const_addr1 is only assigned 0x403000
      --> const_addr2 is only assigned 0x400000
      --> key is only assigned 5
      --> const_addr3 is only assigned 0x406000
      --> c is only assigned 1
      --> d is only assigned 2

      --> A is assigned both: { eax, ecx - 1 }

 RULES about producing an assignment to vars in an instruction at a
 template node such that the resulting expr matches a prog node instr:

  (1) a var in the template can be unified with any prog expr except for
      assignment expressions

  (2) a constant in the template can only be unified with a prog constant

  (3) the memory function (in the template) can only be unified with the
      program's memory function

  (4) a predefined operator in the template (e.g. OR, AND, XOR, NOT,
      BITAND, LEQ, PLUS, MINUS, ...) can only be unified with THE SAME
      operator in the program

  (5) an external function call in the template can only be unified with
      the same external function call in the program

  ==> result of this is a binding relating template variables to program expressions

 - note that we don't require that bindings be consistent (monomorphic) since
   as above we have that A is bound to eax at one point yet bound to ecx - 1 
   at another

   -- such a requirement would be overly restrictive (not resilient to
      obfuscation attacks)

 - instead we want to check program expressions bound to the same template
   variable (e.g. eax is bound to A and so is ecx - 1 )

   --> verify that such expressions change value in the same way that the
       template variable changes value

   ---------------------=====================================
   ACCOMPLISH THIS via : value preservation on def-use chains
   ---------------------=====================================
   - for each def-use chain in the template, check :

     whether the value of the program expression corresponding to the
     template-variable use is the same as the value of the program
     expression corresponding to the template-variable definition

   - e.g. t_1 and t_3 are def-use related for variable A

     p_1 maps to t_1 and p_5 maps to t_3

     R : the program fragment between (exclusive between) p_1 and p_5

     R :     ebx = 0x400000
	     nop
	     ecx = eax + 1

     so the value for A after p_1 must be the same as the value for A
     before p_5

     -- the value for A at p_1 is : eax
     -- the value for A at p_5 is : ecx - 1

     so, confirm that from < p_2, p_3, p_4 >, eax == (ecx - 1)

     "the expressions corresponding to template variable A after p_1
      must be equal in value to the expressions corresponding to 
      template variable A before p_5 (since p_1 and p_5 are related by
      a def-use relationship for variable A)"

     express this via a predicate : 

      for each path I in program fragment R

        val_pre( I )(eax) = val_post( I )(ecx - 1)

      [e.g. I = <p_2, p_3, p_4>]

      val_pre( I )( x ) : the value of x before path I
      val_post( I )( x ) : the value of x after path I

 - for each match between a program node p_i and a template node t_j, the
   algo checks whether the def-use chain is preserved for each program
   expression corresponding to a template var used at the matched node

 - does R maintain the value predicate PHI : 

   PHI = { for all I in R, 

	     ( val_pre<I>(eax) = val_post<I>( ecx - 1 ) ) 
	 }

 - treat decision procedures as oracles that answer the question, 

   "Does a program fragment R maintain an invariant PHI?"

 - another example, def-use chain t_5, t_3 maps to p_8, p_5

   R : < p_9, p_4 >

     : ebx = ebx + 2
       ecx = eax + 1

   definition of A in t_5 : eax
   definition of A in t_3 : ecx - 1

   val_pre( I )( eax ) =? val_post( ecx - 1 ) Yes.

 - another example, def-use chain t_1, t_4 maps to p_1, p_7

   R : < p_2, p_3, p_4, p_5, p_6 >

     : ebx = 0x400000
       nop
       ecx = eax + 1
       ecx - 1 > 0x406000 ?
       eax = ecx - 1

   definition of A in t_1 : eax
   definition of A in t_5 : eax

   val_pre( I )( eax ) =? val_post( eax ) Yes.

   =====================================================
 - Using decision procedures to check value-preservation
   =====================================================
   - want to figure out whether a program fragment P is a semantic nop
     with respect to some conditions, e_1 and e_2

     if -- for every path I in that program fragment -- the value of e_1 
     *before* that path is the same as the value of e_2 *after* that path
     then that PHI( I, e_1, e_2 ) holds

     if ( PHI( I, e_1, e_2 ) for every I in R holds )

        then PHI( P, e_1, e_2 ) holds and D returns TRUE

     if on the other hand, there exists some I' in R for which

	PHI( I', e_1, e_2 ) == "don't know"  or "false"

	then D( P, e_1, e_2 ) = "don't know" or "false"

     we can also determine whether: !PHI( P, e_1, e_2 ) holds...

       if ( PHI( I, e_1, e_2 ) for every I in R *does not hold* )

         then !PHI( P, e_1, e_2 ) does not hold

     D^+ : a decision procedure for PHI( P, e_1, e_2 )
     D^- : a decision procedure for !PHI( P, e_1, e_2 )

   =======================================================================
   - "semantic nops" : some program fragment I is a semantic nop with
     respect to two conditions e_1 and e_2 if the value of e_1 before that
     fragment is the same as the value of e_2 after that fragment
   =======================================================================

   - value-preservation oracle : decision procedure, determines whether a
     given program fragment is a semantic nop w.r.t. certain prog vars

     D determines whether the value predicate, 

       PHI( P, e_1, e_2 ) 

     holds for all paths in P; i.e.

       for all paths I in P, 

	   ( val_pre<I>(e_1) = val_post<I>(e_2) )

   -------------
 - NOP library : identifies sequences of nop instructions
   -------------
   -- annotate basic blocks as nop sequences when applicable
   -- use actual nop instructions plus some sequences which are known to be nops

   -----------------------------
 - randomized symbolic execution
   -----------------------------
   -- program frag executed using a random initial state

   -- at completion, check whether !PHI(P,e_1,e_2) is true

      -- if so, at least one path in the program fragment is not a
         semantic nop; and so whole P is NOT a semantic nop

      -- else, whole P may be a semantic nop

   --------------------------
 - theorem proving : SIMPLIFY
   --------------------------
   -- value preservation problem formulated as a theorem to be proved
      (as long as program frag has NO loops)

   -- program frag represented as state transformer DELTA

   -- then use SIMPLIFY to prove the formula

      DELTA ==> PHI( P, e_1, e_2 )

      - if SIMPLIFY confirms that the formula is valid, 
	then the program fragment is a semantic nop

   -- can't handle programs which include bit-vector operations

   2: ebx = 0x400000
   3: nop
   4: ecx = eax + 1

   Simplify formula :

     (IMPLIES (AND (EQ ebx_1 4194304)
		   (EQ ecx_4 (+ eax_pre 1) )
		   (EQ ecx_post ecx_4)
	       )
              (EQ eax_pre (- eax_post 1))
     )

   same as:

   (ebx_1 == 4194304) && (ecx_4 == (eax_pre + 1)) && (ecx_post == ecx_4)

    ==> ( eax_pre == (eax_post - 1) )

 - theorem proving : UCLID

   -- based on UCLID infinite-state bounded model checker

   -- logic supported by UCLID is a superset of that supported by SIMPLIFY

   -- UCLID precisely models int and bit-vector arith

   -- model program fragment instructions as state transformers for each
      register and for memory

   -- UCLID simulates program frag for a given # of steps and determines
      whether PHI( P, e_1, e_2 ) holds at the end of the simulation

=========================
Strengths and Limitations
=========================
----------------------------------------------------------------
4 classes of obfuscations, A_MD can handle (to varying degrees):
----------------------------------------------------------------
 - code reordering, equivalent instruction replacement, register renaming,
   garbage insertion

(1) code reordering : change order of instructions; maintain execution
		      order using jumps

 - handled via use of control flow graphs

(2) register renaming : reassigns registers in selected program fragments

 - so any tool searching for signature which is based on specific register
   names will miss the obfuscated variant

 - use templates; vars assigned registers only during unification

 - so can detect any program with the same behavior as the template
   irrespective of register allocation

(3) garbage insertion : insert instruction sequences that don't change
			behavior of program

 - uses decision procedures to reason about value predicates on def-use chains

(4) equivalent instruction replacement 

 - uses rich instruction set to replace groups of consecutive instructions
   with other short instruction sequences that have the same semantics

 - e.g. to add 1 to register X, can use:  < add X, 1 > or < inc X >

 - handle limited kind of this via normalize code into IR which supports only
   semantically-disjoint operations

-----------
LIMITATIONS
-----------
 - doesn't recognize that:  "x = x + 2" is equivalent to "eax = eax << 1"

 - can only detect programs that exhibit same ordering of memory updates

   -- recall the problem where we populated a[i] with zero via pattern:

      <1,2,3,...,20> versus <2,4,6,8,...,20,1,3,5,...,19>

   -- comes from use of def-use chains for value preservation checking

   but NB : automatically generating functionally-equivalent variants is hard

Used : (1) decryption-loop template and (2) mass email template
恶意软件检测技术综述 2018体系结构安全大作业申明:转载请注明出处恶意软件检测技术综述摘要本文介绍了恶意软件、恶意软件探测技术和探测器的定义,以及研究它们的现实意义。概述了恶意软件探测技术的具体分类和各个类别的研究现状。结合研究现状,总结了软件探测器性能损耗高,覆盖范围有限的特点,提出了可以结合计算机组成结构原理,开发底层硬件分类器的思想,并且结合国内外硬件探测器研究,列举了几个常用的检测指标,总结了他们的贡献和不足... 阅读详情

相关推荐

malware detection(病毒扫描)经典教材

Springer出版的关于病毒检测的教材,现有的主流技术都有讲到。 pdf格式。

Android Malware Detection with Seq2vec

Android Malware Detection with Seq2vec 基于Seq2vec的安卓恶意软件检测,数据集取自CICMalDroid 2020,并进行了特征提取。 引言 最近在做Android恶意软件静态检测的研究,此前发布了两个版本,都对Android恶意软件有很高的识别率,现在尝试用Seq2vec的方法进行Android恶意软件检测。我尝试使用了Bi-LSTM、CNN,发现,Bi-LSTM实在训练太慢,而CNN网络不但训练快,而且训练集上准确度可以达到97%以上,验证集以及测试集准确度都

m0_63642362的博客 1439

Windows安装ros2(Jazzy版本+win10/win11)-1.配置windows终端

更高版本的terminal可能设置里更加丰富, 有默认以管理员身份启动的选项等,可自行配置。打开微软应用商店, 在其中搜索并下载 Terminal 即可(注意别挂梯子)下载并安装, 安装的位置自行替换,建议别放到系统盘中。点击任务栏中的搜索, 输入store。

weixin_48398592的博客 1454

Machine Learning for Malware Detection

安卓恶意软件检测

YouthExplorer的博客 1514

ADRC自抗扰控制:工程抗扰“黑科技”,附C代码实战!

自抗扰控制(ADRC)是一种革新性的强鲁棒控制策略,通过主动估计和补偿系统扰动,无需精确数学模型即可实现优异控制性能。本文详细解析ADRC三大核心组件:跟踪微分器(TD)实现指令柔化,扩张状态观测器(ESO)实时估计总扰动,非线性状态反馈(NLSEF)完成动态补偿。针对二阶系统,文章提供完整的参数设计方法和C语言实现框架,包括关键函数fhan和fal的代码实现。ADRC将复杂对象"线性化"为积分器串联系统,显著提升抗扰能力,特别适用于电机控制、飞行器姿态等存在模型不确定性和强干扰的场景。

技术工作者 1738

20个闭环渗透测试项目:从漏洞发现到简历突围

渗透测试不仅是工具使用,更是对系统设计缺陷与实现偏差的深度推演。理解OWASP Top 10、Burp Suite等基础能力只是起点,真正具备工程价值的是能复现、可验证、可协作的完整攻击链。本文聚焦真实业务场景下的SSRF协议绕过、JWT签名机制缺陷、Redis未授权利用、Kong网关配置风险及etcd存储结构分析等核心热词,揭示漏洞本质在于架构决策与配置偏差的叠加态。适用于红队实战、甲方安全建设与乙方渗透审计等多类岗位,帮助从业者将技术动作升维为技术叙事。

weixin_32234493的博客 416

[论文翻译](2017ACM)Deep Android Malware Detection (操作码)深度Android恶意软件检测

在本文中,我们提出了一种新颖的Android恶意软件检测系统,该系统使用深度卷积神经网络(CNN)。通过对反汇编程序的原始操作码序列进行静态分析,进行恶意软件分类。恶意软件的特征是通过网络从原始操作码序列中自动学习的,因此不再需要手工设计的恶意软件特征。我们提出的系统的训练流程比现有的基于n-gram的恶意软件检测方法要简单得多,因为网络是端到端训练的,可以同时学习适当的特征并执行分类,因此在训练期间不再需要明确列举数百万个n-gram。

my991201的博客 1003

智能车竞赛走马观碑组:赛道元素与目标板识别策略解析

本文深入解析了智能车竞赛走马观碑组别的核心挑战与策略。重点探讨了如何应对PVC赛道的光照、磨损及无边界线等复杂环境,并详细阐述了基于红色引导区的目标板高效识别流程。通过平衡轻量化模型选择、实时决策与精准控制,实现赛道元素适应性与目标板识别策略的优化,为参赛者提供了一套完整的系统集成与实战调参思路。

x8y9z0的博客 463

Linux Malware Detect (LMD) 常见问题解决方案

Linux Malware Detect (LMD) 是一个开源的 Linux 恶意软件检测工具,旨在帮助用户识别和防御 Linux 系统中的恶意软件。该项目由 R-fx Networks 开发,遵循 GNU GPLv2 许可证。LMD 主要用于共享托管环境中的威胁检测,使用网络边缘入侵检测系统的威胁数据来生成恶意软件签名,并支持用户提交的威胁数据和社区资源。LMD 使用 MD5 文件哈希和 HE...

gitblog_01038的博客 1253

小卫星多普勒频偏MATLAB代码

多普勒频偏是由于发射机和接收机之间的相对运动而引起的频率变化。对于小卫星,由于其速度和高度的变化,多普勒频偏会变得更加明显。本文将探讨小卫星多普勒频偏的原理、影响因素以及补偿方法。多普勒频偏的原理当发射机和接收机之间存在相对运动时,接收到的信号频率会发生变化。这种频率变化称为多普勒频偏。其原理可以描述如下:设发射机和接收机之间的距离为 d,发射信号的频率为 f0,发射机和接收机的相对速度为 v。则接收到的信号频率 f 为:其中 c 为光速。

qq_59747472的博客 247

英伟达 DGX Spark & Reachy Mini 入门教程(一)

英伟达在2026年CES上发布多款开放模型,包括Nemotron推理LLM、Isaac GR00T VLA和Cosmos世界模型,助力开发者构建个性化AI代理。文章详细介绍了如何通过DGXSpark和Reachy Mini机器人打造办公助手,涵盖材料准备(推理/视觉模型、文本转语音服务)、智能体构建(NeMo Agent Toolkit框架)、工具调用和路由策略实现。系统支持本地/云端部署,提供语音交互、视觉识别和动作执行功能,并保持完全开源可定制。最后给出运行演示的终端配置步骤和测试用例,鼓励开发者在此基

2506_90492529的博客 2715

单个样本维度_恶意样本检测——Mathematics Malware Detected Tools

本文为看雪论坛优秀文章看雪论坛作者ID:xiaoduoduo由于缺少测试数据,部分结论可能不正确。更多更准确的结论,还需要进行大量实验。概述mmdt(Mathematics Malware Detected Tools)是一款基于数学方法的最简单的类“机器学习”工具。该工具通过数学方法对目标对象进行处理,生成相应的标准“指纹”,通过对指纹的处理,实现“机器学习”中的“分类”、“聚类”方法。并在此基...

weixin_28963665的博客 608

Yolov8损失函数改进:MPDIoU新型边界框相似度度量,效果秒杀GIoU 、 DIoU 、CIoU 、 EIoU等 | ELSEVIER 2023

ELSEVIER 2023 MPDIoU新型边界框相似度度量助力yolov8,适用提升小目标、遮挡物性能提升

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 7778

【2016年度】移动安全研究资料总结

[转载来源] http://www.droidsec.cn/移动安全研究资料总结(2016年度)/ Research & Papers & Presentations MANIFEST FILES CLASSIFICATION OF ANDROID MALWARE –pdfDroidNative: Semantic-Based Detection of Android Native

4lwin博客 3001

【温室气体数据集】全球总碳柱观测网络 TCCON

【温室气体数据集】全球总碳柱观测网络 TCCON

WW、forever的博客 438

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

恶意软件检测项目教程

恶意软件检测项目教程 1. 项目介绍 项目概述 malware-detection 是一个基于机器学习的恶意软件检测和分类项目。该项目旨在通过分析恶意软件样本的特征,使用机器学习技术来识别和分类不同类型的恶意软件。项目的主要目标是提供一个开源的、可扩展的解决方案,帮助研究人员和安全专家更好地理解和对抗恶意软件。 主要功能 特征提取:从恶意软件样本中提取关键特征,如文件大小、熵、控制流图等。 特征...

gitblog_00367的博客 1253

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

refer_01

A Forced Sampled Execution Approach to Kernel Rootkit Identification Jeffrey Wilhelm and Tzi-cker Chiueh Core Research Group Symantec Research Laboratories {jeffrey wilhelm,tzi-cker chiueh}@s

longcanada的专栏 4694

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Malware Detection

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出版、作者信息和本声明。否则将追究法律责任。http://blog.youkuaiyun.com/topmvp - topmvpShared resources, such as the Internet, have created a highly interconnected cyber-infrastructure. Critical i

TopMVP 629

【论文学习】graph backdoor论文学习

摘要 本文提出了GTA攻击方法,这是在GNN上的第一个后门攻击(backdoor attack)。GTA有如下几个重要的方面:1)graph-oriented:将trigger定义成一个子图,这个子图包括了两个部分,拓扑结构和结点的特征信息。2)input-tailored:对每一个图都会得到一个trigger,通过对攻击有效性(attack effectiveness)和攻击规避性(保证正常图还是被正确分类,注入了trigger的图被错误分类)都进行优化得到trigger。3)下游模型不可知:攻击者不需要

qq_38391210的博客 1856

Android Malware Detection

基于机器学习和深度神经网络的安卓恶意软件静态分析与检测,主要是针对AndroidManifest.xml文件进行分析。Android Malware Detection

weixin_44345870的博客 535

对Malware Detection by Eating a Whole EXE的简单简单简单单理解

核心技术: 既是用神经网络测试一整个文件的二进制代码 ,这之前相关的工作中并没有此想法。 这个方法消除了这个领域特定于知识的代码和特性处理,减少了专门代码的数量,减少了复制和扩展的障碍。 (在其他的检测工作中存在有人工输入代码特性的工作,而这需要特定的知识的代码) ...

weixin_43971116的博客 1093

Deep Android Malware Detection小结

题目:Deep Android Malware Detection 作者:Niall McLaughlin, Jesus Martinez del Rincon, BooJoong Kang 年份:2017 会议:CODASPY 2.解决的问题 之前的方法需要对程序进行分析然后提取具有识别能力的特征用于恶意软件的分类。在本文中应用卷积神经网络来对恶意软件进行分类,该方法是受...

kexinxin1的博客 900

warning: function returns address of local variable【函数返回首地址出错原因】

这个提示就是告诉我,我定义的这个tmp_data这个是局部变量(在自定义函数里面定义的),不能返回他的地址,返回给主函数地址没用的,因为我这个函数用完就释放啦,你拿着我的地址找不到我的啊!~

m0_51429770的博客 1450

C—— warning: function returns address of local variable(函数参数返回错误)

function returns address of local variable

qq_42278665的博客 3650

ACL2020 Semantics-aware BERT for Language Understanding

Semantics-aware BERT for Language Understanding一、 本文所做工作1) 现成的语义角色标记器2) 一种序列编码器3) 一个整合语义信息和文本表示的组件二、 Background and Related Work1) 语言模型。2) 明确的上下文语义。三、 Model1) Semantic Role Labeling2) Encoding3) Integration五、 Conclusion 一、 本文所做工作 目前的预训练语言模型虽然取得很大的成功,但是仅仅引入

qq_41018465的博客 903

论文阅读——Semantic-aware neural style transfer

摘要: 论文地址: Semantic-aware neural style transfer

probie的博客 467
上一篇: 請給Solaris一點掌聲吧
下一篇: Intel 80386 arch
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值