Sie sind auf Seite 1von 19

Syntia: Synthesizing the Semantics

of Obfuscated Code
Tim Blazytko, Moritz Contag, Cornelius Aschermann,
and Thorsten Holz, Ruhr-Universität Bochum
https://www.usenix.org/conference/usenixsecurity17/technical-sessions/presentation/blazytko

This paper is included in the Proceedings of the


26th USENIX Security Symposium
August 16–18, 2017 • Vancouver, BC, Canada
ISBN 978-1-931971-40-9

Open access to the Proceedings of the


26th USENIX Security Symposium
is sponsored by USENIX
Syntia: Synthesizing the Semantics of Obfuscated Code

Tim Blazytko, Moritz Contag, Cornelius Aschermann, Thorsten Holz

Ruhr-Universität Bochum, Germany


{firstname.lastname}@rub.de

Abstract to prevent illegal copies, or in malicious software to im-


pede the analysis process. In practice, different kinds of
Current state-of-the-art deobfuscation approaches operate obfuscation techniques are used to hinder the analysis
on instruction traces and use a mixed approach of sym- process. Most notably, industry-grade obfuscation solu-
bolic execution and taint analysis; two techniques that tions are typically based on Virtual Machine (VM)-based
require precise analysis of the underlying code. However, transformations [38, 55, 57, 58], which are considered one
recent research has shown that both techniques can easily of the strongest obfuscating transformations available [2].
be thwarted by specific transformations. While these protections are not perfect and in fact are
As program synthesis can synthesize code of arbitrary broken regularly, attacking them is still a time-consuming
code complexity, it is only limited by the complexity of task that requires highly specific domain knowledge of
the underlying code’s semantic. In our work, we propose the individual Virtual Machine implementation. Conse-
a generic approach for automated code deobfuscation quently, for example, this gives game publishers a head-
using program synthesis guided by Monte Carlo Tree start in which enough revenue can be generated to stay
Search (MCTS). Specifically, our prototype implementa- profitable. On the other hand, obfuscated malware stays
tion, Syntia, simplifies execution traces by dividing them under the radar for a longer time, until concrete analysis
into distinct trace windows whose semantics are then results can be used to effectively defend against it.
“learned” by the synthesis. To demonstrate the practical
To deal with this problem, prior research has explored
feasibility of our approach, we automatically learn the se-
many different approaches to enable deobfuscation of
mantics of 489 out of 500 random expressions obfuscated
obfuscated code. For example, Rolles proposes static
via Mixed Boolean-Arithmetic. Furthermore, we synthe-
analysis to aid in deobfuscation of VM-based obfuscation
size the semantics of arithmetic instruction handlers in
schemes [44]. However, it incorporates specific imple-
two state-of-the art commercial virtualization-based ob-
mentation details an attacker has to know a priori. Further,
fuscators (VMProtect and Themida) with a success rate
static analysis of obfuscated code is notoriously known
of more than 94%. Finally, to substantiate our claim that
to be intractable in the general case [12]. Hence, recent
the approach is generic and applicable to different use
deobfuscation proposals have shifted more towards dy-
cases, we show that Syntia can also automatically learn
namic analysis [13, 61, 62]. Commonly, they produce
the semantics of ROP gadgets.
an execution trace and use techniques such as (dynamic)
taint analysis or symbolic execution to distinguish input-
1 Introduction dependent instructions. Based on their results, the pro-
gram code can be reduced to only include relevant, input-
Code obfuscation describes the process of applying an dependent instructions. This effectively strips the obfus-
obfuscating transformation to an input program to obtain cation layer. Even though such deobfuscation approaches
an obfuscated copy of the program. Said copy should be sound promising, recent work proposes several ways to
more complex than the input program such that an analyst effectively thwart underlying techniques, such as sym-
cannot easily reason about it. An obfuscating transfor- bolic execution [2]. For this reason, it suggests itself to
mation is further desired to be semantics-preserving, i. e., explore distinct techniques that may be leveraged for code
it must not change observable program behavior [12]. deobfuscation.
Code obfuscation can be leveraged in many application In this paper, we propose an approach orthogonal to
domains, for example in software protection solutions prior work on approximating the underlying semantics

USENIX Association 26th USENIX Security Symposium 643


of obfuscated code. Instead of manually analyzing the only limited by the underlying code’s semantic complex-
instruction handlers used in virtualization-based (VM) ob- ity. We demonstrate that a stochastic program synthesis
fuscation schemes in a complex and tedious manner [44] algorithm based on Monte Carlo Tree Search (MCTS)
or learning merely the bytecode decoding (not the seman- achieves this in a scalable manner. To show feasibility
tics) of these instruction handlers [53], we aim at learning of our approach, we automatically learned the semantics
the semantics of VM-based instruction handlers in an auto- of 489 out of 500 MBA-obfuscated random expressions.
mated way. Furthermore, our goal is to develop a generic Furthermore, we synthesize the semantics of arithmetic
framework that can deal with different use cases. Natu- instruction handlers in two state-of-the art commercial
rally, this includes constructs close to obfuscation, such virtualization-based obfuscators with a success rate of
as Mixed Boolean-Arithmetic (MBA), different kinds of more than 94%. Finally, to show applicability to areas
VM-based obfuscation schemes, or even analysis of code more focused on security aspects, we further automati-
chunks (so called gadgets) used in Return-oriented Pro- cally learn the semantics of ROP gadgets.
gramming (ROP) exploits.
To this extend, we explore how program synthesis can Contributions In summary, we make the following
be leveraged to tackle this problem. Broadly speaking, contributions in this paper:
program synthesis describes the task of automatically con-
structing programs for a given specification. While there • We introduce a generic approach for trace simpli-
exists a variety of program synthesis approaches [21], we fication based on program synthesis to obtain the
focus on SMT-based and stochastic program synthesis in semantics of different kinds of obfuscated code. We
the following, given its proven applicability to problem demonstrate how Monte Carlo Tree Search (MCTS)
domains close to trace simplification and deobfuscation. can be utilized in program synthesis to achieve a
SMT-based program synthesis constructs a loop-free pro- scalable and generic approach.
gram based on first-order logic constraints whose satisfia-
• We implement a prototype of our method in a tool
bility is checked by an SMT solver. For component-based
called Syntia. Based on I/O samples from assembly
synthesis, components are described that build the instruc-
code as input, Syntia can apply MCTS-based pro-
tion set of a synthesized program; for instance, compo-
gram synthesis to compute a simplified expression
nents may be bitwise addition or arithmetic shifts. The
that represents a deobfuscated version of the input.
characteristics of a well-formed program such as the inter-
connectivity of components are defined and the semantics • We demonstrate that Syntia can be applied in sev-
of the program are described as a logical formula. Then, eral different application domains such as simplify-
an SMT solver returns a permutation of the components ing MBA expressions by learning their semantics,
that forms a well-encoded program following the previ- learning the semantics of arithmetic VM instruction
ously specified intent [22, 24], if it is satisfiable, i. e., such handlers and synthesizing the semantics of ROP gad-
a permutation does exist. gets.
Instead of relying on a logical specification of program
intent, oracle-guided program synthesis uses an input- 2 Technical Background
output (I/O) oracle. Given the outputs of an I/O oracle
for arbitrary program inputs, program synthesis learns Before presenting our approach to utilize program syn-
the oracle’s semantics based on a finite set of I/O sam- thesis for recovering the semantics of obfuscated code,
ples. The oracle is iteratively queried with distinguishing we first review several concepts and techniques we use
inputs that are provided by an SMT solver. Locating throughout the rest of the paper.
distinguishing inputs is the most expensive task in this ap-
proach. The resulting synthesized program has the same
input-output behavior as the I/O oracle [24]. Contrary to 2.1 Obfuscation
SMT-based approaches that only construct semantically In the following, we discuss several techniques that
correct programs, stochastic synthesis approximates pro- qualify as an obfuscating transformation, namely
gram equivalence and thus remains faster. In addition, it virtualization-based obfuscation, Return-oriented Pro-
can also find partial correct programs. Program synthesis gramming and Mixed Boolean-Arithmetic.
is modeled as heuristic optimization problem, where the
search is guided by a cost function. It determines, for
2.1.1 Virtualization-based Obfuscation
instance, output similarity of the synthesized expression
and the I/O oracle for same inputs [50]. Contemporary software protection solutions such as VM-
As program synthesis is indifferent to code complex- Protect [58], Themida [38], and major game copy protec-
ity, it can synthesize arbitrarily obfuscated code and is tions such as SecuROM base their security on the concept

644 26th USENIX Security Symposium USENIX Association


Native Code handler function by looking it up in a global handler table
corresponds to
handler_exit (depicted in Figure 1). The latter maps indices, obtained
Bytecode switch from native from the instruction’s bytecode in the decoding step, to
VM Entry to VM context
5b 60 97 84 66 d8 aa 11 22 handlers addresses. In its most simple implementation,
all handler functions return to a central dispatching loop
Fetch which then dispatches the next handler. Eventually, exe-
Handler Table cution flow reaches a designated handler, VM exit, which
handler_add8 performs the context switch back to the native processor
handler_mul16 Decode
context and transfers control back to native code.
handler_not8

handler_sub32
Execute Custom ISA. The design of the target VM-ISA is en-
tirely up to the VM designer. Still, to maximize the
Figure 1: The Fetch–Decode–Execute cycle of a Virtual amount of handlers an analyst has to reverse engineer,
Machine. Native code calls into the VM, upon which VMs often opt for reduced complexity for the individual
startup code is executed (VM entry). It performs the con- handlers, akin to the RISC design principle. To exemplify,
text switch from native to VM context. Then, the next consider the following Intel x86 code:
instruction is fetched from the bytecode stream, mapped 1 mov eax , dword ptr [0 x401000 + ebx * 4]
to the corresponding handler using the handler table (de- 2 pop dword ptr [ eax ]
coding) and, finally, the handler is executed. The process
This might get translated into VM-ISA as follows:
repeats for subsequent VM instructions in the bytecode
until the exit handler is executed, which returns back to 1 vm_mov T0 , vm_context . real_ebx
native code. 2 vm_mov T1 , 4
3 vm_mul T2 , T0 , T1
4 vm_mov T3 , 0 x401000
5 vm_add T4 , T2 , T3
of Virtual Machine-based obfuscation (also known as
6 vm_load T5 , dword ( T4 )
virtualization-based obfuscation [44]).
7 vm_mov vm_context . real_eax , T5
Similar to system-level Virtual Machines (VMs) that 8 vm_mov T6 , T5
emulate a whole system platform, process-level VMs em- 9 vm_mov T7 , vm_context . real_esp
ulate a foreign instruction set architecture (ISA). The 10 vm_add T8 , T7 , T1
core idea is to translate parts of a program, e. g., a func- 11 vm_mov vm_context . real_esp , T8
tion f containing intellectual property, from its native 12 vm_load T9 , dword ( T7 )
architecture—say, Intel x86—into a custom VM-ISA. The 13 vm_store dword ( T6 ), T9
obfuscator then embeds both the bytecode of the virtual- It favors many small, simple handlers over fewer more
ized function (its instructions encoded for the VM-ISA) complicated ones.
along with an interpreter for the new architecture into
the target binary whilst removing the function’s origi-
Bytecode Blinding. In order to prevent global analysis
nal, native code. Every call to f is then replaced with
of instructions, the bytecode bc of each VM instruction is
an invocation of the interpreter. This effectively thwarts
blinded based on its instruction type, i. e., its correspond-
any naive reverse engineering tool operating on the native
ing handler h, at protection time. Likewise, each han-
instruction set and forces an adversary to analyze the inter-
dler unblinds the bytecode before decoding its operands:
preter and re-translate the interpreted bytecode back into
(bc, vm_key) ← unblindh (blinded_bc, vm_key).
native instructions. Commonly, the interpreter is heavily
The routine is parameterized for each handler h and
obfuscated itself. As VM-ISAs can be arbitrarily complex
updates a global key register in the VM context. Conse-
and generated uniquely upon protection time, this process
quently, instruction decoding can be flow-sensitive: An
is highly time-consuming [44].
adversary is unable to patch a single VM instruction with-
out re-blinding all subsequent instructions. This, in turn,
Components. The (VM) context holds internal vari- requires her to extract the unblinding routines from ev-
ables of the VM-ISA such as general-purpose registers or ery handler involved. The individual unblinding routines
the virtual instruction pointer. It is initialized by sequence commonly consist of a combination of arithmetic and
called VM entry, which handles the context switch from logical operations.
native code to bytecode.
After initialization, the VM dispatcher fetches and de- Handler Duplication. In order to easily increase anal-
codes the next instruction and invokes the corresponding ysis complexity, common VMs duplicate handlers such

USENIX Association 26th USENIX Security Symposium 645


that the same virtual instruction can be dispatched by mul- they mention challenges such as verbosity of the gadgets,
tiple handlers. In presence of bytecode blinding, these stack-based chaining, lack of immediates, and the distinc-
handlers’ semantics only differ in the way they unblind tion of function calls and regular control flow. Further,
the bytecode, but perform the same operation on the VM they stress how an accurate emulation of gadgets is im-
context. portant for addressing these challenges. Considering the
aforementioned challenges, at its core, Return-oriented
Architectures. In his paper about interpretation tech- Programming can be seen as an albeit weaker flavor of
niques, Klint denotes the aforementioned concept using obfuscated code. In particular, the chained invocation of
a central decoding loop as the “classical interpretation gadgets is reminiscent of handlers in VM-based obfusca-
method” [28]. An alternative is proposed by Bell with tion schemes following the threaded code principle.
Threaded Code (TC) [4]: He suggests inlining the dis- In addition to its application to exploitation, ROP has
patcher routine into the individual handler functions such seen other fields of applications such as rootkit devel-
that handlers execute in a chained manner, instead of opment [59], software watermarking [34], steganogra-
returning to a central dispatcher. Nevertheless, the dis- phy [33], and code integrity verification [1], which rein-
patcher still indexes a global handler table. forces the importance of automatic ROP chain analysis.
In Klint’s paper, however, he describes an extension of
TC, Direct Threaded Code (DTC). As in the TC approach,
2.1.3 Mixed Boolean-Arithmetic
the dispatcher is appended to each handler. The handler
table, though, is inlined into the bytecode of the instruc- Zhou et al. propose transformations over Boolean-
tion. Each instruction now directly specifies the address arithmetic algebras to hide constants by turning them
of its corresponding handler. This way, in presence of into more complex, but semantically equivalent expres-
bytecode blinding, not all handler addresses are exposed sions, so called MBA expressions [14, 63]. In Section 6.2,
immediately, but only those used on a certain path in the we provide details on their proposal of MBA expressions
bytecode. and show how our approach is still able to simplify them.

Attacks. Several academic works have been published


that propose novel attacks on virtualization-based obfus- 2.2 Trace Simplification
cators [13, 44]. Section 6.3 discusses and classifies them.
Due to the complexity of static analysis of obfuscated
In addition, it draws a comparison to our approach.
code, many deobfuscation approaches proposed recently
make use of dynamic analysis [13,19,19,53,62]. Notably,
2.1.2 Return-oriented Programming they operate on execution traces that record instruction
In Return-oriented Programming (ROP) [30, 52], shell- addresses and accompanying metadata, e. g., register con-
code is expressed as a so-called ROP chain, a list of tent, along a concrete execution path of a program. Sub-
references to gadgets and parameters for those. In the sequently, trace simplification is performed to strip the
preliminary step of an attack, the adversary makes esp obfuscation layer and simplify the underlying code. De-
point to the start of the chain, effectively triggering the pending on the approach, multiple traces are used for sim-
chain upon function return. Gadgets are small, general plification or one single trace is reduced independently.
instruction sequences ending on a ret instruction; other Coogan et al. [13] propose value-based dependence
flavors propose equivalent instructions. Concrete values analysis of a trace in order to track the flow of values
are taken from the ROP chain on the stack. As an example, into system calls using an equational reasoning system.
consider the gadget pop eax; ret: It takes the value on This allows them to reduce the trace to those instructions
top of the stack, places it in eax and, using the ret instruc- relevant to the previously mentioned value flow.
tion, dispatches the next gadget in the chain. By placing Graziano et al. [19] mainly apply standard compiler
an arbitrary immediate value imm32 next to this gadget’s transformations such as dead code elimination or arith-
address in the chain, an attacker effectively encodes the metic simplifications to reduce the trace.
instruction mov eax, imm32 in her ROP shellcode. De- Yadegari et al. [62] use bit-level taint analysis to iden-
pending on the gadget space available to the attacker, this tify instructions relevant to the computation of outputs.
technique allows for arbitrary computations [39, 51]. For subsequent simplification, they introduce the notion
Automated analysis of ROP exploits is a desirable goal. of quasi-invariant locations with respect to an execution.
However, its unique structure poses various challenges These are locations that hold the same value at every use
compared to traditional shellcode detection. In their pa- in the trace and can be considered constants when per-
per, Graziano et al. outline them and propose an analysis forming constant propagation. Similarly, they use several
framework for code-reuse attacks [19]. Amongst others, other compiler optimizations and adapt them to make use

646 26th USENIX Security Symposium USENIX Association


Selection Expansion Simulation Backpropagation
Bound for Trees (UCT) [5,17,29] provides a good balance
between exploration and exploitation. It is obtained by
s
ln n
X j +C , (1)
nj
Tree Default
Policy Policy
where X j represents the average reward of the child
node j, n the current node’s number of visits, n j the visits
of the child node and C the exploration constant. The
Figure 2: Illustration of a single MCTS round (taken from
average reward is referred to as exploitation parameter:
Browne et al. [5]).
if C is decreased, the search is directed towards nodes
with a higher reward. Increasing C, instead, leads to an
intensified exploration of nodes with few simulations.
of information about quasi-invariance to prevent over-
simplification.
2.4 Simulated Annealing
Simulated Annealing is a stochastic search algorithm that
has been used to effectively solve NP-hard combinatorial
2.3 Monte Carlo Tree Search problems [27]. The main idea of Simulated Annealing is
to approximate a global optimum by iteratively improving
Monte Carlo Tree Search (MCTS) is a stochastic, best- an initial candidate and exploring the local neighborhood.
first tree search algorithm that directs the search towards To avoid a convergence to local optima, the search is
an optimal decision, without requiring much domain guided by a falling temperature T that decreases the prob-
knowledge. The algorithm builds a search tree through ability of accepting worse candidates over time [25]; in
reinforcement learning by performing random simula- the following, we assume that a falling temperature de-
tions that estimate the quality of a node [5]. Hence, pends on a decreasing loop counter.
the tree grows asymmetrically. MCTS has had sig-
nificant impact in artificial intelligence for computer
games [16, 35, 49, 56], especially in the context of Com-
puter Go [17, 54].
In an MCTS tree, each node represents a game state; a
directed link from a parent node to its child node repre-
sents a move in the game’s domain. The core algorithm
iteratively builds the decision tree in four main steps that
are also illustrated in Figure 2: (1) The selection step
starts at the root node and successively selects the most- Figure 3: Simulated Annealing approximates a global
promising child node, until an expandable leaf (i. e., a optimum (the darkest area in the map).
non-terminal node that has unvisited children) is reached.
(2) Following, one or more unvisited child nodes are Figure 3 illustrates this process on the example of find-
added to the tree in the expansion step. (3) In the sim- ing the darkest area in a given map. Starting in an initial
ulation step, node rewards are determined for the new state (s0 ), the algorithm always accepts a candidate that
nodes through random playouts. For this, consecutive has a better score than the current one (green arrows). If
game states are randomly derived until a terminal state the score is worse, we accept the worse candidate with
(i. e., the end of the game) is reached; the game’s outcome some probability (the red arrow from s2 to s3 ) that de-
is represented by a reward. (4) Finally, the node rewards pends on the temperature (loop counter) and how much
are propagated backwards through the selected nodes to worse the candidate is. The higher the temperature, the
the root in the backpropagation step. The algorithm ter- more likely the algorithm accepts a significantly worse
minates if either a specified time/iteration limit is reached candidate solution. Otherwise, the candidate is discarded
or an optimal solution is found [5, 8]. (e. g., the crossed out red arrow at s4 ); in this case, we pick
Selecting the most-promising child node can be treated another one in the local neighborhood. This allows the
as a so called multi-armed bandit problem, in which a algorithm to escape from local optima while the tempera-
gambler tries to maximize the sum of rewards by choosing ture is high; for low temperatures (loop counters closer to
one out of many slot machines with an unknown probabil- 0), it mainly accepts better candidate solutions. The algo-
ity distribution. Applied to MCTS, the Upper Confidence rithm terminates after a specified number of iterations.

USENIX Association 26th USENIX Security Symposium 647


3.2 Random Sampling
The goal of random sampling is to derive input-output
relations that describe the semantics of a trace window.
This happens in two steps: First, we determine the inputs
and outputs of the trace window. Then, we replace the
inputs with random values and obverse the outputs.
Generally speaking, we consider register and memory
reads as inputs and register and memory writes as outputs.
Figure 4: Dissecting a given trace (a) into several trace
For inputs, we apply a read-before-write principle: inputs
windows (b). The trace windows can be used to recon-
are only registers/memory locations that are read before
struct a (possibly disconnected) control-flow graph (c).
they have been written; for outputs, we consider the last
writes of a register/memory location as output.
3 Approach 1 mov rax , [ rbp + 0 x8 ]
2 add rax , rcx
3 mov [ rbp + 0 x8 ], rax
Given an instruction trace, we dissect the instruction trace 4 add [ rbp + 0 x8 ], rdx
into trace windows (i. e., subtraces) and aim at learning
their high-level semantics which can be used later on Following this principle, the code above has three in-
for further analysis. In the following, we describe our puts and two outputs: The inputs are the memory read M0
approach which is divided into three distinct parts: in line 1, rcx (line 2) and rdx (line 4). The two outputs
are o0 (line 2) and o1 (line 4).
1. Trace Dissection. The instruction trace is partitioned In the next step, we generate random values and ob-
into unique sequences of assembly instructions in a verse the I/O relationship. For instance, we obtain the
(semi-)automated manner. outputs (7, 14) for the input tuple (2, 5, 7); for the inputs
(1, 7, 10), we obtain (8, 18).
By default, we use register locations as well as memory
2. Random Sampling. We derive random input-output locations as inputs and outputs. However, we support the
pairs for each trace window. These pairs describe option to reduce the inputs and outputs to either register or
the trace window’s semantics. memory locations. For instance, if we know that registers
are only used for intermediate results, we may ignore
3. Program Synthesis. Expressions that map all pro- them since it reduces the complexity for the synthesis.
vided inputs to their corresponding outputs are syn-
thesized. 3.3 Synthesis
This section demonstrates how we synthesize the seman-
3.1 Trace Dissection tics of assembly code; we discuss the inner workings of
our synthesis approach in the next section.
The choice of trace window boundaries highly impacts After we obtained the I/O samples, we combine the
later analysis stages. Most notably, it affects synthesis different samples and synthesize each output separately.
results: if a trace window ends at an intermediary com- These synthesis instances are mutually independent and
putation step, the synthesized formula is not necessarily can be completely parallelized.
succinct or meaningful at all, as it includes spurious se- To exemplify, for the I/O pairs above, we search an
mantics. expression that transforms (2, 5, 7) to 7 and (1, 7, 10) to 8
Yet, we note how trace dissection of ROP chains and for o0 ; for o1 , the expression has to map (2, 5, 7) to 14 and
VM handlers lends itself to a simple heuristic. Namely, (1, 7, 10) to 18. Then, the synthesizer finds o0 = M0 +rcx
we split traces at indirect branches. In the ROP case, this and o1 = M0 + rcx + rdx.
describes the transition between two gadgets (commonly,
on a ret instruction), whereas for VM handlers it distin- 4 Program Synthesis
guishes the invocation of the next handler (cf. Section 6.3).
Figure 4 illustrates the approach. Given concrete trace In the last section, we demonstrated how we obtain I/O
window boundaries, we can reconstruct a control-flow samples from assembly code and apply program synthesis
graph consisting of multiple connected components. A to that context. This section describes our algorithm in
trace window then describes a particular path through a detail; we show how we find an expression that maps
connected component. all inputs to their corresponding outputs for all observed

648 26th USENIX Security Symposium USENIX Association


samples. We use Monte Carlo Tree Search, since it has (focus on exploration), it does not find deeper expressions;
been proven to be very effective when working on infinite if we set C to a lower value, MCTS gets lost in deep
decision trees without requiring much domain knowledge. expressions. To solve this problem, we use an adaption
We consider program synthesis as a single-player game of UCT that is known as Simulated Annealing UCT (SA-
whose purpose is to synthesize an expression whose input- UCT) [47]. The main idea of SA-UCT is to use the
output behavior is as close as possible to given I/O sam- characteristics of Simulated Annealing (cf. Section 2.4)
ples. In essence, we define a context-free grammar that and apply it to UCT. SA-UCT is obtained by replacing
consists of terminal and non-terminal symbols. (Partially) the exploration constant C by a variable T with
derived words of the grammar are game states; the gram-
mar’s production rules represent the moves of the game. N −i
T =C , (2)
Terminal nodes are expressions that contain only terminal N
symbols; these are end states of the game. where N is the maximum number of MCTS iterations
Given a maximum number of iterations and I/O sam- and i the current iteration. Then, SA-UCT is defined as
ples, we iteratively apply the four MCTS steps (cf. Sec- s
tion 2.3), until we find a solution or we reach the timeout. ln n
X j +T . (3)
Starting with a non-terminal expression as root node, we nj
select the most-promising expandable node. A node is
expandable, if there still exist production rules that have T decreases over time, since N−i N converges to 0 for
not been applied to this node. We choose a production increasing values of i. As a result, MCTS places the
rule randomly and expand the selected node. To evaluate emphasis on exploration in the beginning; the more T
the quality of the new node, we perform a random play- decreases, the more the focus shifts to exploitation.
out: First, we randomly derive a terminal expression by
successively applying random production rules. Then, we 4.2 Grammar
evaluate the expressions based on the inputs from the I/O
pairs and compare the output similarity. The similarity Game states are represented by sentential forms of a
score is the node reward. A reward of 1 ends the synthe- context-free grammar that describes valid expressions
sis, since the input-output behavior is the same for the of our high-level abstraction. We introduce a terminal
provided samples. Finally, we propagate the reward back symbol for each input (which corresponds to a variable
to the root. that stores this input) and each valid operator (e. g., ad-
In the following, we give details on node selection, our dition or multiplication). For every data type that can be
grammar, random playouts and backpropagation. Finally, computed we introduce one non-terminal symbol (in our
we discuss the algorithm configuration and parameter running example, we only use a single non-terminal value
tuning. To demonstrate the different steps of our approach, U that represents an unsigned integer). The production
we use the following running example throughout this rules describe how we can derive expressions in our high-
section: level description. Since the sentential forms represent
partial expressions, we will use the term expression to
Example 1 (I/O relationship). Working with bit-vectors of denote the (partial) expression that is represented by a
size 3 (i. e., modulo 23 ), we observe for an expression with given sentential form. Sentences of the grammar are final
two inputs and one output the I/O relations: (2, 2) → 4 states in the game since they do not allow any further
and (4, 5) → 1. A synthesized expression that maps the moves (derivations). They represent expressions that can
inputs to the corresponding outputs is f (a, b) = a + b. be evaluated. We represent expressions in Reverse Polish
Notation (RPN).
4.1 Node Selection Example 2. The grammar in our previous example has
Since we have an infinite search space for program syn- two input symbols V = {a, b}, since each I/O sample has
thesis, node selection must be a trade-off between ex- two inputs. If the grammar supports addition and mul-
ploration and exploitation. The algorithm has to ex- tiplication O = {+, ∗}, there are four production rules:
plore different nodes such that several promising and R = {U → U U + | U U ∗ | a | b}. An unsigned integer
non-promising candidates are known. On the other hand, expression U can be mapped to an addition or multipli-
it has to follow more promising candidates to find deeper cation of two such expressions or a variable. The final
expressions. As described in Section 2.3, the UCT (cf. grammar is ({U}, Σ = V ∪ O, R,U).
Equation 1) provides a good balance between exploitation
and exploration for many MCTS applications. Synthesis Grammar. Our grammar is designed
However, we observed that it does not work for our use to synthesize expressions that represent the se-
case: if we set the exploration constant C to a higher value mantics of bit-vector arithmetic, especially for

USENIX Association 26th USENIX Security Symposium 649


+
U
* U3

U1 U2
UU* UU+ a b
Figure 6: The left-most U in U3 U2 U1 ∗ + is the top-
most-right-most non-terminal in the abstract syntax tree.
(The indices are provided for illustrative purposes only.)
Ub+ UUU++ Ua+ UUU*+

stead, substitute always the right-most non-terminal only,


UU*a+ ba+ then the search would be guided towards most-promising
subexpressions. If the expression is too nested, the syn-
Figure 5: An MCTS tree for program synthesis that grows thesizer would find the partial subexpression but not the
towards the most-promising node b a +, the right-most whole expression. The top-most-right-most derivation is
leaf in layer 3. illustrated in Figure 6, which shows the abstract syntax
tree (AST) of an expression.

the x86 architecture. For every data type (U8 , Example 4. The expression (U + (U ∗U)) is represented
U16 , U32 and U64 ), we define the set of operations as U U U ∗ +. If we successively replace the right-most
as O = {+,−,∗,/s ,/,%s ,%,∧,∨,⊕,,,a ,−1 ,¬, U, the algorithm is unlikely to find expressions such as
sign_ext, zero_ext, extract, ++, 1}, where the ((a + b) + (b ∗ (b ∗ a))), since it is directed into the subex-
operations are binary addition, subtraction, multiplication, pression with the multiplication. Instead, replacing the
signed/unsigned division, signed/unsigned remainder, top-most-right-most non-terminal directs the search to the
bitwise and/or/xor, logical left shift, logical/arithmetic top-most addition and then explores the subexpressions.
right shift as well as unary minus and complement.
The unary operations sign_ext and zero_ext extend
smaller data types to signed/unsigned larger data types.
4.3 Random Playout
Conversely, the unary operator extract transforms One of the key concepts of MCTS are random playouts.
larger data types into smaller data types by extracting the They are used to determine the outcome of a node; this
respective least significant bits. Since the x86 architecture outcome is represented by a reward. In the first step,
allows register concatenation (e. g., for division), we we randomly apply production rules to the current node,
employ the binary operator ++ to concatenate two until we obtain a terminal expression. To avoid infinite
expressions of the same data type. Finally, to synthesize derivations, we set a maximum playout depth. This max-
expressions such as increment and decrement, we use the imum playout depth defines how often a non-terminal
constant 1 as niladic operator. The input set V consists symbol can be mapped to rules that contain non-terminal
of |V | = n variables, where n represents the number of symbols; at the latest we reached the maximum, we map
inputs. non-terminals only to terminal expressions. This happens
in a top-most-right-most manner. Afterwards, we evaluate
Tree Structure. The sentential form U is the root node the expression for all inputs from the I/O samples.
of the MCTS tree. Its child nodes are other expressions
that are produced by applying the production rules to a Example 5. Assuming a maximum playout depth of 2
single non-terminal symbol of the parent. The expression and the expression U U ∗, the first top-most-right-most U
depth (referred to as layer) is equivalent to the number of is randomly substituted with U U ∗, the second one with
derivation steps, as depicted in Figure 5. U U +. After that, the remaining non-terminal symbols
are randomly replaced with variables: U U ∗ ⇒ U U U ∗
Example 3. The root node U is an expression of layer 0. ∗ ⇒ U U + U U ∗ ∗ ⇒ · · · ⇒ a a + b a ∗ ∗. A random
Its children are a, b, U U +, and U U ∗, where a and b are playout for U U + is a b b + +.
terminal expressions of layer 1. Assuming that the right- For the I/O sample (2, 2) → 4, we evaluate g(2, 2) = 0
most U in an expression is replaced, the children of U U + for g(a, b) = ((a + a) ∗ (b ∗ a)) mod (28 ) and h(2, 2) = 6
are U b +, U a +, U U U + +, and U U U ∗ +. To obtain for h(a, b) = (a + (b + b)) mod 28 .
the layer 3 expression b a +, the following derivation
steps are applied: U ⇒ U U + ⇒ U a + ⇒ b a +. We set terminal nodes to inactive after their evaluation,
since they already are end states of the game; there is
To direct the search towards outer expressions, we re- no possibility to improve the node’s reward by random
place the top-most-right-most non-terminal. If we, in- playouts. As a result, MCTS will not take these nodes

650 26th USENIX Security Symposium USENIX Association


into account in further iterations. The node’s reward is integer values as ((1  1)  (1 + (1  1))), we can
the similarity of the evaluated expressions and the out- reduce them to the value 16.
puts from the I/O samples. We describe in the following
section how to measure the similarity to the outputs.
4.7 Algorithm Configuration
4.4 Measuring Similarity of Outputs Two main factors define the algorithm’s success that can-
not be influenced by the user: the number of input vari-
To measure the similarity of two outputs, we compare val- ables and the complexity (e. g., depth) of the expression
ues with different metrics: arithmetic distance, Hamming to synthesize. Contrary, there exist four parameters that
distance, count leading zeros, count trailing zeros, count can be configured by a user to improve the effectiveness
leading ones and count trailing ones. While the numeric and speed: the initial SA-UCT value, the number of I/O
distance is a reliable metric for arithmetic operations, it samples, the maximum number of MCTS iterations and
does not work well with overflows and bitwise operations the maximum playout depth.
(e. g., xor and shifts). In turn, the Hamming distance ad- The SA-UCT parameter T configures the trade-off be-
dresses these operations since it states in how many bits tween exploration and exploitation and depends on the
two values differ. Finally, the leading/trailing zeros/ones maximum number of MCTS iterations; if the maximum
are strong indicators that two values are in the same range. number of MCTS iterations is low, the algorithm focuses
We scale each result between a value of 0 and 1. Since the on exploiting promising candidates within a small period
different metrics compensate each other, we set the total of time. The same holds for small initial values of T .
similarity reward to the average reward of all metrics.
A large number of variables or a higher expression
Example 6. Considering I/O pair (2, 2) → 4, the out- depth requires more MCTS iterations. Besides the maxi-
put similarities for g and h (as defined in Example 5) mum number of MCTS iterations, the maximum playout
are similarity(4, 0) and similarity(4, 6). Limiting to the depth provides more accuracy since it is more probable
metrics of Hamming distance and count leading ze- to hit deeper expressions or more influencing variables
ros (clz), we obtain hamming(4, 0) = hamming(4, 6) = with deeper playouts. On the other hands, deeper playouts
0.67, clz(4, 0) = 0 and clz(4, 6) = 1.0. Therefore, the have an impact on the execution time.
average similarities are similarity(4, 0) = 0.335 and Since random playouts are performed for every node
similarity(4, 6) = 0.835. Related to the random play- and for every I/O pair, the number of I/O samples has a
outs, the evaluated node U U + has a higher reward significant impact on the execution time. In addition, it
than U U ∗. effects the number of false positives, since there are less
expressions that have the same I/O behavior for a larger
During a random playout, we calculate the similarity number of I/O samples. Finally, the MCTS synthesis is
for all I/O samples. The final node reward is the average more precise since the different node rewards are expected
score of all similarity rewards. A reward of 1 finishes pro- to be informative.
gram synthesis, since the evaluated expression produces Since the search space for finding good algorithm con-
exactly the outputs from the I/O samples. figurations for different complexity classes is large, we
approximate an optimal solution by Simulated Annealing.
4.5 Backpropagation We present the details and results in Section 6.1.

After obtaining a score by random playout, we do the


following for the selected node and all its parents, up to 5 Implementation
the root: (1) We update the node’s average reward. This
reward is averaged based on the node’s and its successors’ We implemented a prototype implementation of our ap-
total number of random playouts. (2) If the node is fully proach in our tool Syntia, which is written in Python. For
expanded and its children are all inactive, we set the node trace generation and random sampling, we use the Uni-
to inactive. (3) Finally, we set the current node to its corn Engine [43], a CPU emulator framework. To analyze
parent node. assembly code (e. g., trace dissection), we utilize the dis-
assembler framework Capstone [42]. Furthermore, we
use the SMT solver Z3 [36] for expression simplification.
4.6 Expression Simplification
Initially, Syntia expects a memory dump, a start and
Since MCTS performs a stochastic search, synthesized ex- an end address as input. Then, it emulates the program
pressions are not necessary in their shortest form. There- and outputs the instruction trace. Then, the user has the
fore, we apply some basic standard expression simplifi- opportunity to define its own rules for trace dissection;
cation rules. For example, if the synthesizer constructs otherwise, Syntia dissects the trace at indirect control

USENIX Association 26th USENIX Security Symposium 651


Table 1: Initial Simulated Annealing configuration and plexity classes after 50 Simulated Annealing iterations.
the parameter’s lower/upper bounds. While the I/O samples and the playout depth are mostly in
parameter initial lower bound upper bound a similar range (0 and 20), there is a larger scope for the
SA-UCT 1.0 0.7 2.0
SA-UCT parameter and the maximum number of MCTS
# MCTS iterations 2,000 500 50,000 iterations. Especially for higher complexity classes, this
# I/O samples 30 10 60 is due to the optimization towards a high success rate
playout depth 1 0 2 within 120 seconds. The latter parameters strive towards
larger values without this timeout.
Generally, the parameter configurations set a focus on
transfers. Additionally, the user has to decide if regis- exploration instead of exploitation. We follow this obser-
ter and/or memory locations are used as inputs/outputs vation and adapt the configuration based on our problem
and how many I/O pairs shall be sampled. Syntia traces statements. To describe a configuration, we provide a
register and memory modifications in each trace window, configuration vector of the form (SA-UCT, #iter, #I/O,
derives the inputs and outputs and generates I/O pairs by PD).
random sampling. The last step can be parallelized for
each trace window. Finally, the user defines the synthe-
sis parameters. Syntia creates a synthesis tasks for each 6.2 Mixed Boolean-Arithmetic
(trace window, output) pair. The synthesis tasks are per-
formed in parallel. The synthesis results are simplified by Zhou et al. proposed the concept of MBA expressions [63].
Z3’s term-rewriting engine. By transforming simpler expressions and constants into
MBA expressions over Boolean-arithmetic algebras, they
can generate semantically-equivalent, but much more
6 Experimental Evaluation complex code which is arguably hard to reverse engi-
neer. Effectively, this obfuscating transformation allows
In the following, we evaluate our approach in three areas them to hide formulas and constants in plain code. In
of application. The experiments have been evaluated on a their paper, they define a Boolean-arithmetic algebra as
machine with two Intel Xeon E5-2667 CPUs (in total, 12 follows:
cores and 24 threads) and 96 GiB of memory. However,
we never have used more than 32 GiB of memory even Definition 1 (Boolean-arithmetic algebra [63]). With
though parallel I/O sampling for many trace windows can n a positive integer and B = {0, 1}, the algebraic
be memory intensive; synthesis itself never used more system (Bn , ∧, ∨, ⊕, ¬, ≤, ≥, >, <, ≤s , ≥s , >s , <s , 6=, =,
than 6 GiB of memory. s , , , +, −, ·), where ,  denote left and right
shifts, · (or juxtaposition) denotes multiply, and signed
compares and arithmetic right shift are indicated by s , is
6.1 Parameter Choice a Boolean-arithmetic algebra (BA-algebra), BA[n]. n is
As described in Section 4.7, we approximate an optimal the dimension of the algebra.
algorithm configuration with Simulated Annealing. To
Specifically, they highlight how BA[n] includes,
compute preferably representative results, we generate a
amongst others, the Boolean algebra (Bn , ∧, ∨, ¬) as well
set of 1, 200 randomly generated expressions. We divide
as the integer modular ring Z/(2n ). As a consequence,
this set into three classes with 400 expressions each; to
Mixed Boolean-Arithmetic (MBA) expressions over Bn
prevent overfitting the parameters on a fixed set of inputs,
are hard to simplify in practice. In general, we note that
the experiments of each class are performed with distinct
reducing a complex expression to an equivalent, but sim-
input samples.
pler one by, e. g., removing redundancies, is considered
In each iteration, Simulated Annealing synthesizes the
NP-hard [31].
1, 200 expressions under the same configuration. We set a
Zhou et al. represent MBA expressions as polynomials
timeout of 120 seconds for each synthesis task and prune
over BA[n]. While polynomial MBA expressions are
non-successful tasks by a constant factor of the timeout.
conceptually not restricted in terms of complexity, Zhou
As a result, Simulated Annealing optimizes towards a high
et al. define linear MBA expressions as those polynomials
success rate for synthesis tasks and a minimal average
with degree 1. In particular, f (x, y) = x − (x ⊕ y) − 2(x ∨
time. Table 1 lists the initial algorithm configuration and
y) + 12564 is a linear MBA expression, whereas f (x, y) =
the parameter boundaries.
x + 9(x ∨ y)yx3 is not.
We aim at determining optimal parameters for different
complexity classes. Classes are distinguished by the num-
ber of variables and by the expression’s layer. Table 2 Implementation in Tigress. In practice, MBA expres-
illustrates the final configurations for 12 different com- sions are used in the Tigress C Diversifier/Obfuscator by

652 26th USENIX Security Symposium USENIX Association


Table 2: Parameter choices for different complexity classes that depend on the expression layer and the number of
variables. The parameters are the SA-UCT parameter (SA), the maximum number of MCTS iterations (# iter), the
number of I/O samples (# I/O) and the playout depth (PD).
# variables
2 5 10 20
layer SA # iter # I/O PD SA # iter # I/O PD SA # iter # I/O PD SA # iter # I/O PD
3 1.42 40,569 20 0 1.55 32,375 17 0 1.74 42,397 20 1 1.38 28,089 18 1
5 1.84 35,399 14 0 1.11 28,792 23 0 1.29 27,365 23 0 0.92 34,050 12 0
7 1.25 28,363 20 0 1.01 30,838 23 0 1.23 15,285 22 0 1.42 11,086 22 0

Collberg et al. [9] which uses the technique to encode inte- Table 3: Trace window statistics and synthesis perfor-
ger variables and expressions in which they are used [11]. mance for Tigress (MBA), VMProtect (VMP), Themida
Further, Tigress also supports common arithmetic encod- (flavor Tiger White, TM), and ROP gadgets.
ings to increase an expression’s complexity, albeit not MBA VMP TM ROP
based on MBAs [10]. #trace windows 500 12,577 2,448 78
For example, the rather simple expression x + y + z is #unique windows 500 449 106 78
transformed into the layer 23 expression (((x ⊕ y) + ((x ∧ #instructions per window 116 49 258 3
#inputs per window 5 2 15 3
y)  1)) ∨ z) + (((x ⊕ y) + ((x ∧ y)  1)) ∧ z) using its
#outputs per window 1 2 10 2
arithmetic encoding option. In a second transformation #synthesis tasks 500 1,123 1,092 178
step, Tigress encodes it into a linear MBA expression of I/O sampling time (s) 110 118 60 17
layer 383 (omitted due to complexity). Such expressions overall synthesis time (s) 2,020 4,160 9,946 829
are hard to simplify symbolically. synthesis time per task (s) 4.0 3.7 9.1 4.7

Evaluation Results. We evaluated our approach to sim- To get a better feeling for this probabilistic behavior, we
plify MBA expressions using Syntia. As a testbed, we compared the cumulative numbers of synthesized MBA
built a C program which calls 500 randomly generated expressions for 10 subsequent runs. Figure 7 shows the
functions. Each of these random functions takes 5 in- results averaged over 15 separate experiments. On aver-
put variables and returns an expression of layer 3 to 5. age, the first run synthesizes 89.6% (448 expressions) of
Then, we applied the arithmetic encoding provided by the 500 expressions. A second run yields 22 new expres-
Tigress, followed by the linear MBA encoding. The re- sions (94.0%), while a third run reveals 10 more expres-
sulting program contained expressions of up to 2, 821 sions (96.0%). While converging to 500, the number of
layers, the average layer being 156. The arithmetic encod- newly synthesized expressions decreases in subsequent
ing is applied to highlight that our approach is invariant runs. Comparing the fifth and the eighth run, we only
to the code’s increased symbolic complexity and is only found 5 new expressions (from 489 to 494). After the
concerned with semantical complexity. ninth run, Syntia synthesized 495 (99.0%) of the MBA
Based on a concrete execution trace it can be observed expressions.
that the 500 functions use, on average, 5 memory inputs
(as parameters are passed on the stack) and one register 6.3 VM Instruction Handler
output (the register containing the return value). Table 3
shows statistics for the analysis run using the configura- As introduced in Section 2.1.1, an instruction handler of
tion vector (1.5, 50000, 50, 0). The first two components a Virtual Machine implements the effects of an atomic in-
indicate a strong focus on exploration in favor of exploita- struction according to the custom VM-ISA. It operates on
tion; due to the small number of synthesis tasks, we used the VM context and can perform arbitrarily complex tasks.
50 I/O samples to obtain more precise results. As handlers are heavily obfuscated, manual analysis of a
The sampling phases completed in less than two min- handler’s semantics is a time-consuming task.
utes. Overall, the 500 synthesis tasks were finished
in about 34 minutes, i. e., in 4.0 seconds per expres- Attacking VMs. When faced with virtualization-based
sion. We were able to synthesize 448 out of 500 expres- obfuscations, an attacker typically has two options. For
sions (89.6%). The remaining expressions are not found one, she can analyze the interpreter and, for each han-
due to the probabilistic nature of our algorithm; after 4 dler, extract all information required to re-translate the
subsequent runs, we synthesized 489 expressions (97.8%) bytecode back to native instruction. Especially in face of
in total. handler duplication and bytecode blinding, this requires

USENIX Association 26th USENIX Security Symposium 653


500 distort our results. For verification, we manually reverse
engineered the VM layouts of VMProtect and Themida.
# synthesized expressions 400 Note that the commercial versions of both protection sys-
tems have been used to obfuscate the program. These are
300
known to provide better obfuscation strength compared
200
to the evaluation versions.
We argue that our evaluation program is representative
100 of any program obfuscated with the respective VM-based
obfuscating scheme. As seen in Section 2.1.1, common
0 instructions map to a plethora of VM handlers. Conse-
0 2 4 6 8 10
# synthesis runs quently, if we succeed in recovering the semantics of these
Figure 7: Subsequent synthesis runs increase the number integral building blocks, we are at the same time able to
of synthesized MBA expressions. Each point represents recover other variations of native instructions using these
the average cumulative number of synthesized expres- handlers as well.
sions from 15 separate experiments. This motivates the design of our evaluation program,
which aims to have a wide coverage of all possible arith-
metic and logical operations. We note that this may not be
her to precisely capture all effects produced by the han- the case for real-world test cases, which may not trigger
dlers. This includes both the high-level semantics with all interesting VM handlers. To this extent, our evalua-
regard to input and output variables as well as the indi- tion program is, in fact, more representative than, e. g.,
vidual unblinding routines. In his paper, Rolles discusses malware samples.
how this type of attack requires complete understanding
of the VM and therefore has to be repeated for each virtu-
6.3.1 VMProtect
alization obfuscator [44]. Thus, we note that this attack
does not lend itself easily to full automation. Another ap- In its current version, VMProtect follows the Direct
proach is to perform analyses on the bytecode level. The Threaded Code design principle (cf. Section 2.1.1). Each
idea is that while an attacker cannot learn the full seman- handler directly invokes the next handler based on the
tics of the original code, the analysis of the interaction address encoded directly in the instruction’s bytecode.
of handlers itself reveals enough information about the Hence, reconstructing the handlers requires an instruction
underlying code. This allows the attacker to skip details trace. Also, this impacts trace dissection: since VM han-
like bytecode blinding as she only requires the high-level dlers dispatch the next handler, they end with an indirect
semantics of a handler. Sharif et al. successfully mounted jump. Unsurprisingly, Syntia could automatically dissect
such an attack to recover the CFG of the virtualized func- the instruction trace into trace windows that represent a
tion [53], but do not take semantics other than virtual single VM handler. As evident from Table 3, there are
instruction pointer updates into account. 449 unique trace windows out of a total of 12, 577 in the
We recognize the latter approach as promising and note instruction trace.
how Syntia allows us to automatically extract the high- Further, VMProtect employs handler duplication. For
level semantics of arithmetical and logical instruction example, the 449 instruction handlers contain 12 instances
handlers. This is achieved by operating on an execution performing 8-bit addition, 11 instances for each of addi-
trace through the interpreter and simplify its individual tion (for each flavor of 16-, 32-, 64-bit), nor (8-, 64-bit),
handlers—as distinguished by trace window boundaries— left and right shift (32-, 64-bit); amongst multiple others.
using program synthesis. Especially, we highlight how ob- If Syntia is able to learn one instance in each group, it is
taining the semantics of one handler automatically yields safe to assume that it will successfully synthesize the full
information about the underlying native code at all points group, as supported by our results.
of the trace where this specific handler is used to encode Similarly, the execution trace is made up of all possible
equivalent virtualized semantics. handlers and some of them occur multiple times. Hence,
if we correctly synthesize semantics for, e. g., a 64-bit
Evaluation Setup. We evaluated Syntia to learn the addition, this immediately yields semantics for 772 trace
semantics of arithmetic and logical VM instruction han- windows (6.2% of the full trace, 32.0% of all arithmetic
dlers in recent versions of VMProtect [58] (v3.0.9) and and logical trace windows in the trace). Equivalent rea-
Themida [38] (v2.4.5.0). To this end, we built a program soning applies to 16-bit nor operations in our trace (3.6%
that covers bit-vector arithmetic for operand widths of 8, of the full trace, 18.8% of all arithmetic and logical trace
16, 32, and 64 bit. Since we are interested in analyzing ef- windows). In total, our results reveal semantics for 19.7%
fects of the VM itself, using a synthetic program does not of the full execution trace (2, 482 out of 12, 577 trace win-

654 26th USENIX Security Symposium USENIX Association


dows). Manual analysis suggests that the remaining trace widths. In contrast to VMProtect, handlers are neither
semantics mostly consists of control-flow handling and duplicated nor do they occur multiple times in the execu-
stack operations. These are especially used when switch- tion trace. Hence, the trace itself is much more compact,
ing from the native to the VM context and amount for a spanning 2, 448 trace windows in total; roughly 5 times
large part of the execution trace. shorter than VMProtect’s. Still, Themida’s handlers are
On average, an individual instruction handler consists much longer, with 258 instructions on average.
of 49 instructions. As VMProtect’s VM is stack-based, We ran the analysis using the configuration vector
binary arithmetic handlers pop two arguments from the (1.8, 50000, 20, 0). Due to the higher number of in-
stack and push the result onto the stack. This tremen- puts, this configuration—in comparison to the previous
dously eases identification of inputs and outputs. There- section—sets a much higher focus on exploration as indi-
fore, we mark memory operands as inputs and outputs cated by higher values chosen for the first two parameters.
and use the configuration vector (1.5, 30000, 20, 0) for the Sampling finished in one minute, whereas the synthesis
synthesis. The sampling phase finished in less than two phase took around 166 minutes. At 1, 092 synthesis tasks,
minutes. Overall, the 1, 123 synthesis tasks completed this amounts to roughly 9.1 seconds per task. Eventually,
in less than an hour, which amounts to merely 3.7 sec- we automatically learned the semantics of 34 out of 36
onds per task. In total, in our first run, we automatically arithmetic and logical handlers (94.4%). The remaining
identified 190 out of 196 arithmetical and logical han- handlers (8-bit subtraction and logical or) were not found
dlers (96.9%). The remaining 6 handlers implement 8-bit as we were unable to complete the sampling phase due to
divisions and shifts. Due to their representation in x86 crashes in Unicorn engine.
assembly code, Syntia needs to synthesize more complex
expressions with nested data type conversions. As the
analysis is probabilistic in nature, we scheduled five more
runs which yielded 4 new handlers. Thus, we are able to 6.4 ROP Gadget Analysis
automatically pinpoint 98.9% of all arithmetic and logical
instruction handlers in VMProtect. We further evaluated Syntia on ROP gadgets, specifically,
on four samples that were thankfully provided by De-
6.3.2 Themida bray [62]. They implement bubble sort, factorials, Fi-
bonacci, and matrix multiplication in ROP. To have a
The protection solution Themida supports three basic VM larger set of samples, we also used a CTF challenge [41]
flavors, namely, Tiger, Fish, and Dolphin. Each flavor that has been generated by the ROP compiler Q [51] and
can further be customized to use one of three obfuscation another Fibonacci implementation that has been generated
levels, in increasing complexity: White, Red, and Black. with ROPC [39].
We note that related work on deobfuscation does not di-
Syntia automatically dissected the instruction traces
rectly mention the exact configuration used for Themida.
into 156 individual gadgets. Since many gadgets use
In hopes to be comparable, we opted to use the default
exactly the same instructions, we unified them into 78
flavor Tiger, using level White, in our evaluation. Unlike
unique gadgets. On average, a gadget consists of 3 instruc-
VMProtect, Tiger White uses an explicit handler table
tions with 3 inputs and 2 outputs (register and memory
while inlining the dispatcher routine; i. e., it follows the
locations).
Threaded Code design principle (cf. Section 2.1.1). Con-
sequently, trace dissection again yields one trace window Due to the small numbers of inputs and synthesis tasks,
per instruction handler. Even though the central handler we chose the configuration vector (1.5, 100000, 50, 0) that
table lists 1, 111 handlers, we identified 106 unique trace sets a very strong focus on exploration while accepting
windows along the concrete execution trace. a higher running time. Especially, we experienced both
Themida implements a register-based architecture and effects for the maximum number of MCTS iterations.
stores intermediate computations in one of many register Syntia synthesized partial semantics for 97.4% of the
available in the VM context. This, in turn, affects the gadgets in less than 14 minutes; in total, we were suc-
identification of input and output variables. While in the cessful in 163 out of the 178 (91.5%) synthesis tasks.
case of VMProtect, inputs and outputs are directly taken Our synthesis results include 58 assignments, 17 binary
from two slots on the stack, Themida has a significantly additions, 5 ternary additions, 4 unary minus, 4 binary
higher number of potential inputs and outputs (i. e., all subtractions, 4 register increments/decrements, 2 binary
virtual registers in the VM context, 10 to 15 in our case). multiplications and 1 bitwise and. In addition, we found
Tiger White supports handlers for addition, subtraction, 68 stack pointer increments due to ret statements. The
multiplication, logical left and right shift, bitwise oper- results do not include larger constants or operations such
ations and unary subtraction; each for different operand as ror as they are not part of our grammar.

USENIX Association 26th USENIX Security Symposium 655


7 Discussion mar by control-flow operations is another viable approach
to tackle this limitation.
In the following, we discuss different aspects of program
synthesis for trace simplification and MCTS-based pro-
MCTS-based Program Synthesis. Compared to SMT-
gram synthesis. Furthermore, we point out limitations of
based program synthesis, we obtain candidate solutions,
our approach as well as future work.
even if the synthesizer does not find an exact result. This
is particularly beneficial for applications such as deob-
Program Synthesis for Trace Simplification. Current fuscation, since a human analyst can sometimes infer the
research on deobfuscation [13, 53, 61, 62] operates on full semantics. We decided to utilize MCTS for program
instruction traces and uses a mixed approach consisting synthesis since it has been proven very effective when
of symbolic execution [61] and taint analysis [60]; two operating on large search trees without domain knowl-
approaches that require a precise analysis of the under- edge. However, our approach is not limited to MCTS,
lying code. While techniques exist that defeat taint anal- other stochastic algorithms are also applicable.
ysis [6, 48], recent work shows that symbolic execution Drawn from the observations made in Section 6, we
can similarly be attacked [2]. infer that the MCTS approach is much more effective
with a configuration that focuses on exploration instead of
Program synthesis is an orthogonal approach that oper-
exploitation. The SA-UCT parameter ensures that paths
ates on a purely semantical level as opposed to (binary)
with a higher reward are explored in-depth in later stages
code analysis; it is oblivious to the underlying code con-
of the algorithm. We still try to improve exploration
structs. As a result, syntactical aspects of code complexity
strategies, for instance with Nested Monte Carlo Tree
such as obfuscation or instruction count do not influence
Search [35] and Monte Carlo Beam Search [7].
program synthesis negatively. It is merely concerned with
the complexity of the code’s semantics. The only excep-
tion where code-level artifacts matter is the generation Limitations. In general, limits of program synthesis
of I/O samples; however, this can be realized with small apply to our approach as well. Non-determinism and point
overhead compared to regular execution time using dy- functions—Boolean functions that return 1 for exactly one
namic binary instrumentation [37, 40]. input out of a large input domain—cannot be synthesized
Commonly, instruction traces contain repetitions of practically. This also holds for semantics that have strong
unique trace windows that can be caused by loops or confusion and diffusion properties, such as cryptographic
repeated function calls to the same function. By synthe- algorithms. These are inherently very complex, non-linear
sizing these trace windows, the synthesized semantics expressions with a deep nesting level. Our approach is
pertain for all appearances on the instruction trace; the also limited by the choice of trace window boundaries;
more frequently these trace windows occur in the trace, ending a trace window in intermediate computation steps
the higher the percentage of known semantics in the in- may produce formulas that are not meaningful at all.
struction trace. We stress how VM-based obfuscation
schemes do this to the extreme: a relatively small number
of unique trace windows are used over the whole trace. 8 Related Work
In general, the synthesis results may not be precise se-
mantics since we approximate them based on I/O samples. We now review related work for program synthesis, Monte
If these do not reflect the full semantics, the synthesis Carlo Tree Search and deobfuscation. Furthermore, we
misses edge cases. For instance, we sometimes cannot describe how our work fits into these research areas.
distinguish between an arithmetic and a logical right shift
if the random inputs are no distinguishing inputs. We Program Synthesis. Gulwani et al. [22] introduced an
point out that this is not necessarily a limitation, since a SMT-based program synthesis approach for loop-free pro-
human analyst might still get valuable insights from the grams that requires a logical specification of the desired
approximated semantics. program behavior. Building on this, Jha et al. [24] re-
As future work, we consider improving trace simplifi- placed the specification with an I/O oracle. Upon gener-
cation by a stratified synthesis approach [23]. The main ation of multiple valid program candidates, they derive
idea is to incrementally synthesize larger parts of the in- distinguishing inputs that are used for subsequent oracle
struction trace based on previous results and successively queries. They demonstrated their use case by simplifying
approximate high-level semantics of the entire trace. Fur- a string obfuscation routine of MyDoom. Godfroid and
ther, we note that the work by Sharif et al. [53] is comple- Taly [18] used an SMT-based approach to learn the formal
mentary to our synthesis approach and would also allow semantics of CPU instruction sets; for this, they use the
us to identify control flow. Likewise, extending the gram- CPU as I/O oracle.

656 26th USENIX Security Symposium USENIX Association


Schkufza et al. [50] proved that stochastic program also concerned with (static) analysis of VMs [26]. Specif-
synthesis often outperforms SMT-based approaches. This ically, he lifts a location-sensitive analysis to be usable
is mostly due to the fact that common SMT-based ap- in presence of virtualization-based obfuscation schemes.
proaches effectively enumerate all programs of a given His work highlights how the execution trace of a VM,
size or prove their non-existence. On the other hand, while performing various computations, always exhibits
stochastic approaches focus on promising parts of the a recurring set of addresses. As seen in Section 6, our ap-
search space without searching exhaustively. Schkufza proach actually benefits from this side effect. In contrast,
et al. use this technique for stochastic superoptimization Sharif et al. [53] analyze VMs in a dynamic manner and
on the basis of their tool STOKE. Recent work by Heule record execution traces. In contrast to the work of Rolles,
et al. [23] demonstrates a stratified approach to learn the their goal is not to re-translate, but to directly analyze the
semantics of the x86-64 instruction set, based on STOKE. bytecode itself. Specifically, they aim to reconstruct parts
Their main idea is to re-use synthesis results to synthe- of the underlying code’s control flow from the bytecode.
size more complex instructions in an iterative manner. This approach is closest to our work as we are, in turn,
To the best of our knowledge, STOKE is the only other mostly concerned with arithmetic and logical semantics
stochastic synthesis tool that is able to synthesize low- of a handler.
level semantics. By design, their code only produces Intel More recent results include work by Coogan et al. [13]
x86 code. as well as Yadegari et al. [62]. Both approaches seek to de-
In our case, stochastic techniques have additional prop- obfuscate code based on execution traces by further mak-
erties that are not achieved by previous tools: we obtain ing use of symbolic execution and taint tracking. The for-
partial results that are often already “close” to a real solu- mer approach is focused on the value flow to system calls
tion and might be helpful for a human analyst who tries to reduce a trace whereas Yadegari et al. propose a more
to understand obfuscated code. Furthermore, we can en- general approach and aim to produce fully deobfuscated
code arbitrary complex function symbols in our grammar code. However, to counteract symbolic execution-based
(e. g., complex encoding schemes or hash functions); a deobfuscation approaches, Banescu et al. propose novel
characteristic that is not easily reproduced by SMT-based obfuscating transformations that specifically target their
approaches. deficiencies [2]. For one, they propose a construct akin
In the context of non-academic work, Rolles applied to random opaque predicates [12] that deliberately ex-
some of the above mentioned SMT-based approaches to plodes the number of paths through a function. A second
reverse engineering and deobfuscation [45]. Amongst technique preserves program behavior of the obfuscated
others, he learned obfuscation rules by adapting peephole program for specific input invariants only, effectively in-
superoptimization techniques [3] and extracted metamor- creasing the input domains and thus the search space for
phic code using an oracle-guided approach. In his recent symbolic executors.
work, he performs SMT-based shellcode synthesis [46]. Guinet et al. present arybo, a framework to simplify
MBA expressions [20]. In essence, they perform bit-
blasting and use a Boolean expression solver that tries
Monte Carlo Tree Search. MCTS has been widely to simplify the expression symbolically. Eyrolles [15]
studied in the area of AI in games [16, 35, 49, 56]. Ruijl describes a symbolic approach that uses pattern matching.
et al. [47] combine Simulated Annealing and MCTS by Furthermore, she suggests improvements of current MBA-
introducing SA-UCT for expression simplification. Lim obfuscated implementations that impede these symbolic
and Yoo [32] describe an early exploration on how MCTS deobfuscation techniques [14]. To this effect, we also
can be used for program synthesis and note that it shows argue that symbolic simplification is inherently limited
comparable performance to genetic programming. We by the complexity of the input expression. However, we
extend the research of MCTS-based program synthesis by demonstrated that a synthesis-based approach allows fine-
applying SA-UCT and introducing node pruning. For our tuned simplification, irrespective of syntactical complex-
synthesis approach, we designed a context-free grammar ity, while producing approximate intermediate results.
that learns the semantics of Intel x86 code.

9 Conclusion
Deobfuscation. Rolles provides an academic analysis
of a VM-based obfuscator and outlines a possible attack With our prototype implementation of Syntia we have
on such schemes in general [44]. He proposes using shown that program synthesis can aid in deobfuscation
static analysis to re-translate the VM’s bytecode back into of real-world obfuscated code. In general, our approach
native instructions. This, however, requires minute analy- is vastly different in nature compared to proposed deob-
sis of each obfuscator and hence is time-consuming and fuscation techniques and hence may succeed in scenarios
prone to minor modifications of the scheme. Kinder is where approaches requiring precise code semantics fail.

USENIX Association 26th USENIX Security Symposium 657


Acknowledgments [17] G ELLY, S., KOCSIS , L., S CHOENAUER , M., S EBAG , M., S IL -
VER , D., S ZEPESVÁRI , C., AND T EYTAUD , O. The Grand Chal-

We thank the reviewers for their valuable feedback. This lenge of Computer Go: Monte Carlo Tree Search and Extensions.
Communications of the ACM (2012).
work was supported by the German Research Foundation
(DFG) research training group UbiCrypt (GRK 1817) and [18] G ODEFROID , P., AND TALY, A. Automated Synthesis of Sym-
bolic Instruction Encodings from I/O Samples. In ACM SIGPLAN
by ERC Starting Grant No. 640110 (BASTION). Notices (2012).
[19] G RAZIANO , M., BALZAROTTI , D., AND Z IDOUEMBA , A. ROP-
References MEMU: A Framework for the Analysis of Complex Code-Reuse
Attacks. In ACM Symposium on Information, Computer and Com-
[1] A NDRIESSE , D., B OS , H., AND S LOWINSKA , A. Parallax: Im- munications Security (ASIACCS) (2016).
plicit Code Integrity Verification using Return-Oriented Program-
ming. In Conference on Dependable Systems and Networks (DSN) [20] G UINET, A., E YROLLES , N., AND V IDEAU , M. Arybo: Ma-
(2015). nipulation, Canonicalization and Identification of Mixed Boolean-
Arithmetic Symbolic Expressions. In GreHack Conference (2016).
[2] BANESCU , S., C OLLBERG , C., G ANESH , V., N EWSHAM , Z.,
AND P RETSCHNER , A. Code Obfuscation against Symbolic Exe- [21] G ULWANI , S. Dimensions in Program Synthesis. In Proceedings
cution Attacks. In Annual Computer Security Applications Con- of the 12th international ACM SIGPLAN symposium on Principles
ference (ACSAC) (2016). and practice of declarative programming (2010).
[3] BANSAL , S., AND A IKEN , A. Automatic Generation of Peephole [22] G ULWANI , S., J HA , S., T IWARI , A., AND V ENKATESAN , R.
Superoptimizers. In ACM Sigplan Notices (2006). Synthesis of Loop-free Programs. ACM SIGPLAN Notices (2011).
[4] B ELL , J. R. Threaded Code. Communications of the ACM (1973). [23] H EULE , S., S CHKUFZA , E., S HARMA , R., AND A IKEN , A. Strat-
[5] B ROWNE , C. B., P OWLEY, E., W HITEHOUSE , D., L UCAS , ified synthesis: Automatically Learning the x86-64 Instruction
S. M., C OWLING , P. I., ROHLFSHAGEN , P., TAVENER , S., Set. In ACM SIGPLAN Conference on Programming Language
P EREZ , D., S AMOTHRAKIS , S., AND C OLTON , S. A Survey Design and Implementation (PLDI) (2016).
of Monte Carlo Tree Search Methods. IEEE Transactions on [24] J HA , S., G ULWANI , S., S ESHIA , S. A., AND T IWARI , A. Oracle-
Computational Intelligence and AI in Games (2012). guided Component-based Program Synthesis. In ACM/IEEE 32nd
[6] C AVALLARO , L., S AXENA , P., AND S EKAR , R. Anti-Taint- International Conference on Software Engineering (2010).
Analysis: Practical Evasion Techniques against Information Flow [25] K IM , D.-W., K IM , K.-H., JANG , W., AND C HEN , F. F. Unre-
based Malware Defense. Secure Systems Lab at Stony Brook lated Parallel Machine Scheduling with Setup Times using Simu-
University, Tech. Rep (2007). lated Annealing. Robotics and Computer-Integrated Manufactur-
[7] C AZENAVE , T. Monte carlo beam search. IEEE Transactions on ing (2002).
Computational Intelligence and AI in Games (2012). [26] K INDER , J. Towards Static Analysis of Virtualization-Obfuscated
[8] C HASLOT, G. Monte-Carlo Tree Search. PhD thesis, Universiteit Binaries. In IEEE Working Conference on Reverse Engineering
Maastricht, 2010. (WCRE) (2012).
[9] C OLLBERG , C., M ARTIN , S., M YERS , J., AND NAGRA , J. Dis- [27] K IRKPATRICK , S., G ELATT, C. D., AND V ECCHI , M. P. Opti-
tributed Application Tamper Detection via Continuous Software mization by Simulated Annealing. Science (1983).
Updates. In Annual Computer Security Applications Conference
(ACSAC) (2012). [28] K LINT, P. Interpretation Techniques. Software, Practice and
Experience (1981).
[10] C OLLBERG , C., M ARTIN , S., M YERS , J., AND Z IMMER -
MAN , B. Documentation for Arithmetic Encodings in [29] KOCSIS , L., AND S ZEPESVÁRI , C. Bandit based Monte-Carlo
Tigress. http://tigress.cs.arizona.edu/transformPage/ Planning. In European Conference on Machine Learning (2006).
docs/encodeArithmetic. [30] K RAHMER , S. x86-64 Buffer Overflow Exploits and the Borrowed
[11] C OLLBERG , C., M ARTIN , S., M YERS , J., AND Z IMMERMAN , Code Chunks Exploitation Technique, 2005.
B. Documentation for Data Encodings in Tigress. http:// [31] L IBERATORE , P. The Complexity of Checking Redundancy of
tigress.cs.arizona.edu/transformPage/docs/encodeData. CNF Propositional Formulae. In International Conference on
[12] C OLLBERG , C., T HOMBORSON , C., AND L OW, D. Manufactur- Agents and Artificial Intelligence (2002).
ing Cheap, Resilient, and Stealthy Opaque Constructs. In ACM
[32] L IM , J., AND YOO , S. Field Report: Applying Monte Carlo Tree
Symposium on Principles of Programming Languages (POPL)
Search for Program Synthesis. In International Symposium on
(1998).
Search Based Software Engineering (2016).
[13] C OOGAN , K., L U , G., AND D EBRAY, S. Deobfuscation
of Virtualization-obfuscated Software: A Semantics-Based Ap- [33] L U , K., X IONG , S., AND G AO , D. RopSteg: Program Steganog-
proach. In ACM Conference on Computer and Communications raphy with Return Oriented Programming. In ACM Conference on
Security (CCS) (2011). Data and Application Security and Privacy (CODASPY) (2014).

[14] E YROLLES , N. Obfuscation with Mixed Boolean-Arithmetic Ex- [34] M A , H., L U , K., M A , X., Z HANG , H., J IA , C., AND G AO , D.
pressions: Reconstruction, Analysis and Simplification Tools. PhD Software Watermarking using Return-Oriented Programming. In
thesis, Université de Versailles Saint-Quentin-en-Yvelines, 2017. ACM Symposium on Information, Computer and Communications
Security (ASIACCS) (2015).
[15] E YROLLES , N., G OUBIN , L., AND V IDEAU , M. Defeating MBA-
based Obfuscation. In ACM Workshop on Software PROtection [35] M ARC , S EBAG , M., S ILVER , D., S ZEPESVÁRI , C., AND T EY-
(SPRO) (2016). TAUD , O. Nested Monte-Carlo Search. Communications of the
ACM (2012).
[16] F INNSSON , H. Generalized Monte-Carlo Tree Search Extensions
for General Game Playing. In AAAI Conference on Artificial [36] M ICROSOFT R ESEARCH. The Z3 Theorem Prover. https://
Intelligence (2012). github.com/Z3Prover/z3.

658 26th USENIX Security Symposium USENIX Association


[37] N ETHERCOTE , N., AND S EWARD , J. Valgrind: A Framework for [58] VMP ROTECT S OFTWARE. VMProtect Software Protection. http:
Heavyweight Dynamic Binary Instrumentation. In ACM Sigplan //vmpsoft.com.
Notices (2007). [59] VOGL , S., P FOH , J., K ITTEL , T., AND E CKERT, C. Persistent
[38] O REANS T ECHNOLOGIES. Themida – Advanced Windows Soft- Data-only Malware: Function Hooks without Code. In Symposium
ware Protection System. http://oreans.com/themida.php. on Network and Distributed System Security (NDSS) (2014).
[39] PAKT. ROPC: A Turing complete ROP compiler. https:// [60] YADEGARI , B., AND D EBRAY, S. Bit-level Taint Analysis. In
github.com/pakt/ropc. IEEE International Working Conference on Source Code Analysis
[40] P EWNY, J., G ARMANY, B., G AWLIK , R., ROSSOW, C., AND and Manipulation (2014).
H OLZ , T. Cross-architecture Bug Search in Binary Executables. [61] YADEGARI , B., AND D EBRAY, S. Symbolic Execution of Obfus-
In IEEE Symposium on Security and Privacy (2015). cated Code. In ACM Conference on Computer and Communica-
[41] P LAID CTF. ROP Challenge “quite quixotic chest”. https: tions Security (CCS) (2015).
//ctftime.org/task/2305, 2016. [62] YADEGARI , B., J OHANNESMEYER , B., W HITELY, B., AND
[42] Q UYNH , N. A., D I , T. S., NAGY, B., AND V U , D. H. Capstone D EBRAY, S. A Generic Approach to Automatic Deobfuscation of
Engine. http://www.capstone-engine.org. Executable Code. In IEEE Symposium on Security and Privacy
(2015).
[43] Q UYNH , N. A., AND V U , D. H. Unicorn – The Ultimate CPU
Emulator. http://www.unicorn-engine.org. [63] Z HOU , Y., M AIN , A., G U , Y. X., AND J OHNSON , H. Information
Hiding in Software with Mixed Boolean-Arithmetic Transforms.
[44] ROLLES , R. Unpacking Virtualization Obfuscators. In USENIX
In International Workshop on Information Security Applications
Workshop on Offensive Technologies (WOOT) (2009).
(WISA) (2007).
[45] ROLLES , R. Program Synthesis in Reverse Engineer-
ing. http://www.msreverseengineering.com/blog/2014/12/
12/program-synthesis-in-reverse-engineering, 2014.
[46] ROLLES , R. Synesthesia: A Modern Approach to Shellcode
Generation. http://www.msreverseengineering.com/blog/
2016/11/8/synesthesia-modern-shellcode-synthesis-
ekoparty-2016-talk, 2016.
[47] RUIJL , B., V ERMASEREN , J. A. M., P LAAT, A., AND VAN DEN
H ERIK , H. J. Combining Simulated Annealing and Monte Carlo
Tree Search for Expression Simplification. In International Con-
ference on Agents and Artificial Intelligence (2014).
[48] S ARWAR , G., M EHANI , O., B ORELI , R., AND K AAFAR , D. On
the Effectiveness of Dynamic Taint Analysis for Protecting against
Private Information Leaks on Android-based Devices. Nicta
(2013).
[49] S CHADD , M. P., W INANDS , M. H., TAK , M. J., AND
U ITERWIJK , J. W. Single-player Monte-Carlo Tree Search for
SameGame. Knowledge-Based Systems (2012).
[50] S CHKUFZA , E., S HARMA , R., AND A IKEN , A. Stochastic Su-
peroptimization. ACM SIGPLAN Notices (2013).
[51] S CHWARTZ , E. J., AVGERINOS , T., AND B RUMLEY, D. Q:
Exploit Hardening Made Easy. In USENIX Security Symposium
(2011).
[52] S HACHAM , H. The Geometry of Innocent Flesh on the Bone:
Return-into-libc without Function Calls (on the x86). In ACM
Conference on Computer and Communications Security (CCS)
(2007).
[53] S HARIF, M., L ANZI , A., G IFFIN , J., AND L EE , W. Automatic
Reverse Engineering of Malware Emulators. In IEEE Symposium
on Security and Privacy (2009).
[54] S ILVER , D., H UANG , A., M ADDISON , C. J., G UEZ , A.,
S IFRE , L., VAN D EN D RIESSCHE , G., S CHRITTWIESER , J.,
A NTONOGLOU , I., PANNEERSHELVAM , V., L ANCTOT, M.,
ET AL . Mastering the Game of Go with Deep Neural Networks
and Tree Search. Nature (2016).
[55] S ONY DADC. SecuROM Software Protection. https://
www2.securom.com/Digital-Rights-Management.68.0.html.
[56] S ZITA , I STVÁN AND C HASLOT, G UILLAUME AND S PRONCK ,
P IETER. Monte-Carlo Tree Search in Settlers of Catan. In Ad-
vances in Computer Games (2009).
[57] TAGES SAS. SolidShield Software Protection. https:
//www.solidshield.com/software-protection-and-
licensing.

USENIX Association 26th USENIX Security Symposium 659

Das könnte Ihnen auch gefallen